[theme and reciepice
This commit is contained in:
parent
d52052de90
commit
c489fabb77
@ -29,11 +29,9 @@
|
||||
"*.{ts,tsx,js,jsx,json}": "prettier --write"
|
||||
},
|
||||
"dependencies": {
|
||||
"@chakra-ui/anatomy": "2.3.4",
|
||||
"@chakra-ui/cli": "3.3.1",
|
||||
"@chakra-ui/react": "3.3.1",
|
||||
"@emotion/react": "11.14.0",
|
||||
"@emotion/styled": "11.14.0",
|
||||
"allotment": "1.20.2",
|
||||
"css-mediaquery": "0.1.2",
|
||||
"dayjs": "1.11.13",
|
||||
|
36
front/pnpm-lock.yaml
generated
36
front/pnpm-lock.yaml
generated
@ -8,9 +8,6 @@ importers:
|
||||
|
||||
.:
|
||||
dependencies:
|
||||
'@chakra-ui/anatomy':
|
||||
specifier: 2.3.4
|
||||
version: 2.3.4
|
||||
'@chakra-ui/cli':
|
||||
specifier: 3.3.1
|
||||
version: 3.3.1(@chakra-ui/react@3.3.1(@emotion/react@11.14.0(@types/react@18.3.8)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))
|
||||
@ -20,9 +17,6 @@ importers:
|
||||
'@emotion/react':
|
||||
specifier: 11.14.0
|
||||
version: 11.14.0(@types/react@18.3.8)(react@18.3.1)
|
||||
'@emotion/styled':
|
||||
specifier: 11.14.0
|
||||
version: 11.14.0(@emotion/react@11.14.0(@types/react@18.3.8)(react@18.3.1))(@types/react@18.3.8)(react@18.3.1)
|
||||
allotment:
|
||||
specifier: 1.20.2
|
||||
version: 1.20.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
@ -378,9 +372,6 @@ packages:
|
||||
'@bcoe/v8-coverage@0.2.3':
|
||||
resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==}
|
||||
|
||||
'@chakra-ui/anatomy@2.3.4':
|
||||
resolution: {integrity: sha512-fFIYN7L276gw0Q7/ikMMlZxP7mvnjRaWJ7f3Jsf9VtDOi6eAYIBRrhQe6+SZ0PGmoOkRaBc7gSE5oeIbgFFyrw==}
|
||||
|
||||
'@chakra-ui/cli@3.3.1':
|
||||
resolution: {integrity: sha512-TTpGVT4RuajxzYjMP95Ba3HU052cmdrYgru77ZGD+IDb/HLATjpXNViFAn1R+ITMCxa4v0zqYEWLY9Ex2L090A==}
|
||||
hasBin: true
|
||||
@ -444,16 +435,6 @@ packages:
|
||||
'@emotion/sheet@1.4.0':
|
||||
resolution: {integrity: sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==}
|
||||
|
||||
'@emotion/styled@11.14.0':
|
||||
resolution: {integrity: sha512-XxfOnXFffatap2IyCeJyNov3kiDQWoR08gPUQxvbL7fxKryGBKUZUkG6Hz48DZwVrJSVh9sJboyV1Ds4OW6SgA==}
|
||||
peerDependencies:
|
||||
'@emotion/react': ^11.0.0-rc.0
|
||||
'@types/react': '*'
|
||||
react: '>=16.8.0'
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
|
||||
'@emotion/unitless@0.10.0':
|
||||
resolution: {integrity: sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==}
|
||||
|
||||
@ -5469,8 +5450,6 @@ snapshots:
|
||||
|
||||
'@bcoe/v8-coverage@0.2.3': {}
|
||||
|
||||
'@chakra-ui/anatomy@2.3.4': {}
|
||||
|
||||
'@chakra-ui/cli@3.3.1(@chakra-ui/react@3.3.1(@emotion/react@11.14.0(@types/react@18.3.8)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))':
|
||||
dependencies:
|
||||
'@chakra-ui/react': 3.3.1(@emotion/react@11.14.0(@types/react@18.3.8)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
@ -5595,21 +5574,6 @@ snapshots:
|
||||
|
||||
'@emotion/sheet@1.4.0': {}
|
||||
|
||||
'@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@18.3.8)(react@18.3.1))(@types/react@18.3.8)(react@18.3.1)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.24.7
|
||||
'@emotion/babel-plugin': 11.13.5
|
||||
'@emotion/is-prop-valid': 1.3.1
|
||||
'@emotion/react': 11.14.0(@types/react@18.3.8)(react@18.3.1)
|
||||
'@emotion/serialize': 1.3.3
|
||||
'@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@18.3.1)
|
||||
'@emotion/utils': 1.4.2
|
||||
react: 18.3.1
|
||||
optionalDependencies:
|
||||
'@types/react': 18.3.8
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@emotion/unitless@0.10.0': {}
|
||||
|
||||
'@emotion/use-insertion-effect-with-fallbacks@1.2.0(react@18.3.1)':
|
||||
|
@ -56,6 +56,7 @@ const AppEnvHint = () => {
|
||||
return (
|
||||
<>
|
||||
<Box
|
||||
as="button"
|
||||
zIndex="100000"
|
||||
position="fixed"
|
||||
top="0"
|
||||
@ -63,7 +64,6 @@ const AppEnvHint = () => {
|
||||
insetEnd="0"
|
||||
h="2px"
|
||||
bg="warning.400"
|
||||
as="button"
|
||||
cursor="pointer"
|
||||
data-test-id="devtools"
|
||||
onClick={dialog.onOpen}
|
||||
@ -84,7 +84,7 @@ const AppEnvHint = () => {
|
||||
>
|
||||
{envName.join(' : ')}
|
||||
</Text>
|
||||
</Box>
|
||||
</Box >
|
||||
<DialogRoot open={dialog.open} onOpenChange={dialog.onClose}>
|
||||
<DialogContent>
|
||||
<DialogHeader>Outils développeurs</DialogHeader>
|
||||
|
@ -38,7 +38,14 @@ import { Button } from '../ui/themed';
|
||||
export const TOP_BAR_HEIGHT = '50px';
|
||||
|
||||
export const BUTTON_TOP_BAR_PROPERTY = {
|
||||
theme: '@menu',
|
||||
bg: 'back.100',
|
||||
color: 'brand.900',
|
||||
borderRadius: 0,
|
||||
border: 0,
|
||||
_hover: { background: 'back.300' },
|
||||
_focus: { border: 'none' },
|
||||
fontSize: '20px',
|
||||
textTransform: 'uppercase',
|
||||
height: TOP_BAR_HEIGHT,
|
||||
};
|
||||
|
||||
@ -143,7 +150,7 @@ export const TopBar = ({ title, children }: TopBarProps) => {
|
||||
<MenuRoot>
|
||||
<MenuTrigger asChild>
|
||||
<IconButton
|
||||
as={IconButton}
|
||||
asChild
|
||||
aria-label="Options"
|
||||
{...BUTTON_TOP_BAR_PROPERTY}
|
||||
width={TOP_BAR_HEIGHT}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Flex, Text } from '@chakra-ui/react';
|
||||
import { Flex, Span, Text } from '@chakra-ui/react';
|
||||
import { LuDisc3 } from 'react-icons/lu';
|
||||
|
||||
import { Album } from '@/back-api';
|
||||
@ -25,7 +25,7 @@ export const DisplayAlbum = ({ dataAlbum }: DisplayAlbumProps) => {
|
||||
data={dataAlbum?.covers}
|
||||
size={BASE_WRAP_ICON_SIZE}
|
||||
flex={1}
|
||||
// TODO: iconEmpty={LuDisc3}
|
||||
iconEmpty={<LuDisc3 />}
|
||||
/>
|
||||
<Flex
|
||||
direction="column"
|
||||
@ -36,8 +36,7 @@ export const DisplayAlbum = ({ dataAlbum }: DisplayAlbumProps) => {
|
||||
overflowX="hidden"
|
||||
flex={1}
|
||||
>
|
||||
<Text
|
||||
as="span"
|
||||
<Span
|
||||
// align="left"
|
||||
fontSize="20px"
|
||||
fontWeight="bold"
|
||||
@ -47,9 +46,8 @@ export const DisplayAlbum = ({ dataAlbum }: DisplayAlbumProps) => {
|
||||
// noOfLines={[1, 2]}
|
||||
>
|
||||
{dataAlbum?.name}
|
||||
</Text>
|
||||
<Text
|
||||
as="span"
|
||||
</Span>
|
||||
<Span
|
||||
// align="left"
|
||||
fontSize="15px"
|
||||
userSelect="none"
|
||||
@ -58,7 +56,7 @@ export const DisplayAlbum = ({ dataAlbum }: DisplayAlbumProps) => {
|
||||
// noOfLines={1}
|
||||
>
|
||||
{countTracksOfAnAlbum} track{countTracksOfAnAlbum >= 1 && 's'}
|
||||
</Text>
|
||||
</Span>
|
||||
</Flex>
|
||||
</Flex>
|
||||
);
|
||||
|
@ -1,12 +1,9 @@
|
||||
import { useState } from 'react';
|
||||
|
||||
import {
|
||||
IconButton,
|
||||
} 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';
|
||||
import { Button } from '../ui/button';
|
||||
|
||||
|
||||
export type MenuElement = {
|
||||
name: string;
|
||||
@ -17,21 +14,6 @@ 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 <></>;
|
||||
@ -40,9 +22,11 @@ export const ContextMenu = ({ elements }: ContextMenuProps) => {
|
||||
<MenuRoot
|
||||
data-testid="context-menu">
|
||||
<MenuTrigger asChild
|
||||
marginY="auto"
|
||||
marginRight="4px"
|
||||
data-testid="context-menu_trigger">
|
||||
{/* This is very stupid, we need to set as span to prevent a button in button... WTF */}
|
||||
<Button {...theme.plop} /*theme="@primary"*/>
|
||||
<Button variant="ghost" color="brand.500">
|
||||
<LuMenu />
|
||||
</Button>
|
||||
</MenuTrigger>
|
||||
|
@ -104,14 +104,13 @@ export const CenterIcon = ({
|
||||
return (
|
||||
<Box position="relative" w={sizeIcon} h={sizeIcon} flex="none" {...rest}>
|
||||
<Box
|
||||
as={IconEl}
|
||||
w={sizeIcon}
|
||||
h={sizeIcon}
|
||||
position="absolute"
|
||||
top="50%"
|
||||
left="50%"
|
||||
transform="translate(-50%, -50%)"
|
||||
/>
|
||||
>{IconEl}</Box>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
@ -150,14 +149,13 @@ export const FormCovers = ({
|
||||
<Box width="125px" height="125px" position="relative">
|
||||
<Box width="125px" height="125px" position="absolute">
|
||||
<CenterIcon
|
||||
icon={MdHighlightOff}
|
||||
width="125px"
|
||||
sizeIcon="100%"
|
||||
zIndex="+1"
|
||||
color="#00000020"
|
||||
_hover={{ color: 'red' }}
|
||||
onClick={() => onRemove && onRemove(index)}
|
||||
/>
|
||||
><MdHighlightOff /></CenterIcon>
|
||||
</Box>
|
||||
<Image loading="lazy" src={data} boxSize="full" />
|
||||
</Box>
|
||||
|
@ -25,7 +25,8 @@ 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';
|
||||
import { Button } from '../ui/button';
|
||||
|
||||
|
||||
export type AlbumEditPopUpProps = {};
|
||||
|
||||
@ -168,7 +169,9 @@ export const AlbumEditPopUp = ({ }: AlbumEditPopUpProps) => {
|
||||
<Button
|
||||
onClick={disclosure.onOpen}
|
||||
marginRight="auto"
|
||||
theme="@danger"
|
||||
//theme="@danger"
|
||||
variant="outline"
|
||||
colorScheme=""
|
||||
disabled={countTracksOfAnAlbum !== 0}
|
||||
>
|
||||
<MdDeleteForever /> Remove Media
|
||||
|
@ -4,6 +4,7 @@ import {
|
||||
Flex,
|
||||
Text,
|
||||
useDisclosure,
|
||||
Button,
|
||||
} from '@chakra-ui/react';
|
||||
import { DialogBody, DialogContent, DialogFooter, DialogHeader, DialogRoot } from '@/components/ui/dialog';
|
||||
import {
|
||||
@ -25,7 +26,7 @@ import { useArtistService, useSpecificArtist } from '@/service/Artist';
|
||||
import { useServiceContext } from '@/service/ServiceContext';
|
||||
import { useCountTracksOfAnArtist } from '@/service/Track';
|
||||
import { isNullOrUndefined } from '@/utils/validator';
|
||||
import { Button } from '../ui/themed';
|
||||
//import { Button } from '../ui/themed';
|
||||
|
||||
export type ArtistEditPopUpProps = {};
|
||||
|
||||
@ -217,6 +218,7 @@ export const ArtistEditPopUp = ({ }: ArtistEditPopUpProps) => {
|
||||
<Button
|
||||
onClick={() => setAdmin((value) => !value)}
|
||||
marginRight="auto"
|
||||
variant="@danger"
|
||||
>
|
||||
{admin ? (
|
||||
<>
|
||||
|
@ -109,7 +109,7 @@ export const SelectMultiple = ({
|
||||
return (
|
||||
<Flex direction="column" width="full" gap="0px">
|
||||
{selectedOptions && (
|
||||
<HStack wrap="wrap" /*spacing="5px"*/ justify="left" width="full" marginBottom="2px">
|
||||
<HStack wrap="wrap" gap="5px" justify="left" width="full" marginBottom="2px">
|
||||
{selectedOptions.map((data) => (
|
||||
<Flex align="flex-start" key={data[keyKey]}>
|
||||
<Tag.Root
|
||||
|
@ -20,7 +20,7 @@ export const DisplayTrackSkeleton = () => {
|
||||
{/* <SkeletonText
|
||||
skeletonHeight="20px"
|
||||
noOfLines={1}
|
||||
spacing={0}
|
||||
gap={0}
|
||||
width="50%"
|
||||
marginY="auto"
|
||||
/> */}
|
||||
|
74
front/src/components/ui/avatar.tsx
Normal file
74
front/src/components/ui/avatar.tsx
Normal file
@ -0,0 +1,74 @@
|
||||
"use client"
|
||||
|
||||
import type { GroupProps, SlotRecipeProps } from "@chakra-ui/react"
|
||||
import { Avatar as ChakraAvatar, Group } from "@chakra-ui/react"
|
||||
import * as React from "react"
|
||||
|
||||
type ImageProps = React.ImgHTMLAttributes<HTMLImageElement>
|
||||
|
||||
export interface AvatarProps extends ChakraAvatar.RootProps {
|
||||
name?: string
|
||||
src?: string
|
||||
srcSet?: string
|
||||
loading?: ImageProps["loading"]
|
||||
icon?: React.ReactElement
|
||||
fallback?: React.ReactNode
|
||||
}
|
||||
|
||||
export const Avatar = React.forwardRef<HTMLDivElement, AvatarProps>(
|
||||
function Avatar(props, ref) {
|
||||
const { name, src, srcSet, loading, icon, fallback, children, ...rest } =
|
||||
props
|
||||
return (
|
||||
<ChakraAvatar.Root ref={ref} {...rest}>
|
||||
<AvatarFallback name={name} icon={icon}>
|
||||
{fallback}
|
||||
</AvatarFallback>
|
||||
<ChakraAvatar.Image src={src} srcSet={srcSet} loading={loading} />
|
||||
{children}
|
||||
</ChakraAvatar.Root>
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
interface AvatarFallbackProps extends ChakraAvatar.FallbackProps {
|
||||
name?: string
|
||||
icon?: React.ReactElement
|
||||
}
|
||||
|
||||
const AvatarFallback = React.forwardRef<HTMLDivElement, AvatarFallbackProps>(
|
||||
function AvatarFallback(props, ref) {
|
||||
const { name, icon, children, ...rest } = props
|
||||
return (
|
||||
<ChakraAvatar.Fallback ref={ref} {...rest}>
|
||||
{children}
|
||||
{name != null && children == null && <>{getInitials(name)}</>}
|
||||
{name == null && children == null && (
|
||||
<ChakraAvatar.Icon asChild={!!icon}>{icon}</ChakraAvatar.Icon>
|
||||
)}
|
||||
</ChakraAvatar.Fallback>
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
function getInitials(name: string) {
|
||||
const names = name.trim().split(" ")
|
||||
const firstName = names[0] != null ? names[0] : ""
|
||||
const lastName = names.length > 1 ? names[names.length - 1] : ""
|
||||
return firstName && lastName
|
||||
? `${firstName.charAt(0)}${lastName.charAt(0)}`
|
||||
: firstName.charAt(0)
|
||||
}
|
||||
|
||||
interface AvatarGroupProps extends GroupProps, SlotRecipeProps<"avatar"> {}
|
||||
|
||||
export const AvatarGroup = React.forwardRef<HTMLDivElement, AvatarGroupProps>(
|
||||
function AvatarGroup(props, ref) {
|
||||
const { size, variant, borderless, ...rest } = props
|
||||
return (
|
||||
<ChakraAvatar.PropsProvider value={{ size, variant, borderless }}>
|
||||
<Group gap="0" spaceX="-3" ref={ref} {...rest} />
|
||||
</ChakraAvatar.PropsProvider>
|
||||
)
|
||||
},
|
||||
)
|
40
front/src/components/ui/button.tsx
Normal file
40
front/src/components/ui/button.tsx
Normal file
@ -0,0 +1,40 @@
|
||||
import type { ButtonProps as ChakraButtonProps } from "@chakra-ui/react"
|
||||
import {
|
||||
AbsoluteCenter,
|
||||
Button as ChakraButton,
|
||||
Span,
|
||||
Spinner,
|
||||
} from "@chakra-ui/react"
|
||||
import * as React from "react"
|
||||
|
||||
interface ButtonLoadingProps {
|
||||
loading?: boolean
|
||||
loadingText?: React.ReactNode
|
||||
}
|
||||
|
||||
export interface ButtonProps extends ChakraButtonProps, ButtonLoadingProps {}
|
||||
|
||||
export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
||||
function Button(props, ref) {
|
||||
const { loading, disabled, loadingText, children, ...rest } = props
|
||||
return (
|
||||
<ChakraButton disabled={loading || disabled} ref={ref} {...rest}>
|
||||
{loading && !loadingText ? (
|
||||
<>
|
||||
<AbsoluteCenter display="inline-flex">
|
||||
<Spinner size="inherit" color="inherit" />
|
||||
</AbsoluteCenter>
|
||||
<Span opacity={0}>{children}</Span>
|
||||
</>
|
||||
) : loading && loadingText ? (
|
||||
<>
|
||||
<Spinner size="inherit" color="inherit" />
|
||||
{loadingText}
|
||||
</>
|
||||
) : (
|
||||
children
|
||||
)}
|
||||
</ChakraButton>
|
||||
)
|
||||
},
|
||||
)
|
25
front/src/components/ui/checkbox.tsx
Normal file
25
front/src/components/ui/checkbox.tsx
Normal file
@ -0,0 +1,25 @@
|
||||
import { Checkbox as ChakraCheckbox } from "@chakra-ui/react"
|
||||
import * as React from "react"
|
||||
|
||||
export interface CheckboxProps extends ChakraCheckbox.RootProps {
|
||||
icon?: React.ReactNode
|
||||
inputProps?: React.InputHTMLAttributes<HTMLInputElement>
|
||||
rootRef?: React.Ref<HTMLLabelElement>
|
||||
}
|
||||
|
||||
export const Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(
|
||||
function Checkbox(props, ref) {
|
||||
const { icon, children, inputProps, rootRef, ...rest } = props
|
||||
return (
|
||||
<ChakraCheckbox.Root ref={rootRef} {...rest}>
|
||||
<ChakraCheckbox.HiddenInput ref={ref} {...inputProps} />
|
||||
<ChakraCheckbox.Control>
|
||||
{icon || <ChakraCheckbox.Indicator />}
|
||||
</ChakraCheckbox.Control>
|
||||
{children != null && (
|
||||
<ChakraCheckbox.Label>{children}</ChakraCheckbox.Label>
|
||||
)}
|
||||
</ChakraCheckbox.Root>
|
||||
)
|
||||
},
|
||||
)
|
@ -1,23 +1,35 @@
|
||||
"use client"
|
||||
|
||||
import { ThemeProvider, useTheme, ThemeProviderProps } from "next-themes"
|
||||
import type { IconButtonProps } from "@chakra-ui/react"
|
||||
import { ClientOnly, IconButton, Skeleton } from "@chakra-ui/react"
|
||||
import { ThemeProvider, useTheme } from "next-themes"
|
||||
import type { ThemeProviderProps } from "next-themes"
|
||||
import * as React from "react"
|
||||
import { LuMoon, LuSun } from "react-icons/lu"
|
||||
|
||||
export interface ColorModeProviderProps extends ThemeProviderProps { }
|
||||
export interface ColorModeProviderProps extends ThemeProviderProps {}
|
||||
|
||||
export function ColorModeProvider(props: ColorModeProviderProps) {
|
||||
return (
|
||||
<ThemeProvider attribute="class" themes={['pink', 'dark', 'light']} disableTransitionOnChange {...props} />
|
||||
<ThemeProvider attribute="class" disableTransitionOnChange {...props} />
|
||||
)
|
||||
}
|
||||
|
||||
export function useColorMode() {
|
||||
export type ColorMode = "light" | "dark"
|
||||
|
||||
export interface UseColorModeReturn {
|
||||
colorMode: ColorMode
|
||||
setColorMode: (colorMode: ColorMode) => void
|
||||
toggleColorMode: () => void
|
||||
}
|
||||
|
||||
export function useColorMode(): UseColorModeReturn {
|
||||
const { resolvedTheme, setTheme } = useTheme()
|
||||
const toggleColorMode = () => {
|
||||
console.log(`plop: ${resolvedTheme}`);
|
||||
setTheme(resolvedTheme === "light" ? "pink" : resolvedTheme === "pink" ? "dark" : "light")
|
||||
setTheme(resolvedTheme === "light" ? "dark" : "light")
|
||||
}
|
||||
return {
|
||||
colorMode: resolvedTheme,
|
||||
colorMode: resolvedTheme as ColorMode,
|
||||
setColorMode: setTheme,
|
||||
toggleColorMode,
|
||||
}
|
||||
@ -25,5 +37,39 @@ export function useColorMode() {
|
||||
|
||||
export function useColorModeValue<T>(light: T, dark: T) {
|
||||
const { colorMode } = useColorMode()
|
||||
return colorMode === "light" ? light : dark
|
||||
return colorMode === "dark" ? dark : light
|
||||
}
|
||||
|
||||
export function ColorModeIcon() {
|
||||
const { colorMode } = useColorMode()
|
||||
return colorMode === "dark" ? <LuMoon /> : <LuSun />
|
||||
}
|
||||
|
||||
interface ColorModeButtonProps extends Omit<IconButtonProps, "aria-label"> {}
|
||||
|
||||
export const ColorModeButton = React.forwardRef<
|
||||
HTMLButtonElement,
|
||||
ColorModeButtonProps
|
||||
>(function ColorModeButton(props, ref) {
|
||||
const { toggleColorMode } = useColorMode()
|
||||
return (
|
||||
<ClientOnly fallback={<Skeleton boxSize="8" />}>
|
||||
<IconButton
|
||||
onClick={toggleColorMode}
|
||||
variant="ghost"
|
||||
aria-label="Toggle color mode"
|
||||
size="sm"
|
||||
ref={ref}
|
||||
{...props}
|
||||
css={{
|
||||
_icon: {
|
||||
width: "5",
|
||||
height: "5",
|
||||
},
|
||||
}}
|
||||
>
|
||||
<ColorModeIcon />
|
||||
</IconButton>
|
||||
</ClientOnly>
|
||||
)
|
||||
})
|
||||
|
33
front/src/components/ui/field.tsx
Normal file
33
front/src/components/ui/field.tsx
Normal file
@ -0,0 +1,33 @@
|
||||
import { Field as ChakraField } from "@chakra-ui/react"
|
||||
import * as React from "react"
|
||||
|
||||
export interface FieldProps extends Omit<ChakraField.RootProps, "label"> {
|
||||
label?: React.ReactNode
|
||||
helperText?: React.ReactNode
|
||||
errorText?: React.ReactNode
|
||||
optionalText?: React.ReactNode
|
||||
}
|
||||
|
||||
export const Field = React.forwardRef<HTMLDivElement, FieldProps>(
|
||||
function Field(props, ref) {
|
||||
const { label, children, helperText, errorText, optionalText, ...rest } =
|
||||
props
|
||||
return (
|
||||
<ChakraField.Root ref={ref} {...rest}>
|
||||
{label && (
|
||||
<ChakraField.Label>
|
||||
{label}
|
||||
<ChakraField.RequiredIndicator fallback={optionalText} />
|
||||
</ChakraField.Label>
|
||||
)}
|
||||
{children}
|
||||
{helperText && (
|
||||
<ChakraField.HelperText>{helperText}</ChakraField.HelperText>
|
||||
)}
|
||||
{errorText && (
|
||||
<ChakraField.ErrorText>{errorText}</ChakraField.ErrorText>
|
||||
)}
|
||||
</ChakraField.Root>
|
||||
)
|
||||
},
|
||||
)
|
53
front/src/components/ui/input-group.tsx
Normal file
53
front/src/components/ui/input-group.tsx
Normal file
@ -0,0 +1,53 @@
|
||||
import type { BoxProps, InputElementProps } from "@chakra-ui/react"
|
||||
import { Group, InputElement } from "@chakra-ui/react"
|
||||
import * as React from "react"
|
||||
|
||||
export interface InputGroupProps extends BoxProps {
|
||||
startElementProps?: InputElementProps
|
||||
endElementProps?: InputElementProps
|
||||
startElement?: React.ReactNode
|
||||
endElement?: React.ReactNode
|
||||
children: React.ReactElement<InputElementProps>
|
||||
startOffset?: InputElementProps["paddingStart"]
|
||||
endOffset?: InputElementProps["paddingEnd"]
|
||||
}
|
||||
|
||||
export const InputGroup = React.forwardRef<HTMLDivElement, InputGroupProps>(
|
||||
function InputGroup(props, ref) {
|
||||
const {
|
||||
startElement,
|
||||
startElementProps,
|
||||
endElement,
|
||||
endElementProps,
|
||||
children,
|
||||
startOffset = "6px",
|
||||
endOffset = "6px",
|
||||
...rest
|
||||
} = props
|
||||
|
||||
const child =
|
||||
React.Children.only<React.ReactElement<InputElementProps>>(children)
|
||||
|
||||
return (
|
||||
<Group ref={ref} {...rest}>
|
||||
{startElement && (
|
||||
<InputElement pointerEvents="none" {...startElementProps}>
|
||||
{startElement}
|
||||
</InputElement>
|
||||
)}
|
||||
{React.cloneElement(child, {
|
||||
...(startElement && {
|
||||
ps: `calc(var(--input-height) - ${startOffset})`,
|
||||
}),
|
||||
...(endElement && { pe: `calc(var(--input-height) - ${endOffset})` }),
|
||||
...children.props,
|
||||
})}
|
||||
{endElement && (
|
||||
<InputElement placement="end" {...endElementProps}>
|
||||
{endElement}
|
||||
</InputElement>
|
||||
)}
|
||||
</Group>
|
||||
)
|
||||
},
|
||||
)
|
59
front/src/components/ui/popover.tsx
Normal file
59
front/src/components/ui/popover.tsx
Normal file
@ -0,0 +1,59 @@
|
||||
import { Popover as ChakraPopover, Portal } from "@chakra-ui/react"
|
||||
import { CloseButton } from "./close-button"
|
||||
import * as React from "react"
|
||||
|
||||
interface PopoverContentProps extends ChakraPopover.ContentProps {
|
||||
portalled?: boolean
|
||||
portalRef?: React.RefObject<HTMLElement>
|
||||
}
|
||||
|
||||
export const PopoverContent = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
PopoverContentProps
|
||||
>(function PopoverContent(props, ref) {
|
||||
const { portalled = true, portalRef, ...rest } = props
|
||||
return (
|
||||
<Portal disabled={!portalled} container={portalRef}>
|
||||
<ChakraPopover.Positioner>
|
||||
<ChakraPopover.Content ref={ref} {...rest} />
|
||||
</ChakraPopover.Positioner>
|
||||
</Portal>
|
||||
)
|
||||
})
|
||||
|
||||
export const PopoverArrow = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
ChakraPopover.ArrowProps
|
||||
>(function PopoverArrow(props, ref) {
|
||||
return (
|
||||
<ChakraPopover.Arrow {...props} ref={ref}>
|
||||
<ChakraPopover.ArrowTip />
|
||||
</ChakraPopover.Arrow>
|
||||
)
|
||||
})
|
||||
|
||||
export const PopoverCloseTrigger = React.forwardRef<
|
||||
HTMLButtonElement,
|
||||
ChakraPopover.CloseTriggerProps
|
||||
>(function PopoverCloseTrigger(props, ref) {
|
||||
return (
|
||||
<ChakraPopover.CloseTrigger
|
||||
position="absolute"
|
||||
top="1"
|
||||
insetEnd="1"
|
||||
{...props}
|
||||
asChild
|
||||
ref={ref}
|
||||
>
|
||||
<CloseButton size="sm" />
|
||||
</ChakraPopover.CloseTrigger>
|
||||
)
|
||||
})
|
||||
|
||||
export const PopoverTitle = ChakraPopover.Title
|
||||
export const PopoverDescription = ChakraPopover.Description
|
||||
export const PopoverFooter = ChakraPopover.Footer
|
||||
export const PopoverHeader = ChakraPopover.Header
|
||||
export const PopoverRoot = ChakraPopover.Root
|
||||
export const PopoverBody = ChakraPopover.Body
|
||||
export const PopoverTrigger = ChakraPopover.Trigger
|
15
front/src/components/ui/provider.tsx
Normal file
15
front/src/components/ui/provider.tsx
Normal file
@ -0,0 +1,15 @@
|
||||
"use client"
|
||||
|
||||
import { ChakraProvider, defaultSystem } from "@chakra-ui/react"
|
||||
import {
|
||||
ColorModeProvider,
|
||||
type ColorModeProviderProps,
|
||||
} from "./color-mode"
|
||||
|
||||
export function Provider(props: ColorModeProviderProps) {
|
||||
return (
|
||||
<ChakraProvider value={defaultSystem}>
|
||||
<ColorModeProvider {...props} />
|
||||
</ChakraProvider>
|
||||
)
|
||||
}
|
24
front/src/components/ui/radio.tsx
Normal file
24
front/src/components/ui/radio.tsx
Normal file
@ -0,0 +1,24 @@
|
||||
import { RadioGroup as ChakraRadioGroup } from "@chakra-ui/react"
|
||||
import * as React from "react"
|
||||
|
||||
export interface RadioProps extends ChakraRadioGroup.ItemProps {
|
||||
rootRef?: React.Ref<HTMLDivElement>
|
||||
inputProps?: React.InputHTMLAttributes<HTMLInputElement>
|
||||
}
|
||||
|
||||
export const Radio = React.forwardRef<HTMLInputElement, RadioProps>(
|
||||
function Radio(props, ref) {
|
||||
const { children, inputProps, rootRef, ...rest } = props
|
||||
return (
|
||||
<ChakraRadioGroup.Item ref={rootRef} {...rest}>
|
||||
<ChakraRadioGroup.ItemHiddenInput ref={ref} {...inputProps} />
|
||||
<ChakraRadioGroup.ItemIndicator />
|
||||
{children && (
|
||||
<ChakraRadioGroup.ItemText>{children}</ChakraRadioGroup.ItemText>
|
||||
)}
|
||||
</ChakraRadioGroup.Item>
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
export const RadioGroup = ChakraRadioGroup.Root
|
82
front/src/components/ui/slider.tsx
Normal file
82
front/src/components/ui/slider.tsx
Normal file
@ -0,0 +1,82 @@
|
||||
import { Slider as ChakraSlider, For, HStack } from "@chakra-ui/react"
|
||||
import * as React from "react"
|
||||
|
||||
export interface SliderProps extends ChakraSlider.RootProps {
|
||||
marks?: Array<number | { value: number; label: React.ReactNode }>
|
||||
label?: React.ReactNode
|
||||
showValue?: boolean
|
||||
}
|
||||
|
||||
export const Slider = React.forwardRef<HTMLDivElement, SliderProps>(
|
||||
function Slider(props, ref) {
|
||||
const { marks: marksProp, label, showValue, ...rest } = props
|
||||
const value = props.defaultValue ?? props.value
|
||||
|
||||
const marks = marksProp?.map((mark) => {
|
||||
if (typeof mark === "number") return { value: mark, label: undefined }
|
||||
return mark
|
||||
})
|
||||
|
||||
const hasMarkLabel = !!marks?.some((mark) => mark.label)
|
||||
|
||||
return (
|
||||
<ChakraSlider.Root ref={ref} thumbAlignment="center" {...rest}>
|
||||
{label && !showValue && (
|
||||
<ChakraSlider.Label>{label}</ChakraSlider.Label>
|
||||
)}
|
||||
{label && showValue && (
|
||||
<HStack justify="space-between">
|
||||
<ChakraSlider.Label>{label}</ChakraSlider.Label>
|
||||
<ChakraSlider.ValueText />
|
||||
</HStack>
|
||||
)}
|
||||
<ChakraSlider.Control data-has-mark-label={hasMarkLabel || undefined}>
|
||||
<ChakraSlider.Track>
|
||||
<ChakraSlider.Range />
|
||||
</ChakraSlider.Track>
|
||||
<SliderThumbs value={value} />
|
||||
<SliderMarks marks={marks} />
|
||||
</ChakraSlider.Control>
|
||||
</ChakraSlider.Root>
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
function SliderThumbs(props: { value?: number[] }) {
|
||||
const { value } = props
|
||||
return (
|
||||
<For each={value}>
|
||||
{(_, index) => (
|
||||
<ChakraSlider.Thumb key={index} index={index}>
|
||||
<ChakraSlider.HiddenInput />
|
||||
</ChakraSlider.Thumb>
|
||||
)}
|
||||
</For>
|
||||
)
|
||||
}
|
||||
|
||||
interface SliderMarksProps {
|
||||
marks?: Array<number | { value: number; label: React.ReactNode }>
|
||||
}
|
||||
|
||||
const SliderMarks = React.forwardRef<HTMLDivElement, SliderMarksProps>(
|
||||
function SliderMarks(props, ref) {
|
||||
const { marks } = props
|
||||
if (!marks?.length) return null
|
||||
|
||||
return (
|
||||
<ChakraSlider.MarkerGroup ref={ref}>
|
||||
{marks.map((mark, index) => {
|
||||
const value = typeof mark === "number" ? mark : mark.value
|
||||
const label = typeof mark === "number" ? undefined : mark.label
|
||||
return (
|
||||
<ChakraSlider.Marker key={index} value={value}>
|
||||
<ChakraSlider.MarkerIndicator />
|
||||
{label}
|
||||
</ChakraSlider.Marker>
|
||||
)
|
||||
})}
|
||||
</ChakraSlider.MarkerGroup>
|
||||
)
|
||||
},
|
||||
)
|
46
front/src/components/ui/tooltip.tsx
Normal file
46
front/src/components/ui/tooltip.tsx
Normal file
@ -0,0 +1,46 @@
|
||||
import { Tooltip as ChakraTooltip, Portal } from "@chakra-ui/react"
|
||||
import * as React from "react"
|
||||
|
||||
export interface TooltipProps extends ChakraTooltip.RootProps {
|
||||
showArrow?: boolean
|
||||
portalled?: boolean
|
||||
portalRef?: React.RefObject<HTMLElement>
|
||||
content: React.ReactNode
|
||||
contentProps?: ChakraTooltip.ContentProps
|
||||
disabled?: boolean
|
||||
}
|
||||
|
||||
export const Tooltip = React.forwardRef<HTMLDivElement, TooltipProps>(
|
||||
function Tooltip(props, ref) {
|
||||
const {
|
||||
showArrow,
|
||||
children,
|
||||
disabled,
|
||||
portalled = true,
|
||||
content,
|
||||
contentProps,
|
||||
portalRef,
|
||||
...rest
|
||||
} = props
|
||||
|
||||
if (disabled) return children
|
||||
|
||||
return (
|
||||
<ChakraTooltip.Root {...rest}>
|
||||
<ChakraTooltip.Trigger asChild>{children}</ChakraTooltip.Trigger>
|
||||
<Portal disabled={!portalled} container={portalRef}>
|
||||
<ChakraTooltip.Positioner>
|
||||
<ChakraTooltip.Content ref={ref} {...contentProps}>
|
||||
{showArrow && (
|
||||
<ChakraTooltip.Arrow>
|
||||
<ChakraTooltip.ArrowTip />
|
||||
</ChakraTooltip.Arrow>
|
||||
)}
|
||||
{content}
|
||||
</ChakraTooltip.Content>
|
||||
</ChakraTooltip.Positioner>
|
||||
</Portal>
|
||||
</ChakraTooltip.Root>
|
||||
)
|
||||
},
|
||||
)
|
@ -7,6 +7,8 @@ import {
|
||||
Box,
|
||||
Collapsible,
|
||||
useDisclosure,
|
||||
Text,
|
||||
HStack,
|
||||
} from '@chakra-ui/react';
|
||||
import {
|
||||
FallbackProps,
|
||||
@ -30,7 +32,10 @@ const ErrorFallback = ({ error }: FallbackProps) => {
|
||||
//size="sm"
|
||||
onClick={onToggle}
|
||||
>
|
||||
Show details {open ? <LuChevronUp /> : <LuChevronDown />}
|
||||
<HStack>
|
||||
<Text>Show details</Text>{' '}
|
||||
{open ? <LuChevronUp /> : <LuChevronDown />}
|
||||
</HStack>
|
||||
</Button>
|
||||
<Collapsible.Root open={open}>
|
||||
<Collapsible.Content>
|
||||
|
@ -36,7 +36,7 @@ export const AlbumsPage = () => {
|
||||
<SearchInput onChange={setFilterTitle} />
|
||||
</TopBar>
|
||||
<PageLayout>
|
||||
<HStack wrap="wrap" /*spacing={BASE_WRAP_SPACING}*/ marginX="auto" padding="20px" justify="center">
|
||||
<HStack wrap="wrap" gap={BASE_WRAP_SPACING} marginX="auto" padding="20px" justify="center">
|
||||
{dataAlbums.map((data) => (
|
||||
<Flex align="flex-start"
|
||||
width={BASE_WRAP_WIDTH}
|
||||
|
@ -126,7 +126,6 @@ export const ArtistAlbumDetailPage = () => {
|
||||
backgroundColor={useColorModeValue('#FFFFFF88', '#00000088')}
|
||||
key={data.id}
|
||||
padding="5px"
|
||||
as="button"
|
||||
_hover={{
|
||||
boxShadow: 'outline-over',
|
||||
bgColor: useColorModeValue('#FFFFFFF7', '#000000F7'),
|
||||
|
@ -88,7 +88,7 @@ export const ArtistDetailPage = () => {
|
||||
</Flex>
|
||||
</Flex>
|
||||
|
||||
<HStack wrap="wrap" /*spacing={BASE_WRAP_SPACING}*/ marginX="auto" padding="20px" justify="center">
|
||||
<HStack wrap="wrap" gap={BASE_WRAP_SPACING} marginX="auto" padding="20px" justify="center">
|
||||
{albumIdsOfAnArtist?.map((data) => (
|
||||
<Flex align="flex-start"
|
||||
width={BASE_WRAP_WIDTH}
|
||||
|
@ -64,7 +64,7 @@ export const ArtistsPage = () => {
|
||||
</Tooltip.Root>
|
||||
</TopBar>
|
||||
<PageLayout>
|
||||
<HStack wrap="wrap" /*spacing={BASE_WRAP_SPACING}*/ marginX="auto" padding="20px" justify="center">
|
||||
<HStack wrap="wrap" gap={BASE_WRAP_SPACING} marginX="auto" padding="20px" justify="center">
|
||||
{dataArtist?.map((data) => (
|
||||
<Flex align="flex-start"
|
||||
width={BASE_WRAP_WIDTH}
|
||||
|
@ -35,7 +35,7 @@ export const GendersPage = () => {
|
||||
<SearchInput onChange={setFilterTitle} />
|
||||
</TopBar>
|
||||
<PageLayout>
|
||||
<HStack wrap="wrap" /*spacing="20px"*/ marginX="auto" padding="20px" justify="center">
|
||||
<HStack wrap="wrap" gap="20px" marginX="auto" padding="20px" justify="center">
|
||||
{dataGenders.map((data) => (
|
||||
<Flex align="flex-start"
|
||||
width="270px"
|
||||
|
@ -58,7 +58,7 @@ export const HomePage = () => {
|
||||
<>
|
||||
<TopBar title="Home" />
|
||||
<PageLayout>
|
||||
<HStack wrap="wrap" /*spacing="20px"*/ marginX="auto" padding="20px" justify="center">
|
||||
<HStack wrap="wrap" gap="20px" marginX="auto" padding="20px" justify="center">
|
||||
{homeList.map((data) => (
|
||||
<Flex align="flex-start"
|
||||
width="200px"
|
||||
|
10888
front/src/theme/config sample.ts
Normal file
10888
front/src/theme/config sample.ts
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,17 +1,21 @@
|
||||
|
||||
type PandaColorModel = {
|
||||
value: string;
|
||||
}
|
||||
type ThemeModel = {
|
||||
50: string;
|
||||
100: string;
|
||||
200: string;
|
||||
300: string;
|
||||
400: string;
|
||||
500: string;
|
||||
600: string;
|
||||
700: string;
|
||||
800: string;
|
||||
900: string;
|
||||
50: PandaColorModel;
|
||||
100: PandaColorModel;
|
||||
200: PandaColorModel;
|
||||
300: PandaColorModel;
|
||||
400: PandaColorModel;
|
||||
500: PandaColorModel;
|
||||
600: PandaColorModel;
|
||||
700: PandaColorModel;
|
||||
800: PandaColorModel;
|
||||
900: PandaColorModel;
|
||||
};
|
||||
|
||||
const back = {
|
||||
const back: ThemeModel = {
|
||||
50: { value: '#ebf4fa' },
|
||||
100: { value: '#d1dbe0' },
|
||||
200: { value: '#b6c2c9' },
|
||||
@ -24,7 +28,7 @@ const back = {
|
||||
900: { value: '#020f12' },
|
||||
};
|
||||
|
||||
const brand = {
|
||||
const brand: ThemeModel = {
|
||||
50: { value: '#e3edff' },
|
||||
100: { value: '#b6c9fd' },
|
||||
200: { value: '#88a5f7' },
|
||||
@ -36,7 +40,7 @@ const brand = {
|
||||
800: { value: '#02164a' },
|
||||
900: { value: '#00071e' },
|
||||
};
|
||||
const normalText = {
|
||||
const normalText: ThemeModel = {
|
||||
50: { value: '#f2f2f2' },
|
||||
100: { value: '#d9d9d9' },
|
||||
200: { value: '#bfbfbf' },
|
||||
@ -49,7 +53,7 @@ const normalText = {
|
||||
900: { value: '#0d0d0d' },
|
||||
};
|
||||
|
||||
const green = {
|
||||
const green: ThemeModel = {
|
||||
50: { value: '#f0fdf4' },
|
||||
100: { value: '#dcfce7' },
|
||||
200: { value: '#bbf7d0' },
|
||||
@ -61,7 +65,7 @@ const green = {
|
||||
800: { value: '#166534' },
|
||||
900: { value: '#14532d' },
|
||||
};
|
||||
const blue = {
|
||||
const blue: ThemeModel = {
|
||||
50: { value: '#eff6ff' },
|
||||
100: { value: '#dbeafe' },
|
||||
200: { value: '#bfdbfe' },
|
||||
@ -74,7 +78,7 @@ const blue = {
|
||||
900: { value: '#1e3a8a' },
|
||||
};
|
||||
|
||||
const orange = {
|
||||
const orange: ThemeModel = {
|
||||
50: { value: '#fff7ed' },
|
||||
100: { value: '#ffedd5' },
|
||||
200: { value: '#fed7aa' },
|
||||
@ -86,7 +90,7 @@ const orange = {
|
||||
800: { value: '#9a3412' },
|
||||
900: { value: '#7c2d12' },
|
||||
};
|
||||
const red = {
|
||||
const red: ThemeModel = {
|
||||
50: { value: '#fef2f2' },
|
||||
100: { value: '#fee2e2' },
|
||||
200: { value: '#fecaca' },
|
||||
|
@ -1,21 +1,23 @@
|
||||
import { SystemConfig } from '@chakra-ui/react';
|
||||
import { colors } from './colors';
|
||||
|
||||
const createOutline = (colorScheme = 'gray') =>
|
||||
`0 0 0 3px ${colorScheme}.500/3`;
|
||||
const createOutline = (colorScheme = 'gray') => {
|
||||
return { value: `0 0 0 3px ${colorScheme}.500/3` };
|
||||
}
|
||||
|
||||
export const shadows = {
|
||||
outline: createOutline('brand'),
|
||||
'outline-brand': '0 0 0 1px brand.900',
|
||||
'outline-gray': createOutline('gray'),
|
||||
'outline-over': `4px 4px 5px #00000088`,
|
||||
'outline-darkgray': `0 0 0 3px gray.500/8`,
|
||||
'outline-success': createOutline('success'),
|
||||
'outline-warning': createOutline('warning'),
|
||||
'outline-error': createOutline('error'),
|
||||
'outline-doing': createOutline('doing'),
|
||||
'outline-paused': createOutline('paused'),
|
||||
layout: '0 0 24px 1px rgba(0, 0, 0, 0.05)',
|
||||
smooth: 'inset 0px 0px 16px rgba(0, 0, 0, 0.05)',
|
||||
// 'outline-brand': '0 0 0 1px brand.900',
|
||||
// 'outline-gray': createOutline('gray'),
|
||||
// 'outline-over': `4px 4px 5px #00000088`,
|
||||
// 'outline-darkgray': `0 0 0 3px gray.500/8`,
|
||||
// 'outline-success': createOutline('success'),
|
||||
// 'outline-warning': createOutline('warning'),
|
||||
// 'outline-error': createOutline('error'),
|
||||
// 'outline-doing': createOutline('doing'),
|
||||
// 'outline-paused': createOutline('paused'),
|
||||
//layout: '0 0 24px 1px rgba(0, 0, 0, 0.05)',
|
||||
//smooth: 'inset 0px 0px 16px rgba(0, 0, 0, 0.05)',
|
||||
// smooth-light is used for dark backgrounds
|
||||
'smooth-light': 'inset 0px 0px 16px rgba(255, 255, 255, 0.1)',
|
||||
//'smooth-light': 'inset 0px 0px 16px rgba(255, 255, 255, 0.1)',
|
||||
};
|
||||
|
@ -33,8 +33,12 @@ export const customVariant = ({ bg, bgHover, bgActive, color, colorHover, boxSha
|
||||
};
|
||||
|
||||
const buttonRecipe = defineRecipe({
|
||||
base: {
|
||||
borderRadius: 0,
|
||||
background: "green",
|
||||
},
|
||||
variants: {
|
||||
theme: {
|
||||
variant: {
|
||||
"@primary":
|
||||
customVariant({
|
||||
bg: { _light: 'brand.600', _dark: 'brand.300' },
|
||||
@ -106,4 +110,8 @@ const buttonRecipe = defineRecipe({
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
console.log(`buttonRecipe: ${JSON.stringify(buttonRecipe, null, 2)}`);
|
||||
|
||||
|
||||
export default buttonRecipe;
|
||||
|
@ -1,5 +1,5 @@
|
||||
export { default as Badge } from './badge';
|
||||
export { default as Button } from './button';
|
||||
export { default as button } from './button';
|
||||
export { default as Checkbox } from './checkbox';
|
||||
export { default as Input } from './input';
|
||||
//export { default as NumberInput } from './numberInput.ts_';
|
||||
|
@ -19,7 +19,7 @@ const Color = ({ children, ...rest }: FlexProps) => (
|
||||
|
||||
const Colors = ({ colorScheme = 'gray', ...rest }) => (
|
||||
<HStack
|
||||
// spacing="0"
|
||||
gap="0"
|
||||
overflow="hidden"
|
||||
boxShadow="lg"
|
||||
color={`${colorScheme}.700`}
|
||||
|
@ -1,4 +0,0 @@
|
||||
import { Styles } from '@chakra-ui/theme-tools';
|
||||
|
||||
export const styles: Styles = {
|
||||
};
|
@ -1,6 +1,8 @@
|
||||
import * as recipes from './recipes';
|
||||
import { createSystem, defaultConfig, mergeConfigs, SystemConfig } from "@chakra-ui/react"
|
||||
import { colors } from "./foundations/colors"
|
||||
import { shadows } from './foundations/shadows';
|
||||
import buttonRecipe from './recipes/button';
|
||||
|
||||
const baseTheme: SystemConfig = {
|
||||
globalCss: {
|
||||
@ -17,28 +19,127 @@ const baseTheme: SystemConfig = {
|
||||
}
|
||||
},
|
||||
theme: {
|
||||
...recipes,
|
||||
//recipes: {...recipes},
|
||||
recipes: {
|
||||
button: buttonRecipe,
|
||||
buttonqsdqsd: {
|
||||
base: {
|
||||
"display": "inline-flex",
|
||||
"appearance": "none",
|
||||
"alignItems": "center",
|
||||
"justifyContent": "center",
|
||||
"userSelect": "none",
|
||||
"position": "relative",
|
||||
"borderRadius": "l2",
|
||||
"whiteSpace": "nowrap",
|
||||
"verticalAlign": "middle",
|
||||
"borderWidth": "1px",
|
||||
"borderColor": "transparent",
|
||||
"cursor": "button",
|
||||
"flexShrink": "0",
|
||||
"outline": "0",
|
||||
"lineHeight": "1.2",
|
||||
"isolation": "isolate",
|
||||
"fontWeight": "medium",
|
||||
"transitionProperty": "common",
|
||||
"transitionDuration": "moderate",
|
||||
"focusVisibleRing": "outside",
|
||||
"_disabled": {
|
||||
"layerStyle": "disabled"
|
||||
},
|
||||
"_icon": {
|
||||
"flexShrink": "0"
|
||||
}
|
||||
},
|
||||
"variants": {
|
||||
"variant": {
|
||||
"solid": {
|
||||
//"bg": "colorPalette.solid",
|
||||
"bg": "brand.500",
|
||||
"color": "colorPalette.contrast",
|
||||
"_hover": {
|
||||
"bg": "colorPalette.solid/90"
|
||||
},
|
||||
"_expanded": {
|
||||
"bg": "colorPalette.solid/90"
|
||||
}
|
||||
},
|
||||
"QSDQDS": {
|
||||
|
||||
},
|
||||
"@primary": {
|
||||
bg: {
|
||||
_light: "brand.600",
|
||||
_dark: "brand.300"
|
||||
},
|
||||
color: {
|
||||
_light: "white",
|
||||
_dark: "brand.900"
|
||||
},
|
||||
border: "1px solid transparent",
|
||||
_focus: {
|
||||
border: "1px solid",
|
||||
borderColor: "black"
|
||||
},
|
||||
"_hover": {
|
||||
"bg": {
|
||||
"_light": "brand.700",
|
||||
"_dark": "brand.400"
|
||||
},
|
||||
"color": {
|
||||
"_light": "brand.800",
|
||||
"_dark": "brand.100"
|
||||
},
|
||||
"boxShadow": "outline-over",
|
||||
"_disabled": {
|
||||
"bg": {
|
||||
"_light": "brand.600",
|
||||
"_dark": "brand.300"
|
||||
},
|
||||
"boxShadow": "none"
|
||||
}
|
||||
},
|
||||
"_active": {
|
||||
"bg": {
|
||||
"_light": "brand.600",
|
||||
"_dark": "brand.300"
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
"defaultVariants": {
|
||||
//"size": "md",
|
||||
//"variant": "solid"
|
||||
}
|
||||
},
|
||||
},
|
||||
tokens: {
|
||||
fonts: {
|
||||
heading: { value: `Roboto, Helvetica, Arial, "sans-serif"` },
|
||||
body: { value: `Roboto, Helvetica, Arial, "sans-serif"` },
|
||||
},
|
||||
colors,
|
||||
// spacing: {
|
||||
// vGutter: { value: '6.25rem' },
|
||||
// },
|
||||
shadows
|
||||
},
|
||||
semanticTokens: {
|
||||
colors: {
|
||||
brand: {
|
||||
solid: { value: "{colors.brand.500}" },
|
||||
contrast: { value: "{colors.brand.100}" },
|
||||
fg: { value: "{colors.brand.700}" },
|
||||
muted: { value: "{colors.brand.100}" },
|
||||
subtle: { value: "{colors.brand.200}" },
|
||||
emphasized: { value: "{colors.brand.300}" },
|
||||
focusRing: { value: "{colors.brand.500}" },
|
||||
},
|
||||
},
|
||||
},
|
||||
// semanticTokens: {
|
||||
// colors: {
|
||||
// brand: {
|
||||
// solid: { value: "{colors.brand.500}" },
|
||||
// contrast: { value: "{colors.brand.100}" },
|
||||
// fg: { value: "{colors.brand.700}" },
|
||||
// muted: { value: "{colors.brand.100}" },
|
||||
// subtle: { value: "{colors.brand.200}" },
|
||||
// emphasized: { value: "{colors.brand.300}" },
|
||||
// focusRing: { value: "{colors.brand.500}" },
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
},
|
||||
};
|
||||
const config = mergeConfigs(defaultConfig, baseTheme);
|
||||
//console.log("defaultConfig: " + JSON.stringify(defaultConfig, null, 2));
|
||||
export const systemTheme = createSystem(config);
|
Loading…
x
Reference in New Issue
Block a user