From 91defa42c2684054009dbfdaedddb99a0668149b Mon Sep 17 00:00:00 2001 From: Edouard DUPIN Date: Mon, 13 Jan 2025 23:49:04 +0100 Subject: [PATCH] [FIX] chakra ui component is not full --- front/src/App.tsx | 2 +- front/src/components/TopBar/TopBar.tsx | 52 ++++----- .../components/contextMenu/ContextMenu.tsx | 30 +++-- front/src/components/ui/menu.tsx | 110 ++++++++++++++++++ front/src/components/{ => ui}/toaster.tsx | 15 +-- front/src/utils/data-store.ts | 2 +- 6 files changed, 155 insertions(+), 56 deletions(-) create mode 100644 front/src/components/ui/menu.tsx rename front/src/components/{ => ui}/toaster.tsx (80%) diff --git a/front/src/App.tsx b/front/src/App.tsx index 662bda9..84954eb 100644 --- a/front/src/App.tsx +++ b/front/src/App.tsx @@ -25,7 +25,7 @@ import { environment } from '@/environment'; import { App as SpaApp } from '@/scene/App'; import { USERS, USERS_COLLECTION } from '@/service/session'; import { hashLocalData } from '@/utils/sso'; -import { Toaster } from './components/toaster'; +import { Toaster } from './components/ui/toaster'; const AppEnvHint = () => { const dialog = useDisclosure(); diff --git a/front/src/components/TopBar/TopBar.tsx b/front/src/components/TopBar/TopBar.tsx index 099e695..cff9ad2 100644 --- a/front/src/components/TopBar/TopBar.tsx +++ b/front/src/components/TopBar/TopBar.tsx @@ -11,7 +11,6 @@ import { Flex, HStack, IconButton, - Menu, Text, useDisclosure, } from '@chakra-ui/react'; @@ -33,6 +32,7 @@ import { requestSignIn, requestSignOut, requestSignUp } from '@/utils/sso'; import { useThemeMode } from '@/utils/theme-tools'; import { useSessionService } from '@/service/session'; import { MdHelp, MdHome, MdMore, MdOutlinePlaylistPlay, MdOutlineUploadFile, MdSupervisedUserCircle } from 'react-icons/md'; +import { MenuContent, MenuItem, MenuRoot, MenuTrigger } from '../ui/menu'; export const TOP_BAR_HEIGHT = '50px'; @@ -139,38 +139,36 @@ export const TopBar = ({ title, children }: TopBarProps) => { )} {session?.state === SessionState.CONNECTED && ( - - + + - - - - - - Sign in as {session?.login ?? 'Fail'} - - Settings - Help - - Sign-out - - {colorMode === 'light' ? ( - - Set dark mode - - ) : ( - - Set light mode - - )} - - - + + + + + Sign in as {session?.login ?? 'Fail'} + + Settings + Help + + Sign-out + + {colorMode === 'light' ? ( + + Set dark mode + + ) : ( + + Set light mode + + )} + + )} { return <>; } return ( - - {/* This is very stupid, we need to set as span to prevent a button in button... WTF */} - - - - {elements?.map((data) => ( - - {data.name} - - ))} - - - + + + {elements?.map((data) => ( + + {data.name} + + ))} + + ); }; diff --git a/front/src/components/ui/menu.tsx b/front/src/components/ui/menu.tsx new file mode 100644 index 0000000..763005b --- /dev/null +++ b/front/src/components/ui/menu.tsx @@ -0,0 +1,110 @@ +"use client" + +import { AbsoluteCenter, Menu as ChakraMenu, Portal } from "@chakra-ui/react" +import * as React from "react" +import { LuCheck, LuChevronRight } from "react-icons/lu" + +interface MenuContentProps extends ChakraMenu.ContentProps { + portalled?: boolean + portalRef?: React.RefObject +} + +export const MenuContent = React.forwardRef( + function MenuContent(props, ref) { + const { portalled = true, portalRef, ...rest } = props + return ( + + + + + + ) + }, +) + +export const MenuArrow = React.forwardRef< + HTMLDivElement, + ChakraMenu.ArrowProps +>(function MenuArrow(props, ref) { + return ( + + + + ) +}) + +export const MenuCheckboxItem = React.forwardRef< + HTMLDivElement, + ChakraMenu.CheckboxItemProps +>(function MenuCheckboxItem(props, ref) { + return ( + + + {props.children} + + ) +}) + +export const MenuRadioItem = React.forwardRef< + HTMLDivElement, + ChakraMenu.RadioItemProps +>(function MenuRadioItem(props, ref) { + const { children, ...rest } = props + return ( + + + + + + + {children} + + ) +}) + +export const MenuItemGroup = React.forwardRef< + HTMLDivElement, + ChakraMenu.ItemGroupProps +>(function MenuItemGroup(props, ref) { + const { title, children, ...rest } = props + return ( + + {title && ( + + {title} + + )} + {children} + + ) +}) + +export interface MenuTriggerItemProps extends ChakraMenu.ItemProps { + startIcon?: React.ReactNode +} + +export const MenuTriggerItem = React.forwardRef< + HTMLDivElement, + MenuTriggerItemProps +>(function MenuTriggerItem(props, ref) { + const { startIcon, children, ...rest } = props + return ( + + {startIcon} + {children} + + + ) +}) + +export const MenuRadioItemGroup = ChakraMenu.RadioItemGroup +export const MenuContextTrigger = ChakraMenu.ContextTrigger +export const MenuRoot = ChakraMenu.Root +export const MenuSeparator = ChakraMenu.Separator + +export const MenuItem = ChakraMenu.Item +export const MenuItemText = ChakraMenu.ItemText +export const MenuItemCommand = ChakraMenu.ItemCommand +export const MenuTrigger = ChakraMenu.Trigger diff --git a/front/src/components/toaster.tsx b/front/src/components/ui/toaster.tsx similarity index 80% rename from front/src/components/toaster.tsx rename to front/src/components/ui/toaster.tsx index a31ce3c..f9c636a 100644 --- a/front/src/components/toaster.tsx +++ b/front/src/components/ui/toaster.tsx @@ -9,13 +9,10 @@ import { Toast, createToaster, } from "@chakra-ui/react" -import { useCallback } from "react"; export const toaster = createToaster({ - duration: 3000, - placement: 'top-end', - // offset: { top: '50px' }, - // variant: 'solid', + placement: "bottom-end", + pauseOnPageIdle: true, }) export const toasterAPIError = (error: RestErrorResponse) => { @@ -28,13 +25,9 @@ export const toasterAPIError = (error: RestErrorResponse) => { export const Toaster = () => { return ( - + {(toast) => ( - + {toast.type === "loading" ? ( ) : ( diff --git a/front/src/utils/data-store.ts b/front/src/utils/data-store.ts index 634d6ea..a8153a9 100644 --- a/front/src/utils/data-store.ts +++ b/front/src/utils/data-store.ts @@ -7,7 +7,7 @@ import { DependencyList, useCallback, useEffect, useState } from 'react'; import { RestErrorResponse } from '@/back-api'; import { isNullOrUndefined } from '@/utils/validator'; -import { toasterAPIError } from '@/components/toaster'; +import { toasterAPIError } from '@/components/ui/toaster'; export type DataStoreType = { isLoading: boolean;