diff --git a/front/app-build.json b/front/app-build.json index 13d9fb3..753b2a4 100644 --- a/front/app-build.json +++ b/front/app-build.json @@ -1,6 +1,6 @@ { - "display": "2025-01-13", - "version": "0.0.1-dev\n - 2025-01-13T21:39:39+01:00", + "display": "2025-01-14", + "version": "0.0.1-dev\n - 2025-01-14T20:19:20+01:00", "commit": "0.0.1-dev\n", - "date": "2025-01-13T21:39:39+01:00" + "date": "2025-01-14T20:19:20+01:00" } \ No newline at end of file diff --git a/front/package.json b/front/package.json index 426331e..706a554 100644 --- a/front/package.json +++ b/front/package.json @@ -38,9 +38,10 @@ "css-mediaquery": "0.1.2", "dayjs": "1.11.13", "history": "5.3.0", + "next-themes": "^0.4.4", "react": "18.3.1", - "react-error-boundary": "5.0.0", "react-dom": "18.3.1", + "react-error-boundary": "5.0.0", "react-icons": "5.4.0", "react-router-dom": "7.1.1", "react-select": "5.9.0", diff --git a/front/pnpm-lock.yaml b/front/pnpm-lock.yaml index 39e5c50..63d780a 100644 --- a/front/pnpm-lock.yaml +++ b/front/pnpm-lock.yaml @@ -35,6 +35,9 @@ importers: history: specifier: 5.3.0 version: 5.3.0 + next-themes: + specifier: ^0.4.4 + version: 0.4.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: specifier: 18.3.1 version: 18.3.1 @@ -3820,6 +3823,12 @@ packages: resolution: {integrity: sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==} engines: {node: '>= 0.4.0'} + next-themes@0.4.4: + resolution: {integrity: sha512-LDQ2qIOJF0VnuVrrMSMLrWGjRMkq+0mpgl6e0juCLqdJ+oo8Q84JRWT6Wh11VDQKkMMe+dVzDKLWs5n87T+PkQ==} + peerDependencies: + react: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc + react-dom: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc + node-domexception@1.0.0: resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} engines: {node: '>=10.5.0'} @@ -9838,6 +9847,11 @@ snapshots: netmask@2.0.2: {} + next-themes@0.4.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + node-domexception@1.0.0: {} node-eval@2.0.0: diff --git a/front/src/App.tsx b/front/src/App.tsx index 84954eb..4c119c0 100644 --- a/front/src/App.tsx +++ b/front/src/App.tsx @@ -17,7 +17,6 @@ import { SelectValueText, Stack, Text, - defaultSystem, useDisclosure, } from '@chakra-ui/react'; @@ -26,6 +25,7 @@ import { App as SpaApp } from '@/scene/App'; import { USERS, USERS_COLLECTION } from '@/service/session'; import { hashLocalData } from '@/utils/sso'; import { Toaster } from './components/ui/toaster'; +import { systemTheme } from './theme/theme'; const AppEnvHint = () => { const dialog = useDisclosure(); @@ -120,8 +120,9 @@ const AppEnvHint = () => { }; const App = () => { + return ( - + diff --git a/front/src/components/AudioPlayer.tsx b/front/src/components/AudioPlayer.tsx index 2fffad4..404daa7 100644 --- a/front/src/components/AudioPlayer.tsx +++ b/front/src/components/AudioPlayer.tsx @@ -2,6 +2,7 @@ import { SyntheticEvent, useEffect, useRef, useState } from 'react'; import { Box, + Button, Flex, IconButton, Slider, @@ -31,8 +32,9 @@ import { useSpecificArtists } from '@/service/Artist'; import { useSpecificGender } from '@/service/Gender'; import { useSpecificTrack } from '@/service/Track'; import { DataUrlAccess } from '@/utils/data-url-access'; -import { useThemeMode } from '@/utils/theme-tools'; +import { useColorModeValue } from '@/components/ui/color-mode'; import { isNullOrUndefined } from '@/utils/validator'; +import { Icon } from './Icon'; export enum PlayMode { PLAY_ONE, @@ -62,7 +64,6 @@ const formatTime = (time) => { }; export const AudioPlayer = ({ }: AudioPlayerProps) => { - const { mode } = useThemeMode(); const { playTrackList, trackOffset, previous, next, first } = useActivePlaylistService(); const audioRef = useRef(null); @@ -85,7 +86,7 @@ export const AudioPlayer = ({ }: AudioPlayerProps) => { : '' ); }, [dataTrack, setMediaSource]); - const backColor = mode('back.100', 'back.800'); + const backColor = useColorModeValue('back.100', 'back.800'); const configButton = { borderRadius: 'full', backgroundColor: '#00000000', @@ -93,6 +94,9 @@ export const AudioPlayer = ({ }: AudioPlayerProps) => { boxShadow: 'outline-over', bgColor: 'brand.500', }, + width: "50px", + height: "50px", + padding: "5px", }; useEffect(() => { @@ -285,11 +289,11 @@ export const AudioPlayer = ({ }: AudioPlayerProps) => { aria-label={'Play'} onClick={onPlay} > - isPlaying ? ( - + {isPlaying ? ( + ) : ( - - ) + + )} { {...configButton} aria-label={'jump 15sec in future'} onClick={onFastForward} - > + > + > playModeIcon[playingMode] + >{playModeIcon[playingMode]} )} diff --git a/front/src/components/Layout/PageLayoutInfoCenter.tsx b/front/src/components/Layout/PageLayoutInfoCenter.tsx index 2bb2293..7c5983c 100644 --- a/front/src/components/Layout/PageLayoutInfoCenter.tsx +++ b/front/src/components/Layout/PageLayoutInfoCenter.tsx @@ -5,7 +5,7 @@ import { useLocation } from 'react-router-dom'; import { PageLayout } from '@/components/Layout/PageLayout'; import { colors } from '@/theme/foundations/colors'; -import { useThemeMode } from '@/utils/theme-tools'; +import { useColorModeValue } from '@/components/ui/color-mode'; export type LayoutProps = FlexProps & { children: ReactNode; @@ -22,7 +22,6 @@ export const PageLayoutInfoCenter = ({ window.scrollTo(0, 0); }, [pathname]); - const { mode } = useThemeMode(); return ( {children} diff --git a/front/src/components/TopBar/TopBar.tsx b/front/src/components/TopBar/TopBar.tsx index cff9ad2..4527a82 100644 --- a/front/src/components/TopBar/TopBar.tsx +++ b/front/src/components/TopBar/TopBar.tsx @@ -2,12 +2,6 @@ import { ReactNode } from 'react'; import { Box, - Button, - Drawer, - DrawerBody, - DrawerContent, - DrawerHeader, - DrawerRoot, Flex, HStack, IconButton, @@ -29,15 +23,22 @@ import { useServiceContext } from '@/service/ServiceContext'; import { SessionState } from '@/service/SessionState'; import { colors } from '@/theme/foundations/colors'; 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'; +import { MenuContent, MenuItem, MenuRoot, MenuTrigger } from '@/components/ui/menu'; +import { useColorMode, useColorModeValue } from '@/components/ui/color-mode'; +import { + DrawerBody, + DrawerContent, + DrawerHeader, + DrawerRoot, +} from '@/components/ui/drawer'; +import { Button } from '../ui/themed'; export const TOP_BAR_HEIGHT = '50px'; export const BUTTON_TOP_BAR_PROPERTY = { - colorPalette: '@menu', + theme: '@menu', height: TOP_BAR_HEIGHT, }; @@ -47,11 +48,11 @@ export type TopBarProps = { }; export const TopBar = ({ title, children }: TopBarProps) => { - const { mode, colorMode, toggleColorMode } = useThemeMode(); + const { colorMode, toggleColorMode } = useColorMode(); const { clearToken } = useSessionService(); const { session } = useServiceContext(); - const backColor = mode('back.100', 'back.800'); + const backColor = useColorModeValue('back.100', 'back.800'); const drawerDisclose = useDisclosure(); const onChangeTheme = () => { drawerDisclose.onOpen(); @@ -120,7 +121,7 @@ export const TopBar = ({ title, children }: TopBarProps) => { {session?.state !== SessionState.CONNECTED && ( <> - -
- -
- - - - - + + + Home + + +
+ +
+ + + +
); }; diff --git a/front/src/components/contextMenu/ContextMenu.tsx b/front/src/components/contextMenu/ContextMenu.tsx index 9b202d9..482c365 100644 --- a/front/src/components/contextMenu/ContextMenu.tsx +++ b/front/src/components/contextMenu/ContextMenu.tsx @@ -5,6 +5,8 @@ import { } from '@chakra-ui/react'; import { LuMenu } from 'react-icons/lu'; import { MenuContent, MenuItem, MenuRoot, MenuTrigger } from '../ui/menu'; +import { Button } from '../ui/themed'; +import { customVariant } from '@/theme/recipes/button'; export type MenuElement = { name: string; @@ -15,6 +17,21 @@ export type ContextMenuProps = { elements?: MenuElement[]; }; +const theme = { + plop: { + bg: { _light: 'red', _dark: 'brand.300', _pink: "orange" }, + _hover: { bg: { _light: 'green', _dark: 'brand.400', _pink: "black" } }, + // bg: { _light: 'brand.600', _dark: 'brand.300' }, + // _hover: { bg: { _light: 'brand.700', _dark: 'brand.400' } }, + /* + bgActive: { _light: 'brand.600', _dark: 'brand.300' }, + color: { _light: 'white', _dark: 'brand.900' }, + colorHover: { _light: 'brand.800', _dark: 'brand.100' }, + boxShadowHover: 'outline-over' + */ + } +}; + export const ContextMenu = ({ elements }: ContextMenuProps) => { if (!elements) { return <>; @@ -25,9 +42,9 @@ export const ContextMenu = ({ elements }: ContextMenuProps) => { {/* This is very stupid, we need to set as span to prevent a button in button... WTF */} - + @@ -38,6 +55,6 @@ export const ContextMenu = ({ elements }: ContextMenuProps) => { ))} - + ); }; diff --git a/front/src/components/popup/AlbumEditPopUp.tsx b/front/src/components/popup/AlbumEditPopUp.tsx index 27fd9da..1ba321d 100644 --- a/front/src/components/popup/AlbumEditPopUp.tsx +++ b/front/src/components/popup/AlbumEditPopUp.tsx @@ -1,17 +1,9 @@ import { useRef, useState } from 'react'; import { - Button, Flex, - Dialog, - DialogBody, - DialogContent, - DialogFooter, - DialogHeader, Text, useDisclosure, - DialogRoot, - DialogCloseTrigger, } from '@chakra-ui/react'; import { MdAdminPanelSettings, @@ -32,6 +24,8 @@ import { useAlbumService, useSpecificAlbum } from '@/service/Album'; import { useServiceContext } from '@/service/ServiceContext'; import { useCountTracksWithAlbumId } from '@/service/Track'; import { isNullOrUndefined } from '@/utils/validator'; +import { DialogBody, DialogContent, DialogFooter, DialogHeader, DialogRoot } from '@/components/ui/dialog'; +import { Button } from '../ui/themed'; export type AlbumEditPopUpProps = {}; @@ -174,7 +168,7 @@ export const AlbumEditPopUp = ({ }: AlbumEditPopUpProps) => { ) : ( diff --git a/front/src/components/popup/TrackEditPopUp.tsx b/front/src/components/popup/TrackEditPopUp.tsx index 764abfe..08454d1 100644 --- a/front/src/components/popup/TrackEditPopUp.tsx +++ b/front/src/components/popup/TrackEditPopUp.tsx @@ -1,15 +1,12 @@ import { useRef, useState } from 'react'; import { - Button, - DialogBody, - DialogContent, - DialogFooter, - DialogHeader, - DialogRoot, Text, useDisclosure, } from '@chakra-ui/react'; + +import { DialogBody, DialogContent, DialogFooter, DialogHeader, DialogRoot } from '@/components/ui/dialog'; + import { MdAdminPanelSettings, MdDeleteForever, MdEdit } from 'react-icons/md'; import { useNavigate, useParams } from 'react-router-dom'; @@ -28,6 +25,7 @@ import { useOrderedGenders } from '@/service/Gender'; import { useServiceContext } from '@/service/ServiceContext'; import { useSpecificTrack, useTrackService } from '@/service/Track'; import { isNullOrUndefined } from '@/utils/validator'; +import { Button } from '../ui/themed'; export type TrackEditPopUpProps = {}; @@ -115,7 +113,7 @@ export const TrackEditPopUp = ({ }: TrackEditPopUpProps) => { diff --git a/front/src/components/ui/close-button.tsx b/front/src/components/ui/close-button.tsx new file mode 100644 index 0000000..94af488 --- /dev/null +++ b/front/src/components/ui/close-button.tsx @@ -0,0 +1,17 @@ +import type { ButtonProps } from "@chakra-ui/react" +import { IconButton as ChakraIconButton } from "@chakra-ui/react" +import * as React from "react" +import { LuX } from "react-icons/lu" + +export type CloseButtonProps = ButtonProps + +export const CloseButton = React.forwardRef< + HTMLButtonElement, + CloseButtonProps +>(function CloseButton(props, ref) { + return ( + + {props.children ?? } + + ) +}) diff --git a/front/src/components/ui/color-mode.tsx b/front/src/components/ui/color-mode.tsx new file mode 100644 index 0000000..52ce1a0 --- /dev/null +++ b/front/src/components/ui/color-mode.tsx @@ -0,0 +1,29 @@ +"use client" + +import { ThemeProvider, useTheme, ThemeProviderProps } from "next-themes" + +export interface ColorModeProviderProps extends ThemeProviderProps { } + +export function ColorModeProvider(props: ColorModeProviderProps) { + return ( + + ) +} + +export function useColorMode() { + const { resolvedTheme, setTheme } = useTheme() + const toggleColorMode = () => { + console.log(`plop: ${resolvedTheme}`); + setTheme(resolvedTheme === "light" ? "pink" : resolvedTheme === "pink" ? "dark" : "light") + } + return { + colorMode: resolvedTheme, + setColorMode: setTheme, + toggleColorMode, + } +} + +export function useColorModeValue(light: T, dark: T) { + const { colorMode } = useColorMode() + return colorMode === "light" ? light : dark +} diff --git a/front/src/components/ui/dialog.tsx b/front/src/components/ui/dialog.tsx new file mode 100644 index 0000000..89d68a5 --- /dev/null +++ b/front/src/components/ui/dialog.tsx @@ -0,0 +1,62 @@ +import { Dialog as ChakraDialog, Portal } from "@chakra-ui/react" +import { CloseButton } from "./close-button" +import * as React from "react" + +interface DialogContentProps extends ChakraDialog.ContentProps { + portalled?: boolean + portalRef?: React.RefObject + backdrop?: boolean +} + +export const DialogContent = React.forwardRef< + HTMLDivElement, + DialogContentProps +>(function DialogContent(props, ref) { + const { + children, + portalled = true, + portalRef, + backdrop = true, + ...rest + } = props + + return ( + + {backdrop && } + + + {children} + + + + ) +}) + +export const DialogCloseTrigger = React.forwardRef< + HTMLButtonElement, + ChakraDialog.CloseTriggerProps +>(function DialogCloseTrigger(props, ref) { + return ( + + + {props.children} + + + ) +}) + +export const DialogRoot = ChakraDialog.Root +export const DialogFooter = ChakraDialog.Footer +export const DialogHeader = ChakraDialog.Header +export const DialogBody = ChakraDialog.Body +export const DialogBackdrop = ChakraDialog.Backdrop +export const DialogTitle = ChakraDialog.Title +export const DialogDescription = ChakraDialog.Description +export const DialogTrigger = ChakraDialog.Trigger +export const DialogActionTrigger = ChakraDialog.ActionTrigger diff --git a/front/src/components/ui/drawer.tsx b/front/src/components/ui/drawer.tsx new file mode 100644 index 0000000..ccb96c8 --- /dev/null +++ b/front/src/components/ui/drawer.tsx @@ -0,0 +1,52 @@ +import { Drawer as ChakraDrawer, Portal } from "@chakra-ui/react" +import { CloseButton } from "./close-button" +import * as React from "react" + +interface DrawerContentProps extends ChakraDrawer.ContentProps { + portalled?: boolean + portalRef?: React.RefObject + offset?: ChakraDrawer.ContentProps["padding"] +} + +export const DrawerContent = React.forwardRef< + HTMLDivElement, + DrawerContentProps +>(function DrawerContent(props, ref) { + const { children, portalled = true, portalRef, offset, ...rest } = props + return ( + + + + {children} + + + + ) +}) + +export const DrawerCloseTrigger = React.forwardRef< + HTMLButtonElement, + ChakraDrawer.CloseTriggerProps +>(function DrawerCloseTrigger(props, ref) { + return ( + + + + ) +}) + +export const DrawerTrigger = ChakraDrawer.Trigger +export const DrawerRoot = ChakraDrawer.Root +export const DrawerFooter = ChakraDrawer.Footer +export const DrawerHeader = ChakraDrawer.Header +export const DrawerBody = ChakraDrawer.Body +export const DrawerBackdrop = ChakraDrawer.Backdrop +export const DrawerDescription = ChakraDrawer.Description +export const DrawerTitle = ChakraDrawer.Title +export const DrawerActionTrigger = ChakraDrawer.ActionTrigger diff --git a/front/src/components/ui/index.ts b/front/src/components/ui/index.ts new file mode 100644 index 0000000..e69de29 diff --git a/front/src/components/ui/themed.tsx b/front/src/components/ui/themed.tsx new file mode 100644 index 0000000..f4c48ad --- /dev/null +++ b/front/src/components/ui/themed.tsx @@ -0,0 +1,7 @@ + +import buttonRecipe from '@/theme/recipes/button'; +import { chakra } from '@chakra-ui/react'; + +// we export the element with the application recipe theme. +// cf doc: https://www.chakra-ui.com/docs/theming/recipes +export const Button = chakra("button", buttonRecipe) diff --git a/front/src/errors/ErrorBoundary.tsx b/front/src/errors/ErrorBoundary.tsx index dd15de0..fb2ac8d 100644 --- a/front/src/errors/ErrorBoundary.tsx +++ b/front/src/errors/ErrorBoundary.tsx @@ -1,12 +1,10 @@ import React, { FC } from 'react'; import { - Alert, AlertDescription, AlertRoot, AlertTitle, Box, - Button, Collapsible, useDisclosure, } from '@chakra-ui/react'; @@ -14,7 +12,8 @@ import { FallbackProps, ErrorBoundary as ReactErrorBoundary, } from 'react-error-boundary'; -import { LuChevronDown, LuChevronUp } from 'react-icons/lu'; +import { Button } from '@/components/ui/themed'; +import { LuChevronUp, LuChevronDown } from 'react-icons/lu'; const ErrorFallback = ({ error }: FallbackProps) => { const { open, onToggle } = useDisclosure(); @@ -26,13 +25,12 @@ const ErrorFallback = ({ error }: FallbackProps) => { An unexpected error has occurred. diff --git a/front/src/main.tsx b/front/src/main.tsx index 4e4ff18..5833ad3 100644 --- a/front/src/main.tsx +++ b/front/src/main.tsx @@ -3,6 +3,7 @@ import { StrictMode } from 'react'; import ReactDOM from 'react-dom/client'; import App from '@/App'; +import { ColorModeProvider } from './components/ui/color-mode'; // Render the app const rootElement = document.getElementById('root'); @@ -10,7 +11,9 @@ if (rootElement && !rootElement.innerHTML) { const root = ReactDOM.createRoot(rootElement); root.render( - + + + ); } diff --git a/front/src/scene/album/AlbumDetailPage.tsx b/front/src/scene/album/AlbumDetailPage.tsx index d4d6a10..585296c 100644 --- a/front/src/scene/album/AlbumDetailPage.tsx +++ b/front/src/scene/album/AlbumDetailPage.tsx @@ -15,13 +15,12 @@ import { DisplayTrackFull } from '@/components/track/DisplayTrackFull'; import { useActivePlaylistService } from '@/service/ActivePlaylist'; import { useSpecificAlbum } from '@/service/Album'; import { useTracksOfAnAlbum } from '@/service/Track'; -import { useThemeMode } from '@/utils/theme-tools'; +import { useColorModeValue } from '@/components/ui/color-mode'; import { BASE_WRAP_SPACING } from '@/constants/genericSpacing'; export const AlbumDetailPage = () => { const { albumId } = useParams(); const albumIdInt = albumId ? parseInt(albumId, 10) : undefined; - const { mode } = useThemeMode(); const { playInList } = useActivePlaylistService(); const { dataAlbum } = useSpecificAlbum(albumIdInt); const { tracksOnAnAlbum } = useTracksOfAnAlbum(albumIdInt); @@ -107,13 +106,13 @@ export const AlbumDetailPage = () => { //height="60px" border="1px" borderColor="brand.900" - backgroundColor={mode('#FFFFFF88', '#00000088')} + backgroundColor={useColorModeValue('#FFFFFF88', '#00000088')} key={data.id} padding="5px" as="button" _hover={{ boxShadow: 'outline-over', - bgColor: mode('#FFFFFFF7', '#000000F7'), + bgColor: useColorModeValue('#FFFFFFF7', '#000000F7'), }} > { const [filterTitle, setFilterTitle] = useState(undefined); const { isLoading, dataAlbums } = useOrderedAlbums(filterTitle); - const { mode } = useThemeMode(); const navigate = useNavigate(); const onSelectItem = (albumId: number) => { navigate(`/album/${albumId}`); @@ -44,13 +43,13 @@ export const AlbumsPage = () => { height={BASE_WRAP_HEIGHT} border="1px" borderColor="brand.900" - backgroundColor={mode('#FFFFFF88', '#00000088')} + backgroundColor={useColorModeValue('#FFFFFF88', '#00000088')} key={data.id} padding="5px" as="button" _hover={{ boxShadow: 'outline-over', - bgColor: mode('#FFFFFFF7', '#000000F7'), + bgColor: useColorModeValue('#FFFFFFF7', '#000000F7'), }} onClick={() => onSelectItem(data.id)} > diff --git a/front/src/scene/artist/ArtistAlbumDetailPage.tsx b/front/src/scene/artist/ArtistAlbumDetailPage.tsx index 87ddfdd..6f71a8b 100644 --- a/front/src/scene/artist/ArtistAlbumDetailPage.tsx +++ b/front/src/scene/artist/ArtistAlbumDetailPage.tsx @@ -15,13 +15,12 @@ import { useActivePlaylistService } from '@/service/ActivePlaylist'; import { useSpecificAlbum } from '@/service/Album'; import { useSpecificArtist } from '@/service/Artist'; import { useTracksOfAnAlbum } from '@/service/Track'; -import { useThemeMode } from '@/utils/theme-tools'; +import { useColorModeValue } from '@/components/ui/color-mode'; export const ArtistAlbumDetailPage = () => { const { artistId, albumId } = useParams(); const artistIdInt = artistId ? parseInt(artistId, 10) : undefined; const albumIdInt = albumId ? parseInt(albumId, 10) : undefined; - const { mode } = useThemeMode(); const { playInList } = useActivePlaylistService(); const { dataArtist } = useSpecificArtist(artistIdInt); const { dataAlbum } = useSpecificAlbum(albumIdInt); @@ -124,13 +123,13 @@ export const ArtistAlbumDetailPage = () => { height="60px" border="1px" borderColor="brand.900" - backgroundColor={mode('#FFFFFF88', '#00000088')} + backgroundColor={useColorModeValue('#FFFFFF88', '#00000088')} key={data.id} padding="5px" as="button" _hover={{ boxShadow: 'outline-over', - bgColor: mode('#FFFFFFF7', '#000000F7'), + bgColor: useColorModeValue('#FFFFFFF7', '#000000F7'), }} > { const { artistId } = useParams(); const artistIdInt = artistId ? parseInt(artistId, 10) : undefined; - const { mode } = useThemeMode(); const navigate = useNavigate(); const onSelectItem = (albumId: number) => { navigate(`/artist/${artistIdInt}/album/${albumId}`); @@ -96,13 +95,13 @@ export const ArtistDetailPage = () => { height={BASE_WRAP_HEIGHT} border="1px" borderColor="brand.900" - backgroundColor={mode('#FFFFFF88', '#00000088')} + backgroundColor={useColorModeValue('#FFFFFF88', '#00000088')} key={data} padding="5px" as="button" _hover={{ boxShadow: 'outline-over', - bgColor: mode('#FFFFFFF7', '#000000F7'), + bgColor: useColorModeValue('#FFFFFFF7', '#000000F7'), }} onClick={() => onSelectItem(data)} > diff --git a/front/src/scene/artist/ArtistsPage.tsx b/front/src/scene/artist/ArtistsPage.tsx index 81ef07f..3c2d8c8 100644 --- a/front/src/scene/artist/ArtistsPage.tsx +++ b/front/src/scene/artist/ArtistsPage.tsx @@ -11,7 +11,7 @@ import { PageLayout } from '@/components/Layout/PageLayout'; import { SearchInput } from '@/components/SearchInput'; import { BUTTON_TOP_BAR_PROPERTY, TopBar } from '@/components/TopBar/TopBar'; import { useOrderedArtists } from '@/service/Artist'; -import { useThemeMode } from '@/utils/theme-tools'; +import { useColorModeValue } from '@/components/ui/color-mode'; import { BASE_WRAP_HEIGHT, BASE_WRAP_ICON_SIZE, BASE_WRAP_SPACING, BASE_WRAP_WIDTH } from '@/constants/genericSpacing'; import { MdOutlineForkRight } from 'react-icons/md'; import { useActivePlaylistService } from '@/service/ActivePlaylist'; @@ -21,7 +21,6 @@ import { DataTools, TypeCheck } from '@/utils/data-tools'; const LIMIT_RANDOM_VALUES = 25; export const ArtistsPage = () => { - const { mode } = useThemeMode(); const [filterName, setFilterName] = useState(undefined); const navigate = useNavigate(); const { playInList } = useActivePlaylistService(); @@ -72,13 +71,13 @@ export const ArtistsPage = () => { height={BASE_WRAP_HEIGHT} border="1px" borderColor="brand.900" - backgroundColor={mode('#FFFFFF88', '#00000088')} + backgroundColor={useColorModeValue('#FFFFFF88', '#00000088')} key={data.id} padding="5px" as="button" _hover={{ boxShadow: 'outline-over', - bgColor: mode('#FFFFFFF7', '#000000F7'), + bgColor: useColorModeValue('#FFFFFFF7', '#000000F7'), }} onClick={() => onSelectItem(data)} > diff --git a/front/src/scene/gender/GenderDetailPage.tsx b/front/src/scene/gender/GenderDetailPage.tsx index be1398d..fc727b1 100644 --- a/front/src/scene/gender/GenderDetailPage.tsx +++ b/front/src/scene/gender/GenderDetailPage.tsx @@ -16,12 +16,11 @@ import { useActivePlaylistService } from '@/service/ActivePlaylist'; import { useSpecificGender } from '@/service/Gender'; import { useTracksOfAGender } from '@/service/Track'; //import { useTracksOfAGender } from '@/service/Track'; -import { useThemeMode } from '@/utils/theme-tools'; +import { useColorModeValue } from '@/components/ui/color-mode'; export const GenderDetailPage = () => { const { genderId } = useParams(); const genderIdInt = genderId ? parseInt(genderId, 10) : undefined; - const { mode } = useThemeMode(); const { playInList } = useActivePlaylistService(); const { dataGender } = useSpecificGender(genderIdInt); const { tracksOnAGender } = useTracksOfAGender(genderIdInt); @@ -102,13 +101,13 @@ export const GenderDetailPage = () => { //height="60px" border="1px" borderColor="brand.900" - backgroundColor={mode('#FFFFFF88', '#00000088')} + backgroundColor={useColorModeValue('#FFFFFF88', '#00000088')} key={data.id} padding="5px" as="button" _hover={{ boxShadow: 'outline-over', - bgColor: mode('#FFFFFFF7', '#000000F7'), + bgColor: useColorModeValue('#FFFFFFF7', '#000000F7'), }} > { const [filterTitle, setFilterTitle] = useState(undefined); const { isLoading, dataGenders } = useOrderedGenders(filterTitle); - const { mode } = useThemeMode(); const navigate = useNavigate(); const onSelectItem = (genderId: number) => { navigate(`/gender/${genderId}`); @@ -43,13 +42,13 @@ export const GendersPage = () => { height="120px" border="1px" borderColor="brand.900" - backgroundColor={mode('#FFFFFF88', '#00000088')} + backgroundColor={useColorModeValue('#FFFFFF88', '#00000088')} key={data.id} padding="5px" as="button" _hover={{ boxShadow: 'outline-over', - bgColor: mode('#FFFFFFF7', '#000000F7'), + bgColor: useColorModeValue('#FFFFFFF7', '#000000F7'), }} onClick={() => onSelectItem(data.id)} > diff --git a/front/src/scene/home/AddPage.tsx b/front/src/scene/home/AddPage.tsx index b6f1f39..2f81f54 100644 --- a/front/src/scene/home/AddPage.tsx +++ b/front/src/scene/home/AddPage.tsx @@ -1,7 +1,6 @@ import { useCallback, useState } from 'react'; import { - Button, Flex, Input, Table, @@ -32,6 +31,7 @@ import { useGenderService, useOrderedGenders } from '@/service/Gender'; import { useServiceContext } from '@/service/ServiceContext'; import { useTrackService } from '@/service/Track'; import { isNullOrUndefined } from '@/utils/validator'; +import { Button } from '@/components/ui/themed'; export class ElementList { constructor( @@ -540,7 +540,7 @@ export const AddPage = () => { - + + ), }; @@ -28,8 +28,8 @@ export const Primary = { export const Secondary = { render: () => ( - - + + ), }; @@ -37,8 +37,8 @@ export const Secondary = { export const Danger = { render: () => ( - - + + ), }; @@ -58,7 +58,7 @@ export const Progress = { diff --git a/front/src/theme/styles.ts b/front/src/theme/styles.ts index 051d837..916c1e1 100644 --- a/front/src/theme/styles.ts +++ b/front/src/theme/styles.ts @@ -1,13 +1,4 @@ -// import { Styles } from '@chakra-ui/theme-tools'; -// import { mode } from '@chakra-ui/theme-tools'; +import { Styles } from '@chakra-ui/theme-tools'; -// export const styles: Styles = { -// global: (props) => ({ -// body: { -// overflowY: 'none', -// bg: mode('back.50', 'back.700')(props), -// color: mode('text.900', 'text.50')(props), -// fontFamily: 'Roboto, Helvetica, Arial, "sans-serif"', -// }, -// }), -// }; +export const styles: Styles = { +}; diff --git a/front/src/theme/theme.ts b/front/src/theme/theme.ts index 2f5c3f0..00cfa92 100644 --- a/front/src/theme/theme.ts +++ b/front/src/theme/theme.ts @@ -1,9 +1,23 @@ - -import { createSystem, defaultConfig } from "@chakra-ui/react" +import * as recipes from './recipes'; +import { createSystem, defaultConfig, mergeConfigs, SystemConfig } from "@chakra-ui/react" import { colors } from "./foundations/colors" -export const system = createSystem(defaultConfig, { +const baseTheme: SystemConfig = { + globalCss: { + body: { + overflowY: 'none', + bg: { _light: 'back.50', _dark: 'back.700' }, + color: { _light: 'text.900', _dark: 'text.50' }, + fontFamily: 'Roboto, Helvetica, Arial, "sans-serif"', + }, + svg: { + width: "32px", + height: "32px", + aspectRatio: "square", + } + }, theme: { + ...recipes, tokens: { fonts: { heading: { value: `Roboto, Helvetica, Arial, "sans-serif"` }, @@ -25,4 +39,6 @@ export const system = createSystem(defaultConfig, { }, }, }, -}) \ No newline at end of file +}; +const config = mergeConfigs(defaultConfig, baseTheme); +export const systemTheme = createSystem(config); \ No newline at end of file diff --git a/front/src/utils/theme-tools.ts b/front/src/utils/theme-tools.ts deleted file mode 100644 index 91c87f6..0000000 --- a/front/src/utils/theme-tools.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { useCallback } from 'react'; - -export const useThemeMode = () => { - //const { colorMode, toggleColorMode, setColorMode } = useColorMode(); - const colorMode = "dark"; - const toggleColorMode = () => { } - const setColorMode = (_value: string) => { } - - const mode = useCallback( - (lightValue, darkValue) => (colorMode === 'dark' ? darkValue : lightValue), - [colorMode] - ); - - return { - toggleColorMode, - setColorMode, - mode, - colorMode, - }; -}; diff --git a/front/tsconfig.json b/front/tsconfig.json index 2886a84..1b08d34 100644 --- a/front/tsconfig.json +++ b/front/tsconfig.json @@ -38,7 +38,9 @@ "include": [ "next-env.d.ts", "src/**/*.ts", - "src/**/*.tsx" + "src/**/*.tsx", + "src/theme/recipes/numberInput.ts_", + "src/theme/recipes/modal.ts__" ], "exclude": [ "node_modules"