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
-
- )}
-
-
-
+
+
+
+
+
+
+ {colorMode === 'light' ? (
+
+ ) : (
+
+ )}
+
+
)}
{
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) => (
+
+ ))}
+
+
);
};
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;