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

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 (32) hide show
  1. package/README.md +151 -0
  2. package/dist/index.d.ts +88 -13
  3. package/dist/index.js +295 -110
  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 +3 -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 +3 -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/press-area/PressArea.tsx +24 -0
  19. package/src/components/press-area/press-area.css +17 -0
  20. package/src/components/press-area/pressArea.props.ts +14 -0
  21. package/src/components/tooltip/Tooltip.tsx +87 -0
  22. package/src/components/tooltip/tooltip.css +52 -0
  23. package/src/components/tooltip/tooltip.props.ts +20 -0
  24. package/src/components/tooltip-group/TooltipGroup.tsx +62 -0
  25. package/src/components/tooltip-group/tooltipGroup.props.ts +13 -0
  26. package/src/css/classes/generic/index.css +1 -0
  27. package/src/css/classes/generic/placement.css +171 -0
  28. package/src/css/classes/system/margin.css +40 -40
  29. package/src/index.ts +6 -2
  30. package/src/props/placement.ts +15 -0
  31. package/src/props/shadow.ts +2 -2
  32. 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]
@@ -554,6 +592,17 @@ declare type PositionProps = {
554
592
  left?: Responsive<SpaceAuto>
555
593
  }
556
594
 
595
+ /** @public */
596
+ export declare function PressArea<T extends ElementType = 'button'>(
597
+ props: PressAreaProps<T> & Omit<ComponentPropsWithRef<T>, keyof PressAreaProps<T>>,
598
+ ): JSX.Element
599
+
600
+ /** @public */
601
+ declare interface PressAreaProps<T extends React.ElementType> {
602
+ /** Element to render */
603
+ as?: InteractiveAs<T>
604
+ }
605
+
557
606
  /** @beta */
558
607
  export declare function Radio(props: RadioProps): JSX.Element
559
608
 
@@ -591,9 +640,13 @@ declare type Responsive<T> =
591
640
  length: 6
592
641
  })
593
642
 
643
+ declare const SHADOW: readonly [0, 1, 2, 3, 4, 5]
644
+
645
+ declare type Shadow = (typeof SHADOW)[number]
646
+
594
647
  declare type ShadowProps = {
595
648
  /** CSS **box-shadow** property */
596
- shadow?: string
649
+ shadow?: Shadow
597
650
  }
598
651
 
599
652
  /** @beta */
@@ -701,6 +754,28 @@ declare type ToneProps = {
701
754
  tone?: Tone
702
755
  }
703
756
 
757
+ /** @public */
758
+ export declare function Tooltip({placement, ...props}: TooltipProps): any
759
+
760
+ /** @public */
761
+ export declare function TooltipGroup<T extends ElementType = 'div'>(
762
+ props: TooltipGroupProps<T> & Omit<ComponentPropsWithRef<T>, keyof TooltipGroupProps<T>>,
763
+ ): JSX.Element
764
+
765
+ /** @public */
766
+ declare interface TooltipGroupProps<T extends React.ElementType> {
767
+ /** Element to render */
768
+ as?: T
769
+ }
770
+
771
+ /** @public */
772
+ declare interface TooltipProps extends React.ComponentProps<'div'>, PlacementProps {
773
+ /** Tooltip text */
774
+ text?: React.ReactNode
775
+ /** Disabled state */
776
+ disabled?: boolean
777
+ }
778
+
704
779
  declare interface TypographyProps extends MarginProps, ToneProps {
705
780
  /** CSS **text-align** property */
706
781
  align?: TextAlign