@adea-ai/ui 0.61.0 → 0.62.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/README.md +44 -6
- package/dist/LICENSE +201 -0
- package/dist/NOTICE +50 -0
- package/dist/components/composites/account-menu/index.js +2 -0
- package/dist/components/composites/list-row/index.js +2 -0
- package/dist/components/composites/settings/index.js +2 -0
- package/dist/components/composites/stat/index.js +2 -0
- package/dist/components/composites/update-dialog/index.js +2 -0
- package/dist/components/composites/workspace-mark/index.js +2 -0
- package/dist/components/conversation/index.js +6 -0
- package/dist/components/layout/app-shell/index.js +2 -0
- package/dist/components/layout/page/index.js +2 -0
- package/dist/components/layout/panel/index.js +2 -0
- package/dist/components/layout/side-rail/index.js +3 -0
- package/dist/components/layout/sidebar-nav/index.js +2 -0
- package/dist/components/layout/status-bar/index.js +2 -0
- package/dist/components/layout/top-bar/index.js +2 -0
- package/dist/components/motion/index.js +2 -2
- package/dist/components/theme/index.js +5 -0
- package/dist/components/ui/accordion/index.js +2 -0
- package/dist/components/ui/alert/index.js +2 -0
- package/dist/components/ui/alert-dialog/index.js +2 -0
- package/dist/components/ui/aspect-ratio/index.js +2 -0
- package/dist/components/ui/avatar/index.js +2 -0
- package/dist/components/ui/badge/index.js +2 -0
- package/dist/components/ui/board/index.js +2 -0
- package/dist/components/ui/breadcrumb/index.js +2 -0
- package/dist/components/ui/button/index.js +2 -0
- package/dist/components/ui/button-group/index.js +2 -0
- package/dist/components/ui/calendar/index.js +2 -0
- package/dist/components/ui/card/index.js +2 -0
- package/dist/components/ui/carousel/index.js +2 -0
- package/dist/components/ui/chart/index.js +2 -0
- package/dist/components/ui/checkbox/index.js +2 -0
- package/dist/components/ui/code-block/index.js +2 -0
- package/dist/components/ui/collapsible/index.js +2 -0
- package/dist/components/ui/combobox/index.js +2 -0
- package/dist/components/ui/command/index.js +2 -0
- package/dist/components/ui/context-menu/index.js +2 -0
- package/dist/components/ui/detail-panel/index.js +2 -0
- package/dist/components/ui/dialog/index.js +2 -0
- package/dist/components/ui/diff-block/index.js +2 -0
- package/dist/components/ui/drawer/index.js +2 -0
- package/dist/components/ui/dropdown-menu/index.js +2 -0
- package/dist/components/ui/empty/index.js +2 -0
- package/dist/components/ui/entity-icon/index.js +2 -0
- package/dist/components/ui/field/index.js +2 -0
- package/dist/components/ui/hover-card/index.js +2 -0
- package/dist/components/ui/input/index.js +2 -0
- package/dist/components/ui/input-group/index.js +2 -0
- package/dist/components/ui/input-otp/index.js +2 -0
- package/dist/components/ui/item/index.js +2 -0
- package/dist/components/ui/kbd/index.js +2 -0
- package/dist/components/ui/label/index.js +2 -0
- package/dist/components/ui/menubar/index.js +2 -0
- package/dist/components/ui/modal-dialog/index.js +2 -0
- package/dist/components/ui/navigation-menu/index.js +2 -0
- package/dist/components/ui/pagination/index.js +2 -0
- package/dist/components/ui/popover/index.js +2 -0
- package/dist/components/ui/progress/index.js +2 -0
- package/dist/components/ui/radio-group/index.js +2 -0
- package/dist/components/ui/resizable/index.js +2 -0
- package/dist/components/ui/scroll-area/index.js +2 -0
- package/dist/components/ui/select/index.js +2 -0
- package/dist/components/ui/separator/index.js +2 -0
- package/dist/components/ui/sheet/index.js +2 -0
- package/dist/components/ui/skeleton/index.js +2 -0
- package/dist/components/ui/slider/index.js +2 -0
- package/dist/components/ui/spinner/index.js +2 -0
- package/dist/components/ui/status-chip/index.js +2 -0
- package/dist/components/ui/switch/index.js +2 -0
- package/dist/components/ui/table/index.js +2 -0
- package/dist/components/ui/tabs/index.js +2 -0
- package/dist/components/ui/textarea/index.js +2 -0
- package/dist/components/ui/toast/index.js +2 -0
- package/dist/components/ui/toggle/index.js +2 -0
- package/dist/components/ui/toggle-group/index.js +2 -0
- package/dist/components/ui/tooltip/index.js +2 -0
- package/dist/index.d.ts +2 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -3
- package/dist/r/accordion.json +3 -1
- package/dist/r/account-menu.json +2 -1
- package/dist/r/alert-dialog.json +3 -1
- package/dist/r/alert.json +3 -1
- package/dist/r/app-shell.json +3 -1
- package/dist/r/aspect-ratio.json +3 -1
- package/dist/r/avatar.json +3 -1
- package/dist/r/badge.json +3 -1
- package/dist/r/board.json +3 -1
- package/dist/r/breadcrumb.json +3 -1
- package/dist/r/button-group.json +2 -1
- package/dist/r/button.json +3 -1
- package/dist/r/calendar.json +2 -1
- package/dist/r/card.json +3 -1
- package/dist/r/carousel.json +2 -1
- package/dist/r/chart.json +3 -1
- package/dist/r/checkbox.json +3 -1
- package/dist/r/code-block.json +2 -1
- package/dist/r/collapsible.json +3 -1
- package/dist/r/combobox.json +3 -1
- package/dist/r/command.json +3 -1
- package/dist/r/context-menu.json +3 -1
- package/dist/r/conversation.json +2 -1
- package/dist/r/detail-panel.json +2 -1
- package/dist/r/dialog.json +3 -1
- package/dist/r/diff-block.json +3 -1
- package/dist/r/drawer.json +3 -1
- package/dist/r/dropdown-menu.json +3 -1
- package/dist/r/empty.json +3 -1
- package/dist/r/entity-icon.json +3 -1
- package/dist/r/field.json +3 -1
- package/dist/r/hover-card.json +3 -1
- package/dist/r/input-group.json +3 -1
- package/dist/r/input-otp.json +3 -1
- package/dist/r/input.json +3 -1
- package/dist/r/item.json +3 -1
- package/dist/r/kbd.json +3 -1
- package/dist/r/label.json +3 -1
- package/dist/r/lib.json +50 -0
- package/dist/r/list-row.json +3 -1
- package/dist/r/menubar.json +3 -1
- package/dist/r/modal-dialog.json +2 -1
- package/dist/r/motion.json +22 -0
- package/dist/r/navigation-menu.json +3 -1
- package/dist/r/page.json +3 -1
- package/dist/r/pagination.json +3 -1
- package/dist/r/panel.json +3 -1
- package/dist/r/popover.json +3 -1
- package/dist/r/progress.json +3 -1
- package/dist/r/radio-group.json +3 -1
- package/dist/r/registry.json +320 -73
- package/dist/r/resizable.json +3 -1
- package/dist/r/scroll-area.json +3 -1
- package/dist/r/select.json +3 -1
- package/dist/r/separator.json +3 -1
- package/dist/r/settings.json +3 -1
- package/dist/r/sheet.json +2 -1
- package/dist/r/side-rail.json +3 -1
- package/dist/r/sidebar-nav.json +3 -1
- package/dist/r/skeleton.json +3 -1
- package/dist/r/slider.json +3 -1
- package/dist/r/spinner.json +3 -1
- package/dist/r/src/components/composites/account-menu/account-menu.tsx +150 -0
- package/dist/r/src/components/composites/account-menu/index.ts +1 -0
- package/dist/r/src/components/composites/list-row/index.ts +1 -0
- package/dist/r/src/components/composites/list-row/list-row.tsx +116 -0
- package/dist/r/src/components/composites/settings/index.ts +1 -0
- package/dist/r/src/components/composites/settings/settings.tsx +142 -0
- package/dist/r/src/components/composites/stat/index.ts +9 -0
- package/dist/r/src/components/composites/stat/stat.tsx +155 -0
- package/dist/r/src/components/composites/update-dialog/index.ts +7 -0
- package/dist/r/src/components/composites/update-dialog/update-dialog.tsx +529 -0
- package/dist/r/src/components/composites/workspace-mark/index.ts +1 -0
- package/dist/r/src/components/composites/workspace-mark/workspace-mark.tsx +72 -0
- package/dist/r/src/components/conversation/conversation-avatar.tsx +60 -0
- package/dist/r/src/components/conversation/conversation-surface.tsx +107 -0
- package/dist/r/src/components/conversation/index.ts +25 -0
- package/dist/r/src/components/conversation/message-composer.tsx +239 -0
- package/dist/r/src/components/conversation/message-row.tsx +387 -0
- package/dist/r/src/components/conversation/thread-panel.tsx +141 -0
- package/dist/r/src/components/layout/app-shell/app-shell.tsx +92 -0
- package/dist/r/src/components/layout/app-shell/index.ts +1 -0
- package/dist/r/src/components/layout/page/index.ts +9 -0
- package/dist/r/src/components/layout/page/page.tsx +122 -0
- package/dist/r/src/components/layout/panel/index.ts +12 -0
- package/dist/r/src/components/layout/panel/panel.tsx +166 -0
- package/dist/r/src/components/layout/side-rail/index.ts +12 -0
- package/dist/r/src/components/layout/side-rail/side-rail-context.ts +42 -0
- package/dist/r/src/components/layout/side-rail/side-rail.tsx +405 -0
- package/dist/r/src/components/layout/sidebar-nav/index.ts +14 -0
- package/dist/r/src/components/layout/sidebar-nav/sidebar-nav.tsx +244 -0
- package/dist/r/src/components/layout/status-bar/index.ts +1 -0
- package/dist/r/src/components/layout/status-bar/status-bar.tsx +73 -0
- package/dist/r/src/components/layout/top-bar/index.ts +10 -0
- package/dist/r/src/components/layout/top-bar/top-bar.tsx +166 -0
- package/dist/r/src/components/motion/index.ts +2 -0
- package/dist/r/src/components/motion/presence.tsx +32 -0
- package/dist/r/src/components/theme/appearance-panel.tsx +179 -0
- package/dist/r/src/components/theme/index.ts +22 -0
- package/dist/r/src/components/theme/theme-picker.tsx +174 -0
- package/dist/r/src/components/theme/theme-provider.tsx +309 -0
- package/dist/r/src/components/theme/theme-toggle.tsx +64 -0
- package/dist/r/src/components/ui/accordion/accordion.tsx +66 -0
- package/dist/r/src/components/ui/accordion/index.ts +1 -0
- package/dist/r/src/components/ui/alert/alert.tsx +95 -0
- package/dist/r/src/components/ui/alert/index.ts +1 -0
- package/dist/r/src/components/ui/alert-dialog/alert-dialog.tsx +176 -0
- package/dist/r/src/components/ui/alert-dialog/index.ts +13 -0
- package/dist/r/src/components/ui/aspect-ratio/aspect-ratio.tsx +38 -0
- package/dist/r/src/components/ui/aspect-ratio/index.ts +1 -0
- package/dist/r/src/components/ui/avatar/avatar.tsx +114 -0
- package/dist/r/src/components/ui/avatar/index.ts +9 -0
- package/dist/r/src/components/ui/badge/badge.tsx +59 -0
- package/dist/r/src/components/ui/badge/index.ts +1 -0
- package/dist/r/src/components/ui/board/board.tsx +254 -0
- package/dist/r/src/components/ui/board/index.ts +10 -0
- package/dist/r/src/components/ui/breadcrumb/breadcrumb.tsx +117 -0
- package/dist/r/src/components/ui/breadcrumb/index.ts +9 -0
- package/dist/r/src/components/ui/button/button.tsx +89 -0
- package/dist/r/src/components/ui/button/index.ts +1 -0
- package/dist/r/src/components/ui/button-group/button-group.tsx +92 -0
- package/dist/r/src/components/ui/button-group/index.ts +6 -0
- package/dist/r/src/components/ui/calendar/calendar.tsx +277 -0
- package/dist/r/src/components/ui/calendar/index.ts +1 -0
- package/dist/r/src/components/ui/card/card.tsx +82 -0
- package/dist/r/src/components/ui/card/index.ts +10 -0
- package/dist/r/src/components/ui/carousel/carousel.tsx +209 -0
- package/dist/r/src/components/ui/carousel/index.ts +1 -0
- package/dist/r/src/components/ui/chart/chart.tsx +413 -0
- package/dist/r/src/components/ui/chart/index.ts +17 -0
- package/dist/r/src/components/ui/checkbox/checkbox.tsx +99 -0
- package/dist/r/src/components/ui/checkbox/index.ts +1 -0
- package/dist/r/src/components/ui/code-block/code-block.tsx +238 -0
- package/dist/r/src/components/ui/code-block/index.ts +1 -0
- package/dist/r/src/components/ui/collapsible/collapsible.tsx +54 -0
- package/dist/r/src/components/ui/collapsible/index.ts +1 -0
- package/dist/r/src/components/ui/combobox/combobox.tsx +142 -0
- package/dist/r/src/components/ui/combobox/index.ts +10 -0
- package/dist/r/src/components/ui/command/command.tsx +214 -0
- package/dist/r/src/components/ui/command/index.ts +12 -0
- package/dist/r/src/components/ui/context-menu/context-menu.tsx +163 -0
- package/dist/r/src/components/ui/context-menu/index.ts +15 -0
- package/dist/r/src/components/ui/detail-panel/detail-panel.tsx +161 -0
- package/dist/r/src/components/ui/detail-panel/index.ts +9 -0
- package/dist/r/src/components/ui/dialog/dialog.tsx +138 -0
- package/dist/r/src/components/ui/dialog/index.ts +14 -0
- package/dist/r/src/components/ui/diff-block/diff-block.tsx +286 -0
- package/dist/r/src/components/ui/diff-block/index.ts +11 -0
- package/dist/r/src/components/ui/drawer/drawer.tsx +144 -0
- package/dist/r/src/components/ui/drawer/index.ts +13 -0
- package/dist/r/src/components/ui/dropdown-menu/dropdown-menu.tsx +203 -0
- package/dist/r/src/components/ui/dropdown-menu/index.ts +18 -0
- package/dist/r/src/components/ui/empty/empty.tsx +104 -0
- package/dist/r/src/components/ui/empty/index.ts +10 -0
- package/dist/r/src/components/ui/entity-icon/entity-icon.tsx +154 -0
- package/dist/r/src/components/ui/entity-icon/index.ts +1 -0
- package/dist/r/src/components/ui/field/field.tsx +131 -0
- package/dist/r/src/components/ui/field/index.ts +11 -0
- package/dist/r/src/components/ui/hover-card/hover-card.tsx +48 -0
- package/dist/r/src/components/ui/hover-card/index.ts +1 -0
- package/dist/r/src/components/ui/input/index.ts +1 -0
- package/dist/r/src/components/ui/input/input.tsx +41 -0
- package/dist/r/src/components/ui/input-group/index.ts +8 -0
- package/dist/r/src/components/ui/input-group/input-group.tsx +111 -0
- package/dist/r/src/components/ui/input-otp/index.ts +1 -0
- package/dist/r/src/components/ui/input-otp/input-otp.tsx +108 -0
- package/dist/r/src/components/ui/item/index.ts +10 -0
- package/dist/r/src/components/ui/item/item.tsx +146 -0
- package/dist/r/src/components/ui/kbd/index.ts +1 -0
- package/dist/r/src/components/ui/kbd/kbd.tsx +42 -0
- package/dist/r/src/components/ui/label/index.ts +1 -0
- package/dist/r/src/components/ui/label/label.tsx +36 -0
- package/dist/r/src/components/ui/menubar/index.ts +16 -0
- package/dist/r/src/components/ui/menubar/menubar.tsx +190 -0
- package/dist/r/src/components/ui/modal-dialog/index.ts +1 -0
- package/dist/r/src/components/ui/modal-dialog/modal-dialog.tsx +95 -0
- package/dist/r/src/components/ui/navigation-menu/index.ts +13 -0
- package/dist/r/src/components/ui/navigation-menu/navigation-menu.tsx +229 -0
- package/dist/r/src/components/ui/pagination/index.ts +8 -0
- package/dist/r/src/components/ui/pagination/pagination.tsx +144 -0
- package/dist/r/src/components/ui/popover/index.ts +10 -0
- package/dist/r/src/components/ui/popover/popover.tsx +81 -0
- package/dist/r/src/components/ui/progress/index.ts +1 -0
- package/dist/r/src/components/ui/progress/progress.tsx +67 -0
- package/dist/r/src/components/ui/radio-group/index.ts +1 -0
- package/dist/r/src/components/ui/radio-group/radio-group.tsx +78 -0
- package/dist/r/src/components/ui/resizable/index.ts +6 -0
- package/dist/r/src/components/ui/resizable/resizable.tsx +74 -0
- package/dist/r/src/components/ui/scroll-area/index.ts +1 -0
- package/dist/r/src/components/ui/scroll-area/scroll-area.tsx +66 -0
- package/dist/r/src/components/ui/select/index.ts +11 -0
- package/dist/r/src/components/ui/select/select.tsx +188 -0
- package/dist/r/src/components/ui/separator/index.ts +1 -0
- package/dist/r/src/components/ui/separator/separator.tsx +40 -0
- package/dist/r/src/components/ui/sheet/index.ts +13 -0
- package/dist/r/src/components/ui/sheet/sheet.tsx +132 -0
- package/dist/r/src/components/ui/skeleton/index.ts +1 -0
- package/dist/r/src/components/ui/skeleton/skeleton.tsx +28 -0
- package/dist/r/src/components/ui/slider/index.ts +1 -0
- package/dist/r/src/components/ui/slider/slider.tsx +81 -0
- package/dist/r/src/components/ui/spinner/index.ts +1 -0
- package/dist/r/src/components/ui/spinner/spinner.tsx +58 -0
- package/dist/r/src/components/ui/status-chip/index.ts +8 -0
- package/dist/r/src/components/ui/status-chip/status-chip.tsx +142 -0
- package/dist/r/src/components/ui/switch/index.ts +1 -0
- package/dist/r/src/components/ui/switch/switch.tsx +100 -0
- package/dist/r/src/components/ui/table/index.ts +11 -0
- package/dist/r/src/components/ui/table/table.tsx +125 -0
- package/dist/r/src/components/ui/tabs/index.ts +8 -0
- package/dist/r/src/components/ui/tabs/tabs.tsx +77 -0
- package/dist/r/src/components/ui/textarea/index.ts +1 -0
- package/dist/r/src/components/ui/textarea/textarea.tsx +36 -0
- package/dist/r/src/components/ui/toast/index.ts +1 -0
- package/dist/r/src/components/ui/toast/toast.tsx +220 -0
- package/dist/r/src/components/ui/toggle/index.ts +1 -0
- package/dist/r/src/components/ui/toggle/toggle.tsx +60 -0
- package/dist/r/src/components/ui/toggle-group/index.ts +6 -0
- package/dist/r/src/components/ui/toggle-group/toggle-group.tsx +66 -0
- package/dist/r/src/components/ui/tooltip/index.ts +9 -0
- package/dist/r/src/components/ui/tooltip/tooltip.tsx +102 -0
- package/dist/r/src/lib/keyed-rows.ts +68 -0
- package/dist/r/src/lib/overlay.ts +70 -0
- package/dist/r/src/lib/themes.ts +490 -0
- package/dist/r/src/lib/tokens.ts +688 -0
- package/dist/r/src/lib/utils.ts +76 -0
- package/dist/r/src/lib/variants.ts +62 -0
- package/dist/r/src/lib/version-notes.ts +65 -0
- package/dist/r/src/styles/base.css +644 -0
- package/dist/r/src/styles/fonts.css +26 -0
- package/dist/r/src/styles/globals.css +18 -0
- package/dist/r/src/styles/theme.css +864 -0
- package/dist/r/stat.json +3 -1
- package/dist/r/status-bar.json +3 -1
- package/dist/r/status-chip.json +2 -1
- package/dist/r/switch.json +3 -1
- package/dist/r/table.json +3 -1
- package/dist/r/tabs.json +3 -1
- package/dist/r/textarea.json +3 -1
- package/dist/r/theming.json +42 -0
- package/dist/r/toast.json +3 -1
- package/dist/r/toggle-group.json +2 -1
- package/dist/r/toggle.json +3 -1
- package/dist/r/tooltip.json +3 -1
- package/dist/r/top-bar.json +3 -1
- package/dist/r/update-dialog.json +2 -1
- package/dist/r/workspace-mark.json +2 -1
- package/package.json +10 -9
- package/registry.json +320 -73
- package/src/index.ts +2 -4
- package/dist/components/ui/diff-block/diff-block.test.d.ts +0 -2
- package/dist/components/ui/diff-block/diff-block.test.d.ts.map +0 -1
- package/dist/lib/keyed-rows.test.d.ts +0 -2
- package/dist/lib/keyed-rows.test.d.ts.map +0 -1
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import type { ComponentProps } from 'solid-js'
|
|
2
|
+
import { splitProps } from 'solid-js'
|
|
3
|
+
import { cn } from '../../../lib/utils'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Table.
|
|
7
|
+
*
|
|
8
|
+
* Semantic markup, not a grid of divs. A `<table>` with a caption, a header
|
|
9
|
+
* scope and cells is navigable by a screen reader in ways a flex layout cannot
|
|
10
|
+
* be reproduced into, and it is what makes "row 3 of 12, Name column" work.
|
|
11
|
+
*
|
|
12
|
+
* Two decisions worth keeping:
|
|
13
|
+
*
|
|
14
|
+
* - The header is sticky by default. A scrollable table whose header leaves
|
|
15
|
+
* the viewport makes every row below it anonymous.
|
|
16
|
+
* - Numbers are right-aligned and tabular. `text-end` plus `tabular-nums` is
|
|
17
|
+
* what lets a column of figures be compared by eye; a proportional font
|
|
18
|
+
* with ragged digits is unreadable at a glance.
|
|
19
|
+
*
|
|
20
|
+
* `TableNumericCell` exists so callers do not have to remember the second
|
|
21
|
+
* half of that rule.
|
|
22
|
+
*/
|
|
23
|
+
export function Table(props: ComponentProps<'table'>) {
|
|
24
|
+
const [local, rest] = splitProps(props, ['class'])
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
<div data-slot="table-container" class="relative w-full overflow-x-auto">
|
|
28
|
+
<table data-slot="table" class={cn('w-full caption-bottom text-sm', local.class)} {...rest} />
|
|
29
|
+
</div>
|
|
30
|
+
)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function TableHeader(props: ComponentProps<'thead'>) {
|
|
34
|
+
const [local, rest] = splitProps(props, ['class'])
|
|
35
|
+
return (
|
|
36
|
+
<thead
|
|
37
|
+
data-slot="table-header"
|
|
38
|
+
class={cn(
|
|
39
|
+
'[&_tr]:border-b [&_tr]:border-border sticky top-0 z-(--z-docked) bg-background',
|
|
40
|
+
local.class
|
|
41
|
+
)}
|
|
42
|
+
{...rest}
|
|
43
|
+
/>
|
|
44
|
+
)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function TableBody(props: ComponentProps<'tbody'>) {
|
|
48
|
+
const [local, rest] = splitProps(props, ['class'])
|
|
49
|
+
return (
|
|
50
|
+
<tbody data-slot="table-body" class={cn('[&_tr:last-child]:border-0', local.class)} {...rest} />
|
|
51
|
+
)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function TableFooter(props: ComponentProps<'tfoot'>) {
|
|
55
|
+
const [local, rest] = splitProps(props, ['class'])
|
|
56
|
+
return (
|
|
57
|
+
<tfoot
|
|
58
|
+
data-slot="table-footer"
|
|
59
|
+
class={cn(
|
|
60
|
+
'bg-surface-hover border-t border-border font-medium [&>tr]:last:border-b-0',
|
|
61
|
+
local.class
|
|
62
|
+
)}
|
|
63
|
+
{...rest}
|
|
64
|
+
/>
|
|
65
|
+
)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function TableRow(props: ComponentProps<'tr'>) {
|
|
69
|
+
const [local, rest] = splitProps(props, ['class'])
|
|
70
|
+
|
|
71
|
+
return (
|
|
72
|
+
<tr
|
|
73
|
+
data-slot="table-row"
|
|
74
|
+
class={cn(
|
|
75
|
+
'border-b border-border transition-colors ease-out',
|
|
76
|
+
'hover:bg-surface-hover data-[state=selected]:bg-primary-subtle',
|
|
77
|
+
local.class
|
|
78
|
+
)}
|
|
79
|
+
{...rest}
|
|
80
|
+
/>
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function TableHead(props: ComponentProps<'th'>) {
|
|
85
|
+
const [local, rest] = splitProps(props, ['class'])
|
|
86
|
+
|
|
87
|
+
return (
|
|
88
|
+
<th
|
|
89
|
+
data-slot="table-head"
|
|
90
|
+
scope={props.scope ?? 'col'}
|
|
91
|
+
class={cn(
|
|
92
|
+
'text-muted-foreground h-9 px-3 text-start align-middle text-xs font-medium whitespace-nowrap',
|
|
93
|
+
local.class
|
|
94
|
+
)}
|
|
95
|
+
{...rest}
|
|
96
|
+
/>
|
|
97
|
+
)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function TableCell(props: ComponentProps<'td'>) {
|
|
101
|
+
const [local, rest] = splitProps(props, ['class'])
|
|
102
|
+
return <td data-slot="table-cell" class={cn('px-3 py-2 align-middle', local.class)} {...rest} />
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export function TableNumericCell(props: ComponentProps<'td'>) {
|
|
106
|
+
const [local, rest] = splitProps(props, ['class'])
|
|
107
|
+
return (
|
|
108
|
+
<td
|
|
109
|
+
data-slot="table-cell"
|
|
110
|
+
class={cn('px-3 py-2 text-end align-middle tabular-nums', local.class)}
|
|
111
|
+
{...rest}
|
|
112
|
+
/>
|
|
113
|
+
)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export function TableCaption(props: ComponentProps<'caption'>) {
|
|
117
|
+
const [local, rest] = splitProps(props, ['class'])
|
|
118
|
+
return (
|
|
119
|
+
<caption
|
|
120
|
+
data-slot="table-caption"
|
|
121
|
+
class={cn('text-muted-foreground mt-3 text-sm', local.class)}
|
|
122
|
+
{...rest}
|
|
123
|
+
/>
|
|
124
|
+
)
|
|
125
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { Tabs as KobalteTabs } from '@kobalte/core/tabs'
|
|
2
|
+
import type { ComponentProps } from 'solid-js'
|
|
3
|
+
import { splitProps } from 'solid-js'
|
|
4
|
+
import { cn } from '../../../lib/utils'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Tabs.
|
|
8
|
+
*
|
|
9
|
+
* For switching between sibling views of the *same* subject — a file's code,
|
|
10
|
+
* diff and history. Not for moving between pages: a tab is expected to keep
|
|
11
|
+
* its panel and its scroll position, which a route does not.
|
|
12
|
+
*
|
|
13
|
+
* `appearance="segmented"` gives the joined bar KiroCrew uses inside a pane
|
|
14
|
+
* where a full-width underline would collide with the panel's own header rule.
|
|
15
|
+
*/
|
|
16
|
+
export function Tabs(props: ComponentProps<typeof KobalteTabs>) {
|
|
17
|
+
const [local, rest] = splitProps(props, ['class'])
|
|
18
|
+
return (
|
|
19
|
+
<KobalteTabs
|
|
20
|
+
class={cn('flex flex-col gap-2 data-[orientation=vertical]:flex-row', local.class)}
|
|
21
|
+
{...rest}
|
|
22
|
+
/>
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export type TabsListProps = ComponentProps<typeof KobalteTabs.List> & {
|
|
27
|
+
appearance?: 'underline' | 'segmented'
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function TabsList(props: TabsListProps) {
|
|
31
|
+
const [local, rest] = splitProps(props, ['class', 'appearance'])
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<KobalteTabs.List
|
|
35
|
+
class={cn(
|
|
36
|
+
'inline-flex w-fit shrink-0 items-center justify-center',
|
|
37
|
+
local.appearance === 'segmented'
|
|
38
|
+
? 'gap-0.5 rounded-lg bg-surface-hover p-0.5'
|
|
39
|
+
: 'gap-1 rounded-none border-b border-border',
|
|
40
|
+
'data-[orientation=vertical]:flex-col data-[orientation=vertical]:items-stretch',
|
|
41
|
+
local.class
|
|
42
|
+
)}
|
|
43
|
+
{...rest}
|
|
44
|
+
/>
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export type TabsTriggerProps = ComponentProps<typeof KobalteTabs.Trigger> & {
|
|
49
|
+
appearance?: 'underline' | 'segmented'
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function TabsTrigger(props: TabsTriggerProps) {
|
|
53
|
+
const [local, rest] = splitProps(props, ['class', 'appearance'])
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
<KobalteTabs.Trigger
|
|
57
|
+
class={cn(
|
|
58
|
+
'inline-flex shrink-0 items-center justify-center gap-1.5 whitespace-nowrap text-sm font-medium',
|
|
59
|
+
'transition-colors ease-out outline-none select-none',
|
|
60
|
+
'focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle',
|
|
61
|
+
'disabled:pointer-events-none disabled:opacity-50',
|
|
62
|
+
'text-muted-foreground hover:text-foreground data-[selected]:text-foreground',
|
|
63
|
+
'[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg]:size-4',
|
|
64
|
+
local.appearance === 'segmented'
|
|
65
|
+
? 'h-control-sm rounded-md px-control-sm data-[selected]:bg-card data-[selected]:shadow-xs'
|
|
66
|
+
: 'h-control-md -mb-px rounded-none border-b-2 border-transparent px-2 pb-2 data-[selected]:border-primary',
|
|
67
|
+
local.class
|
|
68
|
+
)}
|
|
69
|
+
{...rest}
|
|
70
|
+
/>
|
|
71
|
+
)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function TabsContent(props: ComponentProps<typeof KobalteTabs.Content>) {
|
|
75
|
+
const [local, rest] = splitProps(props, ['class'])
|
|
76
|
+
return <KobalteTabs.Content class={cn('flex-1 outline-none', local.class)} {...rest} />
|
|
77
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Textarea } from './textarea'
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { ComponentProps } from 'solid-js'
|
|
2
|
+
import { splitProps } from 'solid-js'
|
|
3
|
+
import { cn } from '../../../lib/utils'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Textarea.
|
|
7
|
+
*
|
|
8
|
+
* Shares the Input's border, focus and invalid treatment exactly — the two are
|
|
9
|
+
* the same control at different aspect ratios, and a form that mixes them must
|
|
10
|
+
* not show a seam between them.
|
|
11
|
+
*
|
|
12
|
+
* `field-sizing: content` lets the element grow with its content where the
|
|
13
|
+
* engine supports it, which is the behaviour a chat composer wants; `rows`
|
|
14
|
+
* remains the fallback so an unsupported engine still gets a usable height.
|
|
15
|
+
*/
|
|
16
|
+
export function Textarea(props: ComponentProps<'textarea'>) {
|
|
17
|
+
const [local, rest] = splitProps(props, ['class'])
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<textarea
|
|
21
|
+
data-slot="textarea"
|
|
22
|
+
class={cn(
|
|
23
|
+
'flex field-sizing-content min-h-16 w-full rounded-md border border-input bg-transparent px-control-md py-2 text-sm',
|
|
24
|
+
'transition-[color,box-shadow,border-color] ease-out outline-none',
|
|
25
|
+
'placeholder:text-muted-foreground',
|
|
26
|
+
'selection:bg-primary selection:text-primary-foreground',
|
|
27
|
+
'focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle',
|
|
28
|
+
'aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive-subtle',
|
|
29
|
+
'disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50',
|
|
30
|
+
'resize-y',
|
|
31
|
+
local.class
|
|
32
|
+
)}
|
|
33
|
+
{...rest}
|
|
34
|
+
/>
|
|
35
|
+
)
|
|
36
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Toaster, toast, toaster, type ToastOptions, type ToasterProps } from './toast'
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import { Toast as KobalteToast, type ToastComponentProps, toaster } from '@kobalte/core/toast'
|
|
2
|
+
import { X } from 'lucide-solid'
|
|
3
|
+
import type { ComponentProps, JSX } from 'solid-js'
|
|
4
|
+
import { Show, splitProps } from 'solid-js'
|
|
5
|
+
import { cn } from '../../../lib/utils'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Toast.
|
|
9
|
+
*
|
|
10
|
+
* A short, self-dismissing message about something that already happened.
|
|
11
|
+
*
|
|
12
|
+
* The rules that make toasts helpful rather than hostile are built into this
|
|
13
|
+
* API rather than left to callers:
|
|
14
|
+
*
|
|
15
|
+
* - A toast never carries the only route to an action. Anything important
|
|
16
|
+
* enough to need doing belongs in the interface, not in a message that
|
|
17
|
+
* disappears. `action` exists, but it is a convenience, not a flow.
|
|
18
|
+
* - Errors from user-initiated work get `priority="high"` so a screen reader
|
|
19
|
+
* interrupts to announce them; background progress uses the default low
|
|
20
|
+
* priority so it is not read over whatever the user is doing.
|
|
21
|
+
* - A toast with a way to undo is preferred to a confirmation dialog for a
|
|
22
|
+
* reversible action. Undo after the fact costs the user nothing; a modal
|
|
23
|
+
* before it costs everyone a click.
|
|
24
|
+
*
|
|
25
|
+
* `Toaster` is mounted once, near the root of the app.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
type ToastTone = 'default' | 'success' | 'warning' | 'destructive' | 'info'
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* The tone dot's colour. A custom property rather than five colour utilities
|
|
32
|
+
* because the value is applied inline (the tone is data, not markup) and a
|
|
33
|
+
* Tailwind colour class cannot be built from a runtime value without becoming
|
|
34
|
+
* invisible to the linter.
|
|
35
|
+
*/
|
|
36
|
+
const toastTones: Record<ToastTone, string> = {
|
|
37
|
+
default: 'var(--foreground)',
|
|
38
|
+
success: 'var(--success)',
|
|
39
|
+
warning: 'var(--warning)',
|
|
40
|
+
destructive: 'var(--destructive)',
|
|
41
|
+
info: 'var(--info)',
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export type ToastOptions = {
|
|
45
|
+
title: string
|
|
46
|
+
description?: string
|
|
47
|
+
tone?: ToastTone
|
|
48
|
+
/** A control rendered inside the toast, usually an Undo. */
|
|
49
|
+
action?: JSX.Element
|
|
50
|
+
/** Keep the toast until it is dismissed. Use for a failure the user must see. */
|
|
51
|
+
persistent?: boolean
|
|
52
|
+
/** Milliseconds before auto-dismiss. Overrides the region's setting. */
|
|
53
|
+
duration?: number
|
|
54
|
+
/** Which Toaster region to render into. */
|
|
55
|
+
region?: string
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function ToastCard(props: ToastComponentProps & ToastOptions) {
|
|
59
|
+
const tone = () => props.tone ?? 'default'
|
|
60
|
+
|
|
61
|
+
return (
|
|
62
|
+
<KobalteToast
|
|
63
|
+
toastId={props.toastId}
|
|
64
|
+
/**
|
|
65
|
+
* A user-initiated outcome is announced; a background one waits its turn.
|
|
66
|
+
* A failure the user caused is worth interrupting for; a sync finishing
|
|
67
|
+
* quietly is not.
|
|
68
|
+
*/
|
|
69
|
+
priority={tone() === 'destructive' ? 'high' : 'low'}
|
|
70
|
+
duration={props.duration}
|
|
71
|
+
persistent={props.persistent}
|
|
72
|
+
class={cn(
|
|
73
|
+
'pointer-events-auto flex w-full items-start gap-3 rounded-xl border border-border bg-popover p-3 shadow-lg',
|
|
74
|
+
'data-[opened]:animate-in data-[opened]:slide-in-from-right-full data-[opened]:fade-in-0',
|
|
75
|
+
'data-[closed]:animate-out data-[closed]:slide-out-to-right-full data-[closed]:fade-out-0',
|
|
76
|
+
'data-[swipe=move]:translate-x-(--kb-toast-swipe-move-x) data-[swipe=move]:transition-none',
|
|
77
|
+
'data-[swipe=cancel]:translate-x-0 data-[swipe=cancel]:transition-transform',
|
|
78
|
+
'data-[swipe=end]:animate-out data-[swipe=end]:slide-out-to-right-full'
|
|
79
|
+
)}
|
|
80
|
+
style={{ '--toast-tone': toastTones[tone()] }}
|
|
81
|
+
>
|
|
82
|
+
<span
|
|
83
|
+
aria-hidden="true"
|
|
84
|
+
class="mt-1.5 size-1.5 shrink-0 rounded-full"
|
|
85
|
+
style={{ 'background-color': 'var(--toast-tone)' }}
|
|
86
|
+
/>
|
|
87
|
+
<div class="flex min-w-0 flex-1 flex-col gap-0.5">
|
|
88
|
+
<KobalteToast.Title class="text-sm font-medium">{props.title}</KobalteToast.Title>
|
|
89
|
+
<Show when={props.description}>
|
|
90
|
+
<KobalteToast.Description class="text-sm text-muted-foreground">
|
|
91
|
+
{props.description}
|
|
92
|
+
</KobalteToast.Description>
|
|
93
|
+
</Show>
|
|
94
|
+
<Show when={props.action}>
|
|
95
|
+
<div class="mt-1.5 flex items-center gap-2">{props.action}</div>
|
|
96
|
+
</Show>
|
|
97
|
+
</div>
|
|
98
|
+
<KobalteToast.CloseButton
|
|
99
|
+
aria-label="Dismiss notification"
|
|
100
|
+
class="text-muted-foreground shrink-0 rounded-sm p-0.5 transition-colors ease-out outline-none hover:text-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle"
|
|
101
|
+
>
|
|
102
|
+
<X class="size-3.5" />
|
|
103
|
+
</KobalteToast.CloseButton>
|
|
104
|
+
</KobalteToast>
|
|
105
|
+
)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* The toast API. `show` is the general form; the tone helpers are shorthand for
|
|
110
|
+
* the four cases that come up constantly.
|
|
111
|
+
*/
|
|
112
|
+
export const toast = {
|
|
113
|
+
show(options: ToastOptions): number {
|
|
114
|
+
return toaster.show((props) => <ToastCard {...props} {...options} />, {
|
|
115
|
+
region: options.region,
|
|
116
|
+
})
|
|
117
|
+
},
|
|
118
|
+
success(title: string, options?: Omit<ToastOptions, 'title' | 'tone'>): number {
|
|
119
|
+
return toast.show({ ...options, title, tone: 'success' })
|
|
120
|
+
},
|
|
121
|
+
error(title: string, options?: Omit<ToastOptions, 'title' | 'tone'>): number {
|
|
122
|
+
return toast.show({ ...options, title, tone: 'destructive', persistent: true })
|
|
123
|
+
},
|
|
124
|
+
warning(title: string, options?: Omit<ToastOptions, 'title' | 'tone'>): number {
|
|
125
|
+
return toast.show({ ...options, title, tone: 'warning' })
|
|
126
|
+
},
|
|
127
|
+
info(title: string, options?: Omit<ToastOptions, 'title' | 'tone'>): number {
|
|
128
|
+
return toast.show({ ...options, title, tone: 'info' })
|
|
129
|
+
},
|
|
130
|
+
/**
|
|
131
|
+
* A toast that resolves with a promise: pending, then success or failure.
|
|
132
|
+
* The right shape for an operation with a visible duration, because the user
|
|
133
|
+
* gets one message instead of three.
|
|
134
|
+
*/
|
|
135
|
+
promise<T>(
|
|
136
|
+
promise: Promise<T> | (() => Promise<T>),
|
|
137
|
+
messages: {
|
|
138
|
+
pending: string
|
|
139
|
+
success: string | ((data: T) => string)
|
|
140
|
+
error: string | ((error: unknown) => string)
|
|
141
|
+
}
|
|
142
|
+
): Promise<T> {
|
|
143
|
+
const resolved = typeof promise === 'function' ? promise() : promise
|
|
144
|
+
toaster.promise(resolved, (props) => {
|
|
145
|
+
const tone: ToastTone =
|
|
146
|
+
props.state === 'fulfilled'
|
|
147
|
+
? 'success'
|
|
148
|
+
: props.state === 'rejected'
|
|
149
|
+
? 'destructive'
|
|
150
|
+
: 'default'
|
|
151
|
+
const title =
|
|
152
|
+
props.state === 'pending'
|
|
153
|
+
? messages.pending
|
|
154
|
+
: props.state === 'fulfilled'
|
|
155
|
+
? typeof messages.success === 'function'
|
|
156
|
+
? messages.success(props.data as T)
|
|
157
|
+
: messages.success
|
|
158
|
+
: typeof messages.error === 'function'
|
|
159
|
+
? messages.error(props.error)
|
|
160
|
+
: messages.error
|
|
161
|
+
return (
|
|
162
|
+
<ToastCard
|
|
163
|
+
toastId={props.toastId}
|
|
164
|
+
title={title}
|
|
165
|
+
tone={tone}
|
|
166
|
+
persistent={props.state === 'rejected'}
|
|
167
|
+
/>
|
|
168
|
+
)
|
|
169
|
+
})
|
|
170
|
+
return resolved
|
|
171
|
+
},
|
|
172
|
+
dismiss: toaster.dismiss,
|
|
173
|
+
clear: toaster.clear,
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export type ToasterProps = ComponentProps<typeof KobalteToast.Region> & {
|
|
177
|
+
/** Where the stack sits. Defaults to the bottom-right, clear of the shell. */
|
|
178
|
+
position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'
|
|
179
|
+
region?: string
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const toasterPosition = {
|
|
183
|
+
'top-left': 'top-0 left-0 items-start',
|
|
184
|
+
'top-right': 'top-0 right-0 items-end',
|
|
185
|
+
'bottom-left': 'bottom-0 left-0 items-start',
|
|
186
|
+
'bottom-right': 'bottom-0 right-0 items-end',
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/** Mount once, near the root. Renders the stack and owns its timing defaults. */
|
|
190
|
+
export function Toaster(props: ToasterProps) {
|
|
191
|
+
const [local, rest] = splitProps(props, ['position', 'region', 'class'])
|
|
192
|
+
|
|
193
|
+
return (
|
|
194
|
+
<KobalteToast.Region
|
|
195
|
+
regionId={local.region}
|
|
196
|
+
duration={5000}
|
|
197
|
+
limit={3}
|
|
198
|
+
swipeDirection="right"
|
|
199
|
+
pauseOnInteraction
|
|
200
|
+
pauseOnPageIdle
|
|
201
|
+
/**
|
|
202
|
+
* The toast region is a top layer: opening a dialog must not hide an
|
|
203
|
+
* in-flight notification, and clicking a toast must not dismiss the
|
|
204
|
+
* dialog behind it.
|
|
205
|
+
*/
|
|
206
|
+
class="pointer-events-none fixed z-(--z-toast) flex max-h-screen w-full flex-col gap-2 p-4 sm:max-w-sm"
|
|
207
|
+
{...rest}
|
|
208
|
+
>
|
|
209
|
+
<KobalteToast.List
|
|
210
|
+
class={cn(
|
|
211
|
+
'flex flex-col gap-2',
|
|
212
|
+
toasterPosition[local.position ?? 'bottom-right'],
|
|
213
|
+
local.class
|
|
214
|
+
)}
|
|
215
|
+
/>
|
|
216
|
+
</KobalteToast.Region>
|
|
217
|
+
)
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
export { toaster }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Toggle, toggleVariants, type ToggleProps } from './toggle'
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { ToggleButton } from '@kobalte/core/toggle-button'
|
|
2
|
+
import type { ComponentProps } from 'solid-js'
|
|
3
|
+
import { splitProps } from 'solid-js'
|
|
4
|
+
import { cva, controlInteractive, controlSize, type VariantProps } from '../../../lib/variants'
|
|
5
|
+
import { cn } from '../../../lib/utils'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Toggle.
|
|
9
|
+
*
|
|
10
|
+
* A button that stays pressed. The difference from Button is state, not looks:
|
|
11
|
+
* a Toggle reports `aria-pressed` and holds its pressed appearance until
|
|
12
|
+
* released, which is what makes it right for a formatting control and wrong
|
|
13
|
+
* for a command.
|
|
14
|
+
*
|
|
15
|
+
* Kobalte supplies the pressed state and the keyboard behaviour; the styling
|
|
16
|
+
* adds the one thing a headless primitive cannot know — that a pressed toggle
|
|
17
|
+
* in a toolbar should read as *filled*, not merely outlined.
|
|
18
|
+
*/
|
|
19
|
+
export const toggleVariants = cva(
|
|
20
|
+
`${controlInteractive} inline-flex items-center justify-center rounded-md font-medium whitespace-nowrap select-none hover:bg-surface-hover hover:text-foreground data-[pressed]:bg-surface-active data-[pressed]:text-foreground disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0`,
|
|
21
|
+
{
|
|
22
|
+
variants: {
|
|
23
|
+
variant: {
|
|
24
|
+
default: 'bg-transparent',
|
|
25
|
+
/** Sits inside a field or toolbar that already has a fill. */
|
|
26
|
+
outline: 'border border-border bg-transparent',
|
|
27
|
+
/** Filled even when unpressed, for a segmented control's idle item. */
|
|
28
|
+
subtle: 'bg-surface-hover',
|
|
29
|
+
},
|
|
30
|
+
size: {
|
|
31
|
+
'2xs': `${controlSize['2xs']} [&_svg]:size-3`,
|
|
32
|
+
xs: `${controlSize.xs} [&_svg]:size-3.5`,
|
|
33
|
+
sm: `${controlSize.sm} [&_svg]:size-3.5`,
|
|
34
|
+
md: `${controlSize.md} [&_svg]:size-4`,
|
|
35
|
+
lg: `${controlSize.lg} [&_svg]:size-4`,
|
|
36
|
+
xl: `${controlSize.xl} [&_svg]:size-5`,
|
|
37
|
+
'icon-2xs': 'size-control-2xs p-0 [&_svg]:size-3',
|
|
38
|
+
'icon-xs': 'size-control-xs p-0 [&_svg]:size-3.5',
|
|
39
|
+
'icon-sm': 'size-control-sm p-0 [&_svg]:size-3.5',
|
|
40
|
+
'icon-md': 'size-control-md p-0 [&_svg]:size-4',
|
|
41
|
+
'icon-lg': 'size-control-lg p-0 [&_svg]:size-4',
|
|
42
|
+
'icon-xl': 'size-control-xl p-0 [&_svg]:size-5',
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
defaultVariants: { variant: 'default', size: 'md' },
|
|
46
|
+
}
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
export type ToggleProps = ComponentProps<typeof ToggleButton> & VariantProps<typeof toggleVariants>
|
|
50
|
+
|
|
51
|
+
export function Toggle(props: ToggleProps) {
|
|
52
|
+
const [local, rest] = splitProps(props, ['variant', 'size', 'class'])
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<ToggleButton
|
|
56
|
+
class={cn(toggleVariants({ variant: local.variant, size: local.size }), local.class)}
|
|
57
|
+
{...rest}
|
|
58
|
+
/>
|
|
59
|
+
)
|
|
60
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { ToggleGroup as KobalteToggleGroup } from '@kobalte/core/toggle-group'
|
|
2
|
+
import type { ComponentProps } from 'solid-js'
|
|
3
|
+
import { splitProps } from 'solid-js'
|
|
4
|
+
import type { VariantProps } from '../../../lib/variants'
|
|
5
|
+
import { cn } from '../../../lib/utils'
|
|
6
|
+
import { toggleVariants } from '../toggle/toggle'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* ToggleGroup.
|
|
10
|
+
*
|
|
11
|
+
* A set of related toggles that behave as one control: at most one pressed
|
|
12
|
+
* (`multiple={false}`, the default) or any number (`multiple={true}`). The
|
|
13
|
+
* group owns the selection and the roving focus, which is what makes arrow keys
|
|
14
|
+
* move between items and a screen reader announce the position within the set.
|
|
15
|
+
* A row of independent Toggles looks identical and does neither.
|
|
16
|
+
*
|
|
17
|
+
* `attached` joins the items into one rounded run for a segmented control. The
|
|
18
|
+
* joining lives on the *group*, via child selectors, so an item never has to
|
|
19
|
+
* know whether it sits at an end — which is also where the border collapse
|
|
20
|
+
* (`-ms-px`) belongs.
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* `multiple` is optional here although Kobalte requires it: the primitive models
|
|
24
|
+
* single and multiple selection as two shapes, which forces every caller to state
|
|
25
|
+
* the obvious. Defaulting to single selection keeps the common case a one-word
|
|
26
|
+
* component, and a caller that wants many passes `multiple`.
|
|
27
|
+
*/
|
|
28
|
+
export type ToggleGroupProps = Omit<ComponentProps<typeof KobalteToggleGroup>, 'multiple'> & {
|
|
29
|
+
multiple?: boolean
|
|
30
|
+
variant?: VariantProps<typeof toggleVariants>['variant']
|
|
31
|
+
size?: VariantProps<typeof toggleVariants>['size']
|
|
32
|
+
/** Join the items into one rounded run instead of a spaced row. */
|
|
33
|
+
attached?: boolean
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function ToggleGroup(props: ToggleGroupProps) {
|
|
37
|
+
const [local, rest] = splitProps(props, ['class', 'attached', 'multiple'])
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<KobalteToggleGroup
|
|
41
|
+
multiple={local.multiple ?? false}
|
|
42
|
+
class={cn(
|
|
43
|
+
'flex w-fit flex-row items-center',
|
|
44
|
+
local.attached
|
|
45
|
+
? '[&>*:first-child]:rounded-e-none [&>*:last-child]:rounded-s-none [&>*:not(:first-child):not(:last-child)]:rounded-none [&>*:not(:first-child)]:-ms-px'
|
|
46
|
+
: 'gap-1',
|
|
47
|
+
local.class
|
|
48
|
+
)}
|
|
49
|
+
{...rest}
|
|
50
|
+
/>
|
|
51
|
+
)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export type ToggleGroupItemProps = ComponentProps<typeof KobalteToggleGroup.Item> &
|
|
55
|
+
VariantProps<typeof toggleVariants>
|
|
56
|
+
|
|
57
|
+
export function ToggleGroupItem(props: ToggleGroupItemProps) {
|
|
58
|
+
const [local, rest] = splitProps(props, ['class', 'variant', 'size'])
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<KobalteToggleGroup.Item
|
|
62
|
+
class={cn(toggleVariants({ variant: local.variant, size: local.size }), local.class)}
|
|
63
|
+
{...rest}
|
|
64
|
+
/>
|
|
65
|
+
)
|
|
66
|
+
}
|