From 69595e652a948b93f709b8d0e039dec1afc5a35c Mon Sep 17 00:00:00 2001 From: Maxime Lalo Date: Thu, 18 Jul 2024 11:42:53 +0200 Subject: [PATCH] :sparkles: reviewed code --- .../Elements/Tabs/classes.module.scss | 23 ++++--- src/front/Components/Elements/Tabs/index.tsx | 69 ++++++++++++------- .../Components/Layouts/DesignSystem/index.tsx | 68 +++++++++--------- 3 files changed, 95 insertions(+), 65 deletions(-) diff --git a/src/front/Components/Elements/Tabs/classes.module.scss b/src/front/Components/Elements/Tabs/classes.module.scss index 89a0e389..adfb7e37 100644 --- a/src/front/Components/Elements/Tabs/classes.module.scss +++ b/src/front/Components/Elements/Tabs/classes.module.scss @@ -1,5 +1,5 @@ .root { - .hidden-tester { + .mirror-shadow-element { display: flex; overflow: hidden; background: red; @@ -19,16 +19,6 @@ .show-more-container { position: relative; border-bottom: 1px solid var(--color-neutral-500); - .show-more { - padding: 8px 16px; - display: flex; - color: white; - font-size: 16px; - justify-content: center; - align-items: center; - color: white; - cursor: pointer; - } .vertical-container { position: absolute; @@ -46,4 +36,15 @@ } } } + + .show-more { + padding: 8px 16px; + display: flex; + color: white; + font-size: 16px; + justify-content: center; + align-items: center; + color: white; + cursor: pointer; + } } diff --git a/src/front/Components/Elements/Tabs/index.tsx b/src/front/Components/Elements/Tabs/index.tsx index bd5d04bd..5d7eaae8 100644 --- a/src/front/Components/Elements/Tabs/index.tsx +++ b/src/front/Components/Elements/Tabs/index.tsx @@ -3,7 +3,7 @@ import classes from "./classes.module.scss"; import HorizontalTab, { ITab } from "./HorizontalTab"; import VerticalTabs from "./VerticalTabs"; import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography"; -import { useDebounce, useWindowSize } from "@uidotdev/usehooks"; +import { useWindowSize } from "@uidotdev/usehooks"; import useOpenable from "@Front/Hooks/useOpenable"; export type ITabValue = T & { @@ -20,57 +20,80 @@ type IProps = { onSelect: (value: T) => void; }; -export default function Tabs(props: IProps) { - const { onSelect } = props; - const rootRef = useRef(null); +export default function Tabs({ onSelect, tabs: propsTabs }: IProps) { + const tabs = useRef(propsTabs); + + const shadowElementRef = useRef(null); const [visibleElements, setVisibleElements] = useState[]>([]); const [overflowedElements, setOverflowedElements] = useState[]>([]); - const [selectedTab, setSelectedTab] = useState>(props.tabs[0]!.value); + const [selectedTab, setSelectedTab] = useState>(tabs.current[0]!.value); const { close, isOpen, toggle } = useOpenable(); const windowSize = useWindowSize(); - const windowSizeDebounced = useDebounce(windowSize, 100); const calculateVisibleElements = useCallback(() => { - const container = rootRef.current; - if (!container) return; + const shadowElement = shadowElementRef.current; + if (!shadowElement) return; + + const shadowElementWidth = shadowElement.offsetWidth; + // The first element is the show more element, it needs to be ignored in the calculation + let totalWidth = (shadowElement.children[0]! as HTMLElement).offsetWidth; - const containerWidth = container.offsetWidth; - let totalWidth = 115; let visibleCount = 0; - - const children = Array.from(container.children) as HTMLDivElement[]; - for (let i = 0; i < children.length; i++) { - totalWidth += children[i]!.offsetWidth; - if (totalWidth > containerWidth) { + for (let i = 1; i < shadowElement.children.length; i++) { + totalWidth += (shadowElement.children[i]! as HTMLElement).offsetWidth; + if (totalWidth > shadowElementWidth) { break; } visibleCount++; } - setVisibleElements(props.tabs.slice(0, visibleCount)); - setOverflowedElements(props.tabs.slice(visibleCount)); - }, [props.tabs]); + setVisibleElements(tabs.current.slice(0, visibleCount)); + setOverflowedElements(tabs.current.slice(visibleCount)); + }, []); + + useEffect(() => { + tabs.current = propsTabs; + }, [propsTabs]); useEffect(() => { calculateVisibleElements(); - }, [calculateVisibleElements, windowSizeDebounced]); + }, [calculateVisibleElements, windowSize]); const handleSelect = useCallback( (value: ITabValue) => { setSelectedTab(value); onSelect(value); close(); + calculateVisibleElements(); }, - [close, onSelect], + [close, onSelect, calculateVisibleElements], + ); + + const handleVerticalSelect = useCallback( + (value: ITabValue) => { + const index = tabs.current.findIndex((tab) => tab.value.id === value.id); + const newTabs = [...tabs.current]; + newTabs.splice(index, 1); + newTabs.unshift(tabs.current[index]!); + tabs.current = newTabs; + console.log("Updated values ; ", tabs.current); + handleSelect(value); + }, + [handleSelect], ); return (
-
- {props.tabs.map((element, index) => ( +
+
+ + {overflowedElements.length} de plus... + +
+ {tabs.current.map((element, index) => ( label={element.label} key={element.key ?? index} @@ -106,7 +129,7 @@ export default function Tabs(props: IProps) { label={element.label} key={element.key ?? index} value={element.value} - onSelect={handleSelect} + onSelect={handleVerticalSelect} isSelected={selectedTab === element.value} /> ))} diff --git a/src/front/Components/Layouts/DesignSystem/index.tsx b/src/front/Components/Layouts/DesignSystem/index.tsx index 37d26764..9dcea52f 100644 --- a/src/front/Components/Layouts/DesignSystem/index.tsx +++ b/src/front/Components/Layouts/DesignSystem/index.tsx @@ -8,31 +8,44 @@ import DefaultTemplate from "@Front/Components/LayoutTemplates/DefaultTemplate"; import classes from "./classes.module.scss"; import Tabs from "@Front/Components/Elements/Tabs"; -import { useCallback, useState } from "react"; +import { useCallback, useMemo, useState } from "react"; export default function DesignSystem() { - const userDb = [ - { - username: "Maxime", - id: 1, - }, - { - username: "Vincent", - id: 2, - }, - { - username: "Massi", - id: 3, - }, - { - username: "Maxime", - id: 4, - }, - { - username: "Arnaud", - id: 5, - }, - ]; + const userDb = useMemo( + () => [ + { + username: "Maxime", + id: 1, + }, + { + username: "Vincent", + id: 2, + }, + { + username: "Massi", + id: 3, + }, + { + username: "Maxime", + id: 4, + }, + { + username: "Arnaud", + id: 5, + }, + ], + [], + ); + + const userDbArray = useMemo( + () => + userDb.map((user) => ({ + label: user.username, + key: user.id.toString(), + value: user, + })), + [userDb], + ); const [selectedTab, setSelectedTab] = useState<(typeof userDb)[number]>(userDb[0]!); @@ -45,14 +58,7 @@ export default function DesignSystem() { DesignSystem Tabs - - tabs={userDb.map((user) => ({ - label: user.username, - key: user.id.toString(), - value: user, - }))} - onSelect={onSelect} - /> + tabs={userDbArray} onSelect={onSelect} />
{selectedTab.id} - {selectedTab.username}