@pantoia/ui 0.3.0 → 0.4.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 (62) hide show
  1. package/accordion/index.module.css +4 -4
  2. package/accordion/index.tsx +21 -51
  3. package/alert-dialog/index.tsx +36 -42
  4. package/badge/index.tsx +1 -1
  5. package/button/index.tsx +31 -30
  6. package/callout/index.tsx +4 -4
  7. package/checkbox/index.tsx +20 -85
  8. package/combobox/index.tsx +122 -316
  9. package/command-palette/index.tsx +51 -32
  10. package/dialog/index.tsx +28 -24
  11. package/dist/index.js +5 -5
  12. package/drawer/index.module.css +2 -2
  13. package/drawer/index.tsx +52 -130
  14. package/dropdown-menu/index.tsx +87 -95
  15. package/field/index.tsx +27 -86
  16. package/input/index.tsx +7 -3
  17. package/kbd/index.tsx +2 -2
  18. package/label/index.tsx +6 -8
  19. package/number-field/index.tsx +122 -173
  20. package/package.json +2 -6
  21. package/popover/index.tsx +61 -32
  22. package/radio-group/index.tsx +35 -38
  23. package/registry.json +64 -154
  24. package/select/index.tsx +141 -70
  25. package/switch/index.tsx +13 -6
  26. package/table/index.tsx +1 -2
  27. package/tabs/index.module.css +3 -3
  28. package/tabs/index.tsx +22 -76
  29. package/textarea/index.tsx +19 -7
  30. package/toast/index.module.css +187 -0
  31. package/toast/index.tsx +141 -46
  32. package/toggle/index.tsx +4 -3
  33. package/tokens.css +7 -1
  34. package/tooltip/index.tsx +61 -30
  35. package/utilities.css +11 -6
  36. package/accordion/AGENTS.md +0 -60
  37. package/alert-dialog/AGENTS.md +0 -78
  38. package/badge/AGENTS.md +0 -35
  39. package/button/AGENTS.md +0 -39
  40. package/callout/AGENTS.md +0 -37
  41. package/checkbox/AGENTS.md +0 -54
  42. package/combobox/AGENTS.md +0 -150
  43. package/command-palette/AGENTS.md +0 -41
  44. package/dialog/AGENTS.md +0 -81
  45. package/drawer/AGENTS.md +0 -66
  46. package/dropdown-menu/AGENTS.md +0 -133
  47. package/field/AGENTS.md +0 -92
  48. package/input/AGENTS.md +0 -35
  49. package/kbd/AGENTS.md +0 -17
  50. package/label/AGENTS.md +0 -21
  51. package/number-field/AGENTS.md +0 -49
  52. package/popover/AGENTS.md +0 -64
  53. package/radio-group/AGENTS.md +0 -81
  54. package/select/AGENTS.md +0 -90
  55. package/switch/AGENTS.md +0 -37
  56. package/table/AGENTS.md +0 -82
  57. package/tabs/AGENTS.md +0 -61
  58. package/test-utils.ts +0 -10
  59. package/textarea/AGENTS.md +0 -35
  60. package/toast/AGENTS.md +0 -34
  61. package/toggle/AGENTS.md +0 -37
  62. package/tooltip/AGENTS.md +0 -50
@@ -1,6 +1,6 @@
1
1
  'use client'
2
2
 
3
- import { DropdownMenu as MenuPrimitive } from 'radix-ui'
3
+ import { Menu as MenuPrimitive } from '@base-ui/react/menu'
4
4
  import type { ComponentProps, ReactNode } from 'react'
5
5
 
6
6
  import { tv } from '../tv'
@@ -26,32 +26,34 @@ const PANEL = 'menu float text-fg rounded-r12 z-overlay'
26
26
  + ' open:animate-enter closed:animate-exit'
27
27
  + ' focus-visible:outline-none'
28
28
 
29
- export interface DropdownMenuProps {
30
- open?: boolean
31
- defaultOpen?: boolean
32
- onOpenChange?: (open: boolean) => void
33
- children?: ReactNode
34
- }
29
+ export type DropdownMenuProps = ComponentProps<typeof MenuPrimitive.Root>
35
30
 
36
- export function DropdownMenu({ open, defaultOpen, onOpenChange, children }: DropdownMenuProps) {
37
- return (
38
- <MenuPrimitive.Root open={open} defaultOpen={defaultOpen} onOpenChange={onOpenChange}>
39
- {children}
40
- </MenuPrimitive.Root>
41
- )
31
+ export function DropdownMenu(props: DropdownMenuProps) {
32
+ return <MenuPrimitive.Root {...props} />
42
33
  }
43
34
 
44
- export function DropdownMenuTrigger({ children }: { children: ReactNode }) {
45
- return <MenuPrimitive.Trigger asChild>{children}</MenuPrimitive.Trigger>
35
+ export type DropdownMenuTriggerProps = ComponentProps<typeof MenuPrimitive.Trigger>
36
+
37
+ export function DropdownMenuTrigger(props: DropdownMenuTriggerProps) {
38
+ return <MenuPrimitive.Trigger {...props} />
46
39
  }
47
40
 
48
- export interface DropdownMenuContentProps extends Omit<ComponentProps<typeof MenuPrimitive.Content>, 'align'> {
41
+ export type DropdownMenuContentProps = Omit<ComponentProps<typeof MenuPrimitive.Popup>, 'className'> & {
49
42
  align?: 'start' | 'center' | 'end'
50
43
  arrow?: boolean
44
+ className?: string
51
45
  }
52
46
 
53
47
  const menuPanel = tv({ base: PANEL })
54
48
 
49
+ const menuArrow = tv({
50
+ base: 'data-uncentered:invisible'
51
+ + ' side-top:top-full'
52
+ + ' side-bottom:bottom-full side-bottom:rotate-180'
53
+ + ' side-right:left-0 side-right:origin-top-left side-right:rotate-90 side-right:-translate-y-1/2'
54
+ + ' side-left:right-0 side-left:origin-top-right side-left:-rotate-90 side-left:-translate-y-1/2',
55
+ })
56
+
55
57
  export function DropdownMenuContent({
56
58
  align = 'start',
57
59
  arrow = true,
@@ -61,50 +63,53 @@ export function DropdownMenuContent({
61
63
  }: DropdownMenuContentProps) {
62
64
  return (
63
65
  <MenuPrimitive.Portal>
64
- <MenuPrimitive.Content
65
- {...rest}
66
+ <MenuPrimitive.Positioner
66
67
  align={align}
67
- sideOffset={8}
68
+ sideOffset={arrow ? 14 : 8}
68
69
  arrowPadding={16}
69
- className={menuPanel({ className })}
70
+ className="z-overlay min-w-max will-change-transform"
70
71
  >
71
- {children}
72
-
73
- {arrow && (
74
- <MenuPrimitive.Arrow asChild width={12} height={6}>
75
- <svg viewBox="0 0 12 6" preserveAspectRatio="none" className="fill-bg-panel -translate-y-px">
76
- <path d="M0 0L4.58579 4.58579C5.36683 5.36683 6.63316 5.36684 7.41421 4.58579L12 0" className="stroke-line stroke-1" />
77
- </svg>
78
- </MenuPrimitive.Arrow>
79
- )}
80
- </MenuPrimitive.Content>
72
+ <MenuPrimitive.Popup {...rest} className={menuPanel({ className })}>
73
+ {children}
74
+
75
+ {arrow && (
76
+ <MenuPrimitive.Arrow className={menuArrow()}>
77
+ <svg width={12} height={6} viewBox="0 0 12 6" preserveAspectRatio="none" className="block fill-bg-panel -translate-y-px">
78
+ <path d="M0 0L4.58579 4.58579C5.36683 5.36683 6.63316 5.36684 7.41421 4.58579L12 0" className="stroke-line stroke-1" />
79
+ </svg>
80
+ </MenuPrimitive.Arrow>
81
+ )}
82
+ </MenuPrimitive.Popup>
83
+ </MenuPrimitive.Positioner>
81
84
  </MenuPrimitive.Portal>
82
85
  )
83
86
  }
84
87
 
85
88
  const menuGroup = tv({ base: 'flex flex-col gap-px' })
86
89
 
87
- export function DropdownMenuGroup({ label, className, children }: {
90
+ export type DropdownMenuGroupProps = Omit<ComponentProps<typeof MenuPrimitive.Group>, 'className'> & {
88
91
  label?: string
89
92
  className?: string
90
- children?: ReactNode
91
- }) {
93
+ }
94
+
95
+ export function DropdownMenuGroup({ label, className, children, ...rest }: DropdownMenuGroupProps) {
92
96
  return (
93
- <MenuPrimitive.Group className={menuGroup({ className })}>
97
+ <MenuPrimitive.Group {...rest} className={menuGroup({ className })}>
94
98
  {label && (
95
- <MenuPrimitive.Label className="text-caption text-fg-subtle px-2 pb-1 pt-2">
99
+ <MenuPrimitive.GroupLabel className="text-caption text-fg-subtle px-2 pb-1 pt-2">
96
100
  {label}
97
- </MenuPrimitive.Label>
101
+ </MenuPrimitive.GroupLabel>
98
102
  )}
99
103
  {children}
100
104
  </MenuPrimitive.Group>
101
105
  )
102
106
  }
103
107
 
104
- export interface DropdownMenuItemProps extends Omit<ComponentProps<typeof MenuPrimitive.Item>, 'color'> {
108
+ export type DropdownMenuItemProps = Omit<ComponentProps<typeof MenuPrimitive.Item>, 'className' | 'color'> & {
105
109
  color?: 'neutral' | 'danger'
106
110
  lead?: ReactNode
107
111
  trail?: ReactNode
112
+ className?: string
108
113
  }
109
114
 
110
115
  export function DropdownMenuItem({ color, lead, trail, className, children, ...rest }: DropdownMenuItemProps) {
@@ -122,27 +127,19 @@ export function DropdownMenuItem({ color, lead, trail, className, children, ...r
122
127
  )
123
128
  }
124
129
 
125
- export function DropdownMenuCheckboxItem({ checked, onCheckedChange, disabled, className, children }: {
126
- checked?: boolean
127
- onCheckedChange?: (checked: boolean) => void
128
- disabled?: boolean
130
+ export type DropdownMenuCheckboxItemProps = Omit<ComponentProps<typeof MenuPrimitive.CheckboxItem>, 'className'> & {
129
131
  className?: string
130
- children?: ReactNode
131
- }) {
132
+ }
133
+
134
+ export function DropdownMenuCheckboxItem({ className, children, ...rest }: DropdownMenuCheckboxItemProps) {
132
135
  return (
133
- <MenuPrimitive.CheckboxItem
134
- checked={checked}
135
- onCheckedChange={onCheckedChange}
136
- disabled={disabled}
137
- className={menuItem({ className })}
138
- onSelect={e => e.preventDefault()}
139
- >
136
+ <MenuPrimitive.CheckboxItem {...rest} className={menuItem({ className })}>
140
137
  <span className="menu-lead grid size-4 shrink-0 place-items-center">
141
- <MenuPrimitive.ItemIndicator>
138
+ <MenuPrimitive.CheckboxItemIndicator>
142
139
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={2} strokeLinecap="round" strokeLinejoin="round" aria-hidden="true" className="size-4">
143
140
  <path d="M20 6 9 17l-5-5" />
144
141
  </svg>
145
- </MenuPrimitive.ItemIndicator>
142
+ </MenuPrimitive.CheckboxItemIndicator>
146
143
  </span>
147
144
 
148
145
  <span className="min-w-0 grow">{children}</span>
@@ -150,30 +147,23 @@ export function DropdownMenuCheckboxItem({ checked, onCheckedChange, disabled, c
150
147
  )
151
148
  }
152
149
 
153
- export function DropdownMenuRadioGroup({ value, onValueChange, children }: {
154
- value?: string
155
- onValueChange?: (value: string) => void
156
- children?: ReactNode
157
- }) {
158
- return (
159
- <MenuPrimitive.RadioGroup value={value} onValueChange={onValueChange}>
160
- {children}
161
- </MenuPrimitive.RadioGroup>
162
- )
150
+ export type DropdownMenuRadioGroupProps = ComponentProps<typeof MenuPrimitive.RadioGroup>
151
+
152
+ export function DropdownMenuRadioGroup(props: DropdownMenuRadioGroupProps) {
153
+ return <MenuPrimitive.RadioGroup {...props} />
163
154
  }
164
155
 
165
- export function DropdownMenuRadioItem({ value, disabled, className, children }: {
166
- value: string
167
- disabled?: boolean
156
+ export type DropdownMenuRadioItemProps = Omit<ComponentProps<typeof MenuPrimitive.RadioItem>, 'className'> & {
168
157
  className?: string
169
- children?: ReactNode
170
- }) {
158
+ }
159
+
160
+ export function DropdownMenuRadioItem({ className, children, ...rest }: DropdownMenuRadioItemProps) {
171
161
  return (
172
- <MenuPrimitive.RadioItem value={value} disabled={disabled} className={menuItem({ className })}>
162
+ <MenuPrimitive.RadioItem {...rest} className={menuItem({ className })}>
173
163
  <span className="menu-lead grid size-4 shrink-0 place-items-center">
174
- <MenuPrimitive.ItemIndicator>
164
+ <MenuPrimitive.RadioItemIndicator>
175
165
  <span className="bg-bg-neutral-solid in-disabled:bg-bg-neutral-solid-checked-disabled size-2 rounded-full" />
176
- </MenuPrimitive.ItemIndicator>
166
+ </MenuPrimitive.RadioItemIndicator>
177
167
  </span>
178
168
 
179
169
  <span className="min-w-0 grow">{children}</span>
@@ -183,31 +173,28 @@ export function DropdownMenuRadioItem({ value, disabled, className, children }:
183
173
 
184
174
  const menuSeparator = tv({ base: 'bg-line -mx-1 my-1 h-px' })
185
175
 
186
- export function DropdownMenuSeparator({ className }: { className?: string }) {
187
- return <MenuPrimitive.Separator className={menuSeparator({ className })} />
176
+ export type DropdownMenuSeparatorProps = Omit<ComponentProps<typeof MenuPrimitive.Separator>, 'className'> & {
177
+ className?: string
188
178
  }
189
179
 
190
- export function DropdownMenuSub({ open, defaultOpen, onOpenChange, children }: {
191
- open?: boolean
192
- defaultOpen?: boolean
193
- onOpenChange?: (open: boolean) => void
194
- children?: ReactNode
195
- }) {
196
- return (
197
- <MenuPrimitive.Sub open={open} defaultOpen={defaultOpen} onOpenChange={onOpenChange}>
198
- {children}
199
- </MenuPrimitive.Sub>
200
- )
180
+ export function DropdownMenuSeparator({ className, ...rest }: DropdownMenuSeparatorProps) {
181
+ return <MenuPrimitive.Separator {...rest} className={menuSeparator({ className })} />
201
182
  }
202
183
 
203
- export function DropdownMenuSubTrigger({ disabled, lead, className, children }: {
204
- disabled?: boolean
184
+ export type DropdownMenuSubProps = ComponentProps<typeof MenuPrimitive.SubmenuRoot>
185
+
186
+ export function DropdownMenuSub(props: DropdownMenuSubProps) {
187
+ return <MenuPrimitive.SubmenuRoot {...props} />
188
+ }
189
+
190
+ export type DropdownMenuSubTriggerProps = Omit<ComponentProps<typeof MenuPrimitive.SubmenuTrigger>, 'className'> & {
205
191
  lead?: ReactNode
206
192
  className?: string
207
- children?: ReactNode
208
- }) {
193
+ }
194
+
195
+ export function DropdownMenuSubTrigger({ lead, className, children, ...rest }: DropdownMenuSubTriggerProps) {
209
196
  return (
210
- <MenuPrimitive.SubTrigger disabled={disabled} className={menuItem({ className })}>
197
+ <MenuPrimitive.SubmenuTrigger {...rest} className={menuItem({ className })}>
211
198
  {lead && (
212
199
  <span className="menu-lead grid size-4 shrink-0 place-items-center">
213
200
  {lead}
@@ -219,20 +206,25 @@ export function DropdownMenuSubTrigger({ disabled, lead, className, children }:
219
206
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={2} strokeLinecap="round" strokeLinejoin="round" aria-hidden="true" className="text-fg-subtle size-4 shrink-0">
220
207
  <path d="m9 18 6-6-6-6" />
221
208
  </svg>
222
- </MenuPrimitive.SubTrigger>
209
+ </MenuPrimitive.SubmenuTrigger>
223
210
  )
224
211
  }
225
212
 
226
- export function DropdownMenuSubContent({ className, children, ...rest }: ComponentProps<typeof MenuPrimitive.SubContent>) {
213
+ export type DropdownMenuSubContentProps = Omit<ComponentProps<typeof MenuPrimitive.Popup>, 'className'> & {
214
+ className?: string
215
+ }
216
+
217
+ export function DropdownMenuSubContent({ className, children, ...rest }: DropdownMenuSubContentProps) {
227
218
  return (
228
219
  <MenuPrimitive.Portal>
229
- <MenuPrimitive.SubContent
230
- {...rest}
220
+ <MenuPrimitive.Positioner
231
221
  sideOffset={4}
232
- className={menuPanel({ className })}
222
+ className="z-overlay min-w-max will-change-transform"
233
223
  >
234
- {children}
235
- </MenuPrimitive.SubContent>
224
+ <MenuPrimitive.Popup {...rest} className={menuPanel({ className })}>
225
+ {children}
226
+ </MenuPrimitive.Popup>
227
+ </MenuPrimitive.Positioner>
236
228
  </MenuPrimitive.Portal>
237
229
  )
238
230
  }
package/field/index.tsx CHANGED
@@ -1,6 +1,6 @@
1
1
  'use client'
2
2
 
3
- import { createContext, use, useId, type ReactNode } from 'react'
3
+ import { Field as FieldPrimitive } from '@base-ui/react/field'
4
4
 
5
5
  import { Label } from '../label'
6
6
  import { tv } from '../tv'
@@ -19,66 +19,23 @@ export const field = tv({
19
19
  defaultVariants: { layout: 'stack' },
20
20
  })
21
21
 
22
- export interface FieldContext {
23
- id: string
24
- labelId: string
25
- messageId: string
26
- }
27
-
28
- export interface FieldControl {
29
- id: string
30
- 'aria-labelledby': string
31
- 'aria-invalid': 'true' | undefined
32
- 'aria-describedby': string
33
- }
34
-
35
- const Context = createContext<FieldContext | null>(null)
36
-
37
- export interface FieldProps {
38
- invalid?: boolean
22
+ export type FieldProps = Omit<FieldPrimitive.Root.Props, 'className'> & {
39
23
  layout?: 'stack' | 'inline' | 'split'
40
24
  className?: string
41
- children?: ReactNode | ((args: { control: FieldControl }) => ReactNode)
42
25
  }
43
26
 
44
- export function Field({ invalid = false, layout, className, children }: FieldProps) {
45
- const id = useId()
46
- const ctx: FieldContext = {
47
- id,
48
- labelId: `${id}-label`,
49
- messageId: `${id}-message`,
50
- }
51
-
52
- const control: FieldControl = {
53
- 'id': id,
54
- 'aria-labelledby': ctx.labelId,
55
- 'aria-invalid': invalid ? 'true' : undefined,
56
- 'aria-describedby': ctx.messageId,
57
- }
58
-
59
- return (
60
- <Context value={ctx}>
61
- <div className={field({ layout, className })}>
62
- {typeof children === 'function' ? children({ control }) : children}
63
- </div>
64
- </Context>
65
- )
27
+ export function Field({ layout, className, ...rest }: FieldProps) {
28
+ return <FieldPrimitive.Root {...rest} className={field({ layout, className })} />
66
29
  }
67
30
 
68
31
  const fieldLabel = tv({ base: 'group-has-disabled:text-fg-disabled' })
69
32
 
70
- export function FieldLabel({ className, children }: { className?: string, children?: ReactNode }) {
71
- const ctx = use(Context)
33
+ export type FieldLabelProps = Omit<FieldPrimitive.Label.Props, 'className'> & {
34
+ className?: string
35
+ }
72
36
 
73
- return (
74
- <Label
75
- id={ctx?.labelId}
76
- htmlFor={ctx?.id}
77
- className={fieldLabel({ className })}
78
- >
79
- {children}
80
- </Label>
81
- )
37
+ export function FieldLabel({ render = <Label />, className, ...rest }: FieldLabelProps) {
38
+ return <FieldPrimitive.Label {...rest} render={render} className={fieldLabel({ className })} />
82
39
  }
83
40
 
84
41
  const fieldHelp = tv({
@@ -86,23 +43,17 @@ const fieldHelp = tv({
86
43
  + ' group-has-disabled:text-fg-disabled',
87
44
  })
88
45
 
89
- export function FieldHelp({ className, children }: { className?: string, children?: ReactNode }) {
90
- const ctx = use(Context)
46
+ export type FieldHelpProps = Omit<FieldPrimitive.Description.Props, 'className'> & {
47
+ className?: string
48
+ }
91
49
 
92
- return (
93
- <p
94
- id={ctx?.messageId}
95
- className={fieldHelp({ className })}
96
- >
97
- {children}
98
- </p>
99
- )
50
+ export function FieldHelp({ className, ...rest }: FieldHelpProps) {
51
+ return <FieldPrimitive.Description {...rest} className={fieldHelp({ className })} />
100
52
  }
101
53
 
102
- export interface FieldErrorProps {
54
+ export type FieldErrorProps = Omit<FieldPrimitive.Error.Props, 'className'> & {
103
55
  items?: string | string[]
104
56
  className?: string
105
- children?: ReactNode
106
57
  }
107
58
 
108
59
  const fieldError = tv({
@@ -110,15 +61,11 @@ const fieldError = tv({
110
61
  + ' flex items-start gap-tight',
111
62
  })
112
63
 
113
- export function FieldError({ items, className, children }: FieldErrorProps) {
114
- const ctx = use(Context)
115
- const list = items == null ? [] : Array.isArray(items) ? items : [items]
64
+ export function FieldError({ items, match = true, render = <p />, className, children, ...rest }: FieldErrorProps) {
65
+ const list: string[] = items == null ? [] : Array.isArray(items) ? items : [items]
116
66
 
117
67
  return (
118
- <p
119
- id={ctx?.messageId}
120
- className={fieldError({ className })}
121
- >
68
+ <FieldPrimitive.Error {...rest} match={match} render={render} className={fieldError({ className })}>
122
69
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={2} strokeLinecap="round" strokeLinejoin="round" aria-hidden="true" className="mt-0.5 size-4 shrink-0">
123
70
  <circle cx="12" cy="12" r="10" />
124
71
  <line x1="12" x2="12" y1="8" y2="12" />
@@ -127,7 +74,7 @@ export function FieldError({ items, className, children }: FieldErrorProps) {
127
74
  <span className="flex min-w-0 flex-col gap-0.5">
128
75
  {children ?? list.map(t => <span key={t}>{t}</span>)}
129
76
  </span>
130
- </p>
77
+ </FieldPrimitive.Error>
131
78
  )
132
79
  }
133
80
 
@@ -136,19 +83,16 @@ const fieldPending = tv({
136
83
  + ' flex items-start gap-tight',
137
84
  })
138
85
 
139
- export function FieldPending({ className, children }: { className?: string, children?: ReactNode }) {
140
- const ctx = use(Context)
86
+ export type FieldPendingProps = FieldHelpProps
141
87
 
88
+ export function FieldPending({ className, children, ...rest }: FieldPendingProps) {
142
89
  return (
143
- <p
144
- id={ctx?.messageId}
145
- className={fieldPending({ className })}
146
- >
90
+ <FieldPrimitive.Description {...rest} className={fieldPending({ className })}>
147
91
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={2} strokeLinecap="round" strokeLinejoin="round" aria-hidden="true" className="mt-0.5 size-4 shrink-0 animate-spin motion-reduce:animate-none">
148
92
  <path d="M21 12a9 9 0 1 1-6.219-8.56" />
149
93
  </svg>
150
94
  <span className="min-w-0">{children}</span>
151
- </p>
95
+ </FieldPrimitive.Description>
152
96
  )
153
97
  }
154
98
 
@@ -157,19 +101,16 @@ const fieldSuccess = tv({
157
101
  + ' flex items-start gap-tight',
158
102
  })
159
103
 
160
- export function FieldSuccess({ className, children }: { className?: string, children?: ReactNode }) {
161
- const ctx = use(Context)
104
+ export type FieldSuccessProps = FieldHelpProps
162
105
 
106
+ export function FieldSuccess({ className, children, ...rest }: FieldSuccessProps) {
163
107
  return (
164
- <p
165
- id={ctx?.messageId}
166
- className={fieldSuccess({ className })}
167
- >
108
+ <FieldPrimitive.Description {...rest} className={fieldSuccess({ className })}>
168
109
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={2} strokeLinecap="round" strokeLinejoin="round" aria-hidden="true" className="mt-0.5 size-4 shrink-0">
169
110
  <circle cx="12" cy="12" r="10" />
170
111
  <path d="m16 9-5.5 5.5L8 12" />
171
112
  </svg>
172
113
  <span className="min-w-0">{children}</span>
173
- </p>
114
+ </FieldPrimitive.Description>
174
115
  )
175
116
  }
package/input/index.tsx CHANGED
@@ -1,4 +1,7 @@
1
- import type { InputHTMLAttributes } from 'react'
1
+ 'use client'
2
+
3
+ import { Input as InputPrimitive } from '@base-ui/react/input'
4
+ import type { ComponentProps } from 'react'
2
5
 
3
6
  import { tv } from '../tv'
4
7
 
@@ -26,11 +29,12 @@ export const input = tv({
26
29
  defaultVariants: { surface: 'bare', size: 'md' },
27
30
  })
28
31
 
29
- export interface InputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'size'> {
32
+ export type InputProps = Omit<ComponentProps<typeof InputPrimitive>, 'className' | 'size'> & {
30
33
  surface?: 'bare' | 'well'
31
34
  size?: 'sm' | 'md' | 'lg'
35
+ className?: string
32
36
  }
33
37
 
34
38
  export function Input({ surface, size, className, ...rest }: InputProps) {
35
- return <input {...rest} className={input({ surface, size, className })} />
39
+ return <InputPrimitive {...rest} className={input({ surface, size, className })} />
36
40
  }
package/kbd/index.tsx CHANGED
@@ -3,8 +3,8 @@ import type { HTMLAttributes } from 'react'
3
3
  import { tv } from '../tv'
4
4
 
5
5
  const kbd = tv({
6
- base: 'bg-bg-well text-fg-muted text-micro rounded-r4 inline-flex items-center'
7
- + ' border border-line px-1.5 py-0.5 font-mono',
6
+ base: 'bg-bg-neutral-solid/10 text-fg text-micro rounded-r4 inline-flex items-center'
7
+ + ' border border-transparent px-1.5 py-0.5 font-mono',
8
8
  })
9
9
 
10
10
  export function Kbd({ className, ...rest }: HTMLAttributes<HTMLElement>) {
package/label/index.tsx CHANGED
@@ -1,15 +1,13 @@
1
- import { Label as LabelPrimitive } from 'radix-ui'
2
1
  import type { ComponentProps } from 'react'
3
2
 
4
3
  import { tv } from '../tv'
5
4
 
6
5
  const labelText = tv({ base: 'text-label text-fg' })
7
6
 
8
- export function Label({ className, ...rest }: ComponentProps<typeof LabelPrimitive.Root>) {
9
- return (
10
- <LabelPrimitive.Root
11
- {...rest}
12
- className={labelText({ className })}
13
- />
14
- )
7
+ export type LabelProps = Omit<ComponentProps<'label'>, 'className'> & {
8
+ className?: string
9
+ }
10
+
11
+ export function Label({ className, ...rest }: LabelProps) {
12
+ return <label {...rest} className={labelText({ className })} />
15
13
  }