Merged PR 203: Improve responsive design and refactor layout
This commit is contained in:
parent
50626218ba
commit
0d05f0959c
27 changed files with 968 additions and 485 deletions
|
@ -1,21 +1,22 @@
|
|||
import * as React from 'react';
|
||||
import { ElementsSidebar } from '../ElementsSidebar/ElementsSidebar';
|
||||
import { Sidebar } from '../Sidebar/Sidebar';
|
||||
import { ElementsList } from '../ElementsList/ElementsList';
|
||||
import { History } from '../History/History';
|
||||
import { IAvailableContainer } from '../../Interfaces/IAvailableContainer';
|
||||
import { IContainerModel } from '../../Interfaces/IContainerModel';
|
||||
import { IHistoryState } from '../../Interfaces/IHistoryState';
|
||||
import { CameraIcon, ArrowUpOnSquareIcon } from '@heroicons/react/24/outline';
|
||||
import { FloatingButton } from '../FloatingButton/FloatingButton';
|
||||
import { Bar } from '../Bar/Bar';
|
||||
import { IAvailableSymbol } from '../../Interfaces/IAvailableSymbol';
|
||||
import { Symbols } from '../Symbols/Symbols';
|
||||
import { SymbolsSidebar } from '../SymbolsSidebar/SymbolsSidebar';
|
||||
import { SymbolsSidebar } from '../SymbolsList/SymbolsList';
|
||||
import { PropertyType } from '../../Enums/PropertyType';
|
||||
import { MessagesSidebar } from '../MessagesSidebar/MessagesSidebar';
|
||||
import { Messages } from '../Messages/Messages';
|
||||
import { ICategory } from '../../Interfaces/ICategory';
|
||||
import { Sidebar } from '../Sidebar/Sidebar';
|
||||
import { Components } from '../Components/Components';
|
||||
import { Viewer } from '../Viewer/Viewer';
|
||||
import { Settings } from '../Settings/Settings';
|
||||
|
||||
interface IUIProps {
|
||||
export interface IUIProps {
|
||||
selectedContainer: IContainerModel | undefined
|
||||
current: IHistoryState
|
||||
history: IHistoryState[]
|
||||
|
@ -37,106 +38,157 @@ interface IUIProps {
|
|||
loadState: (move: number) => void
|
||||
}
|
||||
|
||||
function CloseOtherSidebars(
|
||||
setIsSidebarOpen: React.Dispatch<React.SetStateAction<boolean>>,
|
||||
setIsSymbolsOpen: React.Dispatch<React.SetStateAction<boolean>>,
|
||||
setIsMessagesOpen: React.Dispatch<React.SetStateAction<boolean>>
|
||||
): void {
|
||||
setIsSidebarOpen(false);
|
||||
setIsSymbolsOpen(false);
|
||||
setIsMessagesOpen(false);
|
||||
export enum SidebarType {
|
||||
None,
|
||||
Components,
|
||||
Symbols,
|
||||
History,
|
||||
Messages,
|
||||
Settings
|
||||
}
|
||||
|
||||
function UseSetOrToggleSidebar(
|
||||
selectedSidebar: SidebarType,
|
||||
setSelectedSidebar: React.Dispatch<React.SetStateAction<SidebarType>>
|
||||
): (newSidebarType: SidebarType) => void {
|
||||
return (newSidebarType) => {
|
||||
if (newSidebarType === selectedSidebar) {
|
||||
setSelectedSidebar(SidebarType.None);
|
||||
return;
|
||||
}
|
||||
|
||||
setSelectedSidebar(newSidebarType);
|
||||
};
|
||||
}
|
||||
|
||||
export function UI(props: IUIProps): JSX.Element {
|
||||
const [isSidebarOpen, setIsSidebarOpen] = React.useState(true);
|
||||
const [isSymbolsOpen, setIsSymbolsOpen] = React.useState(false);
|
||||
const [isHistoryOpen, setIsHistoryOpen] = React.useState(false);
|
||||
const [isMessagesOpen, setIsMessagesOpen] = React.useState(false);
|
||||
const [selectedSidebar, setSelectedSidebar] = React.useState<SidebarType>(SidebarType.Components);
|
||||
|
||||
let buttonRightOffsetClasses = 'right-12';
|
||||
if (isSidebarOpen || isHistoryOpen || isSymbolsOpen) {
|
||||
buttonRightOffsetClasses = 'right-72';
|
||||
// Please use setOrToggleSidebar rather than setSelectedSidebar so we can close the sidebar
|
||||
const setOrToggleSidebar = UseSetOrToggleSidebar(selectedSidebar, setSelectedSidebar);
|
||||
|
||||
let leftSidebarTitle = '';
|
||||
let rightSidebarTitle = '';
|
||||
let leftChildren: JSX.Element = (<></>);
|
||||
let rightChildren: JSX.Element = (<></>);
|
||||
|
||||
switch (selectedSidebar) {
|
||||
case SidebarType.Components:
|
||||
leftSidebarTitle = 'Components';
|
||||
leftChildren = <Components
|
||||
selectedContainer={props.selectedContainer}
|
||||
componentOptions={props.availableContainers}
|
||||
categories={props.categories}
|
||||
buttonOnClick={props.addContainer}
|
||||
/>;
|
||||
rightSidebarTitle = 'Elements';
|
||||
rightChildren = <ElementsList
|
||||
mainContainer={props.current.mainContainer}
|
||||
symbols={props.current.symbols}
|
||||
selectedContainer={props.selectedContainer}
|
||||
onPropertyChange={props.onPropertyChange}
|
||||
selectContainer={props.selectContainer}
|
||||
addContainer={props.addContainerAt}
|
||||
/>;
|
||||
break;
|
||||
|
||||
case SidebarType.Symbols:
|
||||
leftSidebarTitle = 'Symbols';
|
||||
leftChildren = <Symbols
|
||||
componentOptions={props.availableSymbols}
|
||||
buttonOnClick={props.addSymbol}
|
||||
/>;
|
||||
rightSidebarTitle = 'Symbols';
|
||||
rightChildren = <SymbolsSidebar
|
||||
selectedSymbolId={props.current.selectedSymbolId}
|
||||
symbols={props.current.symbols}
|
||||
onPropertyChange={props.onSymbolPropertyChange}
|
||||
selectSymbol={props.selectSymbol}
|
||||
/>;
|
||||
break;
|
||||
|
||||
case SidebarType.History:
|
||||
leftSidebarTitle = 'Timeline';
|
||||
leftChildren = <History
|
||||
history={props.history}
|
||||
historyCurrentStep={props.historyCurrentStep}
|
||||
jumpTo={props.loadState}
|
||||
/>;
|
||||
break;
|
||||
|
||||
case SidebarType.Messages:
|
||||
leftSidebarTitle = 'Messages';
|
||||
leftChildren = <Messages
|
||||
historyState={props.current}
|
||||
/>;
|
||||
break;
|
||||
|
||||
case SidebarType.Settings:
|
||||
leftSidebarTitle = 'Settings';
|
||||
leftChildren = <Settings
|
||||
saveEditorAsJSON={props.saveEditorAsJSON}
|
||||
saveEditorAsSVG={props.saveEditorAsSVG}
|
||||
/>;
|
||||
break;
|
||||
}
|
||||
if (isHistoryOpen && (isSidebarOpen || isSymbolsOpen)) {
|
||||
buttonRightOffsetClasses = 'right-[544px]';
|
||||
|
||||
const isLeftSidebarOpen = selectedSidebar !== SidebarType.None;
|
||||
const isRightSidebarOpen = selectedSidebar === SidebarType.Components || selectedSidebar === SidebarType.Symbols;
|
||||
|
||||
let isLeftSidebarOpenClasses = 'left-16 -bottom-full md:-left-64 md:bottom-0';
|
||||
let isRightSidebarOpenClasses = 'right-0 -bottom-full md:-right-80 md:bottom-0';
|
||||
|
||||
if (isLeftSidebarOpen) {
|
||||
isLeftSidebarOpenClasses = 'left-16';
|
||||
}
|
||||
|
||||
if (isRightSidebarOpen) {
|
||||
isRightSidebarOpenClasses = 'right-0';
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Bar
|
||||
isSidebarOpen={isSidebarOpen}
|
||||
isSymbolsOpen={isSymbolsOpen}
|
||||
isElementsSidebarOpen={isSidebarOpen}
|
||||
isHistoryOpen={isHistoryOpen}
|
||||
isMessagesOpen={isMessagesOpen}
|
||||
toggleSidebar={() => {
|
||||
CloseOtherSidebars(setIsSidebarOpen, setIsSymbolsOpen, setIsMessagesOpen);
|
||||
setIsSidebarOpen(!isSidebarOpen);
|
||||
isComponentsOpen={selectedSidebar === SidebarType.Components}
|
||||
isSymbolsOpen={selectedSidebar === SidebarType.Symbols}
|
||||
isHistoryOpen={selectedSidebar === SidebarType.History}
|
||||
isMessagesOpen={selectedSidebar === SidebarType.Messages}
|
||||
isSettingsOpen={selectedSidebar === SidebarType.Settings}
|
||||
toggleComponents={() => {
|
||||
setOrToggleSidebar(SidebarType.Components);
|
||||
} }
|
||||
toggleSymbols={() => {
|
||||
CloseOtherSidebars(setIsSidebarOpen, setIsSymbolsOpen, setIsMessagesOpen);
|
||||
setIsSymbolsOpen(!isSymbolsOpen);
|
||||
setOrToggleSidebar(SidebarType.Symbols);
|
||||
} }
|
||||
toggleTimeline={() => {
|
||||
setOrToggleSidebar(SidebarType.History);
|
||||
} }
|
||||
toggleTimeline={() => setIsHistoryOpen(!isHistoryOpen)}
|
||||
toggleMessages={() => {
|
||||
CloseOtherSidebars(setIsSidebarOpen, setIsSymbolsOpen, setIsMessagesOpen);
|
||||
setIsMessagesOpen(!isMessagesOpen);
|
||||
} }/>
|
||||
|
||||
setOrToggleSidebar(SidebarType.Messages);
|
||||
} }
|
||||
toggleSettings={() => {
|
||||
setOrToggleSidebar(SidebarType.Settings);
|
||||
} }
|
||||
/>
|
||||
<Sidebar
|
||||
className={`left-sidebar ${isLeftSidebarOpenClasses}`}
|
||||
title={leftSidebarTitle}
|
||||
>
|
||||
{ leftChildren }
|
||||
</Sidebar>
|
||||
<Viewer
|
||||
isLeftSidebarOpen={isLeftSidebarOpen}
|
||||
isRightSidebarOpen={isRightSidebarOpen}
|
||||
current={props.current}
|
||||
selectedContainer={props.selectedContainer}
|
||||
componentOptions={props.availableContainers}
|
||||
categories={props.categories}
|
||||
isOpen={isSidebarOpen}
|
||||
buttonOnClick={props.addContainer} />
|
||||
<Symbols
|
||||
componentOptions={props.availableSymbols}
|
||||
isOpen={isSymbolsOpen}
|
||||
buttonOnClick={props.addSymbol} />
|
||||
<ElementsSidebar
|
||||
mainContainer={props.current.mainContainer}
|
||||
symbols={props.current.symbols}
|
||||
selectedContainer={props.selectedContainer}
|
||||
isOpen={isSidebarOpen}
|
||||
isHistoryOpen={isHistoryOpen}
|
||||
onPropertyChange={props.onPropertyChange}
|
||||
selectContainer={props.selectContainer}
|
||||
addContainer={props.addContainerAt}
|
||||
/>
|
||||
<SymbolsSidebar
|
||||
selectedSymbolId={props.current.selectedSymbolId}
|
||||
symbols={props.current.symbols}
|
||||
isOpen={isSymbolsOpen}
|
||||
isHistoryOpen={isHistoryOpen}
|
||||
onPropertyChange={props.onSymbolPropertyChange}
|
||||
selectSymbol={props.selectSymbol}
|
||||
/>
|
||||
<MessagesSidebar
|
||||
historyState={props.current}
|
||||
isOpen={isMessagesOpen}
|
||||
/>
|
||||
<History
|
||||
history={props.history}
|
||||
historyCurrentStep={props.historyCurrentStep}
|
||||
isOpen={isHistoryOpen}
|
||||
jumpTo={props.loadState} />
|
||||
|
||||
<FloatingButton className={`fixed z-10 flex flex-col gap-2 items-center bottom-40 ${buttonRightOffsetClasses}`}>
|
||||
<button type="button"
|
||||
className={'transition-all w-10 h-10 p-2 align-middle items-center justify-center rounded-full bg-blue-500 hover:bg-blue-800'}
|
||||
title='Export as JSON'
|
||||
onClick={props.saveEditorAsJSON}
|
||||
>
|
||||
<ArrowUpOnSquareIcon className="heroicon text-white" />
|
||||
</button>
|
||||
<button type="button"
|
||||
className={'transition-all w-10 h-10 p-2 align-middle items-center justify-center rounded-full bg-blue-500 hover:bg-blue-800'}
|
||||
title='Export as SVG'
|
||||
onClick={props.saveEditorAsSVG}
|
||||
>
|
||||
<CameraIcon className="heroicon text-white" />
|
||||
</button>
|
||||
</FloatingButton>
|
||||
<Sidebar
|
||||
className={`right-sidebar ${isRightSidebarOpenClasses}`}
|
||||
title={rightSidebarTitle}
|
||||
>
|
||||
{ rightChildren }
|
||||
</Sidebar>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue