@sanity-labs/ui-poc 0.0.1-alpha.14 → 0.0.1-alpha.15

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 (29) hide show
  1. package/README.md +151 -0
  2. package/dist/index.d.ts +77 -13
  3. package/dist/index.js +282 -119
  4. package/dist/index.js.map +1 -1
  5. package/dist/styles.css +1 -1
  6. package/package.json +1 -1
  7. package/src/components/button/Button.tsx +1 -0
  8. package/src/components/button/button.css +2 -1
  9. package/src/components/button/button.props.ts +16 -0
  10. package/src/components/icon/Icon.tsx +3 -2
  11. package/src/components/icon/icon.props.ts +3 -0
  12. package/src/components/icon-button/IconButton.tsx +27 -0
  13. package/src/components/icon-button/iconButton.props.ts +26 -0
  14. package/src/components/index.css +2 -1
  15. package/src/components/{indicator-group/IndicatorGroup.tsx → indicator-stack/IndicatorStack.tsx} +6 -6
  16. package/src/components/{indicator-group/indicator-group.css → indicator-stack/indicator-stack.css} +1 -1
  17. package/src/components/{indicator-group/indicatorGroup.props.ts → indicator-stack/indicatorStack.props.ts} +2 -2
  18. package/src/components/tooltip/Tooltip.tsx +83 -0
  19. package/src/components/tooltip/tooltip.css +48 -0
  20. package/src/components/tooltip/tooltip.props.ts +20 -0
  21. package/src/components/tooltip-group/TooltipGroup.tsx +62 -0
  22. package/src/components/tooltip-group/tooltipGroup.props.ts +13 -0
  23. package/src/css/classes/generic/index.css +1 -0
  24. package/src/css/classes/generic/placement.css +171 -0
  25. package/src/css/classes/system/margin.css +40 -40
  26. package/src/index.ts +5 -2
  27. package/src/props/placement.ts +15 -0
  28. package/src/props/shadow.ts +2 -2
  29. package/src/types/Placement.ts +15 -0
package/README.md ADDED
@@ -0,0 +1,151 @@
1
+ # Sanity UI 4
2
+
3
+ The next version of Sanity's component library. Faster, simpler, and built on CSS instead of styled-components.
4
+
5
+ ## What's different from v3
6
+
7
+ - **CSS classes instead of styled-components.** No runtime style generation. Smaller bundles, faster renders.
8
+ - **Direct props for layout.** Width, height, position, border, and overflow are first-class props — no more `style={{ ... }}` escape hatches.
9
+ - **Works alongside v3.** Install both packages in the same app. No forced migration.
10
+
11
+ ## Install
12
+
13
+ ```sh
14
+ pnpm add @sanity-labs/ui-poc
15
+ ```
16
+
17
+ Requires React 19.2+ and Node >=20.19 <22 || >=22.12.
18
+
19
+ ## Setup
20
+
21
+ Import the stylesheet at your app entry point. Without it, components render as unstyled HTML with no error.
22
+
23
+ ```tsx
24
+ import '@sanity-labs/ui-poc/styles.css'
25
+ ```
26
+
27
+ If your app uses Sanity UI v3, keep the existing `ThemeProvider` setup.
28
+
29
+ ```tsx
30
+ import {ThemeProvider, studioTheme, ToastProvider} from '@sanity/ui'
31
+ import '@sanity-labs/ui-poc/styles.css'
32
+ import App from './App'
33
+
34
+ createRoot(document.getElementById('root')!).render(
35
+ <ThemeProvider theme={studioTheme}>
36
+ <ToastProvider>
37
+ <App />
38
+ </ToastProvider>
39
+ </ThemeProvider>,
40
+ )
41
+ ```
42
+
43
+ ## Usage
44
+
45
+ Import from `@sanity-labs/ui-poc`. Components not yet in v4 — Menu, Dialog, TextInput, Badge — remain in `@sanity/ui`.
46
+
47
+ ```tsx
48
+ import {Box, Flex, Card, Heading, Text, Button} from '@sanity-labs/ui-poc'
49
+ import {AddIcon} from '@sanity/icons'
50
+
51
+ export default function App() {
52
+ return (
53
+ <Flex minHeight="100vh">
54
+ <Box as="nav" aria-label="Main" padding={3} borderRight width="240px">
55
+ <Heading as="h2" size={1}>
56
+ My App
57
+ </Heading>
58
+ </Box>
59
+ <Box as="main" padding={4} flexGrow={1}>
60
+ <Flex alignItems="center" justifyContent="space-between" flexWrap="wrap" gap={2}>
61
+ <Heading as="h1" size={2}>
62
+ Documents
63
+ </Heading>
64
+ <Button iconStart={AddIcon} text="New" />
65
+ </Flex>
66
+ <Box marginTop={3}>
67
+ <Card density="loose">
68
+ <Text size={1}>First document</Text>
69
+ <Text size={1} muted>
70
+ Edited 2 hours ago
71
+ </Text>
72
+ </Card>
73
+ </Box>
74
+ </Box>
75
+ </Flex>
76
+ )
77
+ }
78
+ ```
79
+
80
+ ## Components
81
+
82
+ All components below are from `@sanity-labs/ui-poc`.
83
+
84
+ ### Layout
85
+
86
+ | Component | What it does |
87
+ | ----------- | ----------------------------------------------------------------------------------- |
88
+ | `Box` | General container. Padding, margin, border, overflow, and position as direct props. |
89
+ | `Flex` | Flexbox layout. `alignItems`, `justifyContent`, `flexDirection`, `gap`. |
90
+ | `Grid` | CSS grid. Use `gridTemplateColumns` with a CSS string (e.g. `"repeat(3, 1fr)"`). |
91
+ | `Container` | Max-width content wrapper. |
92
+ | `HStack` | Horizontal stack. Accepts `gap` and `as` only — use `Flex` for alignment control. |
93
+ | `VStack` | Vertical stack. Accepts `gap` and `as` only — use `Flex` for alignment control. |
94
+ | `Inline` | Inline flow layout with wrapping and gap. |
95
+
96
+ ### Typography
97
+
98
+ | Component | What it does |
99
+ | --------- | ----------------------------------------------------------------------- |
100
+ | `Heading` | Semantic headings (`h1`–`h6`). Always set `as` to match the level. |
101
+ | `Text` | Body copy, captions, labels. Props: `size`, `weight`, `muted`, `align`. |
102
+ | `Label` | Form input label. Use only with form elements. |
103
+ | `Code` | Inline or block code. Uses the system monospace font. |
104
+
105
+ ### Interactive
106
+
107
+ | Component | What it does |
108
+ | ---------- | ------------------------------------------------------------------------------------------------------------------------ |
109
+ | `Button` | `level` (primary/secondary/tertiary), `tone` (neutral/critical), `iconStart`, `iconEnd`, `text`, `fullWidth`, `loading`. |
110
+ | `Checkbox` | Controlled checkbox. Requires `label` (string). |
111
+ | `Radio` | Controlled radio button. |
112
+ | `Switch` | Toggle control. Requires `label` (string). |
113
+ | `Link` | Anchor element styled as a link. |
114
+
115
+ ### Display
116
+
117
+ | Component | What it does |
118
+ | ---------------- | -------------------------------------------------------------------------------------------------------------------- |
119
+ | `Card` | Raised surface with background and `tone`. Does not accept padding, margin, or layout props — wrap content in `Box`. |
120
+ | `Divider` | Horizontal rule between content sections. |
121
+ | `Icon` | Renders a `@sanity/icons` icon component. Always set `aria-label` or `aria-hidden`. |
122
+ | `Indicator` | Status dot with `tone`. |
123
+ | `IndicatorGroup` | Grouped `Indicator` elements. |
124
+ | `Spinner` | Loading indicator. |
125
+
126
+ ### Lists
127
+
128
+ | Component | What it does |
129
+ | --------- | --------------------------------------------------- |
130
+ | `List` | Semantic list. Use `List.Item` and `List.ItemText`. |
131
+
132
+ ### Accessibility
133
+
134
+ | Component | What it does |
135
+ | ---------------- | ------------------------------------------------------------------------------------------------ |
136
+ | `SkipToContent` | Visually hidden skip-nav link. Must be the first focusable element. Requires `hash` and `label`. |
137
+ | `VisuallyHidden` | Hides content visually while keeping it in the accessibility tree. |
138
+
139
+ ### Still from `@sanity/ui`
140
+
141
+ Menu, Dialog, TextInput, Select, Stack, Badge, ThemeProvider, ToastProvider, and other components not yet migrated to v4.
142
+
143
+ ## Contributing
144
+
145
+ We welcome feedback and contributions. Start here:
146
+
147
+ 1. **Try the components** and report what breaks, what confuses, or what's missing.
148
+ 2. **Read the contribution model** — build a recipe with existing building block components, then propose graduating it.
149
+ 3. **Open a PR** following the branch naming and checklist in the developer contribution docs.
150
+
151
+ During preview, the most useful contribution is using the components and telling us what happens.
package/dist/index.d.ts CHANGED
@@ -322,10 +322,26 @@ declare interface HStackProps<T extends React.ElementType> extends Pick<GapProps
322
322
  }
323
323
 
324
324
  /** @public */
325
- export declare function Icon({icon: Component, size, ...props}: IconProps): JSX.Element
325
+ export declare function Icon({size, ...props}: IconProps): JSX.Element
326
326
 
327
327
  declare const ICON_SIZE: readonly [0, 1, 2, 3, 4]
328
328
 
329
+ /** @public */
330
+ export declare function IconButton<T extends ElementType = 'button'>(
331
+ props: IconButtonProps<T> & Omit<ComponentPropsWithRef<T>, keyof IconButtonProps<T>>,
332
+ ): JSX.Element
333
+
334
+ /** @public */
335
+ declare interface IconButtonProps<T extends React_2.ElementType> extends Pick<
336
+ ButtonProps<T>,
337
+ 'as' | 'density' | 'level' | 'loading' | 'tone'
338
+ > {
339
+ /** Button label */
340
+ 'aria-label': string
341
+ /** Icon */
342
+ 'icon': React_2.ComponentType<SVGProps<SVGSVGElement>>
343
+ }
344
+
329
345
  /** @public */
330
346
  declare interface IconProps
331
347
  extends ComponentProps<'svg'>, Pick<TypographyProps, 'muted'>, MarginProps, ToneProps {
@@ -343,17 +359,6 @@ export declare function Indicator<T extends ElementType = 'span'>({
343
359
  ...props
344
360
  }: IndicatorProps<T> & Omit<ComponentPropsWithRef<T>, keyof IndicatorProps<T>>): JSX.Element
345
361
 
346
- /** @public */
347
- export declare function IndicatorGroup<T extends ElementType = 'div'>(
348
- props: IndicatorGroupProps<T> & Omit<ComponentPropsWithRef<T>, keyof IndicatorGroupProps<T>>,
349
- ): JSX.Element
350
-
351
- /** @public */
352
- declare interface IndicatorGroupProps<T extends React.ElementType> {
353
- /** Element to render */
354
- as?: T
355
- }
356
-
357
362
  /** @beta */
358
363
  declare interface IndicatorProps<T extends React.ElementType> extends ToneProps {
359
364
  /** Element to render */
@@ -362,6 +367,17 @@ declare interface IndicatorProps<T extends React.ElementType> extends ToneProps
362
367
  label?: string
363
368
  }
364
369
 
370
+ /** @public */
371
+ export declare function IndicatorStack<T extends ElementType = 'div'>(
372
+ props: IndicatorStackProps<T> & Omit<ComponentPropsWithRef<T>, keyof IndicatorStackProps<T>>,
373
+ ): JSX.Element
374
+
375
+ /** @public */
376
+ declare interface IndicatorStackProps<T extends React.ElementType> {
377
+ /** Element to render */
378
+ as?: T
379
+ }
380
+
365
381
  /** @deprecated Use HStack component instead */
366
382
  /** @public */
367
383
  export declare function Inline<T extends ElementType = 'div'>(
@@ -535,6 +551,28 @@ declare interface PaddingProps {
535
551
  paddingLeft?: Responsive<Space>
536
552
  }
537
553
 
554
+ declare const PLACEMENT: readonly [
555
+ 'top',
556
+ 'top-start',
557
+ 'top-end',
558
+ 'right',
559
+ 'right-start',
560
+ 'right-end',
561
+ 'bottom',
562
+ 'bottom-start',
563
+ 'bottom-end',
564
+ 'left',
565
+ 'left-start',
566
+ 'left-end',
567
+ ]
568
+
569
+ declare type Placement = (typeof PLACEMENT)[number]
570
+
571
+ declare type PlacementProps = {
572
+ /** Placement relative to anchor */
573
+ placement?: Placement
574
+ }
575
+
538
576
  declare const POSITION: readonly ['absolute', 'fixed', 'relative', 'static', 'sticky']
539
577
 
540
578
  declare type Position = (typeof POSITION)[number]
@@ -591,9 +629,13 @@ declare type Responsive<T> =
591
629
  length: 6
592
630
  })
593
631
 
632
+ declare const SHADOW: readonly [0, 1, 2, 3, 4, 5]
633
+
634
+ declare type Shadow = (typeof SHADOW)[number]
635
+
594
636
  declare type ShadowProps = {
595
637
  /** CSS **box-shadow** property */
596
- shadow?: string
638
+ shadow?: Shadow
597
639
  }
598
640
 
599
641
  /** @beta */
@@ -701,6 +743,28 @@ declare type ToneProps = {
701
743
  tone?: Tone
702
744
  }
703
745
 
746
+ /** @public */
747
+ export declare function Tooltip({placement, ...props}: TooltipProps): any
748
+
749
+ /** @public */
750
+ export declare function TooltipGroup<T extends ElementType = 'div'>(
751
+ props: TooltipGroupProps<T> & Omit<ComponentPropsWithRef<T>, keyof TooltipGroupProps<T>>,
752
+ ): JSX.Element
753
+
754
+ /** @public */
755
+ declare interface TooltipGroupProps<T extends React.ElementType> {
756
+ /** Element to render */
757
+ as?: T
758
+ }
759
+
760
+ /** @public */
761
+ declare interface TooltipProps extends React.ComponentProps<'div'>, PlacementProps {
762
+ /** Tooltip text */
763
+ text?: React.ReactNode
764
+ /** Disabled state */
765
+ disabled?: boolean
766
+ }
767
+
704
768
  declare interface TypographyProps extends MarginProps, ToneProps {
705
769
  /** CSS **text-align** property */
706
770
  align?: TextAlign