@sanity/ui 5.0.0-alpha.1 → 5.0.0-alpha.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/README.md +1 -1
  2. package/dist/LazyRefractor-CQ22IeXB.js +19 -0
  3. package/dist/LazyRefractor-CQ22IeXB.js.map +1 -0
  4. package/dist/cli/install.js +2 -1
  5. package/dist/index.d.ts +662 -796
  6. package/dist/index.d.ts.map +1 -0
  7. package/dist/index.js +2081 -1758
  8. package/dist/index.js.map +1 -1
  9. package/dist/polyfills.d.ts +1 -0
  10. package/dist/polyfills.js +5 -0
  11. package/dist/polyfills.js.map +1 -0
  12. package/dist/styles.css +1 -1
  13. package/package.json +16 -9
  14. package/src/cli/install.ts +2 -1
  15. package/src/components/badge/Badge.tsx +53 -0
  16. package/src/components/badge/badge.css +6 -0
  17. package/src/components/badge/badge.props.ts +31 -0
  18. package/src/components/box/box.css +5 -0
  19. package/src/components/box/box.props.ts +7 -2
  20. package/src/components/button/button.props.ts +27 -9
  21. package/src/components/card/card.props.ts +6 -2
  22. package/src/components/checkbox/Checkbox.tsx +4 -3
  23. package/src/components/checkbox/checkbox.props.ts +11 -3
  24. package/src/components/code/code.props.ts +10 -3
  25. package/src/components/container/Container.tsx +5 -1
  26. package/src/components/container/container.css +4 -0
  27. package/src/components/container/container.props.ts +6 -2
  28. package/src/components/dialog/Dialog.tsx +139 -0
  29. package/src/components/dialog/dialog.css +49 -0
  30. package/src/components/dialog/dialog.props.ts +45 -0
  31. package/src/components/eyebrow/Eyebrow.tsx +1 -1
  32. package/src/components/eyebrow/eyebrow.props.ts +6 -2
  33. package/src/components/flex/flex.css +5 -0
  34. package/src/components/flex/flex.props.ts +6 -2
  35. package/src/components/grid/grid.css +5 -0
  36. package/src/components/grid/grid.props.ts +6 -2
  37. package/src/components/h-stack/HStack.tsx +8 -14
  38. package/src/components/h-stack/hStack.props.ts +5 -13
  39. package/src/components/heading/Heading.tsx +1 -1
  40. package/src/components/heading/heading.props.ts +8 -2
  41. package/src/components/icon/icon.props.ts +6 -2
  42. package/src/components/icon-button/iconButton.props.ts +7 -2
  43. package/src/components/index.css +4 -0
  44. package/src/components/indicator/indicator.props.ts +6 -2
  45. package/src/components/indicator-stack/indicatorStack.props.ts +3 -1
  46. package/src/components/inline/inline.props.ts +6 -2
  47. package/src/components/label/label.props.ts +7 -1
  48. package/src/components/link/link.props.ts +4 -4
  49. package/src/components/list/list.props.ts +27 -9
  50. package/src/components/popover/Popover.tsx +85 -0
  51. package/src/components/popover/popover.css +21 -0
  52. package/src/components/popover/popover.props.ts +38 -0
  53. package/src/components/press-area/pressArea.props.ts +3 -1
  54. package/src/components/radio/Radio.tsx +1 -1
  55. package/src/components/radio/radio.props.ts +7 -2
  56. package/src/components/select/Select.tsx +47 -0
  57. package/src/components/select/select.css +67 -0
  58. package/src/components/select/select.props.ts +25 -0
  59. package/src/components/skip-to-content/skipToContent.props.ts +9 -3
  60. package/src/components/spinner/Spinner.tsx +1 -1
  61. package/src/components/spinner/spinner.props.ts +3 -0
  62. package/src/components/switch/Switch.tsx +1 -1
  63. package/src/components/switch/switch.props.ts +7 -2
  64. package/src/components/text/Text.tsx +1 -1
  65. package/src/components/text/text.props.ts +6 -2
  66. package/src/components/tooltip/Tooltip.tsx +59 -55
  67. package/src/components/tooltip/tooltip.css +19 -40
  68. package/src/components/tooltip/tooltip.props.ts +24 -8
  69. package/src/components/tooltip-group/TooltipGroup.tsx +2 -5
  70. package/src/components/tooltip-group/tooltipGroup.props.ts +3 -1
  71. package/src/components/v-stack/VStack.tsx +8 -14
  72. package/src/components/v-stack/vStack.props.ts +5 -13
  73. package/src/components/visually-hidden/visuallyHidden.props.ts +6 -2
  74. package/src/css/classes/generic/display.css +8 -8
  75. package/src/css/classes/generic/placement.css +31 -0
  76. package/src/css/classes/local/animation.css +4 -0
  77. package/src/css/classes/local/index.css +2 -0
  78. package/src/css/classes/local/top-anchor.css +4 -0
  79. package/src/css/classes/system/shadow.css +6 -6
  80. package/src/css/global/reset.css +32 -19
  81. package/src/css/tokens/semantic.css +4 -0
  82. package/src/css/tokens/surface.css +2 -0
  83. package/src/hooks/useIsClient.ts +10 -0
  84. package/src/index.ts +8 -0
  85. package/src/polyfills.ts +17 -0
  86. package/src/props/formElement.ts +34 -0
  87. package/src/types/FormElement.ts +2 -0
  88. package/src/utils/getProps.ts +1 -1
  89. package/src/utils/mergeTriggerProps.ts +66 -0
  90. package/src/utils/renderPortal.tsx +14 -0
  91. package/src/version.ts +2 -2
  92. package/dist/_chunks-es/LazyRefractor.js +0 -20
  93. package/dist/_chunks-es/LazyRefractor.js.map +0 -1
@@ -1,4 +1,4 @@
1
- import {SpinnerIcon} from '@sanity/icons'
1
+ import {SpinnerIcon} from '@sanity/icons/Spinner'
2
2
  import clsx from 'clsx'
3
3
 
4
4
  import {getProps} from '../../utils/getProps'
@@ -4,6 +4,9 @@ import type {Responsive} from '../../types/Responsive'
4
4
 
5
5
  /** @public */
6
6
  export interface SpinnerProps extends React.ComponentProps<'svg'> {
7
+ /**
8
+ * Size of the spinner icon.
9
+ */
7
10
  size?: Responsive<IconSize>
8
11
  }
9
12
 
@@ -17,7 +17,7 @@ export function Switch(props: SwitchProps) {
17
17
 
18
18
  return (
19
19
  <Label
20
- className={clsx(switchClassName, className)}
20
+ className={clsx(switchClassName, 'sui-position-relative', className)}
21
21
  style={style}
22
22
  data-ui="Switch"
23
23
  disabled={props.disabled}
@@ -3,9 +3,14 @@ import {type PropDef} from '../../types/PropDef'
3
3
 
4
4
  /** @beta */
5
5
  export interface SwitchProps extends React.ComponentProps<'input'>, MarginProps {
6
- /** Error state */
6
+ /**
7
+ * Applies error styling to the switch track.
8
+ * @remarks Use when form validation fails. Pair with a visible error message. The prop is visual only.
9
+ */
7
10
  error?: boolean
8
- /** Input label */
11
+ /**
12
+ * Visible label next to the switch.
13
+ */
9
14
  label: React.ReactNode
10
15
  }
11
16
 
@@ -40,7 +40,7 @@ export function Text<T extends ElementType = 'span'>({
40
40
 
41
41
  return (
42
42
  <Component
43
- className={clsx(textClassName, 'sui-overflow-hidden', className)}
43
+ className={clsx(textClassName, props.truncate && 'sui-overflow-hidden', className)}
44
44
  style={style}
45
45
  data-ui="Text"
46
46
  {...rest}
@@ -5,9 +5,13 @@ import {TEXT_SIZE, type TextSize} from '../../types/Text'
5
5
 
6
6
  /** @public */
7
7
  export interface TextProps<T extends React.ElementType = 'span'> extends TypographyProps {
8
- /** Element to render */
8
+ /**
9
+ * HTML element to render.
10
+ */
9
11
  as?: T
10
- /** CSS **font-size** property */
12
+ /**
13
+ * Sets font size.
14
+ */
11
15
  size?: Responsive<TextSize>
12
16
  }
13
17
 
@@ -1,93 +1,97 @@
1
1
  import clsx from 'clsx'
2
- import {cloneElement, useEffect, useId, useState} from 'react'
2
+ import {cloneElement, useId, useState, type ToggleEvent} from 'react'
3
3
 
4
+ import {useIsClient} from '../../hooks/useIsClient'
4
5
  import {getProps} from '../../utils/getProps'
6
+ import {mergeTriggerProps} from '../../utils/mergeTriggerProps'
7
+ import {renderPortal} from '../../utils/renderPortal'
5
8
  import {suffixClassName} from '../../utils/suffixClassName'
6
- import {Box} from '../box/Box'
7
9
  import {type TooltipProps, tooltipProps} from './tooltip.props'
8
10
 
9
11
  const tooltipClassName = suffixClassName('sui-Tooltip')
10
- const tooltipDismissedClassName = suffixClassName('sui-Tooltip-Dismissed')
11
12
 
12
- /** @public */
13
- export function Tooltip({placement = 'bottom', ...props}: TooltipProps) {
13
+ function TooltipRoot({
14
+ placement = 'bottom',
15
+ ...props
16
+ }: TooltipProps & {
17
+ triggerProps?: Record<string, unknown>
18
+ }) {
14
19
  const {
15
20
  children,
16
21
  className,
17
22
  style,
18
- disabled,
19
23
  id: idProp,
20
- text,
24
+ anchorName,
25
+ content,
26
+ portal,
27
+ triggerProps: forwardedTriggerProps,
21
28
  ...rest
22
29
  } = getProps({placement, ...props}, tooltipProps)
23
30
  const reactId = useId()
24
31
  const id = idProp || reactId
25
32
  const [dismissed, setDismissed] = useState(false)
33
+ const isClient = useIsClient()
26
34
 
27
- useEffect(() => {
28
- if (dismissed) {
29
- return
30
- }
31
-
32
- const handleKeyDown = (e: KeyboardEvent) => {
33
- if (e.key === 'Escape') {
34
- setDismissed(true)
35
- }
36
- }
37
-
38
- window.addEventListener('keydown', handleKeyDown)
39
- return () => window.removeEventListener('keydown', handleKeyDown)
40
- }, [dismissed])
41
-
42
- const trigger = cloneElement(children, {
35
+ const triggerProps = {
43
36
  'aria-describedby': id,
44
- 'onMouseEnter': (e) => {
37
+ 'interestfor': id,
38
+ 'style': {anchorName: `--anchor-${anchorName || id}`},
39
+ 'onMouseLeave': () => {
45
40
  setDismissed(false)
46
- children.props.onMouseEnter?.(e)
47
41
  },
48
- 'onFocus': (e) => {
42
+ 'onBlur': () => {
49
43
  setDismissed(false)
50
- children.props.onFocus?.(e)
51
44
  },
52
- 'onClick': (e) => {
45
+ 'onClick': () => {
53
46
  setDismissed(true)
54
- children.props.onClick?.(e)
47
+ document.getElementById(id)?.hidePopover()
55
48
  },
56
- 'style': {
57
- ...children.props.style,
58
- anchorName: `--tooltip-anchor-${id}`,
59
- },
60
- })
49
+ }
50
+
51
+ const trigger = children.type.forwardsTriggerProps
52
+ ? cloneElement(children, {triggerProps})
53
+ : cloneElement(children, mergeTriggerProps(children.props, forwardedTriggerProps, triggerProps))
61
54
 
62
- if (disabled) {
63
- return children
55
+ const handleBeforeToggle = (e: ToggleEvent) => {
56
+ if (e.newState === 'open' && dismissed) {
57
+ e.preventDefault()
58
+ }
64
59
  }
65
60
 
66
61
  return (
67
62
  <>
68
63
  {trigger}
69
64
 
70
- <Box
71
- className={clsx(tooltipClassName, dismissed ? tooltipDismissedClassName : '', className)}
72
- role="tooltip"
73
- style={{
74
- ...style,
75
- positionAnchor: `--tooltip-anchor-${id}`,
76
- }}
77
- data-ui="Tooltip"
78
- id={id}
79
- paddingX={2}
80
- paddingY={1}
81
- radius={2}
82
- position="fixed"
83
- zIndex={9999}
84
- shadow={2}
85
- {...rest}
86
- >
87
- {text}
88
- </Box>
65
+ {renderPortal(
66
+ <div
67
+ className={clsx(
68
+ tooltipClassName,
69
+ 'sui-px2 sui-py1 sui-radius2 sui-position-fixed sui-shadow2',
70
+ className,
71
+ )}
72
+ style={{
73
+ ...style,
74
+ positionAnchor: `--anchor-${anchorName || id}`,
75
+ }}
76
+ data-ui="Tooltip"
77
+ role="tooltip"
78
+ popover="hint"
79
+ id={id}
80
+ onBeforeToggle={handleBeforeToggle}
81
+ {...rest}
82
+ >
83
+ {content}
84
+ </div>,
85
+ isClient,
86
+ portal,
87
+ )}
89
88
  </>
90
89
  )
91
90
  }
92
91
 
92
+ /** @beta */
93
+ export const Tooltip = Object.assign(TooltipRoot, {
94
+ forwardsTriggerProps: true,
95
+ }) as typeof TooltipRoot
96
+
93
97
  export type {TooltipProps}
@@ -1,52 +1,31 @@
1
+ [interestfor] {
2
+ --tooltip-delay: var(--tooltip-delay-group, 500ms);
3
+ /* The interestfor polyfill looks for intereset delay variables */
4
+ --interest-delay-start: var(--tooltip-delay);
5
+ --interest-delay-end: 0ms;
6
+ interest-delay-start: var(--tooltip-delay);
7
+ interest-delay-end: 0ms;
8
+ }
9
+
1
10
  .sui-Tooltip {
2
- --tooltip-delay-open: var(--tooltip-delay-group, 500ms);
3
- --tooltip-delay-close: var(--tooltip-delay-group, 100ms);
4
11
  background: var(--backdrop);
12
+ visibility: hidden;
5
13
  opacity: 0;
6
14
  scale: 0.9;
7
- visibility: hidden;
8
- transition:
9
- opacity 200ms cubic-bezier(0.34, 1.2, 0.64, 1) var(--tooltip-delay-close),
10
- scale 200ms cubic-bezier(0.34, 1.2, 0.64, 1) var(--tooltip-delay-close),
11
- visibility 0s linear calc(var(--tooltip-delay-close) + 200ms);
15
+ transition: none;
12
16
  }
13
17
 
14
- [aria-describedby]:is(:hover, :focus-visible) + [role="tooltip"]:not(.sui-Tooltip-Dismissed) {
18
+ .sui-Tooltip:popover-open {
15
19
  visibility: visible;
16
20
  opacity: 1;
17
21
  scale: 1;
18
- transition:
19
- opacity 200ms cubic-bezier(0.34, 1.2, 0.64, 1) var(--tooltip-delay-open),
20
- scale 200ms cubic-bezier(0.34, 1.2, 0.64, 1) var(--tooltip-delay-open),
21
- visibility 0s linear var(--tooltip-delay-open);
22
- }
23
-
24
- [aria-describedby]:is(:hover, :focus-visible) + .sui-Tooltip-Dismissed[role="tooltip"] {
25
- transition: none;
26
- }
27
-
28
- .sui-Tooltip[class*='placement-bottom'],
29
- .sui-Tooltip[class*='placement-top'] {
30
- margin-block: var(--space-1);
31
- }
32
-
33
- .sui-Tooltip[class*='placement-left'],
34
- .sui-Tooltip[class*='placement-right'] {
35
- margin-inline: var(--space-1);
36
- }
37
-
38
- .sui-Tooltip[class*='bottom'] {
39
- transform-origin: center top;
40
- }
41
-
42
- .sui-Tooltip[class*='top'] {
43
- transform-origin: center bottom;
44
- }
45
-
46
- .sui-Tooltip[class*='left'] {
47
- transform-origin: right center;
22
+ transition: var(--fade-in-transition);
48
23
  }
49
24
 
50
- .sui-Tooltip[class*='right'] {
51
- transform-origin: left center;
25
+ @starting-style {
26
+ .sui-Tooltip:popover-open {
27
+ visibility: hidden;
28
+ opacity: 0;
29
+ scale: 0.9;
30
+ }
52
31
  }
@@ -1,19 +1,35 @@
1
1
  import {type PlacementProps, placementProps} from '../../props/placement'
2
2
  import {type PropDef} from '../../types/PropDef'
3
3
 
4
- /** @public */
5
- export interface TooltipProps extends React.ComponentProps<'div'>, PlacementProps {
6
- /** Tooltip text */
7
- text?: React.ReactNode
8
- /** Disabled state */
9
- disabled?: boolean
4
+ /** @beta */
5
+ export interface TooltipProps
6
+ extends Omit<React.ComponentProps<'div'>, 'children' | 'content'>, PlacementProps {
7
+ /**
8
+ * Shared anchor identifier.
9
+ */
10
+ anchorName?: React.ReactNode
11
+ /**
12
+ * The trigger element.
13
+ */
14
+ children: React.ReactElement<Record<string, unknown>>
15
+ /**
16
+ * The tooltip label.
17
+ */
18
+ content?: React.ReactNode
19
+ /**
20
+ * Renders the label into `document.body` through a React portal instead of inline.
21
+ */
22
+ portal?: boolean
10
23
  }
11
24
 
12
25
  export const tooltipProps: Record<string, PropDef> = {
13
- text: {
26
+ anchorName: {
14
27
  type: 'string',
15
28
  },
16
- disabled: {
29
+ content: {
30
+ type: 'string',
31
+ },
32
+ portal: {
17
33
  type: 'boolean',
18
34
  },
19
35
  ...placementProps,
@@ -23,10 +23,7 @@ export function TooltipGroup<T extends ElementType = 'div'>(
23
23
  return
24
24
  }
25
25
 
26
- if (
27
- e.propertyName === 'visibility' &&
28
- window.getComputedStyle(tooltip).visibility !== 'hidden'
29
- ) {
26
+ if (e.propertyName === 'opacity' && window.getComputedStyle(tooltip).opacity !== '0') {
30
27
  setIsActive(true)
31
28
  }
32
29
  }
@@ -49,7 +46,7 @@ export function TooltipGroup<T extends ElementType = 'div'>(
49
46
  style={{
50
47
  ...style,
51
48
  ...(isActive && {
52
- '--tooltip-delay-group': 0,
49
+ '--tooltip-delay-group': '0ms',
53
50
  }),
54
51
  }}
55
52
  data-ui="TooltipGroup"
@@ -2,7 +2,9 @@ import {type PropDef} from '../../types/PropDef'
2
2
 
3
3
  /** @public */
4
4
  export interface TooltipGroupProps<T extends React.ElementType = 'div'> {
5
- /** Element to render */
5
+ /**
6
+ * HTML element to render.
7
+ */
6
8
  as?: T
7
9
  }
8
10
 
@@ -1,31 +1,25 @@
1
1
  import clsx from 'clsx'
2
2
  import type {ComponentPropsWithRef, ElementType} from 'react'
3
3
 
4
- import {getProps} from '../../utils/getProps'
4
+ import type {ComponentProps} from '../../utils/getProps'
5
5
  import {suffixClassName} from '../../utils/suffixClassName'
6
6
  import {Flex} from '../flex/Flex'
7
- import {type VStackProps, vStackProps} from './vStack.props'
7
+ import {type VStackProps} from './vStack.props'
8
8
 
9
9
  const vStackClassName = suffixClassName('sui-VStack')
10
10
 
11
11
  /** @public */
12
- export function VStack<T extends ElementType = 'div'>(
13
- props: VStackProps<T> & Omit<ComponentPropsWithRef<T>, keyof VStackProps<T>>,
14
- ) {
15
- const {as, children, className, style, ...rest} = getProps(props, vStackProps)
16
- const Component = as || 'div'
17
-
12
+ export function VStack<T extends ElementType = 'div'>({
13
+ className,
14
+ ...props
15
+ }: VStackProps<T> & Omit<ComponentPropsWithRef<T>, keyof VStackProps<T>>) {
18
16
  return (
19
17
  <Flex
20
- as={Component}
21
18
  className={clsx(vStackClassName, className)}
22
- style={style}
23
19
  data-ui="VStack"
24
20
  flexDirection="column"
25
- {...rest}
26
- >
27
- {children}
28
- </Flex>
21
+ {...(props as ComponentProps)}
22
+ />
29
23
  )
30
24
  }
31
25
 
@@ -1,15 +1,7 @@
1
- import {type GapProps, gapProps} from '../../props/gap'
2
- import {type PropDef} from '../../types/PropDef'
1
+ import type {FlexProps} from '../flex/flex.props'
3
2
 
4
3
  /** @public */
5
- export interface VStackProps<T extends React.ElementType = 'div'> extends Pick<GapProps, 'gap'> {
6
- /** Element to render */
7
- as?: T
8
- }
9
-
10
- export const vStackProps: Record<string, PropDef> = {
11
- as: {
12
- type: 'string',
13
- },
14
- gap: gapProps['gap'] as PropDef,
15
- }
4
+ export interface VStackProps<T extends React.ElementType = 'div'> extends Pick<
5
+ FlexProps<T>,
6
+ 'as' | 'gap'
7
+ > {}
@@ -2,9 +2,13 @@ import {type PropDef} from '../../types/PropDef'
2
2
 
3
3
  /** @public */
4
4
  export interface VisuallyHiddenProps<T extends React.ElementType = 'span'> {
5
- /** Element to render */
5
+ /**
6
+ * HTML element to render.
7
+ */
6
8
  as?: T
7
- /** If true, element is visible on :focus-visible */
9
+ /**
10
+ * If true, the element becomes visible on `:focus-visible`.
11
+ */
8
12
  visibleOnFocus?: boolean
9
13
  }
10
14
 
@@ -1,10 +1,10 @@
1
1
  @breakpoints {
2
- .sui-display-block { display: block; }
3
- .sui-display-inline-block { display: inline-block; }
4
- .sui-display-inline { display: inline; }
5
- .sui-display-flex { display: flex; }
6
- .sui-display-inline-flex { display: inline-flex; }
7
- .sui-display-grid { display: grid; }
8
- .sui-display-inline-grid { display: inline-grid; }
9
- .sui-display-none { display: none; }
2
+ .sui-display-block:not([hidden]) { display: block; }
3
+ .sui-display-inline-block:not([hidden]) { display: inline-block; }
4
+ .sui-display-inline:not([hidden]) { display: inline; }
5
+ .sui-display-flex:not([hidden]) { display: flex; }
6
+ .sui-display-inline-flex:not([hidden]) { display: inline-flex; }
7
+ .sui-display-grid:not([hidden]) { display: grid; }
8
+ .sui-display-inline-grid:not([hidden]) { display: inline-grid; }
9
+ .sui-display-none:not([hidden]) { display: none; }
10
10
  }
@@ -1,3 +1,8 @@
1
+ [class*='placement-'] {
2
+ inset: auto;
3
+ margin: 0;
4
+ }
5
+
1
6
  @position-try --top-center {
2
7
  top: auto;
3
8
  right: auto;
@@ -169,3 +174,29 @@
169
174
  bottom: anchor(bottom);
170
175
  position-try-fallbacks: --left-end;
171
176
  }
177
+
178
+ [class*="placement-bottom"],
179
+ [class*="placement-top"] {
180
+ margin-block: var(--space-1);
181
+ }
182
+
183
+ [class*="placement-left"],
184
+ [class*="placement-right"] {
185
+ margin-inline: var(--space-1);
186
+ }
187
+
188
+ [class*="placement-bottom"] {
189
+ transform-origin: center top;
190
+ }
191
+
192
+ [class*="placement-top"] {
193
+ transform-origin: center bottom;
194
+ }
195
+
196
+ [class*="placement-left"] {
197
+ transform-origin: right center;
198
+ }
199
+
200
+ [class*="placement-right"] {
201
+ transform-origin: left center;
202
+ }
@@ -0,0 +1,4 @@
1
+ :root {
2
+ --timing-linear: linear;
3
+ --timing-curve: cubic-bezier(0.34, 1.2, 0.64, 1);
4
+ }
@@ -1,4 +1,6 @@
1
+ @import './animation.css';
1
2
  @import './border.css';
2
3
  @import './text-overflow.css';
3
4
  @import './text-trim.css';
4
5
  @import './tone.css';
6
+ @import './top-anchor.css';
@@ -0,0 +1,4 @@
1
+ .sui-top-anchor {
2
+ inset-block-start: var(--top-anchor);
3
+ max-block-size: calc(100dvh - var(--top-anchor) * 2);
4
+ }
@@ -1,6 +1,6 @@
1
- .sui-shadow0 { box-shadow: var(--shadow0); }
2
- .sui-shadow1 { box-shadow: var(--shadow1); }
3
- .sui-shadow2 { box-shadow: var(--shadow2); }
4
- .sui-shadow3 { box-shadow: var(--shadow3); }
5
- .sui-shadow4 { box-shadow: var(--shadow4); }
6
- .sui-shadow5 { box-shadow: var(--shadow5); }
1
+ .sui-shadow0 { box-shadow: var(--shadow-0); }
2
+ .sui-shadow1 { box-shadow: var(--shadow-1); }
3
+ .sui-shadow2 { box-shadow: var(--shadow-2); }
4
+ .sui-shadow3 { box-shadow: var(--shadow-3); }
5
+ .sui-shadow4 { box-shadow: var(--shadow-4); }
6
+ .sui-shadow5 { box-shadow: var(--shadow-5); }
@@ -17,46 +17,59 @@
17
17
  }
18
18
 
19
19
  /* Prevent adjustments of font size after orientation changes in iOS. */
20
- html {
20
+ :where(html) {
21
21
  -webkit-text-size-adjust: 100%;
22
22
  }
23
23
 
24
- body {
24
+ :where(body) {
25
25
  background: light-dark(var(--white), var(--black));
26
26
  font-family: var(--sans);
27
27
  -webkit-font-smoothing: antialiased;
28
28
  }
29
29
 
30
30
  /* Display multimedia as block by default */
31
- audio,
32
- canvas,
33
- embed,
34
- iframe,
35
- img,
36
- object,
37
- picture,
38
- video {
31
+ :where(
32
+ audio,
33
+ canvas,
34
+ embed,
35
+ iframe,
36
+ img,
37
+ object,
38
+ picture,
39
+ video
40
+ ){
39
41
  display: block;
40
42
  max-width: 100%;
41
43
  }
42
- img,
43
- picture,
44
- video {
44
+ :where(img, picture, video) {
45
45
  block-size: auto;
46
46
  }
47
47
 
48
48
  /* Inherit typography in form controls */
49
- button,
50
- input,
51
- select,
52
- textarea {
49
+ :where(
50
+ button,
51
+ input,
52
+ select,
53
+ textarea
54
+ ) {
55
+ appearance: none;
56
+ color: inherit;
53
57
  font: inherit;
54
58
  line-height: inherit;
55
- color: inherit;
59
+ }
60
+
61
+ /* Remove user agent reduced opacity on disabled form elements */
62
+ :where(
63
+ button,
64
+ input,
65
+ select,
66
+ textarea
67
+ ):disabled {
68
+ opacity: 1;
56
69
  }
57
70
 
58
71
  /* Remove excess space for table borders */
59
- table {
72
+ :where(table) {
60
73
  border-collapse: collapse;
61
74
  border-spacing: 0;
62
75
  }
@@ -18,4 +18,8 @@
18
18
  --hover-transition: border-color 100ms linear, background-color 100ms linear;
19
19
  --inert-background: light-dark(var(--gray-50), var(--gray-950));
20
20
  --inert-foreground: light-dark(var(--gray-400), var(--gray-600));
21
+ --fade-in-transition:
22
+ opacity 200ms cubic-bezier(0.34, 1.2, 0.64, 1),
23
+ scale 200ms cubic-bezier(0.34, 1.2, 0.64, 1), visibility 0s linear,
24
+ display 200ms linear allow-discrete;
21
25
  }
@@ -10,6 +10,8 @@
10
10
  --foreground-high-emphasized: light-dark(var(--white), var(--black));
11
11
  --foreground-low: light-dark(var(--gray-600), var(--gray-400));
12
12
  --foreground-low-emphasized: light-dark(var(--gray-100), var(--gray-900));
13
+ /* Used to create equivalent text + block size for form elements vs UI v3/4. Can drop once migration is complete. */
14
+ --form-element-text: var(--regular) 13px / 1.15 var(--sans);
13
15
  }
14
16
 
15
17
  [class*='sui-tone'] {
@@ -0,0 +1,10 @@
1
+ import {useSyncExternalStore} from 'react'
2
+
3
+ /** @public */
4
+ export function useIsClient() {
5
+ return useSyncExternalStore(
6
+ () => () => {},
7
+ () => true,
8
+ () => false,
9
+ )
10
+ }