diff --git a/docs/examples/spinner/variantGrayscale.tsx b/docs/examples/spinner/variantGrayscale.tsx new file mode 100644 index 0000000000..8f14058364 --- /dev/null +++ b/docs/examples/spinner/variantGrayscale.tsx @@ -0,0 +1,12 @@ +import { Box, Flex, Spinner, useReducedMotion } from 'gestalt'; + +export default function Example() { + const reduced = useReducedMotion(); + return ( + + + + + + ); +} diff --git a/docs/examples/spinner/variantWhite.tsx b/docs/examples/spinner/variantWhite.tsx new file mode 100644 index 0000000000..ca7fcf5950 --- /dev/null +++ b/docs/examples/spinner/variantWhite.tsx @@ -0,0 +1,12 @@ +import { Box, Flex, Spinner, useReducedMotion } from 'gestalt'; + +export default function Example() { + const reduced = useReducedMotion(); + return ( + + + + + + ); +} diff --git a/docs/pages/web/spinner.tsx b/docs/pages/web/spinner.tsx index 42cfb965f6..08c783816b 100644 --- a/docs/pages/web/spinner.tsx +++ b/docs/pages/web/spinner.tsx @@ -1,3 +1,4 @@ +import { useAppContext } from 'docs/docs-components/appContext'; import AccessibilitySection from '../../docs-components/AccessibilitySection'; import docGen, { DocGen } from '../../docs-components/docgen'; import GeneratedPropTable from '../../docs-components/GeneratedPropTable'; @@ -16,8 +17,13 @@ import doOverlay from '../../examples/spinner/doOverlay'; import doWait from '../../examples/spinner/doWait'; import localizationLabels from '../../examples/spinner/localizationLabels'; import main from '../../examples/spinner/main'; +import variantGrayscale from '../../examples/spinner/variantGrayscale'; +import variantWhite from '../../examples/spinner/variantWhite'; export default function DocsPage({ generatedDocGen }: { generatedDocGen: DocGen }) { + const { experiments } = useAppContext(); + const isVREnabled = experiments === 'Tokens'; + return ( @@ -163,6 +169,31 @@ export default function DocsPage({ generatedDocGen }: { generatedDocGen: DocGen sandpackExample={} /> + + {isVREnabled && ( + + + } + title="Grayscale" + /> + + } + title="White" + /> + + )} diff --git a/packages/gestalt/src/Spinner.tsx b/packages/gestalt/src/Spinner.tsx index 49ee1ca0f9..343e114dbf 100644 --- a/packages/gestalt/src/Spinner.tsx +++ b/packages/gestalt/src/Spinner.tsx @@ -9,6 +9,7 @@ import useInExperiment from './useInExperiment'; const SIZE_NAME_TO_PIXEL = { sm: 32, md: 40, + lg: 56, } as const; type Props = { @@ -17,21 +18,21 @@ type Props = { */ accessibilityLabel?: string; /** - * Color of the Spinner. + * Color of the Spinner. `grayscale` and `white` variants are available only in Visual Refresh experiment. */ - color?: 'default' | 'subtle'; + color?: 'default' | 'subtle' | 'grayscale' | 'white'; /** * Whether or not to render with a 300ms delay. The delay is for perceived performance, so you should rarely need to remove it. See the [delay variant](https://gestalt.pinterest.systems/web/spinner#Delay) for more details. */ delay?: boolean; /** - * Indicates if Spinner should be visible. Controlling the component with this prop ensures the outro animation is played. If outro aimation is not intended, prefer conditional rendering. + * Indicates if Spinner should be visible. Controlling the component with this prop ensures the outro animation is played. If outro animation is not intended, prefer conditional rendering. */ show: boolean; /** - * sm: 32px, md: 40px + * sm: 32px, md: 40px, lg: 56px. 'lg' is available only in Visual Refresh experiment and is the default value. */ - size?: 'sm' | 'md'; + size?: 'sm' | 'md' | 'lg'; }; /** @@ -56,7 +57,15 @@ export default function Spinner({ if (isInVRExperiment) { return ( - + ); } @@ -65,7 +74,8 @@ export default function Spinner({
diff --git a/packages/gestalt/src/Spinner/VRSpinner.tsx b/packages/gestalt/src/Spinner/VRSpinner.tsx index ddc91ab876..c7cad75b68 100644 --- a/packages/gestalt/src/Spinner/VRSpinner.tsx +++ b/packages/gestalt/src/Spinner/VRSpinner.tsx @@ -1,12 +1,12 @@ import { useEffect, useState } from 'react'; import classnames from 'classnames'; +import vrLightDesignTokens from 'gestalt-design-tokens/dist/json/vr-theme/variables-light.json'; import styles from './VRSpinner.css'; import Box from '../Box'; import { useDefaultLabelContext } from '../contexts/DefaultLabelProvider'; const SIZE_NAME_TO_PIXEL = { sm: 32, - md: 40, lg: 56, } as const; @@ -14,7 +14,8 @@ type SpinnerBodyProps = { accessibilityLabel: string; delay: boolean; show: boolean; - size: 'sm' | 'md' | 'lg'; + size: 'sm' | 'lg'; + color: 'default' | 'grayscale' | 'white'; onExitAnimationEnd: () => void; }; @@ -23,18 +24,33 @@ function SpinnerBody({ delay, show, size, + color, onExitAnimationEnd, }: SpinnerBodyProps) { + const colorWhite = color === 'white' && vrLightDesignTokens['sema-color-background-light']; + const colorGrayscale = color === 'grayscale' && vrLightDesignTokens['base-color-grayscale-350']; + const nonDefaultSpinnerColor = + colorWhite || colorGrayscale + ? ({ + '--comp-spinner-color-background-1': colorWhite || colorGrayscale, + '--comp-spinner-color-background-2': colorWhite || colorGrayscale, + '--comp-spinner-color-background-3': colorWhite || colorGrayscale, + } as React.CSSProperties) + : {}; + return (
@@ -67,14 +83,16 @@ type Props = { accessibilityLabel?: string; delay?: boolean; show: boolean; - size?: 'sm' | 'md' | 'lg'; + size?: 'sm' | 'lg'; + color?: 'default' | 'grayscale' | 'white'; }; export default function Spinner({ accessibilityLabel, delay = true, show: showProp, - size = 'md', + size = 'lg', + color = 'default', }: Props) { const [show, setShow] = useState(showProp); const { accessibilityLabel: accessibilityLabelDefault } = useDefaultLabelContext('Spinner'); @@ -92,6 +110,7 @@ export default function Spinner({ return (