@adea-ai/ui 0.116.0 → 0.118.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.
- package/dist/components/composites/action-button/action-button.d.ts.map +1 -1
- package/dist/components/composites/action-button/action-button.js +1 -0
- package/dist/components/composites/action-button/action-button.js.map +1 -1
- package/dist/components/composites/list-row/list-row-control.d.ts.map +1 -1
- package/dist/components/composites/list-row/list-row-control.js +1 -0
- package/dist/components/composites/list-row/list-row-control.js.map +1 -1
- package/dist/components/composites/list-row/list-row.d.ts.map +1 -1
- package/dist/components/composites/list-row/list-row.js +16 -9
- package/dist/components/composites/list-row/list-row.js.map +1 -1
- package/dist/components/composites/settings/settings-navigation.d.ts.map +1 -1
- package/dist/components/composites/settings/settings-navigation.js +15 -6
- package/dist/components/composites/settings/settings-navigation.js.map +1 -1
- package/dist/components/composites/settings/settings.d.ts +3 -2
- package/dist/components/composites/settings/settings.d.ts.map +1 -1
- package/dist/components/composites/settings/settings.js +3 -2
- package/dist/components/composites/settings/settings.js.map +1 -1
- package/dist/components/conversation/transcript-composition.d.ts +6 -0
- package/dist/components/conversation/transcript-composition.d.ts.map +1 -1
- package/dist/components/conversation/transcript-composition.js +9 -4
- package/dist/components/conversation/transcript-composition.js.map +1 -1
- package/dist/components/layout/contextual-sidebar/contextual-sidebar.d.ts +2 -0
- package/dist/components/layout/contextual-sidebar/contextual-sidebar.d.ts.map +1 -1
- package/dist/components/layout/contextual-sidebar/contextual-sidebar.js +3 -0
- package/dist/components/layout/contextual-sidebar/contextual-sidebar.js.map +1 -1
- package/dist/components/layout/contextual-sidebar/mobile-contextual-sidebar.d.ts.map +1 -1
- package/dist/components/layout/contextual-sidebar/mobile-contextual-sidebar.js +1 -1
- package/dist/components/layout/contextual-sidebar/mobile-contextual-sidebar.js.map +1 -1
- package/dist/components/layout/pixel-resize-handle/pixel-resize-handle.d.ts +2 -0
- package/dist/components/layout/pixel-resize-handle/pixel-resize-handle.d.ts.map +1 -1
- package/dist/components/layout/pixel-resize-handle/pixel-resize-handle.js +3 -1
- package/dist/components/layout/pixel-resize-handle/pixel-resize-handle.js.map +1 -1
- package/dist/components/ui/alert/alert.d.ts +7 -0
- package/dist/components/ui/alert/alert.d.ts.map +1 -1
- package/dist/components/ui/alert/alert.js +18 -1
- package/dist/components/ui/alert/alert.js.map +1 -1
- package/dist/components/ui/alert/index.d.ts +1 -1
- package/dist/components/ui/alert/index.d.ts.map +1 -1
- package/dist/components/ui/alert/index.js +2 -2
- package/dist/components/ui/badge/badge.d.ts.map +1 -1
- package/dist/components/ui/badge/badge.js +1 -0
- package/dist/components/ui/badge/badge.js.map +1 -1
- package/dist/components/ui/breadcrumb/breadcrumb.d.ts +6 -0
- package/dist/components/ui/breadcrumb/breadcrumb.d.ts.map +1 -1
- package/dist/components/ui/breadcrumb/breadcrumb.js +19 -8
- package/dist/components/ui/breadcrumb/breadcrumb.js.map +1 -1
- package/dist/components/ui/breadcrumb/index.d.ts +1 -1
- package/dist/components/ui/breadcrumb/index.d.ts.map +1 -1
- package/dist/components/ui/breadcrumb/index.js +2 -2
- package/dist/components/ui/button/button.d.ts.map +1 -1
- package/dist/components/ui/button/button.js +1 -0
- package/dist/components/ui/button/button.js.map +1 -1
- package/dist/components/ui/card/card.d.ts +19 -9
- package/dist/components/ui/card/card.d.ts.map +1 -1
- package/dist/components/ui/card/card.js +21 -3
- package/dist/components/ui/card/card.js.map +1 -1
- package/dist/components/ui/card/index.d.ts +1 -1
- package/dist/components/ui/card/index.d.ts.map +1 -1
- package/dist/components/ui/card/index.js +2 -2
- package/dist/components/ui/checkbox/checkbox.d.ts.map +1 -1
- package/dist/components/ui/checkbox/checkbox.js +1 -0
- package/dist/components/ui/checkbox/checkbox.js.map +1 -1
- package/dist/components/ui/dialog/dialog.d.ts +15 -0
- package/dist/components/ui/dialog/dialog.d.ts.map +1 -1
- package/dist/components/ui/dialog/dialog.js +11 -3
- package/dist/components/ui/dialog/dialog.js.map +1 -1
- package/dist/components/ui/dialog/index.d.ts +1 -1
- package/dist/components/ui/dialog/index.d.ts.map +1 -1
- package/dist/components/ui/entity-icon/entity-icon.d.ts +10 -0
- package/dist/components/ui/entity-icon/entity-icon.d.ts.map +1 -1
- package/dist/components/ui/entity-icon/entity-icon.js +11 -2
- package/dist/components/ui/entity-icon/entity-icon.js.map +1 -1
- package/dist/components/ui/field/field.d.ts +11 -1
- package/dist/components/ui/field/field.d.ts.map +1 -1
- package/dist/components/ui/field/field.js +2 -2
- package/dist/components/ui/field/field.js.map +1 -1
- package/dist/components/ui/field/index.d.ts +1 -1
- package/dist/components/ui/field/index.d.ts.map +1 -1
- package/dist/components/ui/input-group/index.d.ts +1 -1
- package/dist/components/ui/input-group/index.d.ts.map +1 -1
- package/dist/components/ui/input-group/input-group.d.ts +8 -1
- package/dist/components/ui/input-group/input-group.d.ts.map +1 -1
- package/dist/components/ui/input-group/input-group.js +16 -20
- package/dist/components/ui/input-group/input-group.js.map +1 -1
- package/dist/components/ui/native-select/native-select.d.ts +8 -1
- package/dist/components/ui/native-select/native-select.d.ts.map +1 -1
- package/dist/components/ui/native-select/native-select.js +9 -2
- package/dist/components/ui/native-select/native-select.js.map +1 -1
- package/dist/components/ui/progress/progress.d.ts.map +1 -1
- package/dist/components/ui/progress/progress.js +6 -3
- package/dist/components/ui/progress/progress.js.map +1 -1
- package/dist/components/ui/radio-group/radio-group.d.ts +18 -3
- package/dist/components/ui/radio-group/radio-group.d.ts.map +1 -1
- package/dist/components/ui/radio-group/radio-group.js +32 -7
- package/dist/components/ui/radio-group/radio-group.js.map +1 -1
- package/dist/components/ui/resizable/resizable.d.ts +7 -2
- package/dist/components/ui/resizable/resizable.d.ts.map +1 -1
- package/dist/components/ui/resizable/resizable.js +7 -6
- package/dist/components/ui/resizable/resizable.js.map +1 -1
- package/dist/components/ui/select/select.d.ts.map +1 -1
- package/dist/components/ui/select/select.js +10 -7
- package/dist/components/ui/select/select.js.map +1 -1
- package/dist/components/ui/sheet/sheet.d.ts +1 -0
- package/dist/components/ui/sheet/sheet.d.ts.map +1 -1
- package/dist/components/ui/sheet/sheet.js +27 -2
- package/dist/components/ui/sheet/sheet.js.map +1 -1
- package/dist/components/ui/slider/slider.d.ts.map +1 -1
- package/dist/components/ui/slider/slider.js +6 -3
- package/dist/components/ui/slider/slider.js.map +1 -1
- package/dist/components/ui/status-chip/status-chip.d.ts.map +1 -1
- package/dist/components/ui/status-chip/status-chip.js +1 -1
- package/dist/components/ui/status-chip/status-chip.js.map +1 -1
- package/dist/components/ui/switch/switch.d.ts.map +1 -1
- package/dist/components/ui/switch/switch.js +1 -0
- package/dist/components/ui/switch/switch.js.map +1 -1
- package/dist/components/ui/tabs/tabs.d.ts +18 -0
- package/dist/components/ui/tabs/tabs.d.ts.map +1 -1
- package/dist/components/ui/tabs/tabs.js +22 -4
- package/dist/components/ui/tabs/tabs.js.map +1 -1
- package/dist/components/ui/toggle/toggle.d.ts.map +1 -1
- package/dist/components/ui/toggle/toggle.js +9 -6
- package/dist/components/ui/toggle/toggle.js.map +1 -1
- package/dist/components/ui/toggle-group/toggle-group.d.ts.map +1 -1
- package/dist/components/ui/toggle-group/toggle-group.js +2 -0
- package/dist/components/ui/toggle-group/toggle-group.js.map +1 -1
- package/dist/components/ui/typography/typography.d.ts +12 -1
- package/dist/components/ui/typography/typography.d.ts.map +1 -1
- package/dist/components/ui/typography/typography.js +16 -2
- package/dist/components/ui/typography/typography.js.map +1 -1
- package/dist/index.js +4 -4
- package/dist/lib/cn-tables.generated.js +5 -5
- package/dist/lib/cn-tables.generated.js.map +1 -1
- package/dist/lib/tokens.d.ts.map +1 -1
- package/dist/lib/tokens.js +7 -2
- package/dist/lib/tokens.js.map +1 -1
- package/dist/r/list-row.json +1 -0
- package/dist/r/registry.json +1 -0
- package/dist/r/src/components/composites/action-button/action-button.tsx +3 -0
- package/dist/r/src/components/composites/list-row/list-row-control.tsx +1 -0
- package/dist/r/src/components/composites/list-row/list-row.tsx +3 -2
- package/dist/r/src/components/composites/settings/settings-navigation.tsx +7 -3
- package/dist/r/src/components/composites/settings/settings.tsx +3 -2
- package/dist/r/src/components/conversation/transcript-composition.tsx +14 -2
- package/dist/r/src/components/layout/contextual-sidebar/contextual-sidebar.tsx +3 -0
- package/dist/r/src/components/layout/contextual-sidebar/mobile-contextual-sidebar.tsx +6 -1
- package/dist/r/src/components/layout/pixel-resize-handle/pixel-resize-handle.tsx +3 -1
- package/dist/r/src/components/ui/alert/alert.tsx +17 -0
- package/dist/r/src/components/ui/alert/index.ts +8 -1
- package/dist/r/src/components/ui/badge/badge.tsx +1 -0
- package/dist/r/src/components/ui/breadcrumb/breadcrumb.tsx +18 -8
- package/dist/r/src/components/ui/breadcrumb/index.ts +1 -0
- package/dist/r/src/components/ui/button/button.tsx +1 -0
- package/dist/r/src/components/ui/card/card.tsx +30 -13
- package/dist/r/src/components/ui/card/index.ts +1 -0
- package/dist/r/src/components/ui/checkbox/checkbox.tsx +1 -0
- package/dist/r/src/components/ui/dialog/dialog.tsx +26 -2
- package/dist/r/src/components/ui/dialog/index.ts +1 -0
- package/dist/r/src/components/ui/entity-icon/entity-icon.tsx +15 -0
- package/dist/r/src/components/ui/field/field.tsx +23 -3
- package/dist/r/src/components/ui/field/index.ts +1 -0
- package/dist/r/src/components/ui/input-group/index.ts +1 -0
- package/dist/r/src/components/ui/input-group/input-group.tsx +28 -5
- package/dist/r/src/components/ui/native-select/native-select.tsx +20 -3
- package/dist/r/src/components/ui/progress/progress.tsx +5 -1
- package/dist/r/src/components/ui/radio-group/radio-group.tsx +40 -3
- package/dist/r/src/components/ui/resizable/resizable.tsx +15 -4
- package/dist/r/src/components/ui/select/select.tsx +1 -0
- package/dist/r/src/components/ui/sheet/sheet.tsx +20 -2
- package/dist/r/src/components/ui/slider/slider.tsx +1 -0
- package/dist/r/src/components/ui/status-chip/status-chip.tsx +1 -0
- package/dist/r/src/components/ui/switch/switch.tsx +1 -0
- package/dist/r/src/components/ui/tabs/tabs.tsx +33 -4
- package/dist/r/src/components/ui/toggle/toggle.tsx +1 -0
- package/dist/r/src/components/ui/toggle-group/toggle-group.tsx +2 -0
- package/dist/r/src/components/ui/typography/typography.tsx +20 -1
- package/dist/r/src/lib/cn-tables.generated.ts +5 -5
- package/dist/r/src/lib/tokens.ts +7 -2
- package/dist/r/src/styles/base.css +4 -1
- package/dist/r/src/styles/theme.css +4 -0
- package/package.json +1 -1
- package/registry.json +1 -0
- package/src/components/composites/action-button/action-button.tsx +3 -0
- package/src/components/composites/list-row/list-row-control.tsx +1 -0
- package/src/components/composites/list-row/list-row.tsx +3 -2
- package/src/components/composites/settings/settings-navigation.tsx +7 -3
- package/src/components/composites/settings/settings.tsx +3 -2
- package/src/components/conversation/transcript-composition.tsx +14 -2
- package/src/components/layout/contextual-sidebar/contextual-sidebar.tsx +3 -0
- package/src/components/layout/contextual-sidebar/mobile-contextual-sidebar.tsx +6 -1
- package/src/components/layout/pixel-resize-handle/pixel-resize-handle.tsx +3 -1
- package/src/components/ui/alert/alert.tsx +17 -0
- package/src/components/ui/alert/index.ts +8 -1
- package/src/components/ui/badge/badge.tsx +1 -0
- package/src/components/ui/breadcrumb/breadcrumb.tsx +18 -8
- package/src/components/ui/breadcrumb/index.ts +1 -0
- package/src/components/ui/button/button.tsx +1 -0
- package/src/components/ui/card/card.tsx +30 -13
- package/src/components/ui/card/index.ts +1 -0
- package/src/components/ui/checkbox/checkbox.tsx +1 -0
- package/src/components/ui/dialog/dialog.tsx +26 -2
- package/src/components/ui/dialog/index.ts +1 -0
- package/src/components/ui/entity-icon/entity-icon.tsx +15 -0
- package/src/components/ui/field/field.tsx +23 -3
- package/src/components/ui/field/index.ts +1 -0
- package/src/components/ui/input-group/index.ts +1 -0
- package/src/components/ui/input-group/input-group.tsx +28 -5
- package/src/components/ui/native-select/native-select.tsx +20 -3
- package/src/components/ui/progress/progress.tsx +5 -1
- package/src/components/ui/radio-group/radio-group.tsx +40 -3
- package/src/components/ui/resizable/resizable.tsx +15 -4
- package/src/components/ui/select/select.tsx +1 -0
- package/src/components/ui/sheet/sheet.tsx +20 -2
- package/src/components/ui/slider/slider.tsx +1 -0
- package/src/components/ui/status-chip/status-chip.tsx +1 -0
- package/src/components/ui/switch/switch.tsx +1 -0
- package/src/components/ui/tabs/tabs.tsx +33 -4
- package/src/components/ui/toggle/toggle.tsx +1 -0
- package/src/components/ui/toggle-group/toggle-group.tsx +2 -0
- package/src/components/ui/typography/typography.tsx +20 -1
- package/src/lib/cn-tables.generated.ts +5 -5
- package/src/lib/tokens.ts +7 -2
- package/src/styles/base.css +4 -1
- package/src/styles/theme.css +4 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type { ComponentProps
|
|
1
|
+
import type { ComponentProps } from 'solid-js'
|
|
2
2
|
import { splitProps } from 'solid-js'
|
|
3
|
+
import { cva, type VariantProps } from '#lib/variants'
|
|
3
4
|
import { cn } from '#lib/utils'
|
|
4
5
|
import { headingVariants } from '../typography'
|
|
5
6
|
|
|
@@ -15,18 +16,36 @@ import { headingVariants } from '../typography'
|
|
|
15
16
|
* The parts are separate components rather than a template because a card's
|
|
16
17
|
* header, content and footer have different padding on purpose: the header and
|
|
17
18
|
* footer are tight, the content breathes.
|
|
19
|
+
*
|
|
20
|
+
* `size` is the card's padding rung, so a caller never sets `p-*` or `gap-*` on
|
|
21
|
+
* a card to make it denser. `sm` tightens the card and its header, content and
|
|
22
|
+
* footer together (the parts' inline padding follows the card, so they stay
|
|
23
|
+
* aligned with each other); `flush` removes the block padding and gap for a
|
|
24
|
+
* card whose body is a list of rows or a scroll area that runs edge to edge.
|
|
18
25
|
*/
|
|
19
|
-
export
|
|
20
|
-
|
|
26
|
+
export const cardVariants = cva(
|
|
27
|
+
'bg-card text-card-foreground flex flex-col rounded-xl border border-border shadow-xs',
|
|
28
|
+
{
|
|
29
|
+
variants: {
|
|
30
|
+
size: {
|
|
31
|
+
/** 16px block padding and gap; the parts carry 16px inline padding. */
|
|
32
|
+
default: 'gap-4 py-4',
|
|
33
|
+
/** 12px everywhere: a dense settings or status card. */
|
|
34
|
+
sm: 'gap-3 py-3 *:data-[slot=card-content]:px-3 *:data-[slot=card-footer]:px-3 *:data-[slot=card-header]:px-3',
|
|
35
|
+
/** No block padding or gap: the card hosts a row list or a scroller. */
|
|
36
|
+
flush: 'gap-0 py-0',
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
defaultVariants: { size: 'default' },
|
|
40
|
+
}
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
export type CardProps = ComponentProps<'div'> & VariantProps<typeof cardVariants>
|
|
44
|
+
|
|
45
|
+
export function Card(props: CardProps) {
|
|
46
|
+
const [local, rest] = splitProps(props, ['class', 'size'])
|
|
21
47
|
return (
|
|
22
|
-
<div
|
|
23
|
-
data-slot="card"
|
|
24
|
-
class={cn(
|
|
25
|
-
'bg-card text-card-foreground flex flex-col gap-4 rounded-xl border border-border py-4 shadow-xs',
|
|
26
|
-
local.class
|
|
27
|
-
)}
|
|
28
|
-
{...rest}
|
|
29
|
-
/>
|
|
48
|
+
<div data-slot="card" class={cn(cardVariants({ size: local.size }), local.class)} {...rest} />
|
|
30
49
|
)
|
|
31
50
|
}
|
|
32
51
|
|
|
@@ -79,5 +98,3 @@ export function CardFooter(props: ComponentProps<'div'>) {
|
|
|
79
98
|
const [local, rest] = splitProps(props, ['class'])
|
|
80
99
|
return <div data-slot="card-footer" class={cn('flex items-center px-4', local.class)} {...rest} />
|
|
81
100
|
}
|
|
82
|
-
|
|
83
|
-
export type CardProps = ComponentProps<'div'> & JSX.HTMLAttributes<HTMLDivElement>
|
|
@@ -271,10 +271,33 @@ export type DialogContentProps = ComponentProps<typeof KobalteDialogContent> & {
|
|
|
271
271
|
closeButton?: JSX.Element | false
|
|
272
272
|
/** Use a 1rem inset as the positioner bounds for tall, viewport-filling surfaces. */
|
|
273
273
|
positioner?: 'default' | 'inset'
|
|
274
|
+
/**
|
|
275
|
+
* The panel's maximum width. `md` (32rem) is the default and right for a
|
|
276
|
+
* confirmation or a short form; `sm` (28rem) for a single question; `lg`
|
|
277
|
+
* (42rem) for a picker or a form with two columns; `xl` (48rem) for a
|
|
278
|
+
* multi-step flow that needs a table or a preview beside its fields.
|
|
279
|
+
*/
|
|
280
|
+
size?: DialogContentSize
|
|
274
281
|
}
|
|
275
282
|
|
|
283
|
+
/** The dialog width ladder, so a caller picks a rung instead of a `max-w-*`. */
|
|
284
|
+
export const dialogContentSizes = {
|
|
285
|
+
sm: 'max-w-md',
|
|
286
|
+
md: 'max-w-lg',
|
|
287
|
+
lg: 'max-w-2xl',
|
|
288
|
+
xl: 'max-w-3xl',
|
|
289
|
+
} as const
|
|
290
|
+
|
|
291
|
+
export type DialogContentSize = keyof typeof dialogContentSizes
|
|
292
|
+
|
|
276
293
|
export function DialogContent(props: DialogContentProps) {
|
|
277
|
-
const [local, rest] = splitProps(props, [
|
|
294
|
+
const [local, rest] = splitProps(props, [
|
|
295
|
+
'class',
|
|
296
|
+
'children',
|
|
297
|
+
'closeButton',
|
|
298
|
+
'positioner',
|
|
299
|
+
'size',
|
|
300
|
+
])
|
|
278
301
|
|
|
279
302
|
return (
|
|
280
303
|
<KobalteDialog.Portal>
|
|
@@ -284,7 +307,8 @@ export function DialogContent(props: DialogContentProps) {
|
|
|
284
307
|
class={cn(
|
|
285
308
|
dialogSurface,
|
|
286
309
|
overlayMotion,
|
|
287
|
-
'relative grid w-full
|
|
310
|
+
'relative grid w-full gap-4 p-5',
|
|
311
|
+
dialogContentSizes[local.size ?? 'md'],
|
|
288
312
|
local.class
|
|
289
313
|
)}
|
|
290
314
|
{...rest}
|
|
@@ -35,6 +35,14 @@ import { cn } from '#lib/utils'
|
|
|
35
35
|
* `shape="rounded"` is the default because a rounded square reads as an object
|
|
36
36
|
* and a circle reads as a person; use `circle` only when the tile really does
|
|
37
37
|
* hold a face.
|
|
38
|
+
*
|
|
39
|
+
* `monochrome` is for a third-party brand mark — a vendor logo drawn with its
|
|
40
|
+
* own `fill`. A brand's hex is chosen for a white page: GitHub's near-black and
|
|
41
|
+
* Slack's aubergine all but vanish on a dark tile, and no tone can be picked
|
|
42
|
+
* that suits every brand in both themes. `monochrome` repaints any explicitly
|
|
43
|
+
* filled shape in the tile's glyph colour (the tone's), so the mark stays
|
|
44
|
+
* recognisable by its shape and legible in every theme. Stroke-drawn icons
|
|
45
|
+
* (Lucide, `fill="none"`) are left alone.
|
|
38
46
|
*/
|
|
39
47
|
export const entityIconVariants = cva(
|
|
40
48
|
'relative inline-flex shrink-0 items-center justify-center overflow-hidden border font-semibold select-none [&_svg]:pointer-events-none [&_svg]:shrink-0',
|
|
@@ -90,6 +98,8 @@ export type EntityIconProps = Omit<ComponentProps<'span'>, 'children'> &
|
|
|
90
98
|
badge?: JSX.Element
|
|
91
99
|
/** A second edge, drawn outside the tile — an active or selected ring. */
|
|
92
100
|
ring?: boolean
|
|
101
|
+
/** Repaint a brand mark's own fills in the tile's glyph colour. */
|
|
102
|
+
monochrome?: boolean
|
|
93
103
|
}
|
|
94
104
|
|
|
95
105
|
/**
|
|
@@ -143,6 +153,7 @@ export function EntityIcon(props: EntityIconProps) {
|
|
|
143
153
|
'fallback',
|
|
144
154
|
'badge',
|
|
145
155
|
'ring',
|
|
156
|
+
'monochrome',
|
|
146
157
|
'shape',
|
|
147
158
|
'size',
|
|
148
159
|
'tone',
|
|
@@ -159,9 +170,13 @@ export function EntityIcon(props: EntityIconProps) {
|
|
|
159
170
|
|
|
160
171
|
return (
|
|
161
172
|
<span
|
|
173
|
+
data-slot="entity-icon"
|
|
162
174
|
class={cn(
|
|
163
175
|
entityIconVariants({ shape: local.shape, size: local.size, tone: local.tone }),
|
|
164
176
|
local.ring && 'ring-2 ring-ring ring-offset-2 ring-offset-background',
|
|
177
|
+
// A presentation attribute (`fill="#4A154B"`) loses to any CSS rule, so
|
|
178
|
+
// this overrides the brand's hex without touching the caller's SVG.
|
|
179
|
+
local.monochrome && "[&_[fill]:not([fill='none'])]:fill-current",
|
|
165
180
|
local.class
|
|
166
181
|
)}
|
|
167
182
|
role="img"
|
|
@@ -188,10 +188,30 @@ export function FieldSet(props: ComponentProps<'fieldset'>) {
|
|
|
188
188
|
return <fieldset class={cn('flex flex-col gap-4', local.class)} {...rest} />
|
|
189
189
|
}
|
|
190
190
|
|
|
191
|
+
export type FieldGroupProps = ComponentProps<'div'> & {
|
|
192
|
+
/**
|
|
193
|
+
* `2` lays the fields out in two columns from the `sm` breakpoint up — a
|
|
194
|
+
* short form of paired values (host and port, a name and a model). A field
|
|
195
|
+
* that needs the full width says `class="col-span-full"`. Below `sm` it is
|
|
196
|
+
* one column again, because two inputs side by side on a phone are each too
|
|
197
|
+
* narrow to read.
|
|
198
|
+
*/
|
|
199
|
+
columns?: 1 | 2
|
|
200
|
+
}
|
|
201
|
+
|
|
191
202
|
/** A visual stack for related controls that does not imply fieldset semantics. */
|
|
192
|
-
export function FieldGroup(props:
|
|
193
|
-
const [local, rest] = splitProps(props, ['class'])
|
|
194
|
-
return
|
|
203
|
+
export function FieldGroup(props: FieldGroupProps) {
|
|
204
|
+
const [local, rest] = splitProps(props, ['class', 'columns'])
|
|
205
|
+
return (
|
|
206
|
+
<div
|
|
207
|
+
data-slot="field-group"
|
|
208
|
+
class={cn(
|
|
209
|
+
local.columns === 2 ? 'grid gap-4 sm:grid-cols-2' : 'flex flex-col gap-4',
|
|
210
|
+
local.class
|
|
211
|
+
)}
|
|
212
|
+
{...rest}
|
|
213
|
+
/>
|
|
214
|
+
)
|
|
195
215
|
}
|
|
196
216
|
|
|
197
217
|
export function FieldLegend(props: ComponentProps<'legend'> & { variant?: 'legend' | 'label' }) {
|
|
@@ -15,15 +15,29 @@ import { cn } from '#lib/utils'
|
|
|
15
15
|
* The focus ring therefore lives on the group and follows `focus-within`. A
|
|
16
16
|
* group containing several focusable things still reads as focused once, which
|
|
17
17
|
* is the correct affordance: the user is somewhere inside it.
|
|
18
|
+
*
|
|
19
|
+
* `size` is the control rung, matching `Input`: `sm` for a toolbar search beside
|
|
20
|
+
* `icon-sm` actions, `md` (the default) everywhere else. The group's input and
|
|
21
|
+
* text follow it.
|
|
18
22
|
*/
|
|
19
|
-
export
|
|
20
|
-
|
|
23
|
+
export type InputGroupProps = ComponentProps<'div'> & {
|
|
24
|
+
size?: 'sm' | 'md' | 'lg'
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function InputGroup(props: InputGroupProps) {
|
|
28
|
+
const [local, rest] = splitProps(props, ['class', 'size'])
|
|
21
29
|
|
|
22
30
|
return (
|
|
23
31
|
<div
|
|
24
32
|
data-slot="input-group"
|
|
33
|
+
data-size={local.size}
|
|
25
34
|
class={cn(
|
|
26
|
-
'border-input flex
|
|
35
|
+
'group/input-group border-input flex w-full min-w-0 items-center gap-1.5 rounded-md border bg-transparent',
|
|
36
|
+
{
|
|
37
|
+
'h-control-sm px-control-xs': local.size === 'sm',
|
|
38
|
+
'h-control-md px-control-sm': local.size === 'md' || local.size === undefined,
|
|
39
|
+
'h-control-lg px-control-md': local.size === 'lg',
|
|
40
|
+
},
|
|
27
41
|
'transition-[color,box-shadow,border-color] ease-out',
|
|
28
42
|
'focus-within:border-ring focus-within:ring-3 focus-within:ring-primary-subtle',
|
|
29
43
|
'has-[[aria-invalid=true]]:border-destructive has-[[aria-invalid=true]]:ring-3 has-[[aria-invalid=true]]:ring-destructive-subtle',
|
|
@@ -64,7 +78,7 @@ export function InputGroupInput(props: ComponentProps<'input'>) {
|
|
|
64
78
|
aria-invalid={field?.['aria-invalid'] ?? local['aria-invalid']}
|
|
65
79
|
aria-errormessage={field?.['aria-errormessage'] ?? local['aria-errormessage']}
|
|
66
80
|
class={cn(
|
|
67
|
-
'h-full min-w-0 flex-1 bg-transparent text-sm outline-none',
|
|
81
|
+
'h-full min-w-0 flex-1 bg-transparent text-sm outline-none group-data-[size=sm]/input-group:text-xs',
|
|
68
82
|
'placeholder:text-muted-foreground',
|
|
69
83
|
'disabled:cursor-not-allowed',
|
|
70
84
|
local.class
|
|
@@ -94,6 +108,7 @@ export function InputGroupAddon(props: InputGroupAddonProps) {
|
|
|
94
108
|
class={cn(
|
|
95
109
|
'text-muted-foreground flex shrink-0 items-center gap-1.5 text-sm select-none',
|
|
96
110
|
'[&_svg]:pointer-events-none [&_svg]:size-4',
|
|
111
|
+
'group-data-[size=sm]/input-group:text-xs group-data-[size=sm]/input-group:[&_svg]:size-3.5',
|
|
97
112
|
{ 'order-first': local.align !== 'end', 'order-last': local.align === 'end' },
|
|
98
113
|
local.class
|
|
99
114
|
)}
|
|
@@ -130,5 +145,13 @@ export function InputGroupButton(props: ComponentProps<'button'>) {
|
|
|
130
145
|
/** Text that reads as a value but is not an input, e.g. a unit or a suffix. */
|
|
131
146
|
export function InputGroupText(props: ComponentProps<'span'> & { children?: JSX.Element }) {
|
|
132
147
|
const [local, rest] = splitProps(props, ['class'])
|
|
133
|
-
return
|
|
148
|
+
return (
|
|
149
|
+
<span
|
|
150
|
+
class={cn(
|
|
151
|
+
'text-muted-foreground text-sm group-data-[size=sm]/input-group:text-xs',
|
|
152
|
+
local.class
|
|
153
|
+
)}
|
|
154
|
+
{...rest}
|
|
155
|
+
/>
|
|
156
|
+
)
|
|
134
157
|
}
|
|
@@ -4,7 +4,14 @@ import { createEffect, For, onMount, Show, splitProps } from 'solid-js'
|
|
|
4
4
|
import { useFormFieldControl } from '#lib/form-field'
|
|
5
5
|
import { cn } from '#lib/utils'
|
|
6
6
|
|
|
7
|
-
export type NativeSelectProps = ComponentProps<'select'> & {
|
|
7
|
+
export type NativeSelectProps = Omit<ComponentProps<'select'>, 'size'> & {
|
|
8
|
+
/**
|
|
9
|
+
* The control rung, matching `Input` and `SelectTrigger`: `sm` for a dense
|
|
10
|
+
* toolbar or pane filter, `md` (the default) everywhere else. This replaces the
|
|
11
|
+
* native `size` attribute, which turns a select into a list box — a different
|
|
12
|
+
* control that this styled single-line select is not.
|
|
13
|
+
*/
|
|
14
|
+
size?: 'sm' | 'md' | 'lg'
|
|
8
15
|
/** Render the choices from data instead of raw option children. */
|
|
9
16
|
options?: readonly NativeSelectOption[]
|
|
10
17
|
/** Initialize an uncontrolled selection after its native options mount. */
|
|
@@ -62,6 +69,7 @@ export type NativeSelectOption = Readonly<{
|
|
|
62
69
|
export function NativeSelect(props: NativeSelectProps) {
|
|
63
70
|
const [local, rest] = splitProps(props, [
|
|
64
71
|
'class',
|
|
72
|
+
'size',
|
|
65
73
|
'children',
|
|
66
74
|
'defaultValue',
|
|
67
75
|
'options',
|
|
@@ -108,7 +116,13 @@ export function NativeSelect(props: NativeSelectProps) {
|
|
|
108
116
|
aria-invalid={field?.['aria-invalid'] ?? local['aria-invalid']}
|
|
109
117
|
aria-errormessage={field?.['aria-errormessage'] ?? local['aria-errormessage']}
|
|
110
118
|
class={cn(
|
|
111
|
-
'
|
|
119
|
+
'min-w-0 appearance-none rounded-md border border-input bg-transparent',
|
|
120
|
+
{
|
|
121
|
+
'h-control-sm px-control-sm pr-8 text-xs': local.size === 'sm',
|
|
122
|
+
'h-control-md px-control-md pr-9 text-sm':
|
|
123
|
+
local.size === 'md' || local.size === undefined,
|
|
124
|
+
'h-control-lg px-control-lg pr-9 text-sm': local.size === 'lg',
|
|
125
|
+
},
|
|
112
126
|
'transition-[color,box-shadow,border-color] ease-out outline-none',
|
|
113
127
|
'focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle',
|
|
114
128
|
'aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive-subtle',
|
|
@@ -132,7 +146,10 @@ export function NativeSelect(props: NativeSelectProps) {
|
|
|
132
146
|
<ChevronDownIcon
|
|
133
147
|
data-slot="native-select-icon"
|
|
134
148
|
aria-hidden="true"
|
|
135
|
-
class=
|
|
149
|
+
class={cn(
|
|
150
|
+
'pointer-events-none absolute end-2 top-1/2 -translate-y-1/2 text-muted-foreground',
|
|
151
|
+
local.size === 'sm' ? 'size-3.5' : 'size-4'
|
|
152
|
+
)}
|
|
136
153
|
/>
|
|
137
154
|
</span>
|
|
138
155
|
)
|
|
@@ -39,7 +39,11 @@ export function Progress(props: ProgressProps) {
|
|
|
39
39
|
])
|
|
40
40
|
|
|
41
41
|
return (
|
|
42
|
-
<KobalteProgress
|
|
42
|
+
<KobalteProgress
|
|
43
|
+
data-slot="progress"
|
|
44
|
+
class={cn('flex w-full flex-col gap-1.5', local.class)}
|
|
45
|
+
{...rest}
|
|
46
|
+
>
|
|
43
47
|
<Show when={local.label || !local.hideValue}>
|
|
44
48
|
<div class="flex items-center justify-between gap-3">
|
|
45
49
|
<Show when={local.label}>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { RadioGroup as KobalteRadioGroup } from '@kobalte/core/radio-group'
|
|
2
2
|
import { Circle } from 'lucide-solid'
|
|
3
|
-
import type { ComponentProps } from 'solid-js'
|
|
3
|
+
import type { ComponentProps, JSX } from 'solid-js'
|
|
4
4
|
import { splitProps } from 'solid-js'
|
|
5
5
|
import { useFormFieldControl } from '#lib/form-field'
|
|
6
6
|
import { cn } from '#lib/utils'
|
|
@@ -37,6 +37,7 @@ export function RadioGroup(props: ComponentProps<typeof KobalteRadioGroup>) {
|
|
|
37
37
|
})
|
|
38
38
|
return (
|
|
39
39
|
<KobalteRadioGroup
|
|
40
|
+
data-slot="radio-group"
|
|
40
41
|
id={field?.id ?? local.id}
|
|
41
42
|
aria-label={local['aria-label']}
|
|
42
43
|
aria-labelledby={field?.['aria-labelledby'] ?? local['aria-labelledby']}
|
|
@@ -58,14 +59,31 @@ export type RadioGroupItemProps = ComponentProps<typeof KobalteRadioGroup.Item>
|
|
|
58
59
|
*/
|
|
59
60
|
label?: string
|
|
60
61
|
description?: string
|
|
62
|
+
/**
|
|
63
|
+
* `card` draws the option as a bordered, selectable card — for a choice
|
|
64
|
+
* whose options need a sentence each (a source type, a sync budget), where a
|
|
65
|
+
* bare radio row reads as a form field rather than a decision. The whole card
|
|
66
|
+
* is the hit target, and the selected card takes the primary edge.
|
|
67
|
+
*/
|
|
68
|
+
variant?: 'default' | 'card'
|
|
69
|
+
/** A leading icon or `EntityIcon` between the radio and the text, for `card`. */
|
|
70
|
+
media?: JSX.Element
|
|
61
71
|
}
|
|
62
72
|
|
|
73
|
+
/**
|
|
74
|
+
* A card option's label stretches an invisible layer over the whole card, so a
|
|
75
|
+
* click anywhere on it — padding, media, description — selects the option
|
|
76
|
+
* through the label's native association with the radio input. Wrapping the
|
|
77
|
+
* card in a `<label>` would nest the item's own label inside another.
|
|
78
|
+
*/
|
|
63
79
|
export function RadioGroupItem(props: RadioGroupItemProps) {
|
|
64
80
|
const [local, rest] = splitProps(props, [
|
|
65
81
|
'class',
|
|
66
82
|
'controlClass',
|
|
67
83
|
'label',
|
|
68
84
|
'description',
|
|
85
|
+
'variant',
|
|
86
|
+
'media',
|
|
69
87
|
'children',
|
|
70
88
|
'aria-label',
|
|
71
89
|
'aria-labelledby',
|
|
@@ -74,11 +92,23 @@ export function RadioGroupItem(props: RadioGroupItemProps) {
|
|
|
74
92
|
'aria-busy',
|
|
75
93
|
'title',
|
|
76
94
|
])
|
|
95
|
+
const card = () => local.variant === 'card'
|
|
77
96
|
|
|
78
97
|
return (
|
|
79
98
|
<KobalteRadioGroup.Item
|
|
99
|
+
data-slot="radio-group-item"
|
|
100
|
+
data-variant={card() ? 'card' : undefined}
|
|
80
101
|
title={local.title}
|
|
81
|
-
class={cn(
|
|
102
|
+
class={cn(
|
|
103
|
+
'group/radio flex items-start gap-2.5',
|
|
104
|
+
{
|
|
105
|
+
'relative rounded-lg border border-border bg-card px-3 py-2.5 transition-[color,box-shadow,border-color,background-color] ease-out hover:bg-surface-hover data-[checked]:border-primary data-[disabled]:cursor-not-allowed data-[disabled]:hover:bg-card':
|
|
106
|
+
card(),
|
|
107
|
+
'has-[input:focus-visible]:border-ring has-[input:focus-visible]:ring-3 has-[input:focus-visible]:ring-primary-subtle':
|
|
108
|
+
card(),
|
|
109
|
+
},
|
|
110
|
+
local.class
|
|
111
|
+
)}
|
|
82
112
|
{...rest}
|
|
83
113
|
>
|
|
84
114
|
<KobalteRadioGroup.ItemInput
|
|
@@ -104,10 +134,17 @@ export function RadioGroupItem(props: RadioGroupItemProps) {
|
|
|
104
134
|
<Circle class="size-2 fill-current" />
|
|
105
135
|
</KobalteRadioGroup.ItemIndicator>
|
|
106
136
|
</KobalteRadioGroup.ItemControl>
|
|
137
|
+
{local.media ? (
|
|
138
|
+
<span data-slot="radio-group-item-media" class="flex shrink-0 items-center">
|
|
139
|
+
{local.media}
|
|
140
|
+
</span>
|
|
141
|
+
) : null}
|
|
107
142
|
{local.children ?? (
|
|
108
143
|
<div class="grid gap-0.5 leading-none">
|
|
109
144
|
{local.label ? (
|
|
110
|
-
<KobalteRadioGroup.ItemLabel
|
|
145
|
+
<KobalteRadioGroup.ItemLabel
|
|
146
|
+
class={cn('text-sm font-medium', card() && 'after:absolute after:inset-0')}
|
|
147
|
+
>
|
|
111
148
|
{local.label}
|
|
112
149
|
</KobalteRadioGroup.ItemLabel>
|
|
113
150
|
) : null}
|
|
@@ -70,8 +70,13 @@ export function ResizablePanel(props: ComponentProps<typeof Resizable.Panel> & {
|
|
|
70
70
|
|
|
71
71
|
export type ResizableHandleProps = ComponentProps<typeof Resizable.Handle> & {
|
|
72
72
|
class?: string
|
|
73
|
-
/**
|
|
74
|
-
|
|
73
|
+
/**
|
|
74
|
+
* Draw a visible grip in the middle of the divider: `true` is the bordered
|
|
75
|
+
* chip with its grip icon; `'rung'` is a quieter translucent bar with no
|
|
76
|
+
* icon, for edges that should read as barely there. Either way the divider
|
|
77
|
+
* keeps its full 24px hit target.
|
|
78
|
+
*/
|
|
79
|
+
withHandle?: boolean | 'rung'
|
|
75
80
|
/**
|
|
76
81
|
* The divider's accessible name. It is a focusable control — arrow keys move
|
|
77
82
|
* the split — so it needs one; without it a screen reader announces an
|
|
@@ -97,7 +102,8 @@ export function ResizableHandle(props: ResizableHandleProps) {
|
|
|
97
102
|
a hairline, but a hairline is far too small to grab. 24px on the
|
|
98
103
|
drag axis meets WCAG 2.5.8's minimum target. */
|
|
99
104
|
'after:absolute after:inset-y-0 after:-inset-x-3 after:w-6',
|
|
100
|
-
'transition-colors ease-out
|
|
105
|
+
'transition-colors ease-out',
|
|
106
|
+
local.withHandle === 'rung' ? 'hover:bg-primary/45' : 'hover:bg-primary',
|
|
101
107
|
'focus-visible:bg-primary focus-visible:outline-none',
|
|
102
108
|
'data-[orientation=vertical]:h-px data-[orientation=vertical]:w-full',
|
|
103
109
|
'data-[orientation=vertical]:after:inset-x-0 data-[orientation=vertical]:after:-inset-y-3 data-[orientation=vertical]:after:h-6 data-[orientation=vertical]:after:w-full',
|
|
@@ -105,7 +111,12 @@ export function ResizableHandle(props: ResizableHandleProps) {
|
|
|
105
111
|
)}
|
|
106
112
|
{...rest}
|
|
107
113
|
>
|
|
108
|
-
{local.withHandle ? (
|
|
114
|
+
{local.withHandle === 'rung' ? (
|
|
115
|
+
<div
|
|
116
|
+
data-slot="resizable-grip"
|
|
117
|
+
class="z-(--z-docked) h-11 w-1.5 flex-none rounded-full bg-border/55 group-data-[orientation=vertical]/resize:h-1.5 group-data-[orientation=vertical]/resize:w-11"
|
|
118
|
+
/>
|
|
119
|
+
) : local.withHandle ? (
|
|
109
120
|
<div class="bg-border z-(--z-docked) flex h-4 w-2.5 items-center justify-center rounded-sm border border-border">
|
|
110
121
|
<GripVertical class="size-2.5 text-muted-foreground" />
|
|
111
122
|
</div>
|
|
@@ -46,6 +46,7 @@ export function SelectTrigger(props: SelectTriggerProps) {
|
|
|
46
46
|
|
|
47
47
|
return (
|
|
48
48
|
<KobalteSelect.Trigger
|
|
49
|
+
data-slot="select-trigger"
|
|
49
50
|
class={cn(
|
|
50
51
|
'border-input bg-transparent flex w-fit items-center justify-between gap-2 rounded-md border px-control-md',
|
|
51
52
|
'whitespace-nowrap transition-[color,box-shadow,border-color] ease-out outline-none',
|
|
@@ -60,6 +60,16 @@ const sheetVariants = cva(
|
|
|
60
60
|
edge: '',
|
|
61
61
|
inset: 'panel-dialog-inset w-lg rounded-xl border',
|
|
62
62
|
},
|
|
63
|
+
/**
|
|
64
|
+
* `panel` gives a start or end sheet the shell's panel width
|
|
65
|
+
* (`--panel-width`, 390px) — the width a pane that collapses into a sheet
|
|
66
|
+
* on a narrow window already had beside the work, so its content does not
|
|
67
|
+
* reflow when it moves. Top and bottom sheets span the window either way.
|
|
68
|
+
*/
|
|
69
|
+
size: {
|
|
70
|
+
default: '',
|
|
71
|
+
panel: '',
|
|
72
|
+
},
|
|
63
73
|
},
|
|
64
74
|
compoundVariants: [
|
|
65
75
|
{
|
|
@@ -82,8 +92,15 @@ const sheetVariants = cva(
|
|
|
82
92
|
variant: 'edge',
|
|
83
93
|
class: 'inset-y-0 end-0 h-full w-80 max-w-[85vw] rounded-s-xl border-s',
|
|
84
94
|
},
|
|
95
|
+
{
|
|
96
|
+
side: ['start', 'end'],
|
|
97
|
+
variant: 'edge',
|
|
98
|
+
size: 'panel',
|
|
99
|
+
class: 'w-panel max-w-[92vw]',
|
|
100
|
+
},
|
|
101
|
+
{ side: ['start', 'end'], variant: 'inset', size: 'panel', class: 'w-panel' },
|
|
85
102
|
],
|
|
86
|
-
defaultVariants: { side: 'end', variant: 'edge' },
|
|
103
|
+
defaultVariants: { side: 'end', variant: 'edge', size: 'default' },
|
|
87
104
|
}
|
|
88
105
|
)
|
|
89
106
|
|
|
@@ -107,6 +124,7 @@ export function SheetContent(props: SheetContentProps) {
|
|
|
107
124
|
'class',
|
|
108
125
|
'side',
|
|
109
126
|
'variant',
|
|
127
|
+
'size',
|
|
110
128
|
'children',
|
|
111
129
|
'closeButton',
|
|
112
130
|
'closeLabel',
|
|
@@ -134,7 +152,7 @@ export function SheetContent(props: SheetContentProps) {
|
|
|
134
152
|
<KobalteDialogContent
|
|
135
153
|
data-variant={variant()}
|
|
136
154
|
class={cn(
|
|
137
|
-
sheetVariants({ side: local.side, variant: variant() }),
|
|
155
|
+
sheetVariants({ side: local.side, variant: variant(), size: local.size }),
|
|
138
156
|
'data-expanded:animate-in data-expanded:fade-in-0 data-expanded:duration-200',
|
|
139
157
|
'data-closed:animate-out data-closed:fade-out-0 data-closed:duration-150',
|
|
140
158
|
local.class
|
|
@@ -42,6 +42,7 @@ export function Slider(props: SliderProps) {
|
|
|
42
42
|
|
|
43
43
|
return (
|
|
44
44
|
<KobalteSlider
|
|
45
|
+
data-slot="slider"
|
|
45
46
|
class={cn(
|
|
46
47
|
'relative flex touch-none flex-col justify-center select-none',
|
|
47
48
|
'data-[orientation=vertical]:h-full data-[orientation=vertical]:w-5 data-[orientation=horizontal]:w-full',
|