💄(front) enhance ui first shot

Based on recent sketches, we decided to implement the new ui. This is
a first shot, more will be coming next.
This commit is contained in:
Nathan Vasse
2024-11-22 17:08:09 +01:00
parent c4206b4b24
commit 0958206057
35 changed files with 6460 additions and 275 deletions

Binary file not shown.

Binary file not shown.

View File

@@ -93,6 +93,66 @@ const config: Config = {
* This way we'll only add the things we need step by step and prevent using lots of differents things.
*/
...pandaPreset.theme.tokens,
colors: defineTokens.colors({
...pandaPreset.theme.tokens.colors,
primaryDark: {
50: { value: '#1B1B35' },
100: { value: '#2B2B5B' },
200: { value: '#3B3B81' },
300: { value: '#4A4AA8' },
400: { value: '#5A5ACE' },
500: { value: '#6A6AF4' },
600: { value: '#8585F6' },
700: { value: '#CACAFB' },
800: { value: '#E3E3FB' },
900: { value: '#ECECFE' },
950: { value: '#F5F5FE' },
action: { value: '#C1C1FB' },
},
primary: {
50: { value: '#F5F5FE' },
100: { value: '#ECECFE' },
200: { value: '#E3E3FB' },
300: { value: '#CACAFB' },
400: { value: '#8585F6' },
500: { value: '#6A6AF4' },
600: { value: '#313178' },
700: { value: '#272747' },
800: { value: '#000091' },
900: { value: '#21213F' },
950: { value: '#1B1B35' },
action: { value: '#1212FF' },
},
greyscale: {
'000': { value: '#FFFFFF' },
50: { value: '#F6F6F6' },
100: { value: '#EEEEEE' },
200: { value: '#E5E5E5' },
250: { value: '#DDDDDD' },
300: { value: '#CECECE' },
400: { value: '#929292' },
500: { value: '#7C7C7C' },
600: { value: '#666666' },
700: { value: '#3A3A3A' },
750: { value: '#353535' },
800: { value: '#2A2A2A' },
900: { value: '#242424' },
950: { value: '#1E1E1E' },
1000: { value: '#161616' },
},
error: {
100: {value: '#391C1C'},
200: {value: '#412121'},
300: {value: '#642626'},
400: {value: '#CE0500'},
500: {value: '#F60700'},
600: {value: '#FF5655'},
700: {value: '#FFBDBD'},
800: {value: '#FFDDDD'},
900: {value: '#FFE9E9'},
950: {value: '#FFF4F4'},
}
}),
animations: {},
blurs: {},
/* just directly use values as tokens. This allows us to follow a specific design scale,
@@ -194,7 +254,7 @@ const config: Config = {
semanticTokens: defineSemanticTokens({
colors: {
default: {
text: { value: '{colors.gray.900}' },
text: { value: '{colors.greyscale.1000}' },
bg: { value: 'white' },
subtle: { value: '{colors.gray.100}' },
'subtle-text': { value: '{colors.gray.600}' },

View File

@@ -30,7 +30,7 @@ function App() {
<Route component={NotFoundScreen} />
</Switch>
</Layout>
<ReactQueryDevtools initialIsOpen={false} />
<ReactQueryDevtools initialIsOpen={false} position="top-left" />
</I18nProvider>
</Suspense>
</QueryClientProvider>

View File

@@ -27,7 +27,7 @@ export const SoundTester = () => {
return (
<>
<Button
invisible
variant="secondaryText"
onPress={() => {
audioRef?.current?.play()
setIsPlaying(true)

View File

@@ -185,8 +185,8 @@ export const IntroSlider = () => {
<ButtonContainer>
<ButtonVerticalCenter>
<Button
variant="greyscale"
square
invisible
aria-label={t('previous.label')}
tooltip={t('previous.tooltip')}
onPress={() => setSlideIndex(slideIndex - 1)}
@@ -221,8 +221,8 @@ export const IntroSlider = () => {
<ButtonContainer>
<ButtonVerticalCenter>
<Button
variant="greyscale"
square
invisible
aria-label={t('next.label')}
tooltip={t('next.tooltip')}
onPress={() => setSlideIndex(slideIndex + 1)}

View File

@@ -207,8 +207,7 @@ export const Home = () => {
)}
<DialogTrigger>
<Button
variant="primary"
outline
variant="secondary"
style={{
height: !isLoggedIn ? '56px' : undefined, // Temporary, Align with ProConnect Button fixed height
}}

View File

@@ -15,6 +15,7 @@ import { InviteDialog } from './InviteDialog'
import { VideoConference } from '../livekit/prefabs/VideoConference'
import posthog from 'posthog-js'
import { css } from '@/styled-system/css'
export const Conference = ({
roomId,
@@ -107,6 +108,9 @@ export const Conference = ({
audio={userConfig.audioEnabled}
video={userConfig.videoEnabled}
connectOptions={connectOptions}
className={css({
backgroundColor: 'primaryDark.50 !important'
})}
>
<VideoConference />
{showInviteDialog && (

View File

@@ -7,9 +7,9 @@ import { Text, text } from '@/primitives/Text'
import {
RiCheckLine,
RiCloseLine,
RiFileCopyLine,
RiFileCopyLine, RiLink,
RiSpam2Fill,
} from '@remixicon/react'
} from '@remixicon/react';
import { useEffect, useState } from 'react'
// fixme - extract in a proper primitive this dialog without overlay
@@ -65,7 +65,7 @@ export const InviteDialog = ({
</Heading>
<Div position="absolute" top="5" right="5">
<Button
invisible
variant="greyscale"
size="xs"
onPress={() => {
dialogProps.onClose?.()
@@ -78,45 +78,24 @@ export const InviteDialog = ({
</Div>
<P>{t('shareDialog.description')}</P>
<Button
variant={isCopied ? 'success' : 'primary'}
size="sm"
variant={isCopied ? 'success' : 'tertiary'}
fullWidth
aria-label={t('shareDialog.copy')}
style={{
justifyContent: 'start',
}}
onPress={() => {
navigator.clipboard.writeText(roomUrl)
setIsCopied(true)
}}
onHoverChange={setIsHovered}
data-attr="share-dialog-copy"
>
{isCopied ? (
<>
<RiCheckLine size={18} style={{ marginRight: '8px' }} />
<RiCheckLine size={24} style={{ marginRight: '8px' }} />
{t('shareDialog.copied')}
</>
) : (
<>
<RiFileCopyLine
size={18}
style={{ marginRight: '8px', minWidth: '18px' }}
/>
{isHovered ? (
t('shareDialog.copy')
) : (
<div
style={{
textOverflow: 'ellipsis',
overflow: 'hidden',
userSelect: 'none',
textWrap: 'nowrap',
}}
>
{roomUrl.replace(/^https?:\/\//, '')}
</div>
)}
<RiFileCopyLine size={24} style={{ marginRight: '8px' }}/>
{t('shareDialog.copyButton')}
</>
)}
</Button>

View File

@@ -43,7 +43,7 @@ const ratingButtonRecipe = cva({
variants: {
selected: {
true: {
backgroundColor: '#1d4ed8',
backgroundColor: 'primary.800',
color: 'white',
},
false: {

View File

@@ -151,7 +151,6 @@ export const Effects = () => {
<HStack>
<ToggleButton
size={'sm'}
legacyStyle
aria-label={tooltipLabel(BlurRadius.LIGHT)}
tooltip={tooltipLabel(BlurRadius.LIGHT)}
isDisabled={processorPending}
@@ -162,7 +161,6 @@ export const Effects = () => {
</ToggleButton>
<ToggleButton
size={'sm'}
legacyStyle
aria-label={tooltipLabel(BlurRadius.NORMAL)}
tooltip={tooltipLabel(BlurRadius.NORMAL)}
isDisabled={processorPending}

View File

@@ -68,6 +68,7 @@ const StyledSidePanel = ({
>
<Button
invisible
variant="greyscale"
size="xs"
onPress={onClose}
aria-label={closeButtonTooltip}

View File

@@ -106,7 +106,7 @@ export const ChatInput = ({
/>
<Button
square
invisible
variant="secondaryText"
size="sm"
onPress={handleSubmit}
isDisabled={isDisabled}

View File

@@ -23,7 +23,7 @@ export const ChatToggle = () => {
>
<ToggleButton
square
legacyStyle
variant="primaryTextDark"
aria-label={t(tooltipLabel)}
tooltip={t(tooltipLabel)}
isSelected={isChatOpen}

View File

@@ -24,7 +24,7 @@ export const HandToggle = () => {
>
<ToggleButton
square
legacyStyle
variant="primaryDark"
aria-label={t(tooltipLabel)}
tooltip={t(tooltipLabel)}
isSelected={isHandRaised}

View File

@@ -16,7 +16,7 @@ export const OptionsButton = () => {
<Menu>
<Button
square
legacyStyle
variant="primaryDark"
aria-label={t('options.buttonLabel')}
tooltip={t('options.buttonLabel')}
>

View File

@@ -69,7 +69,7 @@ export const HandRaisedListItem = ({
</HStack>
<Button
square
invisible
variant="greyscale"
size="sm"
onPress={() => lowerHandParticipant(participant)}
tooltip={t('participants.lowerParticipantHand', { name })}

View File

@@ -63,7 +63,7 @@ const MicIndicator = ({ participant }: MicIndicatorProps) => {
<>
<Button
square
invisible
variant="greyscale"
size="sm"
tooltip={
isLocal(participant)

View File

@@ -29,7 +29,7 @@ export const ParticipantsToggle = () => {
>
<ToggleButton
square
legacyStyle
variant="primaryTextDark"
aria-label={t(tooltipLabel)}
tooltip={t(tooltipLabel)}
isSelected={isParticipantsOpen}

View File

@@ -26,7 +26,7 @@ export const ScreenShareToggle = (
<ToggleButton
isSelected={enabled}
square
legacyStyle
variant="primaryDark"
tooltip={t(tooltipLabel)}
onPress={(e) =>
buttonProps.onClick?.(

View File

@@ -4,7 +4,6 @@ import {
useTrackToggle,
UseTrackToggleProps,
} from '@livekit/components-react'
import { HStack } from '@/styled-system/jsx'
import { Button, Menu, MenuList } from '@/primitives'
import {
RemixiconComponentType,
@@ -19,6 +18,7 @@ import { Track } from 'livekit-client'
import { Shortcut } from '@/features/shortcuts/types'
import { ToggleDevice } from '@/features/rooms/livekit/components/controls/ToggleDevice.tsx'
import { css } from '@/styled-system/css';
export type ToggleSource = Exclude<
Track.Source,
@@ -86,7 +86,10 @@ export const SelectToggleDevice = <T extends ToggleSource>({
const selectLabel = t('choose', { keyPrefix: `join.${config.kind}` })
return (
<HStack gap={0}>
<div className={css({
display: 'flex',
gap: '1px'
})}>
<ToggleDevice {...trackProps} config={config} />
<Menu>
<Button
@@ -94,6 +97,7 @@ export const SelectToggleDevice = <T extends ToggleSource>({
aria-label={selectLabel}
groupPosition="right"
square
variant={trackProps.enabled ? "primaryDark" : "error2"}
>
<RiArrowDownSLine />
</Button>
@@ -109,6 +113,6 @@ export const SelectToggleDevice = <T extends ToggleSource>({
}}
/>
</Menu>
</HStack>
</div>
)
}

View File

@@ -57,9 +57,9 @@ export const ToggleDevice = ({
return (
<ToggleButton
isSelected={enabled}
variant={enabled ? undefined : 'danger'}
toggledStyles={false}
isSelected={!enabled}
variant={enabled ? 'primaryDark' : 'error2'}
shySelected
onPress={() => toggle()}
aria-label={toggleLabel}
tooltip={toggleLabel}

View File

@@ -103,54 +103,75 @@ export function ControlBar({
return (
<div
className={css({
display: 'flex',
gap: '.5rem',
alignItems: 'center',
justifyContent: 'center',
justifyContent: 'space-between',
padding: '.75rem',
borderTop: '1px solid var(--lk-border-color)',
maxHeight: 'var(--lk-control-bar-height)',
height: '80px',
position: 'absolute',
backgroundColor: '#d1d5db',
bottom: 0,
left: 0,
right: 0,
base: {
display: 'flex'
}
})}
>
<SelectToggleDevice
source={Track.Source.Microphone}
onChange={microphoneOnChange}
onDeviceError={(error) =>
onDeviceError?.({ source: Track.Source.Microphone, error })
}
onActiveDeviceChange={(deviceId) =>
saveAudioInputDeviceId(deviceId ?? '')
}
/>
<SelectToggleDevice
source={Track.Source.Camera}
onChange={cameraOnChange}
onDeviceError={(error) =>
onDeviceError?.({ source: Track.Source.Camera, error })
}
onActiveDeviceChange={(deviceId) =>
saveVideoInputDeviceId(deviceId ?? '')
}
/>
{browserSupportsScreenSharing && (
<ScreenShareToggle
<div className={css({
display: 'flex',
gap: '.5rem',
alignItems: 'center',
lg: {
position: 'absolute',
left: '50%',
transform: 'translateX(-50%)',
},
})}>
<SelectToggleDevice
source={Track.Source.Microphone}
onChange={microphoneOnChange}
onDeviceError={(error) =>
onDeviceError?.({ source: Track.Source.ScreenShare, error })
onDeviceError?.({ source: Track.Source.Microphone, error })
}
onActiveDeviceChange={(deviceId) =>
saveAudioInputDeviceId(deviceId ?? '')
}
/>
)}
<HandToggle />
<ChatToggle />
<ParticipantsToggle />
<OptionsButton />
<LeaveButton />
<StartMediaButton />
<SelectToggleDevice
source={Track.Source.Camera}
onChange={cameraOnChange}
onDeviceError={(error) =>
onDeviceError?.({ source: Track.Source.Camera, error })
}
onActiveDeviceChange={(deviceId) =>
saveVideoInputDeviceId(deviceId ?? '')
}
/>
{browserSupportsScreenSharing && (
<ScreenShareToggle
onDeviceError={(error) =>
onDeviceError?.({ source: Track.Source.ScreenShare, error })
}
/>
)}
<HandToggle />
<OptionsButton />
<LeaveButton />
<StartMediaButton />
</div>
<div className={css({
display: 'flex',
gap: '.5rem',
alignItems: 'center',
marginRight: '6.25rem',
lg: {
position: 'absolute',
right: 0
}
})}>
<ChatToggle />
<ParticipantsToggle />
</div>
</div>
)
}

View File

@@ -29,8 +29,7 @@ export const FeedbackRoute = () => {
<Heading>{t('feedback.heading')}</Heading>
<HStack>
<Button
outline
variant="primary"
variant="secondary"
onPress={() => window.history.back()}
>
{t('feedback.back')}

View File

@@ -10,7 +10,7 @@ export const SettingsButton = () => {
<DialogTrigger>
<Button
square
invisible
variant="greyscale"
aria-label={t('settingsButtonLabel')}
tooltip={t('settingsButtonLabel')}
>

View File

@@ -68,7 +68,7 @@ export const AccountTab = ({ id, onOpenChange }: AccountTabProps) => {
marginLeft: 'auto',
})}
>
<Button onPress={handleOnCancel}>
<Button variant="secondary" onPress={handleOnCancel}>
{t('cancel', { ns: 'global' })}
</Button>
<Button variant={'primary'} onPress={handleOnSubmit}>

View File

@@ -29,6 +29,7 @@
"leaveRoomPrompt": "This will make you leave the meeting.",
"shareDialog": {
"copy": "Copy the meeting link",
"copyButton": "Copy link",
"copied": "Link copied to clipboard",
"heading": "Your meeting is ready",
"description": "Share this link with people you want to invite to the meeting.",

View File

@@ -29,6 +29,7 @@
"leaveRoomPrompt": "Revenir à l'accueil vous fera quitter la réunion.",
"shareDialog": {
"copy": "Copier le lien de la réunion",
"copyButton": "Copier le lien",
"copied": "Lien copié dans le presse-papiers",
"heading": "Votre réunion est prête",
"description": "Partagez ce lien avec les personnes que vous souhaitez inviter à la réunion.",

View File

@@ -112,6 +112,7 @@ export const Dialog = ({
{!isAlert && (
<Div position="absolute" top="5" right="5">
<Button
variant="greyscale"
invisible
size="xs"
onPress={() => close()}

View File

@@ -51,7 +51,7 @@ export const Form = ({
{submitLabel}
</Button>
{!!onCancel && (
<Button variant="primary" outline onPress={() => onCancel()}>
<Button variant="secondary" onPress={() => onCancel()}>
{t('cancel')}
</Button>
)}

View File

@@ -66,12 +66,8 @@ const StyledTab = styled(RACTab, {
color: 'box.text',
},
'&[data-selected]': {
backgroundColor: 'primary',
backgroundColor: 'primaryDark.50',
color: 'white',
'&[data-hovered]': {
backgroundColor: 'primary',
color: 'white',
},
},
},
},

View File

@@ -43,7 +43,7 @@ const StyledTooltip = styled(RACTooltip, {
base: {
boxShadow: '0 8px 20px rgba(0 0 0 / 0.1)',
borderRadius: '4px',
backgroundColor: 'gray.800',
backgroundColor: 'primaryDark.100',
color: 'gray.100',
forcedColorAdjust: 'none',
outline: 'none',

View File

@@ -1,184 +1,246 @@
import { type RecipeVariantProps, cva } from '@/styled-system/css'
import { type RecipeVariantProps, cva } from '@/styled-system/css';
export type ButtonRecipe = typeof buttonRecipe
export type ButtonRecipeProps = RecipeVariantProps<ButtonRecipe>
export const buttonRecipe = cva({
base: {
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
transition: 'background 200ms, outline 200ms, border-color 200ms',
cursor: 'pointer',
border: '1px solid transparent',
color: 'colorPalette.text',
backgroundColor: 'colorPalette',
'&[data-hovered]': {
backgroundColor: 'colorPalette.hover',
base: {
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
transition: 'background 200ms, outline 200ms, border-color 200ms',
cursor: 'pointer',
border: '1px solid transparent',
},
'&[data-pressed]': {
backgroundColor: 'colorPalette.active',
variants: {
size: {
default: {
borderRadius: 4,
paddingX: '1',
paddingY: '0.625',
'--square-padding': '{spacing.0.625}',
},
sm: {
borderRadius: 4,
paddingX: '0.5',
paddingY: '0.25',
'--square-padding': '{spacing.0.25}',
},
xs: {
borderRadius: 4,
'--square-padding': '0',
},
},
square: {
true: {
paddingX: 'var(--square-padding)',
paddingY: 'var(--square-padding)',
},
},
variant: {
primary: {
backgroundColor: 'primary.800',
color: 'white',
'&[data-hovered]': {
backgroundColor: 'primary.action',
},
'&[data-pressed]': {
backgroundColor: 'primary.action',
},
'&[data-disabled]': {
backgroundColor: 'greyscale.100',
color: 'greyscale.400',
},
},
secondary: {
backgroundColor: 'white',
color: 'primary.800',
borderColor: 'primary.800',
'&[data-hovered]': {
backgroundColor: 'greyscale.100',
},
'&[data-pressed]': {
backgroundColor: 'greyscale.100',
},
},
secondaryText: {
backgroundColor: 'transparent',
color: 'primary.800',
'&[data-hovered]': {
backgroundColor: 'greyscale.100',
},
'&[data-pressed]': {
backgroundColor: 'greyscale.100',
},
'&[data-disabled]': {
color: 'greyscale.400',
},
},
tertiary: {
backgroundColor: 'primary.100',
color: 'primary.800',
'&[data-hovered]': {
backgroundColor: 'primary.300',
},
'&[data-pressed]': {
backgroundColor: 'primary.300',
},
},
primaryDark: {
backgroundColor: 'primaryDark.100',
color: 'white',
'&[data-pressed]': {
backgroundColor: 'primaryDark.900',
color: 'primaryDark.100'
},
'&[data-hovered]': {
backgroundColor: 'primaryDark.300',
color: 'white',
},
'&[data-selected]': {
backgroundColor: 'primaryDark.900 !important',
color: 'primaryDark.100 !important'
},
},
primaryTextDark: {
backgroundColor: 'transparent',
color: 'primaryDark.800',
'&[data-hovered]': {
backgroundColor: 'primaryDark.100',
},
'&[data-pressed]': {
backgroundColor: 'primaryDark.700',
color: 'primaryDark.100'
},
'&[data-selected]': {
backgroundColor: 'primaryDark.700',
color: 'primaryDark.100'
},
},
greyscale: {
backgroundColor: 'transparent',
color: 'greyscale.400',
'&[data-hovered]': {
color: 'greyscale.800',
},
'&[data-pressed]': {
color: 'greyscale.800',
},
'&[data-selected]': {
color: 'greyscale.800',
},
'&[data-disabled]': {
color: 'greyscale.200',
},
},
danger: {
backgroundColor: 'error.400',
color: 'white',
'&[data-hovered]': {
backgroundColor: 'error.600',
},
'&[data-pressed]': {
backgroundColor: 'error.700',
color: 'error.200',
},
},
error2: {
backgroundColor: 'error.200',
color: 'error.900',
'&[data-hovered]': {
backgroundColor: 'error.300',
},
'&[data-focused]': {
backgroundColor: 'error.200',
},
'&[data-pressed]': {
backgroundColor: 'error.900',
color: 'error.100',
},
'&[data-selected]': {
backgroundColor: 'error.900 !important',
color: 'error.100 !important',
},
'&[data-disabled]': {
backgroundColor: 'error.200',
color: 'error.300',
},
},
// @TODO: better handling of colors… this is a mess
success: {
colorPalette: 'success',
color: 'success.subtle-text',
backgroundColor: 'success.subtle',
'&[data-hovered]': {
backgroundColor: 'success.200',
},
'&[data-pressed]': {
backgroundColor: 'success.subtle!',
},
},
text: {
color: 'primary',
'&[data-hovered]': {
background: 'gray.100 !important',
color: 'primary !important',
},
},
},
invisible: {
true: {
borderColor: 'none!',
backgroundColor: 'none!',
'&[data-hovered]': {
backgroundColor: 'none!',
borderColor: 'colorPalette.active!',
},
'&[data-pressed]': {
borderColor: 'currentcolor',
},
'&[data-disabled]': {
color: 'gray.300',
},
},
},
fullWidth: {
true: {
width: 'full',
},
},
// some toggle buttons make more sense without a "pushed button" style when selected because their content changes to mark the state
shySelected: {},
// if the button is next to other ones to make a "button group", tell where the button is to handle radius
groupPosition: {
left: {
borderTopRightRadius: 0,
borderBottomRightRadius: 0,
},
right: {
borderTopLeftRadius: 0,
borderBottomLeftRadius: 0,
borderLeft: 0,
},
center: {
borderRadius: 0,
},
},
},
'&[data-selected]': {
backgroundColor: 'colorPalette.active',
compoundVariants: [
{
variant: 'primaryDark',
shySelected: true,
css: {
'&[data-selected]': {
backgroundColor: 'primaryDark.100',
color: 'white'
},
}
}
],
defaultVariants: {
size: 'default',
variant: 'primary',
},
'&[data-disabled]': {
cursor: 'auto',
},
},
variants: {
size: {
default: {
borderRadius: 8,
paddingX: '1',
paddingY: '0.625',
'--square-padding': '{spacing.0.625}',
},
sm: {
borderRadius: 4,
paddingX: '0.5',
paddingY: '0.25',
'--square-padding': '{spacing.0.25}',
},
xs: {
borderRadius: 4,
'--square-padding': '0',
},
},
square: {
true: {
paddingX: 'var(--square-padding)',
paddingY: 'var(--square-padding)',
},
},
variant: {
default: {
colorPalette: 'control',
borderColor: 'control.subtle',
},
primary: {
colorPalette: 'primary',
'&[data-disabled]': {
opacity: 0.3,
},
},
// @TODO: better handling of colors… this is a mess
success: {
colorPalette: 'success',
borderColor: 'success.300',
color: 'success.subtle-text',
backgroundColor: 'success.subtle',
'&[data-hovered]': {
backgroundColor: 'success.200',
},
'&[data-pressed]': {
backgroundColor: 'success.subtle!',
},
},
text: {
color: 'primary',
'&[data-hovered]': {
background: 'gray.100 !important',
color: 'primary !important',
},
},
danger: {
colorPalette: 'danger',
borderColor: 'danger.600',
color: 'danger.subtle-text',
backgroundColor: 'danger.subtle',
'&[data-hovered]': {
backgroundColor: 'danger.200',
},
'&[data-pressed]': {
backgroundColor: 'danger.subtle!',
},
},
},
outline: {
true: {
color: 'colorPalette',
backgroundColor: 'transparent!',
borderColor: 'currentcolor!',
'&[data-hovered]': {
backgroundColor: 'colorPalette.subtle!',
},
'&[data-pressed]': {
backgroundColor: 'colorPalette.subtle!',
},
},
},
invisible: {
true: {
borderColor: 'none!',
backgroundColor: 'none!',
'&[data-hovered]': {
backgroundColor: 'none!',
borderColor: 'colorPalette.active!',
},
'&[data-pressed]': {
borderColor: 'currentcolor',
},
'&[data-disabled]': {
color: 'gray.300',
},
},
},
fullWidth: {
true: {
width: 'full',
},
},
// if the button is next to other ones to make a "button group", tell where the button is to handle radius
groupPosition: {
left: {
borderTopRightRadius: 0,
borderBottomRightRadius: 0,
},
right: {
borderTopLeftRadius: 0,
borderBottomLeftRadius: 0,
borderLeft: 0,
},
center: {
borderRadius: 0,
},
},
// some toggle buttons make more sense without a "pushed button" style when selected because their content changes to mark the state
toggledStyles: {
false: {
'&[data-selected]': {
backgroundColor: 'colorPalette',
},
},
},
legacyStyle: {
true: {
borderColor: 'gray.400',
transition: 'border 200ms, background 200ms, color 200ms',
'&[data-hovered]': {
borderColor: 'gray.500',
},
'&[data-pressed]': {
borderColor: 'gray.500',
},
'&[data-selected]': {
backgroundColor: '#1d4ed8',
color: 'white',
borderColor: 'gray.500',
'&[data-hovered]': {
borderColor: '#6b7280',
backgroundColor: '#1e40af',
},
},
},
},
},
defaultVariants: {
size: 'default',
variant: 'default',
outline: false,
toggledStyles: true,
},
})
});

View File

@@ -27,12 +27,12 @@ export const menuItemRecipe = cva({
},
'&[data-focused]': {
color: 'primary.text',
backgroundColor: 'primary',
backgroundColor: 'primaryDark.50',
outline: 'none!',
},
'&[data-hovered]': {
color: 'primary.text',
backgroundColor: 'primary',
backgroundColor: 'primaryDark.50',
outline: 'none!',
},
},

6059
src/frontend/yarn.lock Normal file

File diff suppressed because it is too large Load Diff