Merged PR 203: Improve responsive design and refactor layout

This commit is contained in:
Eric Nguyen 2022-10-03 12:05:16 +00:00
parent 50626218ba
commit 0d05f0959c
27 changed files with 968 additions and 485 deletions

View file

@ -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>
</>
);
}