✨(front) implement new ui of EffectsConfiguration
This new ui implement the new sketches and also enables the usage of virtual background in a nice way.
BIN
src/frontend/public/assets/backgrounds/1.jpg
Normal file
|
After Width: | Height: | Size: 958 KiB |
BIN
src/frontend/public/assets/backgrounds/2.jpg
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
src/frontend/public/assets/backgrounds/3.jpg
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
src/frontend/public/assets/backgrounds/4.jpg
Normal file
|
After Width: | Height: | Size: 1.3 MiB |
BIN
src/frontend/public/assets/backgrounds/5.jpg
Normal file
|
After Width: | Height: | Size: 955 KiB |
BIN
src/frontend/public/assets/backgrounds/6.jpg
Normal file
|
After Width: | Height: | Size: 986 KiB |
BIN
src/frontend/public/assets/backgrounds/7.jpg
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
src/frontend/public/assets/backgrounds/8.jpg
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
src/frontend/public/assets/backgrounds/thumbnails/1.jpg
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
src/frontend/public/assets/backgrounds/thumbnails/2.jpg
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
src/frontend/public/assets/backgrounds/thumbnails/3.jpg
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
src/frontend/public/assets/backgrounds/thumbnails/4.jpg
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
src/frontend/public/assets/backgrounds/thumbnails/5.jpg
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
src/frontend/public/assets/backgrounds/thumbnails/6.jpg
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
src/frontend/public/assets/backgrounds/thumbnails/7.jpg
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
src/frontend/public/assets/backgrounds/thumbnails/8.jpg
Normal file
|
After Width: | Height: | Size: 22 KiB |
16
src/frontend/src/components/icons/BlurOn.tsx
Normal file
18
src/frontend/src/components/icons/BlurOnStrong.tsx
Normal file
@@ -2,12 +2,16 @@ import { LocalVideoTrack } from 'livekit-client'
|
|||||||
import { useEffect, useRef, useState } from 'react'
|
import { useEffect, useRef, useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import {
|
import {
|
||||||
BackgroundBlurFactory,
|
BackgroundProcessorFactory,
|
||||||
BackgroundBlurProcessorInterface,
|
BackgroundProcessorInterface,
|
||||||
|
ProcessorType,
|
||||||
} from '../blur'
|
} from '../blur'
|
||||||
import { css } from '@/styled-system/css'
|
import { css } from '@/styled-system/css'
|
||||||
import { Text, P, ToggleButton, H } from '@/primitives'
|
import { Text, P, ToggleButton, H } from '@/primitives'
|
||||||
import { HStack, styled } from '@/styled-system/jsx'
|
import { styled } from '@/styled-system/jsx'
|
||||||
|
import { BackgroundOptions } from '@livekit/track-processors'
|
||||||
|
import { BlurOn } from '@/components/icons/BlurOn'
|
||||||
|
import { BlurOnStrong } from '@/components/icons/BlurOnStrong'
|
||||||
|
|
||||||
enum BlurRadius {
|
enum BlurRadius {
|
||||||
NONE = 0,
|
NONE = 0,
|
||||||
@@ -15,21 +19,20 @@ enum BlurRadius {
|
|||||||
NORMAL = 10,
|
NORMAL = 10,
|
||||||
}
|
}
|
||||||
|
|
||||||
const isSupported = BackgroundBlurFactory.isSupported()
|
const isSupported = BackgroundProcessorFactory.isSupported()
|
||||||
|
|
||||||
const Information = styled('div', {
|
const Information = styled('div', {
|
||||||
base: {
|
base: {
|
||||||
backgroundColor: 'orange.50',
|
backgroundColor: 'orange.50',
|
||||||
borderRadius: '4px',
|
borderRadius: '4px',
|
||||||
padding: '0.75rem 0.75rem',
|
padding: '0.75rem 0.75rem',
|
||||||
marginTop: '0.8rem',
|
|
||||||
alignItems: 'start',
|
alignItems: 'start',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
export type EffectsConfigurationProps = {
|
export type EffectsConfigurationProps = {
|
||||||
videoTrack: LocalVideoTrack
|
videoTrack: LocalVideoTrack
|
||||||
onSubmit?: (processor?: BackgroundBlurProcessorInterface) => void
|
onSubmit?: (processor?: BackgroundProcessorInterface) => void
|
||||||
layout?: 'vertical' | 'horizontal'
|
layout?: 'vertical' | 'horizontal'
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,46 +58,56 @@ export const EffectsConfiguration = ({
|
|||||||
}
|
}
|
||||||
}, [videoTrack, videoTrack?.isMuted])
|
}, [videoTrack, videoTrack?.isMuted])
|
||||||
|
|
||||||
const toggleBlur = async (blurRadius: number) => {
|
const toggleEffect = async (
|
||||||
|
type: ProcessorType,
|
||||||
|
options: BackgroundOptions
|
||||||
|
) => {
|
||||||
if (!videoTrack) return
|
if (!videoTrack) return
|
||||||
setProcessorPending(true)
|
setProcessorPending(true)
|
||||||
const processor = getProcessor()
|
const processor = getProcessor()
|
||||||
const currentBlurRadius = getBlurRadius()
|
|
||||||
try {
|
try {
|
||||||
if (blurRadius == currentBlurRadius && processor) {
|
if (isSelected(type, options)) {
|
||||||
|
// Stop processor.
|
||||||
await videoTrack.stopProcessor()
|
await videoTrack.stopProcessor()
|
||||||
onSubmit?.(undefined)
|
onSubmit?.(undefined)
|
||||||
} else if (!processor) {
|
} else if (!processor || processor.serialize().type !== type) {
|
||||||
const newProcessor = BackgroundBlurFactory.getProcessor({ blurRadius })!
|
// Change processor.
|
||||||
|
const newProcessor = BackgroundProcessorFactory.getProcessor(
|
||||||
|
type,
|
||||||
|
options
|
||||||
|
)!
|
||||||
await videoTrack.setProcessor(newProcessor)
|
await videoTrack.setProcessor(newProcessor)
|
||||||
onSubmit?.(newProcessor)
|
onSubmit?.(newProcessor)
|
||||||
} else {
|
} else {
|
||||||
processor?.update({ blurRadius })
|
// Update processor.
|
||||||
|
processor?.update(options)
|
||||||
// We want to trigger onSubmit when options changes so the parent component is aware of it.
|
// We want to trigger onSubmit when options changes so the parent component is aware of it.
|
||||||
onSubmit?.(processor)
|
onSubmit?.(processor)
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error applying blur:', error)
|
console.error('Error applying blur:', error)
|
||||||
} finally {
|
} finally {
|
||||||
setProcessorPending(false)
|
// Without setTimeout the DOM is not refreshing when updating the options.
|
||||||
|
setTimeout(() => setProcessorPending(false))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const getProcessor = () => {
|
const getProcessor = () => {
|
||||||
return videoTrack?.getProcessor() as BackgroundBlurProcessorInterface
|
return videoTrack?.getProcessor() as BackgroundProcessorInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
const getBlurRadius = (): BlurRadius => {
|
const isSelected = (type: ProcessorType, options: BackgroundOptions) => {
|
||||||
const processor = getProcessor()
|
const processor = getProcessor()
|
||||||
return processor?.options.blurRadius || BlurRadius.NONE
|
const processorSerialized = processor?.serialize()
|
||||||
|
return (
|
||||||
|
!!processor &&
|
||||||
|
processorSerialized.type === type &&
|
||||||
|
JSON.stringify(processorSerialized.options) === JSON.stringify(options)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const isSelected = (blurRadius: BlurRadius) => {
|
const tooltipLabel = (type: ProcessorType, options: BackgroundOptions) => {
|
||||||
return getBlurRadius() == blurRadius
|
return t(`${type}.${isSelected(type, options) ? 'clear' : 'apply'}`)
|
||||||
}
|
|
||||||
|
|
||||||
const tooltipLabel = (blurRadius: BlurRadius) => {
|
|
||||||
return t(`blur.${isSelected(blurRadius) ? 'clear' : 'apply'}`)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -104,7 +117,7 @@ export const EffectsConfiguration = ({
|
|||||||
? {
|
? {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
gap: '0.5rem',
|
gap: '1.5rem',
|
||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
@@ -112,6 +125,7 @@ export const EffectsConfiguration = ({
|
|||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
md: {
|
md: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
|
overflow: 'hidden',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
@@ -164,49 +178,138 @@ export const EffectsConfiguration = ({
|
|||||||
md: {
|
md: {
|
||||||
borderLeft: '1px solid #dadce0',
|
borderLeft: '1px solid #dadce0',
|
||||||
paddingLeft: '1.5rem',
|
paddingLeft: '1.5rem',
|
||||||
|
width: '420px',
|
||||||
|
flexShrink: 0,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
: {}
|
: {}
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<H
|
|
||||||
lvl={3}
|
|
||||||
style={{
|
|
||||||
marginBottom: '0.4rem',
|
|
||||||
fontWeight: 'bold',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{t('heading')}
|
|
||||||
</H>
|
|
||||||
{isSupported ? (
|
{isSupported ? (
|
||||||
<HStack>
|
<>
|
||||||
<ToggleButton
|
<div>
|
||||||
size={'sm'}
|
<div>
|
||||||
aria-label={tooltipLabel(BlurRadius.LIGHT)}
|
<H
|
||||||
tooltip={tooltipLabel(BlurRadius.LIGHT)}
|
lvl={3}
|
||||||
isDisabled={processorPending}
|
style={{
|
||||||
onPress={async () => await toggleBlur(BlurRadius.LIGHT)}
|
marginBottom: '1rem',
|
||||||
isSelected={isSelected(BlurRadius.LIGHT)}
|
}}
|
||||||
>
|
variant="bodyXsBold"
|
||||||
{t('blur.light')}
|
>
|
||||||
</ToggleButton>
|
{t('blur.title')}
|
||||||
<ToggleButton
|
</H>
|
||||||
size={'sm'}
|
<div
|
||||||
aria-label={tooltipLabel(BlurRadius.NORMAL)}
|
className={css({
|
||||||
tooltip={tooltipLabel(BlurRadius.NORMAL)}
|
display: 'flex',
|
||||||
isDisabled={processorPending}
|
gap: '1.25rem',
|
||||||
onPress={async () => await toggleBlur(BlurRadius.NORMAL)}
|
})}
|
||||||
isSelected={isSelected(BlurRadius.NORMAL)}
|
>
|
||||||
>
|
<ToggleButton
|
||||||
{t('blur.normal')}
|
variant="bigSquare"
|
||||||
</ToggleButton>
|
aria-label={tooltipLabel(ProcessorType.BLUR, {
|
||||||
</HStack>
|
blurRadius: BlurRadius.LIGHT,
|
||||||
|
})}
|
||||||
|
tooltip={tooltipLabel(ProcessorType.BLUR, {
|
||||||
|
blurRadius: BlurRadius.LIGHT,
|
||||||
|
})}
|
||||||
|
isDisabled={processorPending}
|
||||||
|
onChange={async () =>
|
||||||
|
await toggleEffect(ProcessorType.BLUR, {
|
||||||
|
blurRadius: BlurRadius.LIGHT,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
isSelected={isSelected(ProcessorType.BLUR, {
|
||||||
|
blurRadius: BlurRadius.LIGHT,
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<BlurOn />
|
||||||
|
</ToggleButton>
|
||||||
|
<ToggleButton
|
||||||
|
variant="bigSquare"
|
||||||
|
aria-label={tooltipLabel(ProcessorType.BLUR, {
|
||||||
|
blurRadius: BlurRadius.NORMAL,
|
||||||
|
})}
|
||||||
|
tooltip={tooltipLabel(ProcessorType.BLUR, {
|
||||||
|
blurRadius: BlurRadius.NORMAL,
|
||||||
|
})}
|
||||||
|
isDisabled={processorPending}
|
||||||
|
onChange={async () =>
|
||||||
|
await toggleEffect(ProcessorType.BLUR, {
|
||||||
|
blurRadius: BlurRadius.NORMAL,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
isSelected={isSelected(ProcessorType.BLUR, {
|
||||||
|
blurRadius: BlurRadius.NORMAL,
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<BlurOnStrong />
|
||||||
|
</ToggleButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className={css({
|
||||||
|
marginTop: '1.5rem',
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<H
|
||||||
|
lvl={3}
|
||||||
|
style={{
|
||||||
|
marginBottom: '1rem',
|
||||||
|
}}
|
||||||
|
variant="bodyXsBold"
|
||||||
|
>
|
||||||
|
{t('virtual.title')}
|
||||||
|
</H>
|
||||||
|
<div
|
||||||
|
className={css({
|
||||||
|
display: 'flex',
|
||||||
|
gap: '1.25rem',
|
||||||
|
flexWrap: 'wrap',
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
{[...Array(8).keys()].map((i) => {
|
||||||
|
const imagePath = `/assets/backgrounds/${i + 1}.jpg`
|
||||||
|
const thumbnailPath = `/assets/backgrounds/thumbnails/${i + 1}.jpg`
|
||||||
|
return (
|
||||||
|
<ToggleButton
|
||||||
|
key={i}
|
||||||
|
variant="bigSquare"
|
||||||
|
aria-label={tooltipLabel(ProcessorType.VIRTUAL, {
|
||||||
|
imagePath,
|
||||||
|
})}
|
||||||
|
tooltip={tooltipLabel(ProcessorType.VIRTUAL, {
|
||||||
|
imagePath,
|
||||||
|
})}
|
||||||
|
isDisabled={processorPending}
|
||||||
|
onChange={async () =>
|
||||||
|
await toggleEffect(ProcessorType.VIRTUAL, {
|
||||||
|
imagePath,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
isSelected={isSelected(ProcessorType.VIRTUAL, {
|
||||||
|
imagePath,
|
||||||
|
})}
|
||||||
|
className={css({
|
||||||
|
bgSize: 'cover',
|
||||||
|
})}
|
||||||
|
style={{
|
||||||
|
backgroundImage: `url(${thumbnailPath})`,
|
||||||
|
}}
|
||||||
|
></ToggleButton>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Information className={css({ marginTop: '1rem' })}>
|
||||||
|
<Text variant="sm">⚠︎ {t('experimental')}</Text>
|
||||||
|
</Information>
|
||||||
|
</>
|
||||||
) : (
|
) : (
|
||||||
<Text variant="sm">{t('notAvailable')}</Text>
|
<Information>
|
||||||
|
<Text variant="sm">{t('notAvailable')}</Text>
|
||||||
|
</Information>
|
||||||
)}
|
)}
|
||||||
<Information>
|
|
||||||
<Text variant="sm">⚠︎ {t('experimental')}</Text>
|
|
||||||
</Information>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -19,6 +19,11 @@
|
|||||||
"label": ""
|
"label": ""
|
||||||
},
|
},
|
||||||
"heading": "",
|
"heading": "",
|
||||||
|
"effects": {
|
||||||
|
"description": "",
|
||||||
|
"title": "",
|
||||||
|
"subTitle": ""
|
||||||
|
},
|
||||||
"joinLabel": "",
|
"joinLabel": "",
|
||||||
"joinMeeting": "",
|
"joinMeeting": "",
|
||||||
"toggleOff": "",
|
"toggleOff": "",
|
||||||
@@ -102,11 +107,17 @@
|
|||||||
"notAvailable": "",
|
"notAvailable": "",
|
||||||
"heading": "",
|
"heading": "",
|
||||||
"blur": {
|
"blur": {
|
||||||
|
"title": "",
|
||||||
"light": "",
|
"light": "",
|
||||||
"normal": "",
|
"normal": "",
|
||||||
"apply": "",
|
"apply": "",
|
||||||
"clear": ""
|
"clear": ""
|
||||||
},
|
},
|
||||||
|
"virtual": {
|
||||||
|
"title": "",
|
||||||
|
"apply": "",
|
||||||
|
"clear": ""
|
||||||
|
},
|
||||||
"experimental": ""
|
"experimental": ""
|
||||||
},
|
},
|
||||||
"sidePanel": {
|
"sidePanel": {
|
||||||
|
|||||||
@@ -20,7 +20,8 @@
|
|||||||
},
|
},
|
||||||
"effects": {
|
"effects": {
|
||||||
"description": "Apply effects",
|
"description": "Apply effects",
|
||||||
"title": "Effects"
|
"title": "Effects",
|
||||||
|
"subTitle": "Configure your camera's effects."
|
||||||
},
|
},
|
||||||
"heading": "Join the meeting",
|
"heading": "Join the meeting",
|
||||||
"joinLabel": "Join",
|
"joinLabel": "Join",
|
||||||
@@ -102,14 +103,20 @@
|
|||||||
},
|
},
|
||||||
"effects": {
|
"effects": {
|
||||||
"activateCamera": "Your camera is disabled. Choose an option to enable it.",
|
"activateCamera": "Your camera is disabled. Choose an option to enable it.",
|
||||||
"notAvailable": "The blur effect will be available soon on your browser. We're working on it! In the meantime, you can use Google Chrome for best performance or Firefox :(",
|
"notAvailable": "Video effects will be available soon on your browser. We're working on it! In the meantime, you can use Google Chrome for best performance or Firefox :(",
|
||||||
"heading": "Blur",
|
"heading": "Blur",
|
||||||
"blur": {
|
"blur": {
|
||||||
|
"title": "Background blur",
|
||||||
"light": "Light blur",
|
"light": "Light blur",
|
||||||
"normal": "Blur",
|
"normal": "Blur",
|
||||||
"apply": "Enable blur",
|
"apply": "Enable blur",
|
||||||
"clear": "Disable blur"
|
"clear": "Disable blur"
|
||||||
},
|
},
|
||||||
|
"virtual": {
|
||||||
|
"title": "Virtual background",
|
||||||
|
"apply": "Enable virtual background",
|
||||||
|
"clear": "Disable virtual background"
|
||||||
|
},
|
||||||
"experimental": "Experimental feature. A v2 is coming for full browser support and improved quality."
|
"experimental": "Experimental feature. A v2 is coming for full browser support and improved quality."
|
||||||
},
|
},
|
||||||
"sidePanel": {
|
"sidePanel": {
|
||||||
|
|||||||
@@ -21,7 +21,8 @@
|
|||||||
"heading": "Rejoindre la réunion",
|
"heading": "Rejoindre la réunion",
|
||||||
"effects": {
|
"effects": {
|
||||||
"description": "Appliquer des effets",
|
"description": "Appliquer des effets",
|
||||||
"title": "Effets"
|
"title": "Effets",
|
||||||
|
"subTitle": "Paramétrez les effets de votre caméra."
|
||||||
},
|
},
|
||||||
"joinLabel": "Rejoindre",
|
"joinLabel": "Rejoindre",
|
||||||
"joinMeeting": "Rejoindre la réjoindre",
|
"joinMeeting": "Rejoindre la réjoindre",
|
||||||
@@ -102,14 +103,20 @@
|
|||||||
},
|
},
|
||||||
"effects": {
|
"effects": {
|
||||||
"activateCamera": "Votre camera est désactivée. Choisissez une option pour l'activer.",
|
"activateCamera": "Votre camera est désactivée. Choisissez une option pour l'activer.",
|
||||||
"notAvailable": "L'effet de flou sera bientôt disponible sur votre navigateur. Nous y travaillons ! En attendant, vous pouvez utiliser Google Chrome pour une meilleure performance ou Firefox :(",
|
"notAvailable": "Les effets vidéo seront bientôt disponible sur votre navigateur. Nous y travaillons ! En attendant, vous pouvez utiliser Google Chrome pour une meilleure performance ou Firefox :(",
|
||||||
"heading": "Flou",
|
"heading": "Flou",
|
||||||
"blur": {
|
"blur": {
|
||||||
|
"title": "Flou d'arrière-plan",
|
||||||
"light": "Léger flou",
|
"light": "Léger flou",
|
||||||
"normal": "Flou",
|
"normal": "Flou",
|
||||||
"apply": "Appliquer le flou",
|
"apply": "Appliquer le flou",
|
||||||
"clear": "Désactiver le flou"
|
"clear": "Désactiver le flou"
|
||||||
},
|
},
|
||||||
|
"virtual": {
|
||||||
|
"title": "Arrière-plan virtuel",
|
||||||
|
"apply": "Appliquer l'arrière plan virtuel",
|
||||||
|
"clear": "Désactiver l'arrière plan virtuel"
|
||||||
|
},
|
||||||
"experimental": "Fonctionnalité expérimentale. Une v2 arrive pour un support complet sur tous les navigateurs et une meilleur qualité."
|
"experimental": "Fonctionnalité expérimentale. Une v2 arrive pour un support complet sur tous les navigateurs et une meilleur qualité."
|
||||||
},
|
},
|
||||||
"sidePanel": {
|
"sidePanel": {
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ export const ToggleButton = ({
|
|||||||
<TooltipWrapper tooltip={tooltip} tooltipType={tooltipType}>
|
<TooltipWrapper tooltip={tooltip} tooltipType={tooltipType}>
|
||||||
<RACToggleButton
|
<RACToggleButton
|
||||||
{...componentProps}
|
{...componentProps}
|
||||||
className={buttonRecipe(variantProps)}
|
className={[buttonRecipe(variantProps), props.className].join(' ')}
|
||||||
>
|
>
|
||||||
<>
|
<>
|
||||||
{componentProps.children as ReactNode}
|
{componentProps.children as ReactNode}
|
||||||
|
|||||||
@@ -86,6 +86,22 @@ export const buttonRecipe = cva({
|
|||||||
backgroundColor: 'greyscale.100/50',
|
backgroundColor: 'greyscale.100/50',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
bigSquare: {
|
||||||
|
width: '56px',
|
||||||
|
height: '56px',
|
||||||
|
borderColor: 'greyscale.200',
|
||||||
|
borderRadius: '4px',
|
||||||
|
backgroundColor: 'greyscale.50',
|
||||||
|
padding: '0',
|
||||||
|
flexShrink: 0,
|
||||||
|
'&[data-hovered]': {
|
||||||
|
backgroundColor: 'greyscale.100',
|
||||||
|
},
|
||||||
|
transition: 'box-shadow 0.2s ease-in-out',
|
||||||
|
'&[data-selected]': {
|
||||||
|
boxShadow: 'token(colors.primary.400) 0px 0px 0px 3px inset',
|
||||||
|
},
|
||||||
|
},
|
||||||
tertiary: {
|
tertiary: {
|
||||||
backgroundColor: 'primary.100',
|
backgroundColor: 'primary.100',
|
||||||
color: 'primary.800',
|
color: 'primary.800',
|
||||||
|
|||||||