Skip to content
Snippets Groups Projects
Commit 3a5e30ac authored by Loïc Correnson's avatar Loïc Correnson
Browse files

Merge branch 'feature/ivette/sidepanel' into 'master'

[ivette] Add sidePanel in dome/frame

See merge request frama-c/frama-c!4770
parents f06cc960 a665eac7
No related branches found
No related tags found
No related merge requests found
/* ************************************************************************ */
/* */
/* This file is part of Frama-C. */
/* */
/* Copyright (C) 2007-2024 */
/* CEA (Commissariat à l'énergie atomique et aux énergies */
/* alternatives) */
/* */
/* you can redistribute it and/or modify it under the terms of the GNU */
/* Lesser General Public License as published by the Free Software */
/* Foundation, version 2.1. */
/* */
/* It is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU Lesser General Public License for more details. */
/* */
/* See the GNU Lesser General Public License version 2.1 */
/* for more details (enclosed in the file licenses/LGPLv2.1). */
/* */
/* ************************************************************************ */
/**
This package allows us to add a panel inside positioned elements.
It provides some components to create the panel content:
* ListElement
* Text
* Actions
@packageDocumentation
@module dome/frame/Panel
*/
import React from 'react';
import { classes } from 'dome/misc/utils';
import { Hbox } from 'dome/layout/boxes';
/* --------------------------------------------------------------------------*/
/* --- Panel Container */
/* --------------------------------------------------------------------------*/
export type PanelPosition = 'top' | 'bottom' | 'left' | 'right';
interface PanelProps {
/** Additional class. */
className?: string;
/** Position to displayed the panel. Default 'tr' */
position?: PanelPosition;
/** Defaults to `true`. */
visible?: boolean;
/** Defaults to `true`. */
display?: boolean;
/** Panel children. */
children: JSX.Element[];
}
export const Panel = (props: PanelProps): JSX.Element => {
const { visible = true, display = true,
className, position = 'right' } = props;
const classNames = classes(
'dome-xPanel',
'dome-xPanel-'+position,
visible ? 'dome-xPanel-open' : 'dome-xPanel-close',
!display && 'dome-control-erased',
className,
);
return (
<div className={classNames}>
{props.children.map((elt, k) => <Hbox key={k}>{elt}</Hbox>)}
</div>
);
};
/* --------------------------------------------------------------------------*/
/* --- Panel List */
/* --------------------------------------------------------------------------*/
export interface ElementProps {
/** Selection state. */
selected?: boolean;
/** Selection callback. */
onSelection?: () => void;
/** Item element. */
children?: JSX.Element;
}
export function Element(props: ElementProps): JSX.Element {
const { selected = true, onSelection, children } = props;
const classNames = classes(
'dome-xPanel-element',
selected ? 'dome-active' : 'dome-inactive',
);
return (
<div
className={classNames}
onClick={onSelection}
>
{children}
</div>
);
}
interface ListElementProps {
children: JSX.Element[];
}
export function ListElement(props: ListElementProps): JSX.Element {
return (
<div className='dome-xPanel-list'>
{props.children}
</div>
);
}
......@@ -587,3 +587,107 @@ input:checked + .dome-xSwitch-slider:before {
-ms-transform: translateX(13px);
transform: translateX(13px);
}
/* -------------------------------------------------------------------------- */
/* --- Side Panel --- */
/* -------------------------------------------------------------------------- */
.dome-xPanel {
position: absolute;
z-index: 50;
background-color: var(--background-intense);
padding: 10px 5px;
transition: transform .5s ease-in-out, opacity .5s;
button:hover,
button:hover label {
cursor: pointer;
}
&::-webkit-scrollbar { display: none; }
&.dome-xPanel-open {
transform: translate(0);
opacity: 1;
}
&.dome-xPanel-left,
&.dome-xPanel-right {
top: 5px;
padding-top: -5px;
max-height: calc(100% - 10px);
max-width: 350px;
overflow-y: auto;
}
&.dome-xPanel-left {
border-radius: 0 10px 10px 0;
&.dome-xPanel-close {
transform: translateX(-350px);
opacity: 0;
}
}
&.dome-xPanel-right {
right: 0;
border-radius: 10px 0 0 10px;
&.dome-xPanel-close {
transform: translateX(350px);
opacity: 0;
}
}
&.dome-xPanel-top,
&.dome-xPanel-bottom {
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items: center;
width: calc(100% - 10px);
left:5px;
max-height: 200px;
overflow-x: scroll;
label,
.dome-xPanel-list {
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items: center;
}
}
&.dome-xPanel-top {
overflow-x: auto;
border-radius: 0 0 10px 10px;
&.dome-xPanel-close {
transform: translateY(-350px);
opacity: 0;
}
}
&.dome-xPanel-bottom {
bottom: 0;
border-radius: 10px 10px 0 0;
&.dome-xPanel-close {
transform: translateY(350px);
opacity: 0;
}
}
.dome-xPanel-list {
.dome-xPanel-element {
margin:5px;
padding: 2px 10px;
background-color: var(--background);
border-radius: 5px;
&.dome-active {
background-color: var(--background-profound);
}
}
}
}
/* ************************************************************************ */
/* */
/* This file is part of Frama-C. */
/* */
/* Copyright (C) 2007-2024 */
/* CEA (Commissariat à l'énergie atomique et aux énergies */
/* alternatives) */
/* */
/* you can redistribute it and/or modify it under the terms of the GNU */
/* Lesser General Public License as published by the Free Software */
/* Foundation, version 2.1. */
/* */
/* It is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU Lesser General Public License for more details. */
/* */
/* See the GNU Lesser General Public License version 2.1 */
/* for more details (enclosed in the file licenses/LGPLv2.1). */
/* */
/* ************************************************************************ */
/* -------------------------------------------------------------------------- */
/* --- Sandbox Testing of Panel --- */
/* --- Only appears in DEVEL mode. --- */
/* -------------------------------------------------------------------------- */
import React from 'react';
import * as Dome from 'dome';
import { IconButton } from 'dome/controls/buttons';
import { registerSandbox, TitleBar } from 'ivette';
import {
Panel, ListElement, Element, PanelPosition
} from 'dome/frame/panel';
import { Button, ButtonGroup } from 'dome/frame/toolbars';
import { Icon } from 'dome/controls/icons';
import './style.css';
import { Label } from 'dome/controls/labels';
/* -------------------------------------------------------------------------- */
/* --- Use Panel --- */
/* -------------------------------------------------------------------------- */
function UsePanel(): JSX.Element {
const [position, setPosition] = React.useState<PanelPosition>('right');
const [visible, flipVisible] = Dome.useFlipState(true);
const [selected, setSelected] = React.useState(1);
const [list, setList] = React.useState({
flip: true,
list: [
{ id: 1, children: <div>item 1</div> },
{ id: 2, children: <div>item 2</div> },
{ id: 3, children: <div>item 3</div> },
{ id: 4, children: <div>item 4</div> },
]
}
);
return (
<>
<TitleBar>
<IconButton
icon='ANGLE.RIGHT'
title="Change position of Panel."
className={'sandbox-panel-button-position-'+position}
onClick={() => setPosition((val) => {
return val === 'right' ? 'bottom' :
val === 'bottom' ? 'left' :
val === 'left' ? 'top' :
'right';
})
}
/>
<IconButton
icon="SIDEBAR"
title={"show or hide the panel"}
onClick={flipVisible}
/>
</TitleBar>
<div style={{ position: 'relative', height: '100%' }}>
<Panel visible={visible} position={position}>
<Label
label="label"
title="Text Component"
icon="CODE"
>
Content of the Text component.
</Label>
<Label>
<ButtonGroup>
<Button
label='left'
selected={position === 'left'}
onClick={() => setPosition('left')} />
<Button
label='top'
selected={position === 'top'}
onClick={() => setPosition('top')} />
<Button
label='right'
selected={position === 'right'}
onClick={() => setPosition('right')} />
<Button
label='bottom'
selected={position === 'bottom'}
onClick={() => setPosition('bottom')} />
</ButtonGroup>
<Button
icon='SIDEBAR'
title="This button is always selected when the panel is visible."
selected={visible}
onClick={() => flipVisible()} />
</Label>
<Label
label="List icon"
title="Text Component"
>
<Icon id="WARNING"/>
<Icon id="SETTINGS"/>
<Icon id="RELOAD"/>
<Icon id="DOWNLOAD"/>
<Icon id="LOCK"/>
</Label>
<Label
label="Add/remove element"
title="Text Component"
>
<Button
icon='PLUS'
title="This button add an element t the end of the list."
onClick={() => setList((elt) => {
const newId = elt.list.length + 1;
const newChild = "item "+newId;
elt.list.push({
id: newId, children: <div>{newChild}</div>
});
return { flip: !elt.flip, list: elt.list };
}
)}
/>
<Button
icon='MINUS'
title="This button remove the last element of the list."
onClick={() => setList((elt) => {
elt.list.pop();
return { flip: !elt.flip, list: elt.list };
}
)}
/>
</Label>
<ListElement>
{ list.list.map((elt, k) =>
<Element
key={k}
selected={selected === elt.id}
onSelection={() => setSelected(elt.id)}
>
{elt.children}
</Element>
)
}
</ListElement>
</Panel>
</div>
</>
);
}
/* -------------------------------------------------------------------------- */
/* --- Sandbox --- */
/* -------------------------------------------------------------------------- */
registerSandbox({
id: 'sandbox.panel',
label: 'Panel',
children: <UsePanel />,
});
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* --- Sandbox Testing CSS --- */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* --- Sandbox Panel --- */
/* -------------------------------------------------------------------------- */
.sandbox-panel-button-position-right {
transform: rotate(0);
}
.sandbox-panel-button-position-bottom {
transform: rotate(90deg);
}
.sandbox-panel-button-position-left {
transform: rotate(180deg);
}
.sandbox-panel-button-position-top {
transform: rotate(270deg);
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment