@sanity/ui 2.9.0-corel.0 → 2.9.0

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 (98) hide show
  1. package/dist/_chunks-cjs/getTheme_v2.js +110 -54
  2. package/dist/_chunks-cjs/getTheme_v2.js.map +1 -1
  3. package/dist/_chunks-es/getTheme_v2.mjs +110 -54
  4. package/dist/_chunks-es/getTheme_v2.mjs.map +1 -1
  5. package/dist/_legacy/getTheme_v2.esm.js +110 -54
  6. package/dist/_legacy/getTheme_v2.esm.js.map +1 -1
  7. package/dist/index.d.mts +14 -21
  8. package/dist/index.d.ts +14 -21
  9. package/dist/index.esm.js +3327 -3068
  10. package/dist/index.esm.js.map +1 -1
  11. package/dist/index.js +3328 -3070
  12. package/dist/index.js.map +1 -1
  13. package/dist/index.mjs +3327 -3068
  14. package/dist/index.mjs.map +1 -1
  15. package/dist/theme.d.mts +8 -8
  16. package/dist/theme.d.ts +8 -8
  17. package/dist/theme.esm.js +1144 -592
  18. package/dist/theme.esm.js.map +1 -1
  19. package/dist/theme.js +1144 -592
  20. package/dist/theme.js.map +1 -1
  21. package/dist/theme.mjs +1144 -592
  22. package/dist/theme.mjs.map +1 -1
  23. package/package.json +60 -52
  24. package/src/core/__workshop__/constants.ts +15 -19
  25. package/src/core/components/breadcrumbs/__workshop__/example.tsx +1 -3
  26. package/src/core/components/breadcrumbs/__workshop__/index.ts +0 -5
  27. package/src/core/components/breadcrumbs/breadcrumbs.styles.ts +13 -1
  28. package/src/core/components/breadcrumbs/breadcrumbs.tsx +31 -39
  29. package/src/core/components/dialog/dialog.tsx +4 -2
  30. package/src/core/components/menu/__workshop__/tones.tsx +5 -6
  31. package/src/core/components/menu/menu.tsx +15 -11
  32. package/src/core/components/menu/menuButton.tsx +14 -36
  33. package/src/core/components/menu/menuGroup.tsx +2 -1
  34. package/src/core/components/menu/menuItem.tsx +4 -2
  35. package/src/core/components/tab/tabList.tsx +3 -11
  36. package/src/core/components/toast/__workshop__/hook.tsx +1 -1
  37. package/src/core/components/toast/toast.tsx +2 -2
  38. package/src/core/components/toast/toastProvider.tsx +5 -6
  39. package/src/core/components/toast/toastState.ts +6 -0
  40. package/src/core/constants.ts +1 -1
  41. package/src/core/hooks/useArrayProp.ts +14 -9
  42. package/src/core/hooks/useElementRect/__workshop__/example.tsx +2 -2
  43. package/src/core/primitives/avatar/avatarStack.tsx +2 -5
  44. package/src/core/primitives/badge/__workshop__/tones.tsx +6 -13
  45. package/src/core/primitives/button/__workshop__/custom.tsx +4 -3
  46. package/src/core/primitives/button/__workshop__/props.tsx +1 -1
  47. package/src/core/primitives/button/button.tsx +6 -11
  48. package/src/core/primitives/button/styles.ts +1 -1
  49. package/src/core/primitives/card/__workshop__/allTones.tsx +6 -8
  50. package/src/core/primitives/card/__workshop__/asButton.tsx +42 -24
  51. package/src/core/primitives/card/__workshop__/asComponent.tsx +1 -1
  52. package/src/core/primitives/card/__workshop__/checkered.tsx +17 -7
  53. package/src/core/primitives/card/__workshop__/interactive.tsx +10 -3
  54. package/src/core/primitives/card/__workshop__/listNavigation.tsx +5 -3
  55. package/src/core/primitives/card/__workshop__/props.tsx +7 -5
  56. package/src/core/primitives/card/__workshop__/selected.tsx +4 -1
  57. package/src/core/primitives/checkbox/__workshop__/tones.tsx +6 -0
  58. package/src/core/primitives/code/__workshop__/props.tsx +1 -1
  59. package/src/core/primitives/container/__workshop__/example.tsx +1 -1
  60. package/src/core/primitives/flex/__workshop__/example.tsx +3 -3
  61. package/src/core/primitives/flex/flex.tsx +1 -5
  62. package/src/core/primitives/grid/__workshop__/responsive.tsx +12 -12
  63. package/src/core/primitives/heading/__workshop__/opticalAlignment.tsx +13 -25
  64. package/src/core/primitives/heading/heading.tsx +1 -1
  65. package/src/core/primitives/inline/__workshop__/plain.tsx +3 -3
  66. package/src/core/primitives/label/__workshop__/opticalAlignment.tsx +6 -6
  67. package/src/core/primitives/popover/__workshop__/AlignedStory.tsx +1 -1
  68. package/src/core/primitives/popover/__workshop__/MatchReferenceWidthStory.tsx +3 -3
  69. package/src/core/primitives/popover/__workshop__/OpenOnMountStory.tsx +1 -1
  70. package/src/core/primitives/popover/__workshop__/PlainStory.tsx +1 -1
  71. package/src/core/primitives/popover/popover.tsx +6 -5
  72. package/src/core/primitives/radio/__workshop__/plain.tsx +2 -2
  73. package/src/core/primitives/select/__workshop__/readOnly.tsx +1 -1
  74. package/src/core/primitives/text/__workshop__/example.tsx +6 -6
  75. package/src/core/primitives/text/__workshop__/opticalAlignment.tsx +11 -21
  76. package/src/core/primitives/text/styles.ts +0 -1
  77. package/src/core/primitives/text/text.tsx +2 -4
  78. package/src/core/primitives/textArea/__workshop__/plain.tsx +1 -1
  79. package/src/core/primitives/textInput/__workshop__/index.ts +0 -5
  80. package/src/core/primitives/textInput/__workshop__/plain.tsx +1 -2
  81. package/src/core/primitives/textInput/__workshop__/readOnly.tsx +6 -2
  82. package/src/core/primitives/textInput/__workshop__/tones.tsx +38 -0
  83. package/src/core/styles/card/_cardColorStyle.ts +8 -8
  84. package/src/core/styles/flex/flexStyle.ts +0 -18
  85. package/src/core/styles/flex/types.ts +0 -2
  86. package/src/core/theme/__workshop__/debug/story.tsx +18 -11
  87. package/src/core/theme/themeProvider.tsx +4 -6
  88. package/src/core/utils/elementQuery/elementQuery.tsx +16 -17
  89. package/src/core/utils/layer/layerProvider.tsx +1 -1
  90. package/src/theme/build/_deprecated/color/muted/createMuted.ts +2 -2
  91. package/src/theme/build/buildColorTheme.ts +12 -8
  92. package/src/theme/build/renderColorTheme.ts +54 -232
  93. package/src/theme/defaults/colorTokens.ts +13 -18
  94. package/src/theme/system/color/_constants.ts +6 -10
  95. package/src/theme/versioning/themeColor_v0_v2.ts +26 -26
  96. package/src/theme/versioning/v0_v2.ts +4 -4
  97. package/src/core/components/breadcrumbs/__workshop__/buttons.tsx +0 -58
  98. package/src/core/primitives/textInput/__workshop__/multipleTones.tsx +0 -20
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sanity/ui",
3
- "version": "2.9.0-corel.0",
3
+ "version": "2.9.0",
4
4
  "keywords": [
5
5
  "sanity",
6
6
  "ui",
@@ -51,6 +51,32 @@
51
51
  "src",
52
52
  "theme.js"
53
53
  ],
54
+ "scripts": {
55
+ "build": "run-s clean pkg:build pkg:check figma:pkg:build",
56
+ "clean": "rimraf .workshop dist",
57
+ "commit": "cz",
58
+ "cypress:dev": "run-p dev cypress:open",
59
+ "cypress:open": "cypress open",
60
+ "cypress:run": "cypress run",
61
+ "dev": "run-p storybook:dev workshop:dev",
62
+ "figma:pkg:build": "cd figma && pnpm build",
63
+ "format": "prettier --write --cache --ignore-unknown .",
64
+ "lint": "eslint . --ext .cjs,.js,.jsx,.mjs,.ts,.tsx",
65
+ "pkg:build": "pkg build --strict",
66
+ "pkg:check": "pkg --strict",
67
+ "prepare": "husky install",
68
+ "prepack": "pnpm build",
69
+ "release": "semantic-release",
70
+ "storybook:build": "storybook build",
71
+ "storybook:dev": "storybook dev -p 6006",
72
+ "test": "jest",
73
+ "test:browser": "start-server-and-test 'run-s workshop:build workshop:start' http://localhost:1337 'run-s cypress:run'",
74
+ "ts:check": "tsc",
75
+ "watch": "pkg watch --strict",
76
+ "workshop:build": "workshop build",
77
+ "workshop:dev": "workshop dev",
78
+ "workshop:start": "http-server -a localhost -c-0 -p 1337 -s -P http://localhost:1337/index.html? dist"
79
+ },
54
80
  "commitlint": {
55
81
  "extends": [
56
82
  "@commitlint/config-conventional"
@@ -84,6 +110,7 @@
84
110
  "@sanity/icons": "^3.4.0",
85
111
  "csstype": "^3.1.3",
86
112
  "framer-motion": "11.0.8",
113
+ "react-compiler-runtime": "19.0.0-beta-df7b47d-20241124",
87
114
  "react-refractor": "^2.2.0",
88
115
  "use-effect-event": "^1.0.2"
89
116
  },
@@ -95,24 +122,24 @@
95
122
  "@commitlint/cli": "^19.4.0",
96
123
  "@commitlint/config-conventional": "^19.2.2",
97
124
  "@juggle/resize-observer": "^3.4.0",
98
- "@sanity/pkg-utils": "^6.11.7",
99
- "@sanity/prettier-config": "^1.0.2",
125
+ "@sanity/pkg-utils": "^6.11.11",
126
+ "@sanity/prettier-config": "^1.0.3",
100
127
  "@sanity/semantic-release-preset": "^5.0.0",
101
128
  "@sanity/ui-workshop": "^2.0.16",
102
- "@storybook/addon-a11y": "^8.3.6",
103
- "@storybook/addon-docs": "^8.3.6",
104
- "@storybook/addon-essentials": "^8.3.6",
105
- "@storybook/addon-interactions": "^8.3.6",
106
- "@storybook/addon-links": "^8.3.6",
107
- "@storybook/addon-mdx-gfm": "^8.3.6",
108
- "@storybook/addon-storysource": "^8.3.6",
109
- "@storybook/addon-themes": "^8.3.6",
110
- "@storybook/blocks": "^8.3.6",
111
- "@storybook/manager-api": "^8.3.6",
112
- "@storybook/react": "^8.3.6",
113
- "@storybook/react-vite": "^8.3.6",
114
- "@storybook/test": "^8.3.6",
115
- "@storybook/theming": "^8.3.6",
129
+ "@storybook/addon-a11y": "^8.4.5",
130
+ "@storybook/addon-docs": "^8.4.5",
131
+ "@storybook/addon-essentials": "^8.4.5",
132
+ "@storybook/addon-interactions": "^8.4.5",
133
+ "@storybook/addon-links": "^8.4.5",
134
+ "@storybook/addon-mdx-gfm": "^8.4.5",
135
+ "@storybook/addon-storysource": "^8.4.5",
136
+ "@storybook/addon-themes": "^8.4.5",
137
+ "@storybook/blocks": "^8.4.5",
138
+ "@storybook/manager-api": "^8.4.5",
139
+ "@storybook/react": "^8.4.5",
140
+ "@storybook/react-vite": "^8.4.5",
141
+ "@storybook/test": "^8.4.5",
142
+ "@storybook/theming": "^8.4.5",
116
143
  "@testing-library/dom": "^10.4.0",
117
144
  "@testing-library/jest-dom": "^6.6.2",
118
145
  "@testing-library/react": "^16.0.1",
@@ -127,7 +154,7 @@
127
154
  "@typescript-eslint/eslint-plugin": "^7.18.0",
128
155
  "@typescript-eslint/parser": "^7.18.0",
129
156
  "@vitejs/plugin-react": "^4.3.3",
130
- "babel-plugin-react-compiler": "beta",
157
+ "babel-plugin-react-compiler": "19.0.0-beta-df7b47d-20241124",
131
158
  "commitizen": "^4.3.0",
132
159
  "cypress": "^13.13.2",
133
160
  "cypress-real-events": "^1.13.0",
@@ -139,9 +166,9 @@
139
166
  "eslint-plugin-jsx-a11y": "^6.10.2",
140
167
  "eslint-plugin-prettier": "^5.2.1",
141
168
  "eslint-plugin-react": "^7.37.2",
142
- "eslint-plugin-react-compiler": "beta",
169
+ "eslint-plugin-react-compiler": "19.0.0-beta-df7b47d-20241124",
143
170
  "eslint-plugin-react-hooks": "^5.0.0",
144
- "eslint-plugin-storybook": "^0.10.1",
171
+ "eslint-plugin-storybook": "^0.11.0",
145
172
  "http-server": "^14.1.1",
146
173
  "husky": "^8.0.3",
147
174
  "jest": "^29.7.0",
@@ -152,57 +179,38 @@
152
179
  "npm-run-all2": "^5.0.2",
153
180
  "prettier": "^3.3.3",
154
181
  "react": "^18.3.1",
155
- "react-compiler-runtime": "beta",
156
182
  "react-dom": "^18.3.1",
157
183
  "react-is": "^18.3.1",
158
184
  "refractor": "^4.8.1",
159
185
  "rimraf": "^5.0.5",
160
186
  "semantic-release": "^24.0.0",
161
187
  "start-server-and-test": "^2.0.5",
162
- "storybook": "^8.3.6",
188
+ "storybook": "^8.4.5",
163
189
  "styled-components": "^6.1.13",
164
190
  "tsconfig-paths": "^4.2.0",
165
- "typescript": "5.5.3",
166
- "vite": "^5.4.2",
191
+ "typescript": "5.6.3",
192
+ "vite": "^5.4.11",
167
193
  "vite-tsconfig-paths": "^5.0.1"
168
194
  },
169
195
  "peerDependencies": {
170
- "react": "^18",
171
- "react-dom": "^18",
172
- "react-is": "^18",
196
+ "react": "^18 || >=19.0.0-0",
197
+ "react-dom": "^18 || >=19.0.0-0",
198
+ "react-is": "^18 || >=19.0.0-0",
173
199
  "styled-components": "^5.2 || ^6"
174
200
  },
201
+ "packageManager": "pnpm@9.12.3",
175
202
  "engines": {
176
203
  "node": ">=14.0.0"
177
204
  },
178
205
  "publishConfig": {
179
206
  "access": "public"
180
207
  },
208
+ "pnpm": {
209
+ "overrides": {
210
+ "conventional-changelog-conventionalcommits": ">= 8.0.0"
211
+ }
212
+ },
181
213
  "esm.sh": {
182
214
  "bundle": false
183
- },
184
- "scripts": {
185
- "build": "run-s clean pkg:build pkg:check figma:pkg:build",
186
- "clean": "rimraf .workshop dist",
187
- "commit": "cz",
188
- "cypress:dev": "run-p dev cypress:open",
189
- "cypress:open": "cypress open",
190
- "cypress:run": "cypress run",
191
- "dev": "run-p storybook:dev workshop:dev",
192
- "figma:pkg:build": "cd figma && pnpm build",
193
- "format": "prettier --write --cache --ignore-unknown .",
194
- "lint": "eslint . --ext .cjs,.js,.jsx,.mjs,.ts,.tsx",
195
- "pkg:build": "pkg build --strict",
196
- "pkg:check": "pkg --strict",
197
- "release": "semantic-release",
198
- "storybook:build": "storybook build",
199
- "storybook:dev": "storybook dev -p 6006",
200
- "test": "jest",
201
- "test:browser": "start-server-and-test 'run-s workshop:build workshop:start' http://localhost:1337 'run-s cypress:run'",
202
- "ts:check": "tsc",
203
- "watch": "pkg watch --strict",
204
- "workshop:build": "workshop build",
205
- "workshop:dev": "workshop dev",
206
- "workshop:start": "http-server -a localhost -c-0 -p 1337 -s -P http://localhost:1337/index.html? dist"
207
215
  }
208
- }
216
+ }
@@ -14,7 +14,7 @@ import {
14
14
  TextAlign,
15
15
  TextInputType,
16
16
  } from '@sanity/ui'
17
- import {ThemeColorSpotKey, ThemeColorToneKey, ThemeFontWeightKey} from '@sanity/ui/theme'
17
+ import {ThemeColorAvatarColorKey, ThemeFontWeightKey} from '@sanity/ui/theme'
18
18
 
19
19
  export const WORKSHOP_AVATAR_SIZE_OPTIONS: {[key: string]: AvatarSize} = {
20
20
  '0': 0,
@@ -31,6 +31,7 @@ export const WORKSHOP_BADGE_MODE_OPTIONS: {[key: string]: BadgeMode} = {
31
31
  export const WORKSHOP_BADGE_TONE_OPTIONS: {[key: string]: BadgeTone} = {
32
32
  Default: 'default',
33
33
  Primary: 'primary',
34
+ Suggest: 'suggest',
34
35
  Positive: 'positive',
35
36
  Caution: 'caution',
36
37
  Critical: 'critical',
@@ -51,7 +52,9 @@ export const WORKSHOP_BUTTON_TEXT_ALIGN_OPTIONS: {[key: string]: ButtonTextAlign
51
52
 
52
53
  export const WORKSHOP_BUTTON_TONE_OPTIONS: {[key: string]: ButtonTone} = {
53
54
  Default: 'default',
55
+ Neutral: 'neutral',
54
56
  Primary: 'primary',
57
+ Suggest: 'suggest',
55
58
  Positive: 'positive',
56
59
  Caution: 'caution',
57
60
  Critical: 'critical',
@@ -69,13 +72,15 @@ export const WORKSHOP_CARD_AS_OPTIONS: {
69
72
  }
70
73
 
71
74
  export const WORKSHOP_CARD_TONE_OPTIONS: {[key: string]: CardTone} = {
72
- Default: 'default',
73
- Inherit: 'inherit',
74
- Transparent: 'transparent',
75
- Primary: 'primary',
76
- Positive: 'positive',
77
- Caution: 'caution',
78
- Critical: 'critical',
75
+ 'Inherit': 'inherit',
76
+ 'Transparent': 'transparent',
77
+ 'Default': 'default',
78
+ 'Neutral': 'neutral',
79
+ 'Primary (deprecated)': 'primary',
80
+ 'Suggest': 'suggest',
81
+ 'Positive': 'positive',
82
+ 'Caution': 'caution',
83
+ 'Critical': 'critical',
79
84
  }
80
85
 
81
86
  export const WORKSHOP_CODE_LANGUAGE_OPTIONS = {
@@ -203,7 +208,7 @@ export const WORKSHOP_SPACE_OPTIONS = {
203
208
  '9': 9,
204
209
  }
205
210
 
206
- export const WORKSHOP_SPOT_COLOR_OPTIONS: {[key: string]: ThemeColorSpotKey} = {
211
+ export const WORKSHOP_SPOT_COLOR_OPTIONS: {[key: string]: ThemeColorAvatarColorKey} = {
207
212
  Gray: 'gray',
208
213
  Blue: 'blue',
209
214
  Purple: 'purple',
@@ -260,21 +265,12 @@ export const WORKSHOP_TEXT_SIZE_OPTIONS = {
260
265
  }
261
266
 
262
267
  export const WORKSHOP_TEXT_WEIGHT_OPTIONS: {[key: string]: ThemeFontWeightKey | ''} = {
263
- Regular: 'regular',
268
+ Regular: '',
264
269
  Medium: 'medium',
265
270
  Semibold: 'semibold',
266
271
  Bold: 'bold',
267
272
  }
268
273
 
269
- export const WORKSHOP_THEME_COLOR_TONE_OPTIONS: {[key: string]: ThemeColorToneKey} = {
270
- Default: 'default',
271
- Transparent: 'transparent',
272
- Primary: 'primary',
273
- Positive: 'positive',
274
- Caution: 'caution',
275
- Critical: 'critical',
276
- }
277
-
278
274
  export const WORKSHOP_TOAST_STATUS_OPTIONS: {
279
275
  [key: string]: 'error' | 'success' | 'warning' | 'info' | ''
280
276
  } = {
@@ -19,15 +19,13 @@ export default function Example() {
19
19
  return (
20
20
  <Flex align="center" height="fill" justify="center">
21
21
  <Breadcrumbs
22
- gapX={1}
23
- gapY={3}
24
22
  maxLength={maxLength}
25
23
  separator={
26
24
  <Text muted size={1}>
27
25
  /
28
26
  </Text>
29
27
  }
30
- // space={2}
28
+ space={2}
31
29
  >
32
30
  <Text size={1}>
33
31
  <a href="#">Root</a>
@@ -10,10 +10,5 @@ export default defineScope({
10
10
  title: 'Example',
11
11
  component: lazy(() => import('./example')),
12
12
  },
13
- {
14
- name: 'buttons',
15
- title: 'Buttons',
16
- component: lazy(() => import('./buttons')),
17
- },
18
13
  ],
19
14
  })
@@ -1,5 +1,17 @@
1
1
  import {styled} from 'styled-components'
2
+ import {Button} from '../../primitives'
2
3
 
3
- export const Root = styled.nav`
4
+ export const Root = styled.ol`
5
+ margin: 0;
6
+ padding: 0;
7
+ display: flex;
8
+ list-style: none;
9
+ align-items: center;
10
+ white-space: nowrap;
4
11
  line-height: 0;
5
12
  `
13
+
14
+ export const ExpandButton = styled(Button)`
15
+ appearance: none;
16
+ margin: -4px;
17
+ `
@@ -1,19 +1,23 @@
1
- import {Children, forwardRef, isValidElement, useCallback, useMemo, useRef, useState} from 'react'
2
- import {useClickOutsideEvent} from '../../hooks'
3
- import {Box, Button, ButtonProps, Flex, Popover, Stack, Text} from '../../primitives'
4
- import {Root} from './breadcrumbs.styles'
1
+ import {
2
+ Children,
3
+ forwardRef,
4
+ Fragment,
5
+ isValidElement,
6
+ useCallback,
7
+ useMemo,
8
+ useRef,
9
+ useState,
10
+ } from 'react'
11
+ import {useArrayProp, useClickOutsideEvent} from '../../hooks'
12
+ import {Box, Popover, Stack, Text} from '../../primitives'
13
+ import {ExpandButton, Root} from './breadcrumbs.styles'
5
14
 
6
15
  /**
7
16
  * @beta
8
17
  */
9
18
  export interface BreadcrumbsProps {
10
- expandButton?: Omit<ButtonProps, 'onClick' | 'selected'>
11
- gap?: number | number[]
12
- gapX?: number | number[]
13
- gapY?: number | number[]
14
19
  maxLength?: number
15
20
  separator?: React.ReactNode
16
- /** @deprecated - Use `gap`, `gapX`, `gapY` instead */
17
21
  space?: number | number[]
18
22
  }
19
23
 
@@ -24,19 +28,8 @@ export const Breadcrumbs = forwardRef(function Breadcrumbs(
24
28
  props: BreadcrumbsProps & Omit<React.HTMLProps<HTMLOListElement>, 'as' | 'ref' | 'type'>,
25
29
  ref: React.ForwardedRef<HTMLOListElement>,
26
30
  ) {
27
- const {
28
- children,
29
- expandButton: expandButtonProps,
30
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
31
- gap: _gapProp,
32
- gapX = props.gap ?? props.space ?? 2,
33
- gapY = props.gap ?? props.space ?? 2,
34
- maxLength,
35
- separator,
36
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
37
- space: _spaceProp,
38
- ...restProps
39
- } = props
31
+ const {children, maxLength, separator, space: spaceRaw = 2, ...restProps} = props
32
+ const space = useArrayProp(spaceRaw)
40
33
  const [open, setOpen] = useState(false)
41
34
  const expandElementRef = useRef<HTMLButtonElement | null>(null)
42
35
  const popoverElementRef = useRef<HTMLDivElement | null>(null)
@@ -60,25 +53,24 @@ export const Breadcrumbs = forwardRef(function Breadcrumbs(
60
53
  <Popover
61
54
  constrainSize
62
55
  content={
63
- <Stack as="ol" overflow="auto" space={gapY}>
56
+ <Stack as="ol" overflow="auto" padding={space} space={space}>
64
57
  {rawItems.slice(beforeLength - 1, len - afterLength)}
65
58
  </Stack>
66
59
  }
67
60
  key="button"
68
61
  open={open}
69
- padding={2}
70
62
  placement="top"
71
63
  portal
72
64
  ref={popoverElementRef}
73
65
  >
74
- <Button
66
+ <ExpandButton
67
+ fontSize={1}
75
68
  mode="bleed"
76
- padding={0}
77
- text="…"
78
- {...expandButtonProps}
79
69
  onClick={open ? collapse : expand}
70
+ padding={1}
80
71
  ref={expandElementRef}
81
72
  selected={open}
73
+ text="…"
82
74
  />
83
75
  </Popover>,
84
76
  ...rawItems.slice(len - afterLength),
@@ -86,20 +78,20 @@ export const Breadcrumbs = forwardRef(function Breadcrumbs(
86
78
  }
87
79
 
88
80
  return rawItems
89
- }, [collapse, expand, expandButtonProps, gapY, maxLength, open, rawItems])
90
-
91
- const len = items.length
81
+ }, [collapse, expand, maxLength, open, rawItems, space])
92
82
 
93
83
  return (
94
84
  <Root data-ui="Breadcrumbs" {...restProps} ref={ref}>
95
- <Flex align="flex-start" as="ol" gapX={gapX} gapY={gapY} wrap="wrap">
96
- {items.map((item, itemIndex) => (
97
- <Flex align="flex-start" as="li" gapX={gapX} gapY={gapY} key={itemIndex}>
98
- <Box>{item}</Box>
99
- {itemIndex < len - 1 && <Box aria-hidden>{separator || <Text muted>/</Text>}</Box>}
100
- </Flex>
101
- ))}
102
- </Flex>
85
+ {items.map((item, itemIndex) => (
86
+ <Fragment key={itemIndex}>
87
+ {itemIndex > 0 && (
88
+ <Box aria-hidden as="li" paddingX={space}>
89
+ {separator || <Text muted>/</Text>}
90
+ </Box>
91
+ )}
92
+ <Box as="li">{item}</Box>
93
+ </Fragment>
94
+ ))}
103
95
  </Root>
104
96
  )
105
97
  })
@@ -305,13 +305,15 @@ export const Dialog = forwardRef(function Dialog(
305
305
  onFocus,
306
306
  padding: paddingProp = 3,
307
307
  portal: portalProp,
308
- position: positionProp = dialog.position || 'fixed',
308
+ position: _positionProp,
309
309
  scheme,
310
310
  width: widthProp = 0,
311
- zOffset: zOffsetProp = dialog.zOffset || layer.dialog.zOffset,
311
+ zOffset: _zOffsetProp,
312
312
  animate: _animate = false,
313
313
  ...restProps
314
314
  } = props
315
+ const positionProp = _positionProp ?? (dialog.position || 'fixed')
316
+ const zOffsetProp = _zOffsetProp ?? (dialog.zOffset || layer.dialog.zOffset)
315
317
  const prefersReducedMotion = usePrefersReducedMotion()
316
318
  const animate = prefersReducedMotion ? false : _animate
317
319
  const portal = usePortal()
@@ -1,5 +1,6 @@
1
- import {SearchIcon} from '@sanity/icons'
1
+ import {CubeIcon} from '@sanity/icons'
2
2
  import {Box, Card, LayerProvider, Menu, MenuItem} from '@sanity/ui'
3
+ import {THEME_COLOR_STATE_TONES} from '@sanity/ui/theme'
3
4
  import {useBoolean, useSelect} from '@sanity/ui-workshop'
4
5
  import {WORKSHOP_CARD_TONE_OPTIONS} from '../../../__workshop__/constants'
5
6
 
@@ -12,11 +13,9 @@ export default function TonesStory() {
12
13
  <Box padding={[4, 5, 6]}>
13
14
  <Card radius={3} shadow={3} tone={parentTone}>
14
15
  <Menu>
15
- <MenuItem disabled={disabled} icon={SearchIcon} text="Default" tone="default" />
16
- <MenuItem disabled={disabled} icon={SearchIcon} text="Primary" tone="primary" />
17
- <MenuItem disabled={disabled} icon={SearchIcon} text="Positive" tone="positive" />
18
- <MenuItem disabled={disabled} icon={SearchIcon} text="Caution" tone="caution" />
19
- <MenuItem disabled={disabled} icon={SearchIcon} text="Critical" tone="critical" />
16
+ {THEME_COLOR_STATE_TONES.map((tone) => (
17
+ <MenuItem disabled={disabled} icon={CubeIcon} key={tone} text={tone} tone={tone} />
18
+ ))}
20
19
  </Menu>
21
20
  </Card>
22
21
  </Box>
@@ -14,19 +14,21 @@ export interface MenuProps extends ResponsivePaddingProps {
14
14
  /**
15
15
  * @deprecated Use `shouldFocus="first"` instead.
16
16
  */
17
- focusFirst?: boolean
17
+ 'focusFirst'?: boolean
18
18
  /**
19
19
  * @deprecated Use `shouldFocus="last"` instead.
20
20
  */
21
- focusLast?: boolean
22
- onClickOutside?: (event: MouseEvent) => void
23
- onEscape?: () => void
24
- onItemClick?: () => void
25
- onItemSelect?: (index: number) => void
26
- originElement?: HTMLElement | null
27
- registerElement?: (el: HTMLElement) => () => void
28
- shouldFocus?: 'first' | 'last' | null
29
- space?: number | number[]
21
+ 'focusLast'?: boolean
22
+ 'onClickOutside'?: (event: MouseEvent) => void
23
+ 'onEscape'?: () => void
24
+ 'onItemClick'?: () => void
25
+ 'onItemSelect'?: (index: number) => void
26
+ 'originElement'?: HTMLElement | null
27
+ 'registerElement'?: (el: HTMLElement) => () => void
28
+ 'shouldFocus'?: 'first' | 'last' | null
29
+ 'space'?: number | number[]
30
+ 'aria-labelledby'?: string
31
+ 'onBlurCapture'?: (event: FocusEvent) => void
30
32
  }
31
33
 
32
34
  const Root = styled(Box)`
@@ -57,10 +59,12 @@ export const Menu = forwardRef(function Menu(
57
59
  originElement,
58
60
  padding = 1,
59
61
  registerElement,
60
- shouldFocus = (props.focusFirst && 'first') || (props.focusLast && 'last') || null,
62
+ shouldFocus: _shouldFocus,
61
63
  space = 1,
62
64
  ...restProps
63
65
  } = props
66
+ const shouldFocus =
67
+ _shouldFocus ?? ((props.focusFirst && 'first') || (props.focusLast && 'last') || null)
64
68
 
65
69
  const ref = useRef<HTMLDivElement | null>(null)
66
70
 
@@ -169,7 +169,7 @@ export const MenuButton = forwardRef(function MenuButton(
169
169
  }, [buttonElement, disableRestoreFocusOnClose])
170
170
 
171
171
  const handleBlur = useCallback(
172
- (event: React.FocusEvent<HTMLButtonElement>) => {
172
+ (event: FocusEvent) => {
173
173
  const target = event.relatedTarget
174
174
 
175
175
  if (!(target instanceof Node)) {
@@ -199,32 +199,19 @@ export const MenuButton = forwardRef(function MenuButton(
199
199
  return () => setChildMenuElements((els) => els.filter((_el) => _el !== el))
200
200
  }, [])
201
201
 
202
- const menuProps: MenuProps = useMemo(
203
- () => ({
204
- 'aria-labelledby': id,
205
- 'onBlurCapture': handleBlur,
206
- 'onClickOutside': handleMenuClickOutside,
207
- 'onEscape': handleMenuEscape,
208
- 'onItemClick': handleItemClick,
209
- 'originElement': buttonElement,
210
- registerElement,
211
- shouldFocus,
212
- }),
213
- [
214
- buttonElement,
215
- handleMenuClickOutside,
216
- handleMenuEscape,
217
- handleItemClick,
218
- id,
219
- handleBlur,
220
- registerElement,
221
- shouldFocus,
222
- ],
223
- )
202
+ const menuProps: MenuProps = {
203
+ 'aria-labelledby': id,
204
+ 'onBlurCapture': handleBlur,
205
+ 'onClickOutside': handleMenuClickOutside,
206
+ 'onEscape': handleMenuEscape,
207
+ 'onItemClick': handleItemClick,
208
+ 'originElement': buttonElement,
209
+ registerElement,
210
+ shouldFocus,
211
+ }
224
212
 
225
213
  const menu = menuProp && cloneElement(menuProp, menuProps)
226
214
 
227
- const ref = useRef<HTMLButtonElement | null>(null)
228
215
  const button = useMemo(
229
216
  () =>
230
217
  buttonProp &&
@@ -236,7 +223,7 @@ export const MenuButton = forwardRef(function MenuButton(
236
223
  'onMouseDown': handleMouseDown,
237
224
  'aria-haspopup': true,
238
225
  'aria-expanded': open,
239
- 'ref': ref,
226
+ 'ref': setButtonElement,
240
227
  'selected': buttonProp.props.selected ?? open,
241
228
  }),
242
229
  [buttonProp, handleButtonClick, handleButtonKeyDown, handleMouseDown, id, open],
@@ -245,19 +232,10 @@ export const MenuButton = forwardRef(function MenuButton(
245
232
  // Forward button ref to parent
246
233
  useImperativeHandle<HTMLButtonElement | null, HTMLButtonElement | null>(
247
234
  forwardedRef,
248
- () => ref.current,
235
+ () => buttonElement,
236
+ [buttonElement],
249
237
  )
250
238
 
251
- // If there's a button then we need to set the reference element to the cloned button ref
252
- // and if button changes we make sure to update or remove the reference element.
253
- useEffect(() => {
254
- if (!button) return undefined
255
-
256
- setButtonElement(ref.current)
257
-
258
- return () => setButtonElement(null)
259
- }, [button])
260
-
261
239
  const popoverProps: MenuButtonProps['popover'] = useMemo(
262
240
  () => ({
263
241
  boundaryElement: deprecated_boundaryElement,
@@ -53,9 +53,10 @@ export function MenuGroup(
53
53
  onClickOutside,
54
54
  onEscape,
55
55
  onItemClick,
56
- onItemMouseEnter = menu.onMouseEnter,
56
+ onItemMouseEnter: _onItemMouseEnter,
57
57
  registerElement,
58
58
  } = menu
59
+ const onItemMouseEnter = _onItemMouseEnter ?? menu.onMouseEnter
59
60
  const [rootElement, setRootElement] = useState<HTMLButtonElement | HTMLDivElement | null>(null)
60
61
  const [open, setOpen] = useState(false)
61
62
  const [shouldFocus, setShouldFocus] = useState<'first' | 'last' | null>(null)
@@ -72,9 +72,11 @@ export const MenuItem = forwardRef(function MenuItem(
72
72
  activeElement,
73
73
  mount,
74
74
  onItemClick,
75
- onItemMouseEnter = menu.onMouseEnter,
76
- onItemMouseLeave = menu.onMouseLeave,
75
+ onItemMouseEnter: _onItemMouseEnter,
76
+ onItemMouseLeave: _onItemMouseLeave,
77
77
  } = menu
78
+ const onItemMouseEnter = _onItemMouseEnter ?? menu.onMouseEnter
79
+ const onItemMouseLeave = _onItemMouseLeave ?? menu.onMouseLeave
78
80
  const [rootElement, setRootElement] = useState<HTMLDivElement | null>(null)
79
81
  const active = Boolean(activeElement) && activeElement === rootElement
80
82
  const ref = useRef<HTMLDivElement | null>(null)