diff --git a/ivette/src/dome/renderer/frame/panel.tsx b/ivette/src/dome/renderer/frame/panel.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..e5301212fdac427340f47914e02f6e6bd6c7eecf
--- /dev/null
+++ b/ivette/src/dome/renderer/frame/panel.tsx
@@ -0,0 +1,116 @@
+/* ************************************************************************ */
+/*                                                                          */
+/*   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>
+  );
+}
diff --git a/ivette/src/dome/renderer/frame/style.css b/ivette/src/dome/renderer/frame/style.css
index 44f4580e0f4ad8de3985f0b2f90ef70066a8cd6c..c4dd8a880576ffc1ee883344afac7302cc74de82 100644
--- a/ivette/src/dome/renderer/frame/style.css
+++ b/ivette/src/dome/renderer/frame/style.css
@@ -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);
+      }
+    }
+  }
+}
diff --git a/ivette/src/sandbox/panel.tsx b/ivette/src/sandbox/panel.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..407bbde1701091ad5ee99319568eb8448419295e
--- /dev/null
+++ b/ivette/src/sandbox/panel.tsx
@@ -0,0 +1,182 @@
+/* ************************************************************************ */
+/*                                                                          */
+/*   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 />,
+});
+
+/* -------------------------------------------------------------------------- */
diff --git a/ivette/src/sandbox/style.css b/ivette/src/sandbox/style.css
new file mode 100644
index 0000000000000000000000000000000000000000..6263e25d48a2fd23a96c0c5432952ade1cc67abf
--- /dev/null
+++ b/ivette/src/sandbox/style.css
@@ -0,0 +1,19 @@
+/* -------------------------------------------------------------------------- */
+/* --- 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);
+}