Merged PR 315: ErgonomieTreeView

Affichage fonctionnelle sous forme de toolbar vertical, comme dans les IDE

Related work items: #7976
This commit is contained in:
Carl Fuchs 2023-02-07 14:25:53 +00:00 committed by Eric Nguyen
parent acb5ba2d82
commit 8a99ef4cfd
13 changed files with 240 additions and 133 deletions

View file

@ -4,11 +4,11 @@ import { expect, describe, it, vi } from 'vitest';
import { PositionReference } from '../../Enums/PositionReference';
import { IContainerProperties } from '../../Interfaces/IContainerProperties';
import { Orientation } from '../../Enums/Orientation';
import { Properties } from './ContainerProperties';
import { ContainerProperties } from './ContainerProperties';
describe.concurrent('Properties', () => {
it('No properties', () => {
render(<Properties
render(<ContainerProperties
properties={undefined}
onChange={() => {}}
symbols={new Map()}
@ -67,7 +67,7 @@ describe.concurrent('Properties', () => {
(prop as any)[key] = value;
});
const { container, rerender } = render(<Properties
const { container, rerender } = render(<ContainerProperties
properties={prop}
onChange={handleChange}
symbols={new Map()}
@ -108,7 +108,7 @@ describe.concurrent('Properties', () => {
expect(prop.parentId).toBe('parentId');
expect(prop.x).toBe(2);
expect(prop.y).toBe(2);
rerender(<Properties
rerender(<ContainerProperties
properties={Object.assign({}, prop)}
onChange={handleChange}
symbols={new Map()}

View file

@ -10,7 +10,7 @@ interface IPropertiesProps {
onChange: (key: string, value: string | number | boolean | number[], type?: PropertyType) => void
}
export function Properties(props: IPropertiesProps): JSX.Element {
export function ContainerProperties(props: IPropertiesProps): JSX.Element {
if (props.properties === undefined) {
return <div></div>;
}

View file

@ -36,6 +36,30 @@ export function SelectContainer(
return history;
}
/**
* Deselect a container
* @returns New history
*/
export function DeselectContainer(
containerId: string,
fullHistory: IHistoryState[],
historyCurrentStep: number
): IHistoryState[] {
const history = GetCurrentHistory(fullHistory, historyCurrentStep);
const current = history[history.length - 1];
history.push({
lastAction: `Deselect ${containerId}`,
mainContainer: current.mainContainer,
containers: structuredClone(current.containers),
selectedContainerId: 'undefined',
typeCounters: Object.assign({}, current.typeCounters),
symbols: structuredClone(current.symbols),
selectedSymbolId: current.selectedSymbolId
});
return history;
}
/**
* Delete a container
* @param containerId containerId of the container to delete
@ -115,7 +139,7 @@ export function DeleteContainer(
* If the selected container is removed, select the sibling after,
* If there is no sibling, select the parent,
*
* @param mainContainerClone Main container
* @param containers
* @param selectedContainerId Current selected container
* @param parent Parent of the selected/deleted container
* @param index Index of the selected/deleted container
@ -127,11 +151,10 @@ function GetSelectedContainerOnDelete(
parent: IContainerModel,
index: number
): string {
const newSelectedContainerId = FindContainerById(containers, selectedContainerId)?.properties.id ??
parent.children.at(index) ??
parent.children.at(index - 1) ??
parent.properties.id;
return newSelectedContainerId;
return FindContainerById(containers, selectedContainerId)?.properties.id ??
parent.children.at(index) ??
parent.children.at(index - 1) ??
parent.properties.id;
}
/**
@ -157,11 +180,15 @@ function UnlinkContainerFromSymbols(
}
/**
* Handled the property change event in the properties form
* @param key Property name
* @param value New value of the property
* @returns void
*/
* Handled the property change event in the properties form
* @param key Property name
* @param value New value of the property
* @param type
* @param selected
* @param fullHistory
* @param historyCurrentStep
* @returns void
*/
export function OnPropertyChange(
key: string,
value: string | number | boolean | number[],
@ -201,6 +228,7 @@ export function OnPropertyChange(
/**
* Sort the parent children by x
* @param containers
* @param parent The clone used for the sort
* @returns void
*/
@ -265,6 +293,7 @@ export function SortChildren(
/**
* Set the container with properties and behaviors (mutate)
* @param containers
* @param container Container to update
* @param key Key of the property to update
* @param value Value of the property to update
@ -371,9 +400,8 @@ function AssignProperty(container: IContainerModel, key: string, value: string |
/**
* Link a symbol to a container
* @param containerId Container id
* @param oldSymbolId Old Symbol id
* @param newSymbolId New Symbol id
* @param symbols Current list of symbols
* @param oldSymbol
* @param newSymbol
* @returns
*/
export function LinkSymbol(

View file

@ -1,14 +1,17 @@
import * as React from 'react';
import { useState } from 'react';
import useSize from '@react-hook/size';
import { FixedSizeList as List } from 'react-window';
import { Properties } from '../ContainerProperties/ContainerProperties';
import { ExclamationTriangleIcon } from '@heroicons/react/24/outline';
import { ContainerProperties } from '../ContainerProperties/ContainerProperties';
import { IContainerModel } from '../../Interfaces/IContainerModel';
import { FindContainerById, MakeRecursionDFSIterator } from '../../utils/itertools';
import { ISymbolModel } from '../../Interfaces/ISymbolModel';
import { PropertyType } from '../../Enums/PropertyType';
import { ExclamationTriangleIcon } from '@heroicons/react/24/outline';
import { ToggleSideBar } from '../Sidebar/ToggleSideBar/ToggleSideBar';
import { Text } from '../Text/Text';
interface IElementsListProps {
interface IElementsSideBarProps {
containers: Map<string, IContainerModel>
mainContainer: IContainerModel
symbols: Map<string, ISymbolModel>
@ -20,6 +23,8 @@ interface IElementsListProps {
) => void
selectContainer: (containerId: string) => void
addContainer: (index: number, type: string, parent: string) => void
isExpanded: boolean
onExpandChange: () => void
}
function RemoveBorderClasses(target: HTMLButtonElement, exception: string = ''): void {
@ -119,10 +124,11 @@ function HandleOnDrop(
}
}
export function ElementsList(props: IElementsListProps): JSX.Element {
export function ElementsSideBar(props: IElementsSideBarProps): JSX.Element {
// States
const divRef = React.useRef<HTMLDivElement>(null);
const [, height] = useSize(divRef);
const [,height] = useSize(divRef);
const [showProperties, setShowProperties] = useState(props.isExpanded);
// Render
const it = MakeRecursionDFSIterator(props.mainContainer, props.containers, 0, [0, 0], true);
@ -160,10 +166,21 @@ export function ElementsList(props: IElementsListProps): JSX.Element {
}
return (
<div className='h-full flex flex-col'>
<div ref={divRef} className='h-1/2'>
<div className='flex flex-row h-full w-full' >
{showProperties &&
<div className='flex flex-1 flex-col w-64 border-r-2 border-slate-400'>
<ContainerProperties
properties={props.selectedContainer?.properties}
symbols={props.symbols}
onChange={props.onPropertyChange}
/>
</div>
}
<div className='flex w-64' ref={divRef}>
<div className='w-6'>
<ToggleSideBar title={Text({ textId: '@Properties' })} checked={showProperties} onChange={(newValue) => { setShowProperties(newValue); props.onExpandChange(); }} />
</div>
<List
className="List divide-y divide-black overflow-y-auto"
itemCount={containers.length}
itemSize={35}
height={height}
@ -172,13 +189,6 @@ export function ElementsList(props: IElementsListProps): JSX.Element {
{Row}
</List>
</div>
<div className='grow overflow-auto'>
<Properties
properties={props.selectedContainer?.properties}
symbols={props.symbols}
onChange={props.onPropertyChange}
/>
</div>
</div>
);
}

View file

@ -0,0 +1,4 @@
.text-vertical{
text-align: right;
writing-mode: vertical-rl;
}

View file

@ -0,0 +1,23 @@
import * as React from 'react';
import './ToggleSideBar.scss';
interface IToggleSidebarProps {
title: string
checked: boolean
onChange: (newValue: boolean) => void
}
export function ToggleSideBar({ title, checked, onChange }: IToggleSidebarProps): JSX.Element {
return (
<div className={`${(checked ? 'bg-slate-400 hover:bg-slate-500' : 'bg-slate-300 hover:bg-slate-400')}`}>
<button
className={'w-full py-2'}
type='button'
onClick={() => onChange(!checked)}
>
<p className='text-vertical'>{title}
</p>
</button>
</div>
);
}

View file

@ -14,7 +14,7 @@ export function SymbolProperties(props: ISymbolPropertiesProps): JSX.Element {
}
return (
<div className='h-full p-3 bg-slate-200 overflow-y-auto'>
<div className='h-full p-3 bg-slate-200 overflow-y-auto '>
<SymbolForm
symbol={props.symbol}
symbols={props.symbols}

View file

@ -3,18 +3,24 @@ import useSize from '@react-hook/size';
import { FixedSizeList as List } from 'react-window';
import { ISymbolModel } from '../../Interfaces/ISymbolModel';
import { SymbolProperties } from '../SymbolProperties/SymbolProperties';
import { ToggleSideBar } from '../Sidebar/ToggleSideBar/ToggleSideBar';
import { Text } from '../Text/Text';
import { useState } from 'react';
interface ISymbolsSidebarProps {
selectedSymbolId: string
symbols: Map<string, ISymbolModel>
onPropertyChange: (key: string, value: string | number | boolean) => void
selectSymbol: (symbolId: string) => void
isExpanded: boolean
onExpandChange: (isExpanded: boolean) => void
}
export function SymbolsSidebar(props: ISymbolsSidebarProps): JSX.Element {
// States
const divRef = React.useRef<HTMLDivElement>(null);
const height = useSize(divRef)[1];
const [showProperties, setShowProperties] = useState(props.isExpanded);
// Render
const symbols = [...props.symbols.values()];
function Row({ index, style }: { index: number, style: React.CSSProperties }): JSX.Element {
@ -39,12 +45,22 @@ export function SymbolsSidebar(props: ISymbolsSidebarProps): JSX.Element {
</button>
);
}
const selectedSymbol = props.symbols.get(props.selectedSymbolId);
return (
<div className='h-full'>
<div ref={divRef} className='h-1/2 text-gray-800'>
<div className='flex flex-row h-full w-full'>
{showProperties && <div className='flex flex-1 flex-col w-64 border-r-2 border-slate-400'>
{(selectedSymbol == null) && <h1 className={'p-4'}>{Text({ textId: '@NoSymbolSelected' })}</h1>}
<SymbolProperties
symbol={selectedSymbol}
symbols={props.symbols}
onChange={props.onPropertyChange}
/>
</div>}
<div className={'flex w-64'} ref={divRef}>
<div className='w-6'>
<ToggleSideBar title={Text({ textId: '@Properties' })} checked={showProperties} onChange={(newValue) => { setShowProperties(newValue); props.onExpandChange(newValue); }} />
</div>
<List
className='List divide-y divide-black'
itemCount={symbols.length}
itemSize={35}
height={height}
@ -53,13 +69,6 @@ export function SymbolsSidebar(props: ISymbolsSidebarProps): JSX.Element {
{Row}
</List>
</div>
<div>
<SymbolProperties
symbol={props.symbols.get(props.selectedSymbolId)}
symbols={props.symbols}
onChange={props.onPropertyChange}
/>
</div>
</div>
);
}

View file

@ -1,9 +1,9 @@
import * as React from 'react';
import { ElementsList } from '../ElementsList/ElementsList';
import { ElementsSideBar } from '../ElementsList/ElementsSideBar';
import { History } from '../History/History';
import { Bar } from '../Bar/Bar';
import { Bar, BAR_WIDTH } from '../Bar/Bar';
import { Symbols } from '../Symbols/Symbols';
import { SymbolsSidebar } from '../SymbolsList/SymbolsList';
import { SymbolsSidebar } from '../SymbolsList/SymbolsSidebar';
import { PropertyType } from '../../Enums/PropertyType';
import { Messages } from '../Messages/Messages';
import { Sidebar } from '../Sidebar/Sidebar';
@ -37,7 +37,9 @@ export interface IUIProps {
export enum SidebarType {
None,
Components,
ComponentsExpanded,
Symbols,
SymbolsExpanded,
History,
Messages,
Settings
@ -59,6 +61,7 @@ function UseSetOrToggleSidebar(
export function UI({ editorState, ...methods }: IUIProps): JSX.Element {
const [selectedSidebar, setSelectedSidebar] = React.useState<SidebarType>(SidebarType.Components);
const [messages, setMessages] = React.useState<IMessage[]>([]);
const current = GetCurrentHistoryState(editorState.history, editorState.historyCurrentStep);
const configuration = editorState.configuration;
@ -78,7 +81,7 @@ export function UI({ editorState, ...methods }: IUIProps): JSX.Element {
);
}
// Please use setOrToggleSidebar rather than setSelectedSidebar so we can close the sidebar
// Please use setOrToggleSidebar rather than setSelectedSidebar, so we can close the sidebar
const setOrToggleSidebar = UseSetOrToggleSidebar(selectedSidebar, setSelectedSidebar);
let leftSidebarTitle = '';
@ -104,7 +107,7 @@ export function UI({ editorState, ...methods }: IUIProps): JSX.Element {
buttonOnClick={methods.addContainer}
/>;
rightSidebarTitle = Text({ textId: '@Elements' });
rightChildren = <ElementsList
rightChildren = <ElementsSideBar
containers={current.containers}
mainContainer={mainContainer}
symbols={current.symbols}
@ -112,9 +115,31 @@ export function UI({ editorState, ...methods }: IUIProps): JSX.Element {
onPropertyChange={methods.onPropertyChange}
selectContainer={methods.selectContainer}
addContainer={methods.addContainerAt}
isExpanded ={false}
onExpandChange={() => setOrToggleSidebar(SidebarType.ComponentsExpanded) }
/>;
break;
case SidebarType.ComponentsExpanded:
leftSidebarTitle = Text({ textId: '@Components' });
leftChildren = <Components
selectedContainer={selectedContainer}
componentOptions={configuration.AvailableContainers}
categories={configuration.Categories}
buttonOnClick={methods.addContainer}
/>;
rightSidebarTitle = Text({ textId: '@Elements' });
rightChildren = <ElementsSideBar
containers={current.containers}
mainContainer={mainContainer}
symbols={current.symbols}
selectedContainer={selectedContainer}
onPropertyChange={methods.onPropertyChange}
selectContainer={methods.selectContainer}
addContainer={methods.addContainerAt}
isExpanded ={true}
onExpandChange={() => setOrToggleSidebar(SidebarType.Components) }
/>;
break;
case SidebarType.Symbols:
leftSidebarTitle = Text({ textId: '@SymbolsLeft' });
leftChildren = <Symbols
@ -127,6 +152,24 @@ export function UI({ editorState, ...methods }: IUIProps): JSX.Element {
symbols={current.symbols}
onPropertyChange={methods.onSymbolPropertyChange}
selectSymbol={methods.selectSymbol}
isExpanded ={false}
onExpandChange={() => setOrToggleSidebar(SidebarType.SymbolsExpanded) }
/>;
break;
case SidebarType.SymbolsExpanded:
leftSidebarTitle = Text({ textId: '@SymbolsLeft' });
leftChildren = <Symbols
componentOptions={configuration.AvailableSymbols}
buttonOnClick={methods.addSymbol}
/>;
rightSidebarTitle = Text({ textId: '@SymbolsRight' });
rightChildren = <SymbolsSidebar
selectedSymbolId={current.selectedSymbolId}
symbols={current.symbols}
onPropertyChange={methods.onSymbolPropertyChange}
selectSymbol={methods.selectSymbol}
isExpanded ={true}
onExpandChange={() => setOrToggleSidebar(SidebarType.Symbols)}
/>;
break;
@ -159,6 +202,7 @@ export function UI({ editorState, ...methods }: IUIProps): JSX.Element {
const isLeftSidebarOpen = selectedSidebar !== SidebarType.None;
const isRightSidebarOpen = selectedSidebar === SidebarType.Components || selectedSidebar === SidebarType.Symbols;
const isRightSidebarOpenExpanded = selectedSidebar === SidebarType.ComponentsExpanded || selectedSidebar === SidebarType.SymbolsExpanded;
const isLeftSidebarOpenClasses = new Set<string>([
'left-sidebar',
@ -170,14 +214,29 @@ export function UI({ editorState, ...methods }: IUIProps): JSX.Element {
let isRightSidebarOpenClasses = 'right-0 -bottom-full md:-right-80 md:bottom-0';
let marginSidebar = BAR_WIDTH;
const viewerMarginClasses = new Set<string>([
'ml-16'
]);
if (isLeftSidebarOpen) {
isLeftSidebarOpenClasses.delete('-bottom-full');
isLeftSidebarOpenClasses.delete('md:-left-64');
isLeftSidebarOpenClasses.delete('md:bottom-0');
marginSidebar += 256;
viewerMarginClasses.add(' md:ml-80');
}
if (isRightSidebarOpen) {
if (isRightSidebarOpen || isRightSidebarOpenExpanded) {
isRightSidebarOpenClasses = 'right-0';
if (isRightSidebarOpenExpanded) {
viewerMarginClasses.add(' md:mr-[32rem]');
marginSidebar += 512;
} else {
viewerMarginClasses.add(' md:mr-64');
marginSidebar += 256;
}
} else {
isLeftSidebarOpenClasses.delete('left-sidebar');
isLeftSidebarOpenClasses.add('left-sidebar-single');
@ -186,16 +245,24 @@ export function UI({ editorState, ...methods }: IUIProps): JSX.Element {
return (
<>
<Bar
isComponentsOpen={selectedSidebar === SidebarType.Components}
isSymbolsOpen={selectedSidebar === SidebarType.Symbols}
isComponentsOpen={selectedSidebar === SidebarType.Components || selectedSidebar === SidebarType.ComponentsExpanded}
isSymbolsOpen={selectedSidebar === SidebarType.Symbols || selectedSidebar === SidebarType.SymbolsExpanded}
isHistoryOpen={selectedSidebar === SidebarType.History}
isMessagesOpen={selectedSidebar === SidebarType.Messages}
isSettingsOpen={selectedSidebar === SidebarType.Settings}
toggleComponents={() => {
setOrToggleSidebar(SidebarType.Components);
if (selectedSidebar === SidebarType.ComponentsExpanded) {
setOrToggleSidebar(SidebarType.ComponentsExpanded);
} else {
setOrToggleSidebar(SidebarType.Components);
}
} }
toggleSymbols={() => {
setOrToggleSidebar(SidebarType.Symbols);
if (selectedSidebar === SidebarType.SymbolsExpanded) {
setOrToggleSidebar(SidebarType.SymbolsExpanded);
} else {
setOrToggleSidebar(SidebarType.Symbols);
}
} }
toggleTimeline={() => {
setOrToggleSidebar(SidebarType.History);
@ -214,11 +281,11 @@ export function UI({ editorState, ...methods }: IUIProps): JSX.Element {
{ leftChildren }
</Sidebar>
<Viewer
isLeftSidebarOpen={isLeftSidebarOpen}
isRightSidebarOpen={isRightSidebarOpen}
className={`${[...viewerMarginClasses.values()].join(' ')} w-full h-full`}
current={current}
selectedContainer={selectedContainer}
selectContainer={methods.selectContainer}
margin={marginSidebar}
/>
<Sidebar
className={`right-sidebar ${isRightSidebarOpenClasses}`}

View file

@ -10,48 +10,38 @@ import { AddDimensions } from '../Canvas/DimensionLayer';
import { RenderSelector } from '../Canvas/Selector';
import { SVG } from '../SVG/SVG';
import { RenderSymbol } from '../Canvas/Symbol';
import { useState } from 'react';
interface IViewerProps {
isLeftSidebarOpen: boolean
isRightSidebarOpen: boolean
className?: string
current: IHistoryState
selectedContainer: IContainerModel | undefined
selectContainer: (containerId: string) => void
margin: number
}
interface IViewer {
viewerWidth: number
viewerHeight: number
}
function OnResize(
isLeftSidebarOpen: boolean,
isRightSidebarOpen: boolean,
setViewer: React.Dispatch<React.SetStateAction<IViewer>>
): void {
let marginSidebar = BAR_WIDTH;
if (isLeftSidebarOpen) {
marginSidebar += 256;
}
if (isRightSidebarOpen) {
marginSidebar += 256;
export function Viewer({
className,
current,
selectedContainer,
selectContainer,
margin
}: IViewerProps): JSX.Element {
function computeWidth(margin: number): number {
return window.innerWidth - (window.innerWidth < 768 ? BAR_WIDTH : margin);
}
const margin = window.innerWidth < 768 ? BAR_WIDTH : marginSidebar;
setViewer({
viewerWidth: window.innerWidth - margin,
viewerHeight: window.innerHeight
});
}
const [windowSize, setWindowSize] = useState([
computeWidth(margin),
window.innerHeight
]);
function UseSVGAutoResizerOnWindowResize(
isLeftSidebarOpen: boolean,
isRightSidebarOpen: boolean,
setViewer: React.Dispatch<React.SetStateAction<IViewer>>
): void {
React.useEffect(() => {
function SVGAutoResizer(): void {
OnResize(isLeftSidebarOpen, isRightSidebarOpen, setViewer);
setWindowSize([
computeWidth(margin),
window.innerHeight
]);
}
window.addEventListener('resize', SVGAutoResizer);
@ -60,41 +50,13 @@ function UseSVGAutoResizerOnWindowResize(
window.removeEventListener('resize', SVGAutoResizer);
};
});
}
function UseSVGAutoResizerOnSidebar(
isLeftSidebarOpen: boolean,
isRightSidebarOpen: boolean,
setViewer: React.Dispatch<React.SetStateAction<IViewer>>
): void {
React.useEffect(() => {
OnResize(isLeftSidebarOpen, isRightSidebarOpen, setViewer);
}, [isLeftSidebarOpen, isRightSidebarOpen, setViewer]);
}
export function Viewer({
isLeftSidebarOpen, isRightSidebarOpen,
current,
selectedContainer,
selectContainer
}: IViewerProps): JSX.Element {
let marginClasses = 'ml-16';
let marginSidebar = BAR_WIDTH;
if (isLeftSidebarOpen) {
marginClasses += ' md:ml-80';
marginSidebar += 256;
}
if (isRightSidebarOpen) {
marginClasses += ' md:mr-64';
marginSidebar += 256;
}
const margin = window.innerWidth < 768 ? BAR_WIDTH : marginSidebar;
const [viewer, setViewer] = React.useState<IViewer>({
viewerWidth: window.innerWidth - margin,
viewerHeight: window.innerHeight
});
setWindowSize([
computeWidth(margin),
window.innerHeight
]);
}, [margin]);
const mainContainer = FindContainerById(current.containers, current.mainContainer);
@ -102,9 +64,6 @@ export function Viewer({
return <></>;
}
UseSVGAutoResizerOnWindowResize(isLeftSidebarOpen, isRightSidebarOpen, setViewer);
UseSVGAutoResizerOnSidebar(isLeftSidebarOpen, isRightSidebarOpen, setViewer);
if (USE_EXPERIMENTAL_CANVAS_API) {
function Draw(ctx: CanvasRenderingContext2D, frameCount: number, scale: number, translatePos: IPoint): void {
if (mainContainer === undefined) {
@ -169,9 +128,9 @@ export function Viewer({
return (
<SVG
className={marginClasses}
viewerWidth={viewer.viewerWidth}
viewerHeight={viewer.viewerHeight}
className={className}
viewerWidth={windowSize[0]}
viewerHeight={windowSize[1]}
width={mainContainer.properties.width}
height={mainContainer.properties.height}
containers={current.containers}
@ -179,6 +138,7 @@ export function Viewer({
symbols={current.symbols}
selectContainer={selectContainer}
>
{mainContainer}
</SVG>
);
@ -206,10 +166,11 @@ function RenderDimensions(
currentTransform: [number, number]
): void {
ctx.save();
const containerLeftDim = leftDim - (DIMENSION_MARGIN * (depth + 1)) / scale;
const containerTopDim = topDim - (DIMENSION_MARGIN * (depth + 1)) / scale;
const containerBottomDim = bottomDim + (DIMENSION_MARGIN * (depth + 1)) / scale;
const containerRightDim = rightDim + (DIMENSION_MARGIN * (depth + 1)) / scale;
const depthOffset = (DIMENSION_MARGIN * (depth + 1)) / scale;
const containerLeftDim = leftDim - depthOffset;
const containerTopDim = topDim - depthOffset;
const containerBottomDim = bottomDim + depthOffset;
const containerRightDim = rightDim + depthOffset;
const dimMapped = [containerLeftDim, containerBottomDim, containerTopDim, containerRightDim];
AddDimensions(ctx, containers, container, dimMapped, currentTransform, scale, depth);
ctx.restore();

View file

@ -2,12 +2,14 @@
"@StartFromScratch": "Start from scratch",
"@LoadConfigFile": "Load a configuration file",
"@GoBack": "Go back",
"@Properties" : "Properties",
"@Components": "Components",
"@Elements": "Elements",
"@Symbols": "Symbols",
"@SymbolsLeft": "Symbols",
"@SymbolsRight": "Symbols",
"@NoSymbolSelected": "No symbol selected",
"@Timeline": "Timeline",
"@Messages": "Messages",
"@Settings": "Settings",

View file

@ -2,12 +2,14 @@
"@StartFromScratch": "Partir de zéro",
"@LoadConfigFile": "Charger un fichier de configuration",
"@GoBack": "Revenir",
"@Properties" : "Propriétés",
"@Components": "Composants",
"@Elements": "Éléments",
"@Symbols": "Symboles",
"@SymbolsLeft": "Symboles",
"@SymbolsRight": "Symboles",
"@NoSymbolSelected": "Pas de symbol sélectionné",
"@Timeline": "Chronologie",
"@Messages": "Messages",
"@Settings": "Paramètres",

View file

@ -21,10 +21,11 @@
.right-sidebar {
@apply fixed shadow-lg z-20
w-[calc(100%_-_4rem)] md:w-64
h-1/2 md:h-full bottom-0 md:bottom-0
}
.sidebar-title {
@apply p-3 md:p-5 font-bold h-12 md:h-16
}