From 067b16f692da7e16d0582bf8d82eedfacfe0943b Mon Sep 17 00:00:00 2001
From: rlazarini <remi.lazarini@cea.fr>
Date: Mon, 16 Sep 2024 10:33:03 +0200
Subject: [PATCH] [ivette] Add sidePanel in dome/frame

---
 ivette/src/dome/renderer/frame/sidePanel.tsx | 162 +++++++++++++++++++
 ivette/src/dome/renderer/frame/style.css     |  73 +++++++++
 2 files changed, 235 insertions(+)
 create mode 100644 ivette/src/dome/renderer/frame/sidePanel.tsx

diff --git a/ivette/src/dome/renderer/frame/sidePanel.tsx b/ivette/src/dome/renderer/frame/sidePanel.tsx
new file mode 100644
index 00000000000..ef314ca6167
--- /dev/null
+++ b/ivette/src/dome/renderer/frame/sidePanel.tsx
@@ -0,0 +1,162 @@
+/* ************************************************************************ */
+/*                                                                          */
+/*   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 allow us to add a side panel inside the elements.
+
+  The main element is SidePanel.
+  This component needs two chidren :
+  ```
+  <SidePANEL>
+    <PanelContent />
+    <A />
+  </SidePanel>
+  ```
+  "A" is the content that needs a sidePanel,
+  the first child is the panel content.
+
+  This package provide some components to creating the side panel content :
+  * ListElement
+  * Text
+  * Actions
+
+  @packageDocumentation
+  @module dome/frame/sidePanel
+ */
+
+import { Label } from 'dome/controls/labels';
+import React from 'react';
+import { classes } from 'dome/misc/utils';
+
+
+/* --------------------------------------------------------------------------*/
+/* --- SidePanel Container                                                   */
+/* --------------------------------------------------------------------------*/
+interface SidePanelProps {
+  className?: string;
+  show?: boolean;
+  position?: 'left' | 'right'
+  children: [JSX.Element, JSX.Element];
+}
+
+export const SidePanel = (props: SidePanelProps): JSX.Element => {
+  const { show = true, className, position } = props;
+  const classContainer = 'dome-sidepanel-container';
+
+  const classNames = classes(
+    classContainer,
+    position === 'left' ? classContainer+'-left' : classContainer+'-right',
+    className,
+  );
+  const [A, panelContent] = props.children;
+
+  return (
+    <div className='dome-sidepanel'>
+      { show &&
+        <div className={classNames}>
+          {panelContent}
+        </div>
+      }
+      {A}
+    </div>
+  );
+};
+
+/* --------------------------------------------------------------------------*/
+/* --- SidePanel List                                                        */
+/* --------------------------------------------------------------------------*/
+export interface ElementProps {
+  label: string;
+  onClickName?: () => void;
+  content: JSX.Element;
+}
+
+const Element = (props: ElementProps): JSX.Element => {
+  const { label, onClickName,  content } = props;
+
+  const nameClasse = classes(
+    'dome-sidepanel-element-name',
+    onClickName && "action"
+  );
+
+  return (
+    <div className='dome-sidepanel-element'>
+      <div
+        className={nameClasse}
+        onClick={() => { if(onClickName) onClickName(); }}
+      >{label}</div>
+      <div className='dome-sidepanel-element-content'>
+        {content}
+      </div>
+    </div>
+  );
+};
+
+interface ListElementProps {
+  list: ElementProps[];
+}
+
+export function ListElement(props: ListElementProps): JSX.Element {
+  return (
+    <div className='dome-sidepanel-list'>
+      { props.list.map((elt, k) => <Element
+          key={k}
+          {...elt}
+        />)
+      }
+    </div>
+  );
+}
+
+/* --------------------------------------------------------------------------*/
+/* --- SidePanel Text                                                        */
+/* --------------------------------------------------------------------------*/
+interface TextProps {
+  label: string;
+  content?: string | JSX.Element;
+}
+
+export function Text(props: TextProps): JSX.Element {
+  return (
+    <div className='dome-sidepanel-text'>
+      <Label>
+        {props.label}
+      </Label>
+      {props.content}
+    </div>
+  );
+}
+
+/* --------------------------------------------------------------------------*/
+/* --- SidePanel Button                                                      */
+/* --------------------------------------------------------------------------*/
+interface ActionsProps {
+  children: React.ReactNode;
+}
+
+export function Actions(props: ActionsProps): JSX.Element {
+  return (
+    <div className='dome-sidepanel-actions'>
+      {props.children}
+    </div>
+  );
+}
diff --git a/ivette/src/dome/renderer/frame/style.css b/ivette/src/dome/renderer/frame/style.css
index 44f4580e0f4..0c28dc4ee8c 100644
--- a/ivette/src/dome/renderer/frame/style.css
+++ b/ivette/src/dome/renderer/frame/style.css
@@ -587,3 +587,76 @@ input:checked + .dome-xSwitch-slider:before {
   -ms-transform: translateX(13px);
   transform: translateX(13px);
 }
+
+/* -------------------------------------------------------------------------- */
+/* --- Side Panel                                                         --- */
+/* -------------------------------------------------------------------------- */
+.dome-sidepanel {
+    position: relative;
+    width: 100%;
+    height: 100%;
+
+    .dome-sidepanel-container {
+      position: absolute;
+      top:0;
+      max-width: 350px;
+      max-height: 100%;
+      overflow-y: scroll;
+      z-index: 50;
+      background-color: var(--background-interaction);
+      padding: 10px 5px;
+
+      &::-webkit-scrollbar { display: none; }
+
+      &.dome-sidepanel-container-left {
+        border-radius: 0 20px 20px 0;
+      }
+      &.dome-sidepanel-container-right {
+        right: 0;
+        border-radius: 20px 0 0 20px;
+      }
+
+      .dome-sidepanel-text {
+        color: var(--text);
+        padding-bottom: 3px;
+      }
+
+      .dome-sidepanel-actions {
+        display: flex;
+
+        button:hover,
+        button:hover label {
+          cursor: pointer;
+        }
+      }
+
+      .dome-sidepanel-list {
+        .dome-sidepanel-element {
+          margin:5px;
+          background-color: var(--background);
+          overflow-x: hidden;
+          border-radius: 0 10px 0 10px;
+
+          .dome-sidepanel-element-name {
+            background-color: var(--background-profound);
+            font-weight: bold;
+            width: 100%;
+            padding: 5px 10px;
+
+            &.action:hover {
+              cursor: pointer;
+              background-color: var(--background-profound-hover);
+            }
+          }
+
+          .dome-sidepanel-element-content {
+            padding: 4px;
+
+            &:has(*){
+              padding: 10px;
+            }
+          }
+        }
+      }
+    }
+  }
-- 
GitLab