flow: ui
This commit is contained in:
parent
8015c9ea06
commit
987551e975
1
attribution.txt
Normal file
1
attribution.txt
Normal file
|
@ -0,0 +1 @@
|
|||
"Document" icon made by Becris from www.flaticon.com
|
|
@ -4,7 +4,9 @@ import {hot} from 'react-hot-loader';
|
|||
import React, {useState} from 'react';
|
||||
|
||||
import TypeRenderersContext from './context/typeRenderers';
|
||||
import Resource from './resource';
|
||||
import Resources from './resources';
|
||||
import Sidebar from './sidebar';
|
||||
import SidebarIcons from './sidebar-icons';
|
||||
import {all as allTypeRenderers} from './type-renderers.scwp';
|
||||
|
||||
const typeRenderMap = () => Object.values(allTypeRenderers()).reduce((r, M) => {
|
||||
|
@ -15,9 +17,21 @@ const typeRenderMap = () => Object.values(allTypeRenderers()).reduce((r, M) => {
|
|||
const App = () => {
|
||||
const [typeRenderers] = useState(typeRenderMap());
|
||||
return (
|
||||
<div className="app">
|
||||
<TypeRenderersContext.Provider value={typeRenderers}>
|
||||
<Resource uri="/resources/cha0s/initial/mama-kitty.entity.json" />
|
||||
<div className="panes horizontal">
|
||||
<div className="sidebar-icons-wrapper pane">
|
||||
<SidebarIcons />
|
||||
</div>
|
||||
<div className="sidebar-wrapper pane">
|
||||
<Sidebar />
|
||||
</div>
|
||||
<div className="resources-wrapper pane">
|
||||
<Resources />
|
||||
</div>
|
||||
</div>
|
||||
</TypeRenderersContext.Provider>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
.app {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.panes {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
&.horizontal .pane {
|
||||
float: left;
|
||||
height: 100%;
|
||||
}
|
||||
&.vertical .pane {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar-icons-wrapper {
|
||||
width: 4em;
|
||||
}
|
||||
|
||||
.sidebar-wrapper {
|
||||
width: 24em;
|
||||
}
|
||||
|
||||
.resources-wrapper {
|
||||
width: calc(100% - 28em);
|
||||
}
|
|
@ -144,3 +144,81 @@ select {
|
|||
outline: none;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.react-tabs {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.react-tabs__tab-list {
|
||||
background-color: #272727;
|
||||
font-family: Ubuntu, "Droid Sans", sans-serif;
|
||||
font-size: 0.9em;
|
||||
overflow-x: hidden;
|
||||
scrollbar-width: thin;
|
||||
white-space: nowrap;
|
||||
width: 100%;
|
||||
&::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
}
|
||||
&::-webkit-scrollbar-track {
|
||||
background: #2e1d1d;
|
||||
}
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background-color: #777;
|
||||
border-radius: 0;
|
||||
border-width: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
.react-tabs__tab {
|
||||
background-color: #2d2d2d;
|
||||
color: #aaaaaa;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
height: 3em;
|
||||
&:not(:last-of-type) {
|
||||
border-right: 1px solid #282828;
|
||||
}
|
||||
&:hover {
|
||||
color: #ddd;
|
||||
}
|
||||
.wrapper {
|
||||
align-content: space-between;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
height: 100%;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
.icon {
|
||||
padding: 0.75em;
|
||||
}
|
||||
.close {
|
||||
color: #999999;
|
||||
padding: 0.25em;
|
||||
visibility: hidden;
|
||||
&:hover {
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
&:hover .close {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
|
||||
.react-tabs__tab--selected[class] {
|
||||
background-color: #212121;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.react-tabs__tab-panel {
|
||||
display: none;
|
||||
overflow-y: auto;
|
||||
height: calc(100% - 3em);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.react-tabs__tab-panel--selected {
|
||||
display: block;
|
||||
}
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
import './app.scss';
|
||||
|
||||
import {compose} from '@avocado/core';
|
||||
import contempo from 'contempo';
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import {registerHooks} from 'scwp';
|
||||
|
||||
import {all} from './resources.scwp';
|
||||
|
||||
const decorate = compose(
|
||||
contempo(require('./resource.raw.scss')),
|
||||
);
|
||||
|
||||
const resources = Object.values(all()).map((M) => M.default);
|
||||
|
||||
const Resource = (props) => {
|
||||
|
@ -29,7 +33,7 @@ Resource.propTypes = {
|
|||
uri: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
export default Resource;
|
||||
export default decorate(Resource);
|
||||
|
||||
if (module.hot) {
|
||||
registerHooks({
|
||||
|
|
4
src/client/resource.raw.scss
Normal file
4
src/client/resource.raw.scss
Normal file
|
@ -0,0 +1,4 @@
|
|||
:scope {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
53
src/client/resources.jsx
Normal file
53
src/client/resources.jsx
Normal file
|
@ -0,0 +1,53 @@
|
|||
import {compose} from '@avocado/core';
|
||||
import contempo from 'contempo';
|
||||
import React, {useState} from 'react';
|
||||
import {
|
||||
Tab,
|
||||
Tabs,
|
||||
TabList,
|
||||
TabPanel,
|
||||
} from 'react-tabs';
|
||||
|
||||
import Resource from './resource';
|
||||
|
||||
const decorate = compose(
|
||||
contempo(require('./resources.raw.scss')),
|
||||
);
|
||||
|
||||
const Sidebar = (props) => {
|
||||
const [tabIndex, setTabIndex] = useState(0);
|
||||
const uris = [
|
||||
'/resources/cha0s/initial/kitty.entity.json',
|
||||
'/resources/cha0s/initial/mama-kitty.entity.json',
|
||||
];
|
||||
return (
|
||||
<div className="resources">
|
||||
<Tabs
|
||||
selectedIndex={tabIndex}
|
||||
onSelect={(index) => setTabIndex(index)}
|
||||
>
|
||||
<TabList>
|
||||
{uris.map((uri) => (
|
||||
<Tab key={uri}>
|
||||
<span className="wrapper">
|
||||
<span className="icon" />
|
||||
<span className="text">{uri}</span>
|
||||
<span className="close">✕</span>
|
||||
</span>
|
||||
</Tab>
|
||||
))}
|
||||
</TabList>
|
||||
{uris.map((uri) => (
|
||||
<TabPanel>
|
||||
<Resource key={uri} uri={uri} />
|
||||
</TabPanel>
|
||||
))}
|
||||
</Tabs>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Sidebar.propTypes = {
|
||||
};
|
||||
|
||||
export default decorate(Sidebar);
|
17
src/client/resources.raw.scss
Normal file
17
src/client/resources.raw.scss
Normal file
|
@ -0,0 +1,17 @@
|
|||
:scope {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.react-tabs__tab .wrapper {
|
||||
padding: 0 0.5em;
|
||||
}
|
||||
|
||||
.react-tabs__tab .wrapper .text {
|
||||
padding: 0 0.5em;
|
||||
}
|
||||
|
||||
// :scope > .react-tabs > .react-tabs__tab-list {
|
||||
// margin-left: 4em;
|
||||
// width: calc(100% - 3em);
|
||||
// }
|
|
@ -1,65 +1,4 @@
|
|||
%tabs {
|
||||
|
||||
.react-tabs__tab-list {
|
||||
background-color: #272727;
|
||||
font-family: Ubuntu, "Droid Sans", sans-serif;
|
||||
font-size: 0.9em;
|
||||
overflow-x: hidden;
|
||||
scrollbar-width: thin;
|
||||
white-space: nowrap;
|
||||
width: 100%;
|
||||
&::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
}
|
||||
&::-webkit-scrollbar-track {
|
||||
background: #2e1d1d;
|
||||
}
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background-color: #777;
|
||||
border-radius: 0;
|
||||
border-width: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
.react-tabs__tab {
|
||||
background-color: #2d2d2d;
|
||||
color: #aaaaaa;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
&:not(:last-of-type) {
|
||||
border-right: 1px solid #282828;
|
||||
}
|
||||
&:hover {
|
||||
color: #ddd;
|
||||
}
|
||||
.wrapper {
|
||||
align-content: space-between;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
justify-content: space-evenly;
|
||||
height: 3em;
|
||||
width: 10em;
|
||||
}
|
||||
.icon {
|
||||
padding: 0.75em;
|
||||
}
|
||||
.close {
|
||||
color: #999999;
|
||||
padding: 0.25em;
|
||||
visibility: hidden;
|
||||
&:hover {
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
&:hover .close {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
|
||||
.react-tabs__tab--selected[class] {
|
||||
background-color: #212121;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
39
src/client/sidebar-icons.jsx
Normal file
39
src/client/sidebar-icons.jsx
Normal file
|
@ -0,0 +1,39 @@
|
|||
import {compose} from '@avocado/core';
|
||||
import classnames from 'classnames';
|
||||
import contempo from 'contempo';
|
||||
import React, {useState} from 'react';
|
||||
|
||||
const decorate = compose(
|
||||
contempo(require('./sidebar-icons.raw.scss')),
|
||||
);
|
||||
|
||||
const SidebarIcons = () => {
|
||||
const [opened, setOpened] = useState(false);
|
||||
return (
|
||||
<div className="sidebar-icons">
|
||||
<button
|
||||
className={classnames(
|
||||
'icon',
|
||||
'files',
|
||||
{opened},
|
||||
)}
|
||||
onClick={() => setOpened(!opened)}
|
||||
type="button"
|
||||
>
|
||||
|
||||
<svg
|
||||
viewBox="0 0 477.867 477.867"
|
||||
>
|
||||
<path
|
||||
d="M421.649,90.317L336.316,4.983c-1.589-1.593-3.481-2.852-5.564-3.703c-2.059-0.841-4.261-1.276-6.485-1.28H102.4 C74.123,0,51.2,22.923,51.2,51.2v375.467c0,28.277,22.923,51.2,51.2,51.2h273.067c28.277,0,51.2-22.923,51.2-51.2V102.4 C426.643,97.87,424.841,93.531,421.649,90.317z M341.333,58.266l27.068,27.068h-27.068V58.266z M392.533,426.667 c0,9.426-7.641,17.067-17.067,17.067H102.4c-9.426,0-17.067-7.641-17.067-17.067V51.2c0-9.426,7.641-17.067,17.067-17.067h204.8 V102.4c0,9.426,7.641,17.067,17.067,17.067h68.267V426.667z"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
SidebarIcons.propTypes = {
|
||||
};
|
||||
|
||||
export default decorate(SidebarIcons);
|
29
src/client/sidebar-icons.raw.scss
Normal file
29
src/client/sidebar-icons.raw.scss
Normal file
|
@ -0,0 +1,29 @@
|
|||
:scope {
|
||||
background-color: #333333;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.icon {
|
||||
align-items: center;
|
||||
background-color: inherit;
|
||||
border: none;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
height: 4em;
|
||||
width: 4em;
|
||||
svg {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
path {
|
||||
fill: #999999;
|
||||
}
|
||||
}
|
||||
&:hover svg path {
|
||||
fill: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
.files {
|
||||
padding: 0.75em;
|
||||
}
|
20
src/client/sidebar.jsx
Normal file
20
src/client/sidebar.jsx
Normal file
|
@ -0,0 +1,20 @@
|
|||
import {compose} from '@avocado/core';
|
||||
// import classnames from 'classnames';
|
||||
import contempo from 'contempo';
|
||||
import React from 'react';
|
||||
|
||||
const decorate = compose(
|
||||
contempo(require('./sidebar.raw.scss')),
|
||||
);
|
||||
|
||||
const Sidebar = () => {
|
||||
// const [active, setActive] = useState(false);
|
||||
return (
|
||||
<div className="sidebar" />
|
||||
);
|
||||
};
|
||||
|
||||
Sidebar.propTypes = {
|
||||
};
|
||||
|
||||
export default decorate(Sidebar);
|
5
src/client/sidebar.raw.scss
Normal file
5
src/client/sidebar.raw.scss
Normal file
|
@ -0,0 +1,5 @@
|
|||
:scope {
|
||||
background-color: #272727;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
|
@ -1,12 +1,19 @@
|
|||
:scope {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.document-pane {
|
||||
border-right: 1px solid #1a1a1a;
|
||||
display: none;
|
||||
float: left;
|
||||
width: calc(100% - 36em);
|
||||
height: 100vh;
|
||||
width: calc(100% - 58em);
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.settings-pane {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
float: left;
|
||||
// width: 58em;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
|
|
@ -1,18 +1,12 @@
|
|||
@import '~/client/scss/tabs.scss';
|
||||
@import '~/client/scss/trait.scss';
|
||||
|
||||
.react-tabs {
|
||||
@extend %tabs;
|
||||
:scope {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.react-tabs__tab-panel {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.react-tabs__tab-panel--selected {
|
||||
display: block;
|
||||
height: calc(100vh - 2.7em);
|
||||
overflow-y: auto;
|
||||
.react-tabs__tab .wrapper {
|
||||
width: 10em;
|
||||
}
|
||||
|
||||
.react-tabs__tab-panel input {
|
||||
|
|
Loading…
Reference in New Issue
Block a user