@sanity/ui 2.0.0-alpha.2 → 2.0.0-alpha.21

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 (96) hide show
  1. package/dist/index.cjs.mjs +28 -0
  2. package/dist/index.d.ts +476 -12
  3. package/dist/index.esm.js +1326 -524
  4. package/dist/index.esm.js.map +1 -1
  5. package/dist/index.js +1353 -523
  6. package/dist/index.js.map +1 -1
  7. package/package.json +6 -8
  8. package/src/components/autocomplete/autocomplete.tsx +6 -0
  9. package/src/components/dialog/constants.ts +4 -0
  10. package/src/components/dialog/dialog.tsx +79 -15
  11. package/src/components/hotkeys/hotkeys.tsx +2 -0
  12. package/src/components/menu/menu.tsx +2 -0
  13. package/src/components/menu/menuButton.tsx +2 -0
  14. package/src/components/menu/menuGroup.tsx +22 -23
  15. package/src/components/menu/menuItem.tsx +29 -35
  16. package/src/components/tab/tab.tsx +4 -1
  17. package/src/components/toast/toast.tsx +4 -0
  18. package/src/primitives/_selectable/style.ts +2 -1
  19. package/src/primitives/avatar/avatar.tsx +16 -9
  20. package/src/primitives/avatar/avatarCounter.tsx +3 -3
  21. package/src/primitives/avatar/styles.ts +1 -1
  22. package/src/primitives/badge/badge.tsx +7 -3
  23. package/src/primitives/box/box.tsx +3 -0
  24. package/src/primitives/button/__workshop__/sanityUploadButton.tsx +2 -1
  25. package/src/primitives/button/button.tsx +7 -3
  26. package/src/primitives/button/styles.ts +9 -2
  27. package/src/primitives/card/card.tsx +4 -0
  28. package/src/primitives/card/styles.ts +2 -0
  29. package/src/primitives/checkbox/checkbox.tsx +2 -0
  30. package/src/primitives/code/code.tsx +1 -0
  31. package/src/primitives/container/container.tsx +2 -0
  32. package/src/primitives/flex/flex.tsx +2 -0
  33. package/src/primitives/grid/grid.tsx +2 -0
  34. package/src/primitives/heading/heading.tsx +2 -0
  35. package/src/primitives/inline/inline.tsx +3 -0
  36. package/src/primitives/kbd/kbd.tsx +2 -0
  37. package/src/primitives/label/label.tsx +2 -0
  38. package/src/primitives/popover/popover.tsx +6 -1
  39. package/src/primitives/radio/radio.tsx +2 -0
  40. package/src/primitives/select/select.tsx +2 -0
  41. package/src/primitives/select/styles.ts +2 -0
  42. package/src/primitives/spinner/spinner.tsx +2 -0
  43. package/src/primitives/stack/stack.tsx +2 -0
  44. package/src/primitives/switch/switch.tsx +4 -0
  45. package/src/primitives/text/text.tsx +3 -0
  46. package/src/primitives/textArea/textArea.tsx +4 -1
  47. package/src/primitives/textInput/textInput.tsx +10 -1
  48. package/src/primitives/tooltip/__workshop__/customPortal.tsx +99 -0
  49. package/src/primitives/tooltip/__workshop__/index.ts +15 -0
  50. package/src/primitives/tooltip/__workshop__/overflowingBoundary.tsx +73 -0
  51. package/src/primitives/tooltip/__workshop__/resizableBoundary.tsx +85 -0
  52. package/src/primitives/tooltip/constants.ts +1 -0
  53. package/src/primitives/tooltip/tooltip.test.tsx +192 -0
  54. package/src/primitives/tooltip/tooltip.tsx +109 -33
  55. package/src/primitives/types.ts +4 -0
  56. package/src/styles/input/textInputStyle.ts +11 -6
  57. package/src/theme/_internal/__workshop__/build/story.tsx +288 -0
  58. package/src/theme/_internal/__workshop__/build/theme.ts +3 -0
  59. package/src/theme/_internal/__workshop__/index.ts +14 -0
  60. package/src/theme/_internal/build/buildTheme.test.ts +78 -0
  61. package/src/theme/_internal/build/buildTheme.ts +16 -0
  62. package/src/theme/_internal/build/colorTheme/buildColorTheme.test.ts +185 -0
  63. package/src/theme/_internal/build/colorTheme/buildColorTheme.ts +164 -0
  64. package/src/theme/_internal/build/colorTheme/renderColorTheme.ts +242 -0
  65. package/src/theme/_internal/build/colorTheme/resolveColorTokens.ts +121 -0
  66. package/src/theme/_internal/build/defaults/colorPalette.ts +8 -0
  67. package/src/theme/_internal/build/defaults/colorTokens.ts +147 -0
  68. package/src/theme/_internal/build/helpers.ts +65 -0
  69. package/src/theme/_internal/build/index.ts +1 -0
  70. package/src/theme/_internal/config/helpers.ts +47 -0
  71. package/src/theme/_internal/config/index.ts +3 -0
  72. package/src/theme/_internal/config/token/index.ts +2 -0
  73. package/src/theme/_internal/config/token/parseTokenKey.test.ts +72 -0
  74. package/src/theme/_internal/config/token/parseTokenKey.ts +88 -0
  75. package/src/theme/_internal/config/token/parseTokenValue.test.ts +45 -0
  76. package/src/theme/_internal/config/token/parseTokenValue.ts +123 -0
  77. package/src/theme/_internal/config/types.ts +137 -0
  78. package/src/theme/_internal/constants.ts +48 -0
  79. package/src/theme/_internal/helpers.ts +19 -0
  80. package/src/theme/_internal/index.ts +5 -0
  81. package/src/theme/_internal/types.ts +91 -0
  82. package/src/theme/index.ts +1 -0
  83. package/src/theme/lib/color-fns/blend/multiply.ts +2 -2
  84. package/src/theme/lib/color-fns/blend/screen.ts +2 -2
  85. package/src/theme/lib/color-fns/convert.ts +15 -1
  86. package/src/theme/lib/color-fns/parse.ts +7 -3
  87. package/src/theme/lib/color-fns/types.ts +11 -0
  88. package/src/theme/lib/theme/avatar.ts +2 -0
  89. package/src/theme/lib/theme/color/_legacy/createColorTheme.ts +7 -0
  90. package/src/theme/lib/theme/color/_legacy/index.ts +1 -0
  91. package/src/theme/lib/theme/color/_legacy/legacyColor.ts +3997 -0
  92. package/src/theme/studioTheme/color.ts +98 -82
  93. package/src/theme/studioTheme/helpers.ts +15 -1
  94. package/src/theme/studioTheme/theme.ts +5 -5
  95. package/src/theme/studioTheme/tints.ts +244 -84
  96. package/src/types/button.ts +5 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sanity/ui",
3
- "version": "2.0.0-alpha.2",
3
+ "version": "2.0.0-alpha.21",
4
4
  "sideEffects": false,
5
5
  "types": "./dist/index.d.ts",
6
6
  "source": "./src/index.ts",
@@ -44,15 +44,15 @@
44
44
  "test": "jest",
45
45
  "test:browser": "start-server-and-test 'run-s workshop:build workshop:start' http://localhost:1337 'run-s cypress:run'",
46
46
  "watch": "pkg watch --strict",
47
- "workshop:build": "node -r esbuild-register -r tsconfig-paths/register scripts/build",
48
- "workshop:dev": "node -r esbuild-register -r tsconfig-paths/register scripts/dev",
47
+ "workshop:build": "workshop build",
48
+ "workshop:dev": "workshop dev",
49
49
  "workshop:start": "http-server -a localhost -c-0 -p 1337 -s -P http://localhost:1337/index.html? dist",
50
50
  "storybook": "storybook dev -p 6006",
51
51
  "build-storybook": "storybook build"
52
52
  },
53
53
  "dependencies": {
54
54
  "@floating-ui/react-dom": "2.0.0",
55
- "@sanity/color": "^2.2.5",
55
+ "@sanity/color": "3.0.0-beta.6",
56
56
  "@sanity/icons": "^2.4.1",
57
57
  "csstype": "^3.1.2",
58
58
  "framer-motion": "^10.16.2",
@@ -68,7 +68,7 @@
68
68
  "@juggle/resize-observer": "^3.4.0",
69
69
  "@sanity/pkg-utils": "^2.4.8",
70
70
  "@sanity/semantic-release-preset": "^4.1.4",
71
- "@sanity/ui-workshop": "^1.2.11",
71
+ "@sanity/ui-workshop": "^2.0.0",
72
72
  "@storybook/addon-a11y": "^7.4.5",
73
73
  "@storybook/addon-docs": "^7.4.5",
74
74
  "@storybook/addon-essentials": "^7.4.5",
@@ -100,8 +100,6 @@
100
100
  "cypress": "^13.1.0",
101
101
  "cypress-real-events": "^1.10.1",
102
102
  "cz-conventional-changelog": "^3.3.0",
103
- "esbuild": "^0.19.2",
104
- "esbuild-register": "^3.4.2",
105
103
  "eslint": "^8.48.0",
106
104
  "eslint-config-prettier": "^9.0.0",
107
105
  "eslint-plugin-import": "^2.28.1",
@@ -126,7 +124,7 @@
126
124
  "rimraf": "^5.0.1",
127
125
  "semantic-release": "^21.1.1",
128
126
  "start-server-and-test": "^2.0.0",
129
- "storybook": "^7.4.5",
127
+ "storybook": "^7.5.2",
130
128
  "styled-components": "^6.0.7",
131
129
  "tsconfig-paths": "^4.2.0",
132
130
  "typescript": "^5.2.2"
@@ -60,6 +60,7 @@ export interface AutocompleteProps<Option extends BaseAutocompleteOption = BaseA
60
60
  onSelect?: (value: string) => void
61
61
  /** @beta */
62
62
  openButton?: boolean | AutocompleteOpenButtonProps
63
+ /** The options to render. */
63
64
  options?: Option[]
64
65
  padding?: number | number[]
65
66
  popover?: Omit<PopoverProps, 'content' | 'onMouseEnter' | 'onMouseLeave' | 'open'> &
@@ -68,6 +69,7 @@ export interface AutocompleteProps<Option extends BaseAutocompleteOption = BaseA
68
69
  radius?: Radius | Radius[]
69
70
  /** @beta */
70
71
  relatedElements?: HTMLElement[]
72
+ /** The callback function for rendering each option. */
71
73
  renderOption?: (option: Option) => ReactElement
72
74
  /** @beta */
73
75
  renderPopover?: (
@@ -82,6 +84,7 @@ export interface AutocompleteProps<Option extends BaseAutocompleteOption = BaseA
82
84
  ) => ReactNode
83
85
  renderValue?: (value: string, option?: Option) => string
84
86
  suffix?: ReactNode
87
+ /** The current value. */
85
88
  value?: string
86
89
  }
87
90
 
@@ -684,6 +687,9 @@ const InnerAutocomplete = forwardRef(function InnerAutocomplete<
684
687
  })
685
688
 
686
689
  /**
690
+ * The Autocomplete component is typically used for search components.
691
+ * It consists of a text input for writing a query, and properties for rendering suggestions.
692
+ *
687
693
  * @public
688
694
  */
689
695
  export const Autocomplete = InnerAutocomplete as <Option extends BaseAutocompleteOption>(
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Left/right border offsets for header + footer components (in px).
3
+ */
4
+ export const BORDER_OFFSET_X: number = 12
@@ -8,12 +8,13 @@ import {
8
8
  isHTMLElement,
9
9
  } from '../../helpers'
10
10
  import {useArrayProp, useClickOutside, useForwardedRef, useGlobalKeyDown} from '../../hooks'
11
- import {Box, Button, Card, Container, Flex, Text} from '../../primitives'
11
+ import {Box, Button, Card, CardProps, Container, Flex, Text} from '../../primitives'
12
12
  import {ResponsivePaddingProps, ResponsiveWidthProps} from '../../primitives/types'
13
13
  import {responsivePaddingStyle, ResponsivePaddingStyleProps} from '../../styles/internal'
14
14
  import {ThemeColorSchemeKey, useTheme} from '../../theme'
15
15
  import {DialogPosition, Radius} from '../../types'
16
16
  import {Layer, LayerProps, Portal, useBoundaryElement, useLayer, usePortal} from '../../utils'
17
+ import {BORDER_OFFSET_X} from './constants'
17
18
  import {
18
19
  dialogStyle,
19
20
  responsiveDialogPositionStyle,
@@ -71,6 +72,15 @@ interface DialogCardProps extends ResponsiveWidthProps {
71
72
  shadow: number | number[]
72
73
  }
73
74
 
75
+ interface DialogHeaderProps extends CardProps {
76
+ $hasScrolledFromTop: boolean
77
+ $isContentScrollable: boolean
78
+ }
79
+ interface DialogFooterProps extends CardProps {
80
+ $hasScrolledToBottom: boolean
81
+ $isContentScrollable: boolean
82
+ }
83
+
74
84
  function isTargetWithinScope(
75
85
  boundaryElement: HTMLElement | null,
76
86
  portalElement: HTMLElement | null,
@@ -118,7 +128,7 @@ const DialogLayout = styled(Flex)`
118
128
  width: 100%;
119
129
  `
120
130
 
121
- const DialogHeader = styled(Card)`
131
+ const DialogHeader = styled(Box)<DialogHeaderProps>`
122
132
  position: relative;
123
133
  z-index: 2;
124
134
 
@@ -126,10 +136,13 @@ const DialogHeader = styled(Card)`
126
136
  content: '';
127
137
  display: block;
128
138
  position: absolute;
129
- left: 0;
130
- right: 0;
139
+ left: ${BORDER_OFFSET_X}px;
140
+ right: ${BORDER_OFFSET_X}px;
131
141
  bottom: -1px;
132
- border-bottom: 1px solid var(--card-hairline-soft-color);
142
+ border-bottom: 1px solid var(--card-border-color);
143
+ width: auto;
144
+ opacity: ${(props) => (props.$isContentScrollable && props.$hasScrolledFromTop ? 1 : 0)};
145
+ transition: opacity 200ms ease-in;
133
146
  }
134
147
  `
135
148
 
@@ -140,10 +153,22 @@ const DialogContent = styled(Box)`
140
153
  outline: none;
141
154
  `
142
155
 
143
- const DialogFooter = styled(Box)`
156
+ const DialogFooter = styled(Box)<DialogFooterProps>`
144
157
  position: relative;
145
158
  z-index: 3;
146
- border-top: 1px solid var(--card-hairline-soft-color);
159
+
160
+ &:before {
161
+ content: '';
162
+ display: block;
163
+ position: absolute;
164
+ left: ${BORDER_OFFSET_X}px;
165
+ right: ${BORDER_OFFSET_X}px;
166
+ top: -1px;
167
+ border-top: 1px solid var(--card-border-color);
168
+ width: auto;
169
+ opacity: ${(props) => (props.$isContentScrollable && !props.$hasScrolledToBottom ? 1 : 0)};
170
+ transition: opacity 200ms ease-in;
171
+ }
147
172
  `
148
173
 
149
174
  const DialogCard = forwardRef(function DialogCard(
@@ -180,6 +205,9 @@ const DialogCard = forwardRef(function DialogCard(
180
205
  const labelId = `${id}_label`
181
206
  const showCloseButton = Boolean(onClose) && hideCloseButton === false
182
207
  const showHeader = Boolean(header) || showCloseButton
208
+ const [isContentScrollable, setIsContentScrollable] = useState(false)
209
+ const [hasScrolledFromTop, setHasScrolledFromTop] = useState(false)
210
+ const [hasScrolledToBottom, setHasScrolledToBottom] = useState(false)
183
211
 
184
212
  useEffect(() => {
185
213
  if (!autoFocus) return
@@ -248,29 +276,56 @@ const DialogCard = forwardRef(function DialogCard(
248
276
  [contentRef],
249
277
  )
250
278
 
279
+ const handleContentUpdate = useCallback(() => {
280
+ if (localContentRef.current) {
281
+ setIsContentScrollable(
282
+ localContentRef.current.clientHeight < localContentRef.current.scrollHeight,
283
+ )
284
+ setHasScrolledFromTop(localContentRef.current.scrollTop > 0)
285
+ setHasScrolledToBottom(
286
+ localContentRef.current.scrollTop >=
287
+ localContentRef.current.scrollHeight - localContentRef.current.clientHeight,
288
+ )
289
+ }
290
+ }, [])
291
+
292
+ useEffect(() => {
293
+ const resizeObserver = new ResizeObserver(handleContentUpdate)
294
+
295
+ if (localContentRef.current) {
296
+ resizeObserver.observe(localContentRef.current)
297
+ }
298
+
299
+ return () => {
300
+ resizeObserver.disconnect()
301
+ }
302
+ }, [contentRef, handleContentUpdate])
303
+
251
304
  return (
252
305
  <DialogContainer data-ui="DialogCard" width={width}>
253
306
  <DialogCardRoot radius={radius} ref={setRef} scheme={scheme} shadow={shadow}>
254
307
  <DialogLayout direction="column">
255
308
  {showHeader && (
256
- <DialogHeader>
257
- <Flex>
258
- <Box flex={1} padding={4}>
309
+ <DialogHeader
310
+ $isContentScrollable={isContentScrollable}
311
+ $hasScrolledFromTop={hasScrolledFromTop}
312
+ >
313
+ <Flex align="center">
314
+ <Box flex={1} margin={1} padding={4}>
259
315
  {header && (
260
- <Text id={labelId} weight="semibold">
316
+ <Text id={labelId} size={1} weight="medium">
261
317
  {header}
262
318
  </Text>
263
319
  )}
264
320
  </Box>
265
321
  {showCloseButton && (
266
- <Box padding={2}>
322
+ <Box padding={3}>
267
323
  <Button
268
324
  aria-label="Close dialog"
269
325
  disabled={!onClose}
270
326
  icon={CloseIcon}
271
327
  mode="bleed"
272
328
  onClick={onClose}
273
- padding={3}
274
329
  />
275
330
  </Box>
276
331
  )}
@@ -278,11 +333,18 @@ const DialogCard = forwardRef(function DialogCard(
278
333
  </DialogHeader>
279
334
  )}
280
335
 
281
- <DialogContent flex={1} ref={setContentRef} tabIndex={-1}>
336
+ <DialogContent flex={1} ref={setContentRef} tabIndex={-1} onScroll={handleContentUpdate}>
282
337
  {children}
283
338
  </DialogContent>
284
339
 
285
- {footer && <DialogFooter>{footer}</DialogFooter>}
340
+ {footer && (
341
+ <DialogFooter
342
+ $isContentScrollable={isContentScrollable}
343
+ $hasScrolledToBottom={hasScrolledToBottom}
344
+ >
345
+ {footer}
346
+ </DialogFooter>
347
+ )}
286
348
  </DialogLayout>
287
349
  </DialogCardRoot>
288
350
  </DialogContainer>
@@ -290,6 +352,8 @@ const DialogCard = forwardRef(function DialogCard(
290
352
  })
291
353
 
292
354
  /**
355
+ * The Dialog component.
356
+ *
293
357
  * @public
294
358
  */
295
359
  export const Dialog = forwardRef(function Dialog(
@@ -29,6 +29,8 @@ const Key = styled(KBD)`
29
29
  `
30
30
 
31
31
  /**
32
+ * Represent hotkeys (a keyboard combination) with semantic `<kbd>` elements.
33
+ *
32
34
  * @public
33
35
  */
34
36
  export const Hotkeys = forwardRef(function Hotkeys(
@@ -35,6 +35,8 @@ const Root = styled(Box)`
35
35
  `
36
36
 
37
37
  /**
38
+ * The `Menu` component is a building block for application menus.
39
+ *
38
40
  * @public
39
41
  */
40
42
  export const Menu = forwardRef(function Menu(
@@ -47,6 +47,8 @@ export interface MenuButtonProps {
47
47
  }
48
48
 
49
49
  /**
50
+ * The `MenuButton` component follows the WAI-ARIA specification for menu buttons.
51
+ *
50
52
  * @public
51
53
  */
52
54
  export const MenuButton = forwardRef(function MenuButton(
@@ -4,6 +4,7 @@ import {isValidElementType} from 'react-is'
4
4
  import {useArrayProp} from '../../hooks'
5
5
  import {Box, Flex, Popover, PopoverProps, Text} from '../../primitives'
6
6
  import {Selectable} from '../../primitives/_selectable'
7
+ import {useRootTheme} from '../../theme'
7
8
  import {Radius, SelectableTone} from '../../types'
8
9
  import {Menu} from './menu'
9
10
  import {useMenu} from './useMenu'
@@ -33,7 +34,7 @@ export function MenuGroup(
33
34
  const {
34
35
  as = 'button',
35
36
  children,
36
- fontSize,
37
+ fontSize = 1,
37
38
  icon,
38
39
  onClick,
39
40
  padding = 3,
@@ -45,6 +46,7 @@ export function MenuGroup(
45
46
  ...restProps
46
47
  } = props
47
48
  const menu = useMenu()
49
+ const {scheme} = useRootTheme()
48
50
  const {
49
51
  activeElement,
50
52
  mount,
@@ -166,6 +168,7 @@ export function MenuGroup(
166
168
  data-selected={!withinMenu && active ? '' : undefined}
167
169
  $radius={useArrayProp(radius)}
168
170
  $tone={tone}
171
+ $scheme={scheme}
169
172
  onClick={handleClick}
170
173
  onKeyDown={handleKeyDown}
171
174
  onMouseEnter={handleMouseEnter}
@@ -173,28 +176,24 @@ export function MenuGroup(
173
176
  tabIndex={-1}
174
177
  type={as === 'button' ? 'button' : undefined}
175
178
  >
176
- <Box padding={padding}>
177
- <Flex>
178
- {icon && (
179
- <Text size={fontSize}>
180
- {isValidElement(icon) && icon}
181
- {isValidElementType(icon) && createElement(icon)}
182
- </Text>
183
- )}
184
-
185
- <Box flex={1} marginLeft={icon ? space : undefined}>
186
- <Text size={fontSize} textOverflow="ellipsis">
187
- {text}
188
- </Text>
189
- </Box>
190
-
191
- <Box marginLeft={space}>
192
- <Text size={fontSize}>
193
- <ChevronRightIcon />
194
- </Text>
195
- </Box>
196
- </Flex>
197
- </Box>
179
+ <Flex gap={space} padding={padding}>
180
+ {icon && (
181
+ <Text size={fontSize}>
182
+ {isValidElement(icon) && icon}
183
+ {isValidElementType(icon) && createElement(icon)}
184
+ </Text>
185
+ )}
186
+
187
+ <Box flex={1}>
188
+ <Text size={fontSize} textOverflow="ellipsis" weight="medium">
189
+ {text}
190
+ </Text>
191
+ </Box>
192
+
193
+ <Text size={fontSize}>
194
+ <ChevronRightIcon />
195
+ </Text>
196
+ </Flex>
198
197
  </Selectable>
199
198
  </Popover>
200
199
  )
@@ -12,6 +12,7 @@ import {useArrayProp, useForwardedRef} from '../../hooks'
12
12
  import {Box, Flex, Text} from '../../primitives'
13
13
  import {Selectable} from '../../primitives/_selectable'
14
14
  import {ResponsivePaddingProps, ResponsiveRadiusProps} from '../../primitives/types'
15
+ import {useRootTheme} from '../../theme'
15
16
  import {SelectableTone} from '../../types/selectable'
16
17
  import {Hotkeys} from '../hotkeys'
17
18
  import {useMenu} from './useMenu'
@@ -44,7 +45,7 @@ export const MenuItem = forwardRef(function MenuItem(
44
45
  as = 'button',
45
46
  children,
46
47
  disabled,
47
- fontSize = 2,
48
+ fontSize = 1,
48
49
  hotkeys,
49
50
  icon,
50
51
  iconRight,
@@ -64,6 +65,7 @@ export const MenuItem = forwardRef(function MenuItem(
64
65
  tone = 'default',
65
66
  ...restProps
66
67
  } = props
68
+ const {scheme} = useRootTheme()
67
69
  const menu = useMenu()
68
70
  const {
69
71
  activeElement,
@@ -120,7 +122,8 @@ export const MenuItem = forwardRef(function MenuItem(
120
122
  forwardedAs={as}
121
123
  $radius={useArrayProp(radius)}
122
124
  $padding={useArrayProp(0)}
123
- $tone={tone}
125
+ $tone={disabled ? 'default' : tone}
126
+ $scheme={scheme}
124
127
  disabled={disabled}
125
128
  onClick={handleClick}
126
129
  onMouseEnter={onItemMouseEnter}
@@ -131,43 +134,34 @@ export const MenuItem = forwardRef(function MenuItem(
131
134
  type={as === 'button' ? 'button' : undefined}
132
135
  >
133
136
  {(icon || text || iconRight) && (
134
- <Box as="span" {...paddingProps}>
135
- <Flex as="span">
136
- {icon && (
137
- <Text size={fontSize}>
138
- {isValidElement(icon) && icon}
139
- {isValidElementType(icon) && createElement(icon)}
140
- </Text>
141
- )}
137
+ <Flex as="span" gap={space} align="center" {...paddingProps}>
138
+ {icon && (
139
+ <Text size={fontSize}>
140
+ {isValidElement(icon) && icon}
141
+ {isValidElementType(icon) && createElement(icon)}
142
+ </Text>
143
+ )}
142
144
 
143
- {text && (
144
- <Box
145
- flex={1}
146
- marginLeft={icon ? space : undefined}
147
- marginRight={iconRight ? space : undefined}
148
- >
149
- <Text size={fontSize} textOverflow="ellipsis">
150
- {text}
151
- </Text>
152
- </Box>
153
- )}
145
+ {text && (
146
+ <Box flex={1}>
147
+ <Text size={fontSize} textOverflow="ellipsis" weight="medium">
148
+ {text}
149
+ </Text>
150
+ </Box>
151
+ )}
154
152
 
155
- {hotkeys && (
156
- <Box marginLeft={space} style={{marginTop: -4, marginBottom: -4}}>
157
- <Hotkeys fontSize={fontSize} keys={hotkeys} />
158
- </Box>
159
- )}
153
+ {hotkeys && (
154
+ <Hotkeys fontSize={fontSize} keys={hotkeys} style={{marginTop: -4, marginBottom: -4}} />
155
+ )}
160
156
 
161
- {iconRight && (
162
- <Text size={fontSize}>
163
- {isValidElement(iconRight) && iconRight}
164
- {isValidElementType(iconRight) && createElement(iconRight)}
165
- </Text>
166
- )}
167
- </Flex>
168
- </Box>
157
+ {iconRight && (
158
+ <Text size={fontSize}>
159
+ {isValidElement(iconRight) && iconRight}
160
+ {isValidElementType(iconRight) && createElement(iconRight)}
161
+ </Text>
162
+ )}
163
+ </Flex>
169
164
  )}
170
-
171
165
  {children && (
172
166
  <Box as="span" {...paddingProps}>
173
167
  {children}
@@ -31,7 +31,10 @@ const CustomButton = styled(Button)`
31
31
  */
32
32
  export const Tab = forwardRef(function Tab(
33
33
  props: TabProps &
34
- Omit<React.HTMLProps<HTMLButtonElement>, 'aria-controls' | 'as' | 'id' | 'label' | 'type'>,
34
+ Omit<
35
+ React.HTMLProps<HTMLButtonElement>,
36
+ 'aria-controls' | 'as' | 'id' | 'label' | 'type' | 'width'
37
+ >,
35
38
  forwardedRef: React.ForwardedRef<HTMLButtonElement>,
36
39
  ) {
37
40
  const {
@@ -37,6 +37,10 @@ const TextBox = styled(Flex)`
37
37
  `
38
38
 
39
39
  /**
40
+ * The `Toast` component gives feedback to users when an action has taken place.
41
+ *
42
+ * Toasts can be closed with a close button, or auto-dismiss after a certain timeout.
43
+ *
40
44
  * @public
41
45
  */
42
46
  export function Toast(
@@ -22,6 +22,8 @@ export function selectableBaseStyle(): ReturnType<typeof css> {
22
22
  font: inherit;
23
23
  text-align: inherit;
24
24
  border: 0;
25
+ width: -moz-available;
26
+ width: -webkit-fill-available;
25
27
  width: stretch;
26
28
  }
27
29
 
@@ -99,7 +101,6 @@ export function selectableColorStyle(
99
101
  &:hover {
100
102
  ${_colorVarsStyle(base, tone.hovered)}
101
103
  }
102
-
103
104
  &:active {
104
105
  ${_colorVarsStyle(base, tone.pressed)}
105
106
  }
@@ -11,6 +11,8 @@ import {avatarStyle, responsiveAvatarSizeStyle} from './styles'
11
11
  * @public
12
12
  */
13
13
  export interface AvatarProps {
14
+ /** @beta */
15
+ __unstable_hideInnerStroke?: boolean
14
16
  animateArrowFrom?: AvatarPosition
15
17
  arrowPosition?: AvatarPosition
16
18
  as?: React.ElementType | keyof JSX.IntrinsicElements
@@ -41,6 +43,8 @@ const Stroke = styled.ellipse(avatarStyle.stroke)
41
43
  const Initials = styled.div(avatarStyle.initials)
42
44
 
43
45
  /**
46
+ * Avatars are used to represent people and other agents (e.g. bots).
47
+ *
44
48
  * @public
45
49
  */
46
50
  export const Avatar = forwardRef(function Avatar(
@@ -48,6 +52,7 @@ export const Avatar = forwardRef(function Avatar(
48
52
  ref: React.ForwardedRef<HTMLDivElement>,
49
53
  ) {
50
54
  const {
55
+ __unstable_hideInnerStroke,
51
56
  as: asProp,
52
57
  color: colorKey = 'gray',
53
58
  src,
@@ -140,13 +145,15 @@ export const Avatar = forwardRef(function Avatar(
140
145
  </defs>
141
146
 
142
147
  <circle cx={_radius} cy={_radius} r={_radius} fill={`url(#${imageId})`} />
143
- <BgStroke
144
- cx={_radius}
145
- cy={_radius}
146
- rx={_radius}
147
- ry={_radius}
148
- vectorEffect="non-scaling-stroke"
149
- />
148
+ {!__unstable_hideInnerStroke && (
149
+ <BgStroke
150
+ cx={_radius}
151
+ cy={_radius}
152
+ rx={_radius}
153
+ ry={_radius}
154
+ vectorEffect="non-scaling-stroke"
155
+ />
156
+ )}
150
157
  <Stroke
151
158
  cx={_radius}
152
159
  cy={_radius}
@@ -161,8 +168,8 @@ export const Avatar = forwardRef(function Avatar(
161
168
  {(imageFailed || !src) && initials && (
162
169
  <>
163
170
  <Initials>
164
- <Text as="span" size={initialsSize}>
165
- <strong>{initials}</strong>
171
+ <Text as="span" size={initialsSize} weight="medium">
172
+ {initials}
166
173
  </Text>
167
174
  </Initials>
168
175
  </>
@@ -36,7 +36,7 @@ function _avatarCounterBaseStyle(props: ThemeProps) {
36
36
  background: var(--card-bg-color);
37
37
  box-shadow:
38
38
  0 0 0 1px var(--card-bg-color),
39
- inset 0 0 0 1.5px var(--card-hairline-hard-color);
39
+ inset 0 0 0 1px var(--card-hairline-hard-color);
40
40
  padding: 0 ${rem(theme.sanity.space[2])};
41
41
 
42
42
  &:not([hidden]) {
@@ -73,8 +73,8 @@ export const AvatarCounter = forwardRef(function AvatarCounter(
73
73
 
74
74
  return (
75
75
  <Root $size={size} data-ui="AvatarCounter" ref={ref}>
76
- <Text as="span" size={counterSize}>
77
- <strong>{count}</strong>
76
+ <Text as="span" size={counterSize} weight="medium">
77
+ {count}
78
78
  </Text>
79
79
  </Root>
80
80
  )
@@ -152,7 +152,7 @@ function avatarBgStrokeStyle(): CSSObject {
152
152
 
153
153
  function avatarStrokeStyle(): CSSObject {
154
154
  return {
155
- strokeWidth: '3px',
155
+ strokeWidth: '2px',
156
156
 
157
157
  '[data-status="editing"] &': {
158
158
  strokeDasharray: '2 4',
@@ -4,7 +4,7 @@ import {useArrayProp} from '../../hooks'
4
4
  import {responsiveRadiusStyle, ResponsiveRadiusStyleProps} from '../../styles/internal'
5
5
  import {BadgeMode, BadgeTone} from '../../types'
6
6
  import {Box, BoxProps} from '../box'
7
- import {Label} from '../label'
7
+ import {Text} from '../text'
8
8
  import {ResponsiveRadiusProps} from '../types'
9
9
  import {badgeStyle} from './styles'
10
10
  import {BadgeStyleProps} from './types'
@@ -25,6 +25,8 @@ const Root = styled(Box)<BadgeStyleProps & ResponsiveRadiusStyleProps>(
25
25
  )
26
26
 
27
27
  /**
28
+ * Badges are used to tag resources.
29
+ *
28
30
  * @public
29
31
  */
30
32
  export const Badge = forwardRef(function Badge(
@@ -33,7 +35,7 @@ export const Badge = forwardRef(function Badge(
33
35
  ) {
34
36
  const {
35
37
  children,
36
- fontSize,
38
+ fontSize = 1,
37
39
  mode = 'default',
38
40
  padding = 1,
39
41
  radius = 2,
@@ -51,7 +53,9 @@ export const Badge = forwardRef(function Badge(
51
53
  padding={useArrayProp(padding)}
52
54
  ref={ref}
53
55
  >
54
- <Label size={fontSize}>{children}</Label>
56
+ <Text size={fontSize} weight="medium">
57
+ {children}
58
+ </Text>
55
59
  </Root>
56
60
  )
57
61
  })
@@ -51,6 +51,9 @@ const Root = styled.div<
51
51
  )
52
52
 
53
53
  /**
54
+ * The `Box` component is a basic layout wrapper component which provides utility properties
55
+ * for flex, margins and padding.
56
+ *
54
57
  * @public
55
58
  */
56
59
  export const Box = forwardRef(function Box(