@sanity/ui 4.2.0 → 5.0.0-alpha.10

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 (339) hide show
  1. package/README.md +194 -28
  2. package/bin/sanity-ui.js +14 -0
  3. package/dist/_chunks-es/LazyRefractor.js +20 -0
  4. package/dist/_chunks-es/LazyRefractor.js.map +1 -0
  5. package/dist/cli/checks.js +148 -0
  6. package/dist/cli/config.js +23 -0
  7. package/dist/cli/detect.js +181 -0
  8. package/dist/cli/doctor.js +49 -0
  9. package/dist/cli/index.js +69 -0
  10. package/dist/cli/init.js +189 -0
  11. package/dist/cli/install.js +79 -0
  12. package/dist/cli/log.js +66 -0
  13. package/dist/cli/selfPackage.js +11 -0
  14. package/dist/cli/styles.js +185 -0
  15. package/dist/cli/test-utils.js +8 -0
  16. package/dist/cli/tsconfig.js +236 -0
  17. package/dist/cli/types.js +1 -0
  18. package/dist/cli/versions.js +45 -0
  19. package/dist/index.d.ts +1203 -1469
  20. package/dist/index.js +2123 -1989
  21. package/dist/index.js.map +1 -1
  22. package/dist/polyfills.d.ts +1 -0
  23. package/dist/polyfills.js +5 -0
  24. package/dist/polyfills.js.map +1 -0
  25. package/dist/styles.css +1 -547
  26. package/package.json +57 -58
  27. package/src/cli/checks.test.ts +38 -0
  28. package/src/cli/checks.ts +200 -0
  29. package/src/cli/config.ts +44 -0
  30. package/src/cli/detect.test.ts +191 -0
  31. package/src/cli/detect.ts +205 -0
  32. package/src/cli/doctor.test.ts +52 -0
  33. package/src/cli/doctor.ts +65 -0
  34. package/src/cli/index.ts +77 -0
  35. package/src/cli/init.ts +225 -0
  36. package/src/cli/install.test.ts +52 -0
  37. package/src/cli/install.ts +108 -0
  38. package/src/cli/log.ts +79 -0
  39. package/src/cli/selfPackage.ts +14 -0
  40. package/src/cli/styles.test.ts +130 -0
  41. package/src/cli/styles.ts +205 -0
  42. package/src/cli/test-utils.ts +10 -0
  43. package/src/cli/tsconfig.test.ts +174 -0
  44. package/src/cli/tsconfig.ts +282 -0
  45. package/src/cli/types.ts +77 -0
  46. package/src/cli/versions.test.ts +35 -0
  47. package/src/cli/versions.ts +41 -0
  48. package/src/components/badge/Badge.tsx +53 -0
  49. package/src/components/badge/badge.css +6 -0
  50. package/src/components/badge/badge.props.ts +31 -0
  51. package/src/components/box/Box.tsx +30 -0
  52. package/src/components/box/box.css +4 -0
  53. package/src/components/box/box.props.ts +29 -0
  54. package/src/components/button/Button.tsx +78 -0
  55. package/src/components/button/button.css +72 -0
  56. package/src/components/button/button.props.ts +122 -0
  57. package/src/components/card/Card.tsx +31 -0
  58. package/src/components/card/card.css +4 -0
  59. package/src/components/card/card.props.ts +58 -0
  60. package/src/components/checkbox/Checkbox.tsx +64 -0
  61. package/src/components/checkbox/checkbox.css +100 -0
  62. package/src/components/checkbox/checkbox.props.ts +33 -0
  63. package/src/components/code/Code.tsx +38 -0
  64. package/src/components/code/LazyRefractor.tsx +9 -0
  65. package/src/components/code/code.css +40 -0
  66. package/src/components/code/code.props.ts +44 -0
  67. package/src/components/container/Container.tsx +30 -0
  68. package/src/components/container/container.css +4 -0
  69. package/src/components/container/container.props.ts +28 -0
  70. package/src/components/dialog/Dialog.tsx +139 -0
  71. package/src/components/dialog/dialog.css +49 -0
  72. package/src/components/dialog/dialog.props.ts +45 -0
  73. package/src/components/divider/Divider.tsx +23 -0
  74. package/src/components/divider/divider.props.ts +9 -0
  75. package/src/components/eyebrow/Eyebrow.tsx +54 -0
  76. package/src/components/eyebrow/eyebrow.css +11 -0
  77. package/src/components/eyebrow/eyebrow.props.ts +28 -0
  78. package/src/components/flex/Flex.tsx +30 -0
  79. package/src/components/flex/flex.css +4 -0
  80. package/src/components/flex/flex.props.ts +33 -0
  81. package/src/components/grid/Grid.tsx +30 -0
  82. package/src/components/grid/grid.css +4 -0
  83. package/src/components/grid/grid.props.ts +33 -0
  84. package/src/components/h-stack/HStack.tsx +34 -0
  85. package/src/components/h-stack/hStack.props.ts +17 -0
  86. package/src/components/heading/Heading.tsx +54 -0
  87. package/src/components/heading/heading.css +9 -0
  88. package/src/components/heading/heading.props.ts +31 -0
  89. package/src/components/icon/Icon.tsx +24 -0
  90. package/src/components/icon/icon.css +17 -0
  91. package/src/components/icon/icon.props.ts +35 -0
  92. package/src/components/icon-button/IconButton.tsx +32 -0
  93. package/src/components/icon-button/iconButton.props.ts +31 -0
  94. package/src/components/index.css +28 -0
  95. package/src/components/indicator/Indicator.tsx +42 -0
  96. package/src/components/indicator/indicator.css +4 -0
  97. package/src/components/indicator/indicator.props.ts +24 -0
  98. package/src/components/indicator-stack/IndicatorStack.tsx +31 -0
  99. package/src/components/indicator-stack/indicator-stack.css +7 -0
  100. package/src/components/indicator-stack/indicatorStack.props.ts +15 -0
  101. package/src/components/inline/Inline.tsx +38 -0
  102. package/src/components/inline/inline.css +4 -0
  103. package/src/components/inline/inline.props.ts +100 -0
  104. package/src/components/label/Label.tsx +34 -0
  105. package/src/components/label/label.css +3 -0
  106. package/src/components/label/label.props.ts +25 -0
  107. package/src/components/link/Link.tsx +29 -0
  108. package/src/components/link/link.css +12 -0
  109. package/src/components/link/link.props.ts +23 -0
  110. package/src/components/list/List.tsx +167 -0
  111. package/src/components/list/list.css +25 -0
  112. package/src/components/list/list.props.ts +130 -0
  113. package/src/components/popover/Popover.tsx +85 -0
  114. package/src/components/popover/popover.css +21 -0
  115. package/src/components/popover/popover.props.ts +38 -0
  116. package/src/components/press-area/PressArea.tsx +29 -0
  117. package/src/components/press-area/press-area.css +22 -0
  118. package/src/components/press-area/pressArea.props.ts +16 -0
  119. package/src/components/radio/Radio.tsx +48 -0
  120. package/src/components/radio/radio.css +97 -0
  121. package/src/components/radio/radio.props.ts +25 -0
  122. package/src/components/skip-to-content/SkipToContent.tsx +35 -0
  123. package/src/components/skip-to-content/skip-to-content.css +9 -0
  124. package/src/components/skip-to-content/skipToContent.props.ts +25 -0
  125. package/src/components/spinner/Spinner.tsx +28 -0
  126. package/src/components/spinner/spinner.css +10 -0
  127. package/src/components/spinner/spinner.props.ts +19 -0
  128. package/src/components/switch/Switch.tsx +48 -0
  129. package/src/components/switch/switch.css +119 -0
  130. package/src/components/switch/switch.props.ts +25 -0
  131. package/src/components/text/Text.tsx +53 -0
  132. package/src/components/text/text.css +9 -0
  133. package/src/components/text/text.props.ts +28 -0
  134. package/src/components/tooltip/Tooltip.tsx +97 -0
  135. package/src/components/tooltip/tooltip.css +31 -0
  136. package/src/components/tooltip/tooltip.props.ts +36 -0
  137. package/src/components/tooltip-group/TooltipGroup.tsx +64 -0
  138. package/src/components/tooltip-group/tooltipGroup.props.ts +15 -0
  139. package/src/components/v-stack/VStack.tsx +32 -0
  140. package/src/components/v-stack/vStack.props.ts +17 -0
  141. package/src/components/visually-hidden/VisuallyHidden.tsx +29 -0
  142. package/src/components/visually-hidden/visually-hidden.css +9 -0
  143. package/src/components/visually-hidden/visuallyHidden.props.ts +23 -0
  144. package/src/css/classes/dynamic/flex-child.css +5 -0
  145. package/src/css/classes/dynamic/grid-child.css +8 -0
  146. package/src/css/classes/dynamic/grid-parent.css +6 -0
  147. package/src/css/classes/dynamic/height.css +5 -0
  148. package/src/css/classes/dynamic/index.css +7 -0
  149. package/src/css/classes/dynamic/line-clamp.css +5 -0
  150. package/src/css/classes/dynamic/readme.md +3 -0
  151. package/src/css/classes/dynamic/width.css +7 -0
  152. package/src/css/classes/dynamic/z-index.css +3 -0
  153. package/src/css/classes/generic/display.css +10 -0
  154. package/src/css/classes/generic/flex.css +24 -0
  155. package/src/css/classes/generic/grid.css +7 -0
  156. package/src/css/classes/generic/index.css +7 -0
  157. package/src/css/classes/generic/overflow.css +19 -0
  158. package/src/css/classes/generic/placement.css +202 -0
  159. package/src/css/classes/generic/position.css +7 -0
  160. package/src/css/classes/generic/readme.md +3 -0
  161. package/src/css/classes/generic/text-align.css +5 -0
  162. package/src/css/classes/index.css +4 -0
  163. package/src/css/classes/local/animation.css +4 -0
  164. package/src/css/classes/local/border.css +20 -0
  165. package/src/css/classes/local/index.css +6 -0
  166. package/src/css/classes/local/readme.md +3 -0
  167. package/src/css/classes/local/text-overflow.css +5 -0
  168. package/src/css/classes/local/text-trim.css +45 -0
  169. package/src/css/classes/local/tone.css +75 -0
  170. package/src/css/classes/local/top-anchor.css +4 -0
  171. package/src/css/classes/system/color.css +223 -0
  172. package/src/css/classes/system/container.css +8 -0
  173. package/src/css/classes/system/font-family.css +2 -0
  174. package/src/css/classes/system/font-weight.css +4 -0
  175. package/src/css/classes/system/gap.css +37 -0
  176. package/src/css/classes/system/index.css +10 -0
  177. package/src/css/classes/system/inset.css +56 -0
  178. package/src/css/classes/system/margin.css +148 -0
  179. package/src/css/classes/system/padding.css +78 -0
  180. package/src/css/classes/system/radius.css +10 -0
  181. package/src/css/classes/system/readme.md +3 -0
  182. package/src/css/classes/system/shadow.css +6 -0
  183. package/src/css/classes/system/typography.css +31 -0
  184. package/src/css/global/font-face.css +20 -0
  185. package/src/css/global/index.css +2 -0
  186. package/src/css/global/reset.css +76 -0
  187. package/src/css/tokens/index.css +3 -0
  188. package/src/css/tokens/opacity.css +6 -0
  189. package/src/css/tokens/semantic.css +25 -0
  190. package/src/css/tokens/surface.css +27 -0
  191. package/src/hooks/useIsClient.ts +10 -0
  192. package/src/index.css +18 -0
  193. package/src/index.ts +65 -0
  194. package/src/polyfills.ts +15 -0
  195. package/src/props/border.ts +51 -0
  196. package/src/props/flexChild.ts +29 -0
  197. package/src/props/flexParent.ts +47 -0
  198. package/src/props/gap.ts +31 -0
  199. package/src/props/gridChild.ts +50 -0
  200. package/src/props/gridParent.ts +45 -0
  201. package/src/props/height.ts +29 -0
  202. package/src/props/layout.ts +44 -0
  203. package/src/props/margin.ts +59 -0
  204. package/src/props/overflow.ts +30 -0
  205. package/src/props/padding.ts +59 -0
  206. package/src/props/placement.ts +16 -0
  207. package/src/props/position.ts +52 -0
  208. package/src/props/shadow.ts +15 -0
  209. package/src/props/tone.ts +15 -0
  210. package/src/props/typography.ts +62 -0
  211. package/src/props/width.ts +29 -0
  212. package/src/props/zIndex.ts +15 -0
  213. package/src/styles.css.d.ts +1 -0
  214. package/src/styles.css.node.js +2 -0
  215. package/src/styles.css.test.ts +24 -0
  216. package/src/types/Button.ts +8 -0
  217. package/src/types/Code.ts +6 -0
  218. package/src/types/Container.ts +3 -0
  219. package/src/types/Density.ts +3 -0
  220. package/src/types/Display.ts +11 -0
  221. package/src/types/Eyebrow.ts +3 -0
  222. package/src/types/Flex.ts +22 -0
  223. package/src/types/FontWeight.ts +3 -0
  224. package/src/types/Grid.ts +3 -0
  225. package/src/types/Heading.ts +6 -0
  226. package/src/types/Icon.ts +3 -0
  227. package/src/types/Interactive.ts +8 -0
  228. package/src/types/List.ts +2 -0
  229. package/src/types/Overflow.ts +3 -0
  230. package/src/types/Placement.ts +16 -0
  231. package/src/types/Position.ts +3 -0
  232. package/src/types/PropDef.ts +73 -0
  233. package/src/types/Radius.ts +3 -0
  234. package/src/types/Responsive.ts +10 -0
  235. package/src/types/Shadow.ts +3 -0
  236. package/src/types/Space.ts +15 -0
  237. package/src/types/Text.ts +3 -0
  238. package/src/types/TextAlign.ts +3 -0
  239. package/src/types/Tone.ts +3 -0
  240. package/src/utils/getProps.test.ts +156 -0
  241. package/src/utils/getProps.ts +156 -0
  242. package/src/utils/mergeTriggerProps.ts +66 -0
  243. package/src/utils/renderPortal.tsx +14 -0
  244. package/src/utils/suffixClassName.ts +5 -0
  245. package/src/version.ts +3 -0
  246. package/LICENSE +0 -21
  247. package/dist/_system-CTe2lb5l.d.ts +0 -40
  248. package/dist/_system-CTe2lb5l.d.ts.map +0 -1
  249. package/dist/arrow-BmX6qbAS.js +0 -170
  250. package/dist/arrow-BmX6qbAS.js.map +0 -1
  251. package/dist/autocomplete.d.ts +0 -140
  252. package/dist/autocomplete.d.ts.map +0 -1
  253. package/dist/autocomplete.js +0 -470
  254. package/dist/autocomplete.js.map +0 -1
  255. package/dist/breadcrumbs.d.ts +0 -18
  256. package/dist/breadcrumbs.d.ts.map +0 -1
  257. package/dist/breadcrumbs.js +0 -119
  258. package/dist/breadcrumbs.js.map +0 -1
  259. package/dist/button-BNyKSDyA.js +0 -180
  260. package/dist/button-BNyKSDyA.js.map +0 -1
  261. package/dist/button-dnqMFkWg.d.ts +0 -76
  262. package/dist/button-dnqMFkWg.d.ts.map +0 -1
  263. package/dist/card-C0a0wQTc.d.ts +0 -7
  264. package/dist/card-C0a0wQTc.d.ts.map +0 -1
  265. package/dist/code.d.ts +0 -20
  266. package/dist/code.d.ts.map +0 -1
  267. package/dist/code.js +0 -90
  268. package/dist/code.js.map +0 -1
  269. package/dist/codeFontStyle-84SMhFtI.js +0 -11
  270. package/dist/codeFontStyle-84SMhFtI.js.map +0 -1
  271. package/dist/component-DVlwaWB-.d.ts +0 -25
  272. package/dist/component-DVlwaWB-.d.ts.map +0 -1
  273. package/dist/element-BYgCE_iK.js +0 -51
  274. package/dist/element-BYgCE_iK.js.map +0 -1
  275. package/dist/factory-BzXTX8_Q.js +0 -3056
  276. package/dist/factory-BzXTX8_Q.js.map +0 -1
  277. package/dist/flex-DmbDG2ks.js +0 -76
  278. package/dist/flex-DmbDG2ks.js.map +0 -1
  279. package/dist/font-EtfxKPUz.d.ts +0 -49
  280. package/dist/font-EtfxKPUz.d.ts.map +0 -1
  281. package/dist/getElementRef-Jw7gY0eV.js +0 -102
  282. package/dist/getElementRef-Jw7gY0eV.js.map +0 -1
  283. package/dist/getScopedTheme-C-sZsyAz.js +0 -267
  284. package/dist/getScopedTheme-C-sZsyAz.js.map +0 -1
  285. package/dist/getTheme_v2-y09KqtEb.js +0 -487
  286. package/dist/getTheme_v2-y09KqtEb.js.map +0 -1
  287. package/dist/grid-6JSgMj1O.js +0 -115
  288. package/dist/grid-6JSgMj1O.js.map +0 -1
  289. package/dist/helpers-C8xxXAQC.js +0 -63
  290. package/dist/helpers-C8xxXAQC.js.map +0 -1
  291. package/dist/hotkeys-CaHsQlsO.js +0 -168
  292. package/dist/hotkeys-CaHsQlsO.js.map +0 -1
  293. package/dist/index.d.ts.map +0 -1
  294. package/dist/layer-Bl5R3uNR.js +0 -61
  295. package/dist/layer-Bl5R3uNR.js.map +0 -1
  296. package/dist/layer-ChlP9Ik6.d.ts +0 -242
  297. package/dist/layer-ChlP9Ik6.d.ts.map +0 -1
  298. package/dist/menu.d.ts +0 -146
  299. package/dist/menu.d.ts.map +0 -1
  300. package/dist/menu.js +0 -626
  301. package/dist/menu.js.map +0 -1
  302. package/dist/popover-B7-28L8y.js +0 -408
  303. package/dist/popover-B7-28L8y.js.map +0 -1
  304. package/dist/popover-CMlQeKn0.d.ts +0 -96
  305. package/dist/popover-CMlQeKn0.d.ts.map +0 -1
  306. package/dist/popover.d.ts +0 -2
  307. package/dist/popover.js +0 -3
  308. package/dist/refractor-CC48DwHi.js +0 -20
  309. package/dist/refractor-CC48DwHi.js.map +0 -1
  310. package/dist/responsiveFont-CilwaORG.js +0 -55
  311. package/dist/responsiveFont-CilwaORG.js.map +0 -1
  312. package/dist/rgba-BSYaEUW6.d.ts +0 -846
  313. package/dist/rgba-BSYaEUW6.d.ts.map +0 -1
  314. package/dist/selectable-B0GUIL74.d.ts +0 -7
  315. package/dist/selectable-B0GUIL74.d.ts.map +0 -1
  316. package/dist/stack-rsNFPq2-.js +0 -112
  317. package/dist/stack-rsNFPq2-.js.map +0 -1
  318. package/dist/styles-css.d.ts +0 -2
  319. package/dist/styles-css.js +0 -4
  320. package/dist/textInput-pSfQjkmx.js +0 -313
  321. package/dist/textInput-pSfQjkmx.js.map +0 -1
  322. package/dist/theme.d.ts +0 -280
  323. package/dist/theme.d.ts.map +0 -1
  324. package/dist/theme.js +0 -55
  325. package/dist/theme.js.map +0 -1
  326. package/dist/toast.d.ts +0 -73
  327. package/dist/toast.d.ts.map +0 -1
  328. package/dist/toast.js +0 -302
  329. package/dist/toast.js.map +0 -1
  330. package/dist/tooltip.d.ts +0 -88
  331. package/dist/tooltip.d.ts.map +0 -1
  332. package/dist/tooltip.js +0 -435
  333. package/dist/tooltip.js.map +0 -1
  334. package/dist/useClickOutsideEvent-wGLGWBZN.js +0 -36
  335. package/dist/useClickOutsideEvent-wGLGWBZN.js.map +0 -1
  336. package/dist/useElementSize-BJvbGHq8.js +0 -51
  337. package/dist/useElementSize-BJvbGHq8.js.map +0 -1
  338. package/dist/useLayer-D1usxIE0.js +0 -712
  339. package/dist/useLayer-D1usxIE0.js.map +0 -1
@@ -0,0 +1,31 @@
1
+ import {type ToneProps, toneProps} from '../../props/tone'
2
+ import {type PropDef} from '../../types/PropDef'
3
+
4
+ /** @public */
5
+ export interface BadgeProps<T extends React.ElementType = 'span'> extends ToneProps {
6
+ /**
7
+ * HTML element to render.
8
+ */
9
+ as?: T
10
+ /**
11
+ * Shows an icon in the start position (left side in left-to-right languages).
12
+ */
13
+ iconStart?: React.ElementType | React.ReactNode
14
+ /**
15
+ * Sets Badge's text label. Use instead of children unless you have a special use case.
16
+ */
17
+ text?: string
18
+ }
19
+
20
+ export const badgeProps: Record<string, PropDef> = {
21
+ as: {
22
+ type: 'string',
23
+ },
24
+ iconStart: {
25
+ type: 'string',
26
+ },
27
+ text: {
28
+ type: 'string',
29
+ },
30
+ ...toneProps,
31
+ }
@@ -0,0 +1,30 @@
1
+ import clsx from 'clsx'
2
+ import type {ComponentPropsWithRef, ElementType} from 'react'
3
+
4
+ import {getProps} from '../../utils/getProps'
5
+ import {suffixClassName} from '../../utils/suffixClassName'
6
+ import {type BoxProps, boxProps} from './box.props'
7
+
8
+ const boxClassName = suffixClassName('sui-Box')
9
+
10
+ /** @public */
11
+ export function Box<T extends ElementType = 'div'>({
12
+ display = 'block',
13
+ minHeight = '0',
14
+ minWidth = '0',
15
+ ...props
16
+ }: BoxProps<T> & Omit<ComponentPropsWithRef<T>, keyof BoxProps<T>>) {
17
+ const {as, children, className, style, ...rest} = getProps(
18
+ {display, minHeight, minWidth, ...props},
19
+ boxProps,
20
+ )
21
+ const Component = as || 'div'
22
+
23
+ return (
24
+ <Component className={clsx(boxClassName, className)} style={style} data-ui="Box" {...rest}>
25
+ {children}
26
+ </Component>
27
+ )
28
+ }
29
+
30
+ export type {BoxProps}
@@ -0,0 +1,4 @@
1
+ .sui-Box[class*='sui-tone'] {
2
+ --box-background: var(--background-low);
3
+ background-color: var(--box-background);
4
+ }
@@ -0,0 +1,29 @@
1
+ import {type LayoutProps, layoutProps} from '../../props/layout'
2
+ import {DISPLAY_BLOCK, type DisplayBlock} from '../../types/Display'
3
+ import {type PropDef} from '../../types/PropDef'
4
+ import type {Responsive} from '../../types/Responsive'
5
+
6
+ /** @public */
7
+ export interface BoxProps<T extends React.ElementType = 'div'> extends LayoutProps {
8
+ /**
9
+ * HTML element or component to render.
10
+ */
11
+ as?: T
12
+ /**
13
+ * CSS `display` property.
14
+ * @remarks Does not include `'flex'` or `'grid'`. Use the Flex or Grid components for those.
15
+ */
16
+ display?: Responsive<DisplayBlock>
17
+ }
18
+
19
+ export const boxProps: Record<string, PropDef> = {
20
+ as: {
21
+ type: 'string',
22
+ },
23
+ display: {
24
+ type: 'union',
25
+ className: 'display',
26
+ values: DISPLAY_BLOCK,
27
+ },
28
+ ...layoutProps,
29
+ }
@@ -0,0 +1,78 @@
1
+ import clsx from 'clsx'
2
+ import {type ComponentPropsWithRef, type ElementType, isValidElement} from 'react'
3
+
4
+ import {getProps} from '../../utils/getProps'
5
+ import {suffixClassName} from '../../utils/suffixClassName'
6
+ import {Flex} from '../flex/Flex'
7
+ import {Icon} from '../icon/Icon'
8
+ import {Spinner} from '../spinner/Spinner'
9
+ import {Text} from '../text/Text'
10
+ import {type ButtonProps, buttonProps} from './button.props'
11
+
12
+ const buttonClassName = suffixClassName('sui-Button')
13
+
14
+ /** @public */
15
+ export function Button<T extends ElementType = 'button'>({
16
+ density = 'regular',
17
+ level = 'primary',
18
+ tone = 'neutral',
19
+ ...props
20
+ }: ButtonProps<T> & Omit<ComponentPropsWithRef<T>, keyof ButtonProps<T>>) {
21
+ const {
22
+ as,
23
+ children,
24
+ className,
25
+ disabled,
26
+ style,
27
+ iconStart: IconStart,
28
+ iconEnd: IconEnd,
29
+ loading,
30
+ text,
31
+ ...rest
32
+ } = getProps({density, level, tone, ...props}, buttonProps)
33
+ const Component = as || 'button'
34
+
35
+ return (
36
+ <Component
37
+ className={clsx(
38
+ buttonClassName,
39
+ 'sui-display-inline-flex sui-align-items-center sui-justify-content-center sui-radius2 sui-position-relative sui-overflow-hidden',
40
+ className,
41
+ )}
42
+ style={style}
43
+ data-ui="Button"
44
+ disabled={disabled || loading}
45
+ aria-busy={loading ? true : undefined}
46
+ {...rest}
47
+ >
48
+ {loading && (
49
+ <Flex position="absolute" inset={0} alignItems="center" justifyContent="center">
50
+ <Spinner />
51
+ </Flex>
52
+ )}
53
+
54
+ {IconStart &&
55
+ (isValidElement(IconStart) ? (
56
+ IconStart
57
+ ) : (
58
+ <Icon icon={IconStart} marginX={-1} marginY={-2} size={1} />
59
+ ))}
60
+
61
+ {text && (
62
+ <Text size={1} weight="medium" trim>
63
+ {text}
64
+ </Text>
65
+ )}
66
+
67
+ {children}
68
+ {IconEnd &&
69
+ (isValidElement(IconEnd) ? (
70
+ IconEnd
71
+ ) : (
72
+ <Icon icon={IconEnd} marginX={-1} marginY={-2} size={1} />
73
+ ))}
74
+ </Component>
75
+ )
76
+ }
77
+
78
+ export type {ButtonProps}
@@ -0,0 +1,72 @@
1
+ .sui-Button {
2
+ background: var(--background-color);
3
+ box-shadow: inset 0 0 0 1px var(--border-color, transparent);
4
+ color: var(--foreground-color);
5
+ text-decoration: none;
6
+ transition: var(--hover-transition);
7
+ appearance: none;
8
+ }
9
+
10
+ .sui-Button:hover {
11
+ background: color-mix(
12
+ in srgb,
13
+ var(--tone-500) 25%,
14
+ var(--background-color)
15
+ );
16
+ }
17
+
18
+ .sui-Button.sui-button-level-primary:hover {
19
+ background: color-mix(
20
+ in srgb,
21
+ var(--tone-950) 25%,
22
+ var(--background-color)
23
+ );
24
+ }
25
+
26
+ .sui-Button[class*='sui-tone']:disabled {
27
+ --background-color: var(--inert-background);
28
+ --foreground-color: var(--inert-foreground);
29
+ --border-color: transparent;
30
+ pointer-events: none;
31
+ }
32
+
33
+ .sui-Button:focus-visible {
34
+ outline: var(--focus-outline);
35
+ outline-offset: var(--focus-offset);
36
+ }
37
+
38
+ .sui-Button :is([data-sanity-icon], .sui-Spinner, .sui-Text) {
39
+ color: inherit;
40
+ }
41
+
42
+ .sui-Button > .sui-Flex + * {
43
+ opacity: 0;
44
+ }
45
+
46
+ .sui-button-level-primary {
47
+ --background-color: var(--background-high-emphasized);
48
+ --foreground-color: var(--foreground-low-emphasized);
49
+ }
50
+
51
+ .sui-button-level-primary.sui-tone-critical {
52
+ --background-color: var(--background-low-emphasized);
53
+ }
54
+
55
+ .sui-button-level-secondary {
56
+ --background-color: var(--background-high);
57
+ --foreground-color: var(--foreground-high);
58
+ --border-color: var(--separator-low)
59
+ }
60
+
61
+ .sui-button-level-secondary.sui-tone-critical {
62
+ --foreground-color: var(--foreground-low);
63
+ }
64
+
65
+ .sui-button-level-tertiary {
66
+ --background-color: transparent;
67
+ --foreground-color: var(--foreground-high);
68
+ }
69
+
70
+ .sui-button-level-tertiary.sui-tone-critical {
71
+ --foreground-color: var(--foreground-low);
72
+ }
@@ -0,0 +1,122 @@
1
+ import {gapProps} from '../../props/gap'
2
+ import {heightProps} from '../../props/height'
3
+ import {paddingProps} from '../../props/padding'
4
+ import {widthProps} from '../../props/width'
5
+ import {
6
+ BUTTON_DENSITY,
7
+ BUTTON_LEVEL,
8
+ BUTTON_TONE,
9
+ type ButtonDensity,
10
+ type ButtonLevel,
11
+ type ButtonTone,
12
+ } from '../../types/Button'
13
+ import type {InteractiveAs} from '../../types/Interactive'
14
+ import {type PropDef} from '../../types/PropDef'
15
+ import type {Responsive} from '../../types/Responsive'
16
+
17
+ /** @public */
18
+ export interface ButtonProps<T extends React.ElementType = 'button'> {
19
+ /**
20
+ * HTML element to render.
21
+ */
22
+ as?: InteractiveAs<T>
23
+ /**
24
+ * Sets padding and gap together to specify size.
25
+ */
26
+ density?: ButtonDensity
27
+ /**
28
+ * Sets Button to fill the width of its container.
29
+ */
30
+ fullWidth?: Responsive<boolean>
31
+ /**
32
+ * Shows an icon in the start position (left side in left-to-right languages).
33
+ */
34
+ iconStart?: React.ElementType | React.ReactNode
35
+ /**
36
+ * Shows an icon in the end position (right side in left-to-right languages).
37
+ */
38
+ iconEnd?: React.ElementType | React.ReactNode
39
+ /**
40
+ * Sets the importance of Button's action.
41
+ */
42
+ level?: ButtonLevel
43
+ /**
44
+ * Places Button into a loading state.
45
+ */
46
+ loading?: boolean
47
+ /**
48
+ * Sets Button's text label.
49
+ */
50
+ text?: string
51
+ /**
52
+ * Sets Button's semantic meaning and related color.
53
+ */
54
+ tone?: ButtonTone
55
+ }
56
+
57
+ export const buttonProps: Record<string, PropDef> = {
58
+ as: {
59
+ type: 'string',
60
+ },
61
+ density: {
62
+ type: 'composite',
63
+ values: BUTTON_DENSITY,
64
+ composition: {
65
+ gap: {
66
+ propDef: gapProps['gap'] as PropDef,
67
+ mapping: {
68
+ regular: 2,
69
+ loose: 3,
70
+ },
71
+ },
72
+ padding: {
73
+ propDef: paddingProps['padding'] as PropDef,
74
+ mapping: {
75
+ regular: 2,
76
+ loose: 3,
77
+ },
78
+ },
79
+ minHeight: {
80
+ propDef: heightProps['minHeight'] as PropDef,
81
+ mapping: {
82
+ regular: '25px',
83
+ loose: '33px',
84
+ },
85
+ },
86
+ minWidth: {
87
+ propDef: widthProps['minWidth'] as PropDef,
88
+ mapping: {
89
+ regular: '25px',
90
+ loose: '33px',
91
+ },
92
+ },
93
+ },
94
+ },
95
+ fullWidth: {
96
+ type: 'boolean',
97
+ className: 'width-full',
98
+ inverseClassName: 'width-auto',
99
+ },
100
+ iconStart: {
101
+ type: 'string',
102
+ },
103
+ iconEnd: {
104
+ type: 'string',
105
+ },
106
+ level: {
107
+ type: 'union',
108
+ className: 'button-level',
109
+ values: BUTTON_LEVEL,
110
+ },
111
+ loading: {
112
+ type: 'boolean',
113
+ },
114
+ text: {
115
+ type: 'string',
116
+ },
117
+ tone: {
118
+ type: 'union',
119
+ className: 'tone',
120
+ values: BUTTON_TONE,
121
+ },
122
+ }
@@ -0,0 +1,31 @@
1
+ import clsx from 'clsx'
2
+ import type {ComponentPropsWithRef, ElementType} from 'react'
3
+
4
+ import {getProps} from '../../utils/getProps'
5
+ import {suffixClassName} from '../../utils/suffixClassName'
6
+ import {type CardProps, cardProps} from './card.props'
7
+
8
+ const cardClassName = suffixClassName('sui-Card')
9
+
10
+ /** @public */
11
+ export function Card<T extends ElementType = 'div'>({
12
+ density = 'regular',
13
+ tone = 'neutral',
14
+ ...props
15
+ }: CardProps<T> & Omit<ComponentPropsWithRef<T>, keyof CardProps<T>>) {
16
+ const {as, children, className, style, ...rest} = getProps({density, tone, ...props}, cardProps)
17
+ const Component = as || 'div'
18
+
19
+ return (
20
+ <Component
21
+ className={clsx(cardClassName, 'sui-border', className)}
22
+ style={style}
23
+ data-ui="Card"
24
+ {...rest}
25
+ >
26
+ {children}
27
+ </Component>
28
+ )
29
+ }
30
+
31
+ export type {CardProps}
@@ -0,0 +1,4 @@
1
+ .sui-Card {
2
+ --card-background: var(--background-low);
3
+ background-color: var(--card-background);
4
+ }
@@ -0,0 +1,58 @@
1
+ import {borderProps} from '../../props/border'
2
+ import {gapProps} from '../../props/gap'
3
+ import {type MarginProps, marginProps} from '../../props/margin'
4
+ import {paddingProps} from '../../props/padding'
5
+ import {type ToneProps, toneProps} from '../../props/tone'
6
+ import {DENSITY, type Density} from '../../types/Density'
7
+ import {type PropDef} from '../../types/PropDef'
8
+ import {type Responsive} from '../../types/Responsive'
9
+
10
+ /** @public */
11
+ export interface CardProps<T extends React.ElementType = 'div'> extends MarginProps, ToneProps {
12
+ /**
13
+ * HTML element or component to render.
14
+ */
15
+ as?: T
16
+ /**
17
+ * Sets padding, gap, and border-radius together to specify size. This prop is used in place of separate `padding`, `gap`, and `border-radius` props.
18
+ */
19
+ density?: Responsive<Density>
20
+ }
21
+
22
+ export const cardProps: Record<string, PropDef> = {
23
+ as: {
24
+ type: 'string',
25
+ },
26
+ density: {
27
+ type: 'composite',
28
+ values: DENSITY,
29
+ composition: {
30
+ gap: {
31
+ propDef: gapProps['gap'] as PropDef,
32
+ mapping: {
33
+ compact: 2,
34
+ regular: 3,
35
+ loose: 4,
36
+ },
37
+ },
38
+ padding: {
39
+ propDef: paddingProps['padding'] as PropDef,
40
+ mapping: {
41
+ compact: 3,
42
+ regular: 4,
43
+ loose: 5,
44
+ },
45
+ },
46
+ radius: {
47
+ propDef: borderProps['radius'] as PropDef,
48
+ mapping: {
49
+ compact: 2,
50
+ regular: 3,
51
+ loose: 4,
52
+ },
53
+ },
54
+ },
55
+ } satisfies PropDef<Density>,
56
+ ...toneProps,
57
+ ...marginProps,
58
+ }
@@ -0,0 +1,64 @@
1
+ import {CheckmarkIcon} from '@sanity/icons/Checkmark'
2
+ import {RemoveIcon} from '@sanity/icons/Remove'
3
+ import clsx from 'clsx'
4
+ import {useEffect, useRef} from 'react'
5
+
6
+ import {getProps} from '../../utils/getProps'
7
+ import {suffixClassName} from '../../utils/suffixClassName'
8
+ import {Box} from '../box/Box'
9
+ import {Label} from '../label/Label'
10
+ import {VisuallyHidden} from '../visually-hidden/VisuallyHidden'
11
+ import {type CheckboxProps, checkboxProps} from './checkbox.props'
12
+
13
+ const checkboxClassName = suffixClassName('sui-Checkbox')
14
+ const checkboxInputClassName = suffixClassName('sui-CheckboxInput')
15
+ const checkboxMarkClassName = suffixClassName('sui-CheckboxMark')
16
+
17
+ /** @beta */
18
+ export function Checkbox(props: CheckboxProps) {
19
+ const inputRef = useRef<HTMLInputElement>(null)
20
+ const {className, style, disabled, error, indeterminate, label, ...rest} = getProps(
21
+ props,
22
+ checkboxProps,
23
+ )
24
+
25
+ useEffect(() => {
26
+ if (inputRef.current) {
27
+ inputRef.current.indeterminate = indeterminate
28
+ }
29
+ }, [indeterminate])
30
+
31
+ return (
32
+ <Label
33
+ className={clsx(checkboxClassName, 'sui-position-relative', className)}
34
+ style={style}
35
+ data-ui="Checkbox"
36
+ disabled={disabled}
37
+ error={error}
38
+ >
39
+ <VisuallyHidden
40
+ as="input"
41
+ type="checkbox"
42
+ className={checkboxInputClassName}
43
+ ref={inputRef}
44
+ disabled={disabled}
45
+ {...rest}
46
+ />
47
+
48
+ <Box
49
+ as="span"
50
+ className={clsx(checkboxMarkClassName, error && 'sui-error')}
51
+ position="relative"
52
+ radius={2}
53
+ width="17px"
54
+ height="17px"
55
+ >
56
+ {indeterminate ? <RemoveIcon /> : <CheckmarkIcon />}
57
+ </Box>
58
+
59
+ {label}
60
+ </Label>
61
+ )
62
+ }
63
+
64
+ export type {CheckboxProps}
@@ -0,0 +1,100 @@
1
+ /*
2
+ * Custom checkbox, base
3
+ */
4
+ .sui-CheckboxMark {
5
+ /* Background and border colours are computed relatively in hover states;
6
+ we use custom properties to make this easier */
7
+ --background-color: var(--backdrop);
8
+ --border-color: var(--separator-high);
9
+ background-color: var(--background-color);
10
+ border: 1px solid var(--border-color);
11
+ color: transparent;
12
+ font-size: 16px;
13
+ transition: var(--hover-transition);
14
+ }
15
+
16
+ /**
17
+ * Hover - uses relative border/background colours to darken/lighten in both normal & error state
18
+ */
19
+ /** Checkbox border (unchecked) */
20
+ .sui-Checkbox:hover .sui-CheckboxMark {
21
+ border-color: light-dark(
22
+ oklch(from var(--border-color) calc(l - var(--hover-lightness-delta)) c h),
23
+ oklch(from var(--border-color) calc(l + var(--hover-lightness-delta)) c h)
24
+ );
25
+ }
26
+
27
+ /** Checkbox background (checked, indeterminate) */
28
+ .sui-Checkbox:hover .sui-CheckboxInput:is(:checked, :indeterminate) + .sui-CheckboxMark {
29
+ background-color: light-dark(
30
+ oklch(from var(--background-color) calc(l - var(--hover-lightness-delta)) c h),
31
+ oklch(from var(--background-color) calc(l + var(--hover-lightness-delta)) c h)
32
+ );
33
+ }
34
+
35
+ /**
36
+ * Focus
37
+ */
38
+ .sui-CheckboxInput:focus-visible + .sui-CheckboxMark {
39
+ outline: var(--focus-outline);
40
+ outline-offset: var(--focus-offset);
41
+ }
42
+
43
+ /**
44
+ * Checked/indeterminate
45
+ */
46
+ .sui-CheckboxInput:is(:checked, :indeterminate) + .sui-CheckboxMark {
47
+ --background-color: var(--active-background-emphasized);
48
+ --border-color: transparent;
49
+ color: var(--active-foreground-emphasized);
50
+ }
51
+
52
+ /**
53
+ * Disabled
54
+ */
55
+ .sui-CheckboxInput:disabled + .sui-CheckboxMark {
56
+ --background-color: var(--inert-background);
57
+ --border-color: var(--separator-low);
58
+ }
59
+
60
+ /* Turn hover (and all pointer events) off for disabled checkboxes */
61
+ .sui-Checkbox:has(:disabled) {
62
+ pointer-events: none;
63
+ }
64
+
65
+ /**
66
+ * Disabled, but checked/indeterminate
67
+ */
68
+ .sui-CheckboxInput:is(:checked, :indeterminate):disabled + .sui-CheckboxMark {
69
+ --border-color: var(--separator-low);
70
+ color: var(--inert-foreground);
71
+ }
72
+
73
+ /**
74
+ * Error
75
+ */
76
+ .sui-CheckboxMark.sui-error {
77
+ --border-color: var(--error-separator);
78
+ }
79
+
80
+ /**
81
+ * Error, checked/indeterminate
82
+ */
83
+ .sui-CheckboxInput:is(:checked, :indeterminate) + .sui-CheckboxMark.sui-error {
84
+ --background-color: var(--error-background-emphasized);
85
+ }
86
+
87
+ /**
88
+ * Check/dash icons
89
+ */
90
+ .sui-CheckboxMark svg {
91
+ position: absolute;
92
+ top: 50%;
93
+ left: 50%;
94
+ transform: translate(-50%, -50%);
95
+ }
96
+
97
+ .sui-CheckboxMark path {
98
+ vector-effect: non-scaling-stroke;
99
+ stroke-width: 1.5px;
100
+ }
@@ -0,0 +1,33 @@
1
+ import {type MarginProps, marginProps} from '../../props/margin'
2
+ import {type PropDef} from '../../types/PropDef'
3
+
4
+ /** @beta */
5
+ export interface CheckboxProps extends React.ComponentProps<'input'>, MarginProps {
6
+ /**
7
+ * Applies error styling to the checkbox mark.
8
+ * @remarks Use when form validation fails. Pair with a visible error message. The prop is visual only.
9
+ */
10
+ error?: boolean
11
+ /**
12
+ * Renders the "mixed state" mark (a horizontal line).
13
+ * @remarks Use when the checkbox controls a group with some-but-not-all children checked.
14
+ */
15
+ indeterminate?: boolean
16
+ /**
17
+ * Visible label next to the checkbox.
18
+ */
19
+ label: React.ReactNode
20
+ }
21
+
22
+ export const checkboxProps: Record<string, PropDef> = {
23
+ error: {
24
+ type: 'boolean',
25
+ },
26
+ indeterminate: {
27
+ type: 'boolean',
28
+ },
29
+ label: {
30
+ type: 'string',
31
+ },
32
+ ...marginProps,
33
+ }