@squadbase/vantage 0.0.1 → 0.1.1

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 (187) hide show
  1. package/README.md +24 -4
  2. package/dist/{chunk-ZGDU5YLH.js → chunk-5L2MH2NG.js} +16 -7
  3. package/dist/chunk-5L2MH2NG.js.map +1 -0
  4. package/dist/chunk-7IPAXPPY.js +51 -0
  5. package/dist/chunk-7IPAXPPY.js.map +1 -0
  6. package/dist/chunk-A2UUGASH.js +12 -0
  7. package/dist/chunk-A2UUGASH.js.map +1 -0
  8. package/dist/chunk-DTDVSFRY.js +29 -0
  9. package/dist/chunk-DTDVSFRY.js.map +1 -0
  10. package/dist/chunk-WQZYXXQW.js +2249 -0
  11. package/dist/chunk-WQZYXXQW.js.map +1 -0
  12. package/dist/{chunk-73J5ZD4C.js → chunk-YLAB6UQS.js} +17 -3
  13. package/dist/chunk-YLAB6UQS.js.map +1 -0
  14. package/dist/cli.js +607 -36
  15. package/dist/cli.js.map +1 -1
  16. package/dist/client/index.d.ts +2 -1
  17. package/dist/client/index.js +3 -1
  18. package/dist/client/index.js.map +1 -1
  19. package/dist/components/index.d.ts +575 -0
  20. package/dist/components/index.js +2097 -0
  21. package/dist/components/index.js.map +1 -0
  22. package/dist/{define-page-B6y9TOfZ.d.ts → define-page-BfhrK99G.d.ts} +5 -0
  23. package/dist/index.d.ts +2 -2
  24. package/dist/index.js +1 -1
  25. package/dist/index.js.map +1 -1
  26. package/dist/markdown/index.d.ts +9 -0
  27. package/dist/markdown/index.js +26 -0
  28. package/dist/markdown/index.js.map +1 -0
  29. package/dist/query/index.d.ts +95 -2
  30. package/dist/query/index.js +102 -1
  31. package/dist/query/index.js.map +1 -1
  32. package/dist/router/index.d.ts +86 -1
  33. package/dist/router/index.js +71 -7
  34. package/dist/router/index.js.map +1 -1
  35. package/dist/server/node.js +6 -1
  36. package/dist/server/node.js.map +1 -1
  37. package/dist/ui/index.d.ts +316 -200
  38. package/dist/ui/index.js +566 -511
  39. package/dist/ui/index.js.map +1 -1
  40. package/dist/vite/index.js +2 -2
  41. package/docs/en/agent-skills.md +89 -0
  42. package/docs/en/api-and-server.md +84 -0
  43. package/docs/en/build-and-deploy.md +280 -0
  44. package/docs/en/cli-reference.md +311 -0
  45. package/docs/en/components.md +235 -0
  46. package/docs/en/data-fetching.md +142 -0
  47. package/docs/en/environment-variables.md +69 -0
  48. package/docs/en/getting-started.md +95 -0
  49. package/docs/en/index.md +65 -0
  50. package/docs/en/markdown/markdown-renderer.md +44 -0
  51. package/docs/en/pages-and-metadata.md +59 -0
  52. package/docs/en/parts/app-shell.md +54 -0
  53. package/docs/en/parts/dashboard-card.md +64 -0
  54. package/docs/en/parts/data-table.md +86 -0
  55. package/docs/en/parts/date-range-picker.md +41 -0
  56. package/docs/en/parts/echart.md +53 -0
  57. package/docs/en/parts/filter-bar.md +66 -0
  58. package/docs/en/parts/funnel-steps.md +33 -0
  59. package/docs/en/parts/metric-value.md +23 -0
  60. package/docs/en/parts/multi-select.md +27 -0
  61. package/docs/en/parts/page-shell.md +45 -0
  62. package/docs/en/parts/placeholder.md +38 -0
  63. package/docs/en/parts/searchable-select.md +47 -0
  64. package/docs/en/parts/section-header.md +20 -0
  65. package/docs/en/parts/segmented-control.md +25 -0
  66. package/docs/en/parts/sparkline.md +47 -0
  67. package/docs/en/parts/status-badge.md +44 -0
  68. package/docs/en/parts/trend-indicator.md +26 -0
  69. package/docs/en/routing.md +177 -0
  70. package/docs/en/ui/accordion.md +36 -0
  71. package/docs/en/ui/alert.md +31 -0
  72. package/docs/en/ui/badge.md +23 -0
  73. package/docs/en/ui/breadcrumb.md +38 -0
  74. package/docs/en/ui/button.md +39 -0
  75. package/docs/en/ui/calendar.md +28 -0
  76. package/docs/en/ui/card.md +35 -0
  77. package/docs/en/ui/checkbox.md +34 -0
  78. package/docs/en/ui/cn.md +34 -0
  79. package/docs/en/ui/collapsible.md +21 -0
  80. package/docs/en/ui/command.md +37 -0
  81. package/docs/en/ui/dialog.md +52 -0
  82. package/docs/en/ui/dropdown-menu.md +50 -0
  83. package/docs/en/ui/empty.md +22 -0
  84. package/docs/en/ui/error-state.md +50 -0
  85. package/docs/en/ui/input-group.md +30 -0
  86. package/docs/en/ui/input.md +28 -0
  87. package/docs/en/ui/label.md +19 -0
  88. package/docs/en/ui/loading.md +19 -0
  89. package/docs/en/ui/popover.md +34 -0
  90. package/docs/en/ui/progress.md +28 -0
  91. package/docs/en/ui/scroll-area.md +23 -0
  92. package/docs/en/ui/select.md +63 -0
  93. package/docs/en/ui/separator.md +15 -0
  94. package/docs/en/ui/sheet.md +28 -0
  95. package/docs/en/ui/sidebar.md +92 -0
  96. package/docs/en/ui/skeleton.md +16 -0
  97. package/docs/en/ui/slider.md +21 -0
  98. package/docs/en/ui/spinner.md +14 -0
  99. package/docs/en/ui/switch.md +19 -0
  100. package/docs/en/ui/table.md +24 -0
  101. package/docs/en/ui/tabs.md +23 -0
  102. package/docs/en/ui/textarea.md +15 -0
  103. package/docs/en/ui/toggle-group.md +26 -0
  104. package/docs/en/ui/toggle.md +19 -0
  105. package/docs/en/ui/tooltip.md +22 -0
  106. package/docs/en/ui/use-is-mobile.md +18 -0
  107. package/docs/en/ui-and-theming.md +95 -0
  108. package/docs/index.json +1346 -0
  109. package/docs/ja/agent-skills.md +87 -0
  110. package/docs/ja/api-and-server.md +84 -0
  111. package/docs/ja/build-and-deploy.md +279 -0
  112. package/docs/ja/cli-reference.md +305 -0
  113. package/docs/ja/components.md +231 -0
  114. package/docs/ja/data-fetching.md +142 -0
  115. package/docs/ja/environment-variables.md +68 -0
  116. package/docs/ja/getting-started.md +95 -0
  117. package/docs/ja/index.md +65 -0
  118. package/docs/ja/markdown/markdown-renderer.md +43 -0
  119. package/docs/ja/pages-and-metadata.md +59 -0
  120. package/docs/ja/parts/app-shell.md +54 -0
  121. package/docs/ja/parts/dashboard-card.md +64 -0
  122. package/docs/ja/parts/data-table.md +85 -0
  123. package/docs/ja/parts/date-range-picker.md +41 -0
  124. package/docs/ja/parts/echart.md +52 -0
  125. package/docs/ja/parts/filter-bar.md +64 -0
  126. package/docs/ja/parts/funnel-steps.md +33 -0
  127. package/docs/ja/parts/metric-value.md +25 -0
  128. package/docs/ja/parts/multi-select.md +27 -0
  129. package/docs/ja/parts/page-shell.md +45 -0
  130. package/docs/ja/parts/placeholder.md +37 -0
  131. package/docs/ja/parts/searchable-select.md +47 -0
  132. package/docs/ja/parts/section-header.md +20 -0
  133. package/docs/ja/parts/segmented-control.md +26 -0
  134. package/docs/ja/parts/sparkline.md +47 -0
  135. package/docs/ja/parts/status-badge.md +44 -0
  136. package/docs/ja/parts/trend-indicator.md +26 -0
  137. package/docs/ja/routing.md +175 -0
  138. package/docs/ja/ui/accordion.md +37 -0
  139. package/docs/ja/ui/alert.md +31 -0
  140. package/docs/ja/ui/badge.md +23 -0
  141. package/docs/ja/ui/breadcrumb.md +38 -0
  142. package/docs/ja/ui/button.md +39 -0
  143. package/docs/ja/ui/calendar.md +28 -0
  144. package/docs/ja/ui/card.md +35 -0
  145. package/docs/ja/ui/checkbox.md +34 -0
  146. package/docs/ja/ui/cn.md +34 -0
  147. package/docs/ja/ui/collapsible.md +21 -0
  148. package/docs/ja/ui/command.md +36 -0
  149. package/docs/ja/ui/dialog.md +51 -0
  150. package/docs/ja/ui/dropdown-menu.md +50 -0
  151. package/docs/ja/ui/empty.md +22 -0
  152. package/docs/ja/ui/error-state.md +50 -0
  153. package/docs/ja/ui/input-group.md +30 -0
  154. package/docs/ja/ui/input.md +28 -0
  155. package/docs/ja/ui/label.md +19 -0
  156. package/docs/ja/ui/loading.md +19 -0
  157. package/docs/ja/ui/popover.md +34 -0
  158. package/docs/ja/ui/progress.md +28 -0
  159. package/docs/ja/ui/scroll-area.md +24 -0
  160. package/docs/ja/ui/select.md +64 -0
  161. package/docs/ja/ui/separator.md +15 -0
  162. package/docs/ja/ui/sheet.md +28 -0
  163. package/docs/ja/ui/sidebar.md +92 -0
  164. package/docs/ja/ui/skeleton.md +16 -0
  165. package/docs/ja/ui/slider.md +21 -0
  166. package/docs/ja/ui/spinner.md +14 -0
  167. package/docs/ja/ui/switch.md +19 -0
  168. package/docs/ja/ui/table.md +24 -0
  169. package/docs/ja/ui/tabs.md +24 -0
  170. package/docs/ja/ui/textarea.md +15 -0
  171. package/docs/ja/ui/toggle-group.md +27 -0
  172. package/docs/ja/ui/toggle.md +19 -0
  173. package/docs/ja/ui/tooltip.md +22 -0
  174. package/docs/ja/ui/use-is-mobile.md +18 -0
  175. package/docs/ja/ui-and-theming.md +95 -0
  176. package/package.json +29 -4
  177. package/registry/blocks/sales-overview.tsx +43 -19
  178. package/registry/ui/data-table.tsx +702 -102
  179. package/skills/vantage-add-feature/SKILL.md +153 -0
  180. package/skills/vantage-app/SKILL.md +291 -0
  181. package/skills/vantage-pitfalls/SKILL.md +139 -0
  182. package/templates/AGENTS.md +313 -0
  183. package/theme.css +178 -40
  184. package/dist/chunk-73J5ZD4C.js.map +0 -1
  185. package/dist/chunk-ATYZ45XL.js +0 -19
  186. package/dist/chunk-ATYZ45XL.js.map +0 -1
  187. package/dist/chunk-ZGDU5YLH.js.map +0 -1
@@ -0,0 +1,37 @@
1
+ # Command
2
+
3
+ > A filterable command list — the base for a ⌘K palette.
4
+
5
+ A list that narrows as you type. It is what powers
6
+ [`SearchableSelect`](parts/searchable-select) and
7
+ [`MultiSelect`](parts/multi-select), and on its own it makes a ⌘K palette.
8
+
9
+ ```tsx
10
+ import {
11
+ Command,
12
+ CommandDialog,
13
+ CommandInput,
14
+ CommandList,
15
+ CommandEmpty,
16
+ CommandGroup,
17
+ CommandItem,
18
+ CommandShortcut,
19
+ CommandSeparator,
20
+ } from "@squadbase/vantage/ui";
21
+ ```
22
+
23
+ ## Parts
24
+
25
+ | Part | Role |
26
+ | --- | --- |
27
+ | `Command` | The root; owns filtering and keyboard handling |
28
+ | `CommandDialog` | The same thing inside a `Dialog` — for a ⌘K palette |
29
+ | `CommandInput` | The search field |
30
+ | `CommandList` | The scroll region |
31
+ | `CommandEmpty` | Shown when nothing matches |
32
+ | `CommandGroup` | A group with a `heading` |
33
+ | `CommandItem` | One item; `value` / `onSelect` |
34
+ | `CommandShortcut` | The key hint on the right |
35
+
36
+ Filtering runs against the items' text by default. To search on the server, set
37
+ `shouldFilter={false}` and replace the items yourself.
@@ -0,0 +1,52 @@
1
+ # Dialog
2
+
3
+ > The modal dialog.
4
+
5
+ A modal centred on the screen. For one that slides in from the edge use
6
+ [`Sheet`](ui/sheet); for a light bubble use
7
+ [`Popover`](ui/popover).
8
+
9
+ ```tsx
10
+ import {
11
+ Dialog,
12
+ DialogTrigger,
13
+ DialogContent,
14
+ DialogHeader,
15
+ DialogTitle,
16
+ DialogDescription,
17
+ DialogFooter,
18
+ DialogClose,
19
+ DialogOverlay,
20
+ DialogPortal,
21
+ } from "@squadbase/vantage/ui";
22
+ ```
23
+
24
+ ## Parts
25
+
26
+ | Part | Role |
27
+ | --- | --- |
28
+ | `Dialog` | The state: `open` / `defaultOpen` / `onOpenChange` |
29
+ | `DialogTrigger` | What opens it; `render` turns it into a button |
30
+ | `DialogContent` | The panel. `showCloseButton` (default `true`) toggles the × |
31
+ | `DialogHeader` / `DialogTitle` / `DialogDescription` | The heading block |
32
+ | `DialogFooter` | The button row; `showCloseButton` adds a close button |
33
+ | `DialogClose` | Anything that closes it |
34
+
35
+ `DialogTitle` is required for assistive technology. If you don't want it visible, keep it and add
36
+ `className="sr-only"`.
37
+
38
+ ## Opening without a trigger
39
+
40
+ To open from code — after a form submit, say — own the `open` state yourself.
41
+
42
+ ```tsx
43
+ const [open, setOpen] = useState(false);
44
+
45
+ <Dialog open={open} onOpenChange={setOpen}>
46
+ <DialogContent>…</DialogContent>
47
+ </Dialog>;
48
+ ```
49
+
50
+ > [!NOTE]
51
+ > Base UI has no `asChild`. Write `<DialogTrigger render={<Button />}>Label</DialogTrigger>` — the
52
+ > label goes in `children`, not inside the element you pass to `render`.
@@ -0,0 +1,50 @@
1
+ # DropdownMenu
2
+
3
+ > A menu opened from a button, with checkbox, radio and submenu items.
4
+
5
+ An action menu opened from a button — the per-row "…" menu, or a table's column-visibility toggle.
6
+
7
+ ```tsx
8
+ import {
9
+ DropdownMenu,
10
+ DropdownMenuTrigger,
11
+ DropdownMenuContent,
12
+ DropdownMenuGroup,
13
+ DropdownMenuLabel,
14
+ DropdownMenuItem,
15
+ DropdownMenuCheckboxItem,
16
+ DropdownMenuRadioGroup,
17
+ DropdownMenuRadioItem,
18
+ DropdownMenuSeparator,
19
+ DropdownMenuShortcut,
20
+ DropdownMenuSub,
21
+ DropdownMenuSubTrigger,
22
+ DropdownMenuSubContent,
23
+ DropdownMenuPortal,
24
+ } from "@squadbase/vantage/ui";
25
+ ```
26
+
27
+ ## The props you'll use
28
+
29
+ | Prop | Goes on | Meaning |
30
+ | --- | --- | --- |
31
+ | `align` / `side` / `sideOffset` | `DropdownMenuContent` | Where it opens |
32
+ | `variant="destructive"` | `DropdownMenuItem` | Destructive colouring |
33
+ | `inset` | `Item` / `Label` / `SubTrigger` | Indent past the icon column |
34
+ | `checked` / `onCheckedChange` | `DropdownMenuCheckboxItem` | Checked state |
35
+ | `value` / `onValueChange` | `DropdownMenuRadioGroup` | Single choice |
36
+
37
+ ## Submenus
38
+
39
+ ```tsx
40
+ <DropdownMenuSub>
41
+ <DropdownMenuSubTrigger>Export</DropdownMenuSubTrigger>
42
+ <DropdownMenuSubContent>
43
+ <DropdownMenuItem>CSV</DropdownMenuItem>
44
+ <DropdownMenuItem>JSON</DropdownMenuItem>
45
+ </DropdownMenuSubContent>
46
+ </DropdownMenuSub>
47
+ ```
48
+
49
+ > [!NOTE]
50
+ > Use `render` to make the trigger a button — Base UI has no `asChild`.
@@ -0,0 +1,22 @@
1
+ # Empty
2
+
3
+ > The zero-results state.
4
+
5
+ What to show when there are no results. The icon, description and action are all optional.
6
+
7
+ ```tsx
8
+ import { Empty } from "@squadbase/vantage/ui";
9
+ ```
10
+
11
+ | Prop | Type | Default | Description |
12
+ | --- | --- | --- | --- |
13
+ | `title` | `string` | `"Nothing here yet"` | The heading. |
14
+ | `description` | `string` | | Supporting text under the heading. |
15
+ | `icon` | `ReactNode` | | Artwork above the heading. |
16
+ | `action` | `ReactNode` | | The next step — a button or link — at the bottom. |
17
+ | `className` | `string` | | Classes to add. |
18
+
19
+ > [!NOTE]
20
+ > When it has no rows, [`DataTable`](parts/data-table) draws its own "no data" row
21
+ > inside the table. Reach for `Empty` when you want to replace the table entirely — for instance, when
22
+ > nothing has been created yet.
@@ -0,0 +1,50 @@
1
+ # ErrorState
2
+
3
+ > The failure state.
4
+
5
+ Shown when a load or an action failed. It carries `role="alert"` and is framed in the destructive
6
+ colours.
7
+
8
+ ```tsx
9
+ import { ErrorState } from "@squadbase/vantage/ui";
10
+ ```
11
+
12
+ | Prop | Type | Default | Description |
13
+ | --- | --- | --- | --- |
14
+ | `title` | `string` | `"Something went wrong"` | The heading. |
15
+ | `message` | `ReactNode` | | The details — an error message can go straight in. |
16
+ | `action` | `ReactNode` | | A retry button, typically. |
17
+ | `className` | `string` | | Classes to add. |
18
+
19
+ ## All three states together
20
+
21
+ The usual shape is to map the query's state onto the three branches.
22
+
23
+ ```tsx
24
+ import { useQuery, apiFetch } from "@squadbase/vantage/query";
25
+ import { Button, Loading, Empty, ErrorState } from "@squadbase/vantage/ui";
26
+ import { DataTablePreset } from "@squadbase/vantage/components";
27
+
28
+ export default function Customers() {
29
+ const { data, isLoading, error, refetch } = useQuery({
30
+ queryKey: ["customers"],
31
+ queryFn: () => apiFetch("/api/customers").then((r) => r.json()),
32
+ });
33
+
34
+ if (isLoading) return <Loading label="Loading customers…" />;
35
+ if (error)
36
+ return (
37
+ <ErrorState
38
+ message={error.message}
39
+ action={<Button variant="outline" onClick={() => refetch()}>Retry</Button>}
40
+ />
41
+ );
42
+ if (data.length === 0) return <Empty title="No customers yet" />;
43
+
44
+ return <DataTablePreset columns={columns} data={data} />;
45
+ }
46
+ ```
47
+
48
+ > [!NOTE]
49
+ > To surface a deliberate error message from your API, throw `HttpError(status, message)` in
50
+ > `server/api`. Anything else becomes a generic 500 — see [API & server](api-and-server).
@@ -0,0 +1,30 @@
1
+ # InputGroup
2
+
3
+ > Attach icons, text or buttons to either end of an input.
4
+
5
+ A frame that places icons, units or small buttons inside the field — search boxes, or inputs with a
6
+ `%` or currency suffix.
7
+
8
+ ```tsx
9
+ import {
10
+ InputGroup,
11
+ InputGroupInput,
12
+ InputGroupTextarea,
13
+ InputGroupAddon,
14
+ InputGroupText,
15
+ InputGroupButton,
16
+ } from "@squadbase/vantage/ui";
17
+ ```
18
+
19
+ ## Parts
20
+
21
+ | Part | Role |
22
+ | --- | --- |
23
+ | `InputGroup` | The frame; the focus ring lives here |
24
+ | `InputGroupInput` / `InputGroupTextarea` | The field itself, borderless |
25
+ | `InputGroupAddon` | Where attachments go. `align`: `inline-start` (default) \| `inline-end` \| `block-start` \| `block-end` |
26
+ | `InputGroupText` | Short text such as a unit |
27
+ | `InputGroupButton` | A small button. `size`: `xs` (default) \| `sm` \| `icon-xs` \| `icon-sm` |
28
+
29
+ `block-start` / `block-end` place the addon above or below the field — pair either with
30
+ `InputGroupTextarea` for a textarea with its own toolbar.
@@ -0,0 +1,28 @@
1
+ # Input
2
+
3
+ > The single-line text input.
4
+
5
+ A plain `<input>` with the theme's border and focus ring. The props are the native ones, `type`
6
+ included.
7
+
8
+ ```tsx
9
+ import { Input } from "@squadbase/vantage/ui";
10
+ ```
11
+
12
+ Tie a [`Label`](ui/label) to it with `htmlFor`.
13
+
14
+ ## States
15
+
16
+ | Written as | Looks like |
17
+ | --- | --- |
18
+ | `disabled` | Dimmed, not interactive |
19
+ | `aria-invalid` | Border and ring turn `destructive` |
20
+ | `readOnly` | Unchanged, but not editable |
21
+
22
+ Validation styling is just `aria-invalid` — pass the boolean straight through.
23
+
24
+ ```tsx
25
+ <Input aria-invalid={Boolean(error)} />
26
+ ```
27
+
28
+ To attach an icon or button on either end, use [`InputGroup`](ui/input-group).
@@ -0,0 +1,19 @@
1
+ # Label
2
+
3
+ > The form label.
4
+
5
+ A `<label>` with consistent type and a dimmed disabled state. Either tie it with `htmlFor` or wrap
6
+ the control.
7
+
8
+ ```tsx
9
+ import { Label } from "@squadbase/vantage/ui";
10
+ ```
11
+
12
+ Wrapping a checkbox or switch in a `Label` makes the text clickable too.
13
+
14
+ ```tsx
15
+ <Label className="flex items-center gap-2">
16
+ <Switch />
17
+ Auto-refresh
18
+ </Label>
19
+ ```
@@ -0,0 +1,19 @@
1
+ # Loading
2
+
3
+ > A centred spinner with a label.
4
+
5
+ The loading state for a whole panel. It carries `role="status"` and `aria-live="polite"`, so screen
6
+ readers announce it too. One of the three state components Vantage adds on top of shadcn/ui,
7
+ alongside `Empty` and `ErrorState`.
8
+
9
+ ```tsx
10
+ import { Loading } from "@squadbase/vantage/ui";
11
+ ```
12
+
13
+ | Prop | Type | Default | Description |
14
+ | --- | --- | --- | --- |
15
+ | `label` | `string` | `"Loading…"` | Text shown next to the spinner. |
16
+ | `className` | `string` | | Classes to add. By default it centres within a 30vh minimum height. |
17
+
18
+ To hold the layout while waiting use [`Skeleton`](ui/skeleton); in tight spots such
19
+ as a button, [`Spinner`](ui/spinner).
@@ -0,0 +1,34 @@
1
+ # Popover
2
+
3
+ > A bubble anchored to its trigger.
4
+
5
+ A panel that opens anchored to an element. If you need to trap focus, use
6
+ [`Dialog`](ui/dialog); for a caption alone, [`Tooltip`](ui/tooltip).
7
+
8
+ ```tsx
9
+ import {
10
+ Popover,
11
+ PopoverTrigger,
12
+ PopoverContent,
13
+ PopoverHeader,
14
+ PopoverTitle,
15
+ PopoverDescription,
16
+ } from "@squadbase/vantage/ui";
17
+ ```
18
+
19
+ ## Placement
20
+
21
+ Set by `PopoverContent`'s `side` (default `bottom`), `align` (default `center`) and `sideOffset`
22
+ (default `4`).
23
+
24
+ ## Matching the trigger's width
25
+
26
+ Base UI exposes a `--anchor-width` CSS variable — the equivalent of Radix's
27
+ `--radix-popover-trigger-width`.
28
+
29
+ ```tsx
30
+ <PopoverContent className="w-(--anchor-width)">…</PopoverContent>
31
+ ```
32
+
33
+ > [!NOTE]
34
+ > To make the trigger a button write `render={<Button />}`. Base UI has no `asChild`.
@@ -0,0 +1,28 @@
1
+ # Progress
2
+
3
+ > The progress bar, with optional label and value.
4
+
5
+ A bar for 0–100 progress. Put a label or value inside `Progress` and the bar is drawn beneath them
6
+ automatically.
7
+
8
+ ```tsx
9
+ import {
10
+ Progress,
11
+ ProgressTrack,
12
+ ProgressIndicator,
13
+ ProgressLabel,
14
+ ProgressValue,
15
+ } from "@squadbase/vantage/ui";
16
+ ```
17
+
18
+ ## Parts
19
+
20
+ | Part | Role |
21
+ | --- | --- |
22
+ | `Progress` | The root. `value` (`null` for indeterminate) |
23
+ | `ProgressLabel` | The heading |
24
+ | `ProgressValue` | The current value, as a percentage by default |
25
+ | `ProgressTrack` / `ProgressIndicator` | The bar itself — `Progress` renders these for you |
26
+
27
+ Pass `value={null}` when the total isn't known. If you only mean "loading",
28
+ [`Skeleton`](ui/skeleton) or [`Spinner`](ui/spinner) says it better.
@@ -0,0 +1,23 @@
1
+ # ScrollArea
2
+
3
+ > A scroll region with a consistent, non-native scrollbar.
4
+
5
+ Gives a fixed-height region a styled scrollbar instead of the OS one — dropdown contents, long log
6
+ output, and the like.
7
+
8
+ ```tsx
9
+ import { ScrollArea, ScrollBar } from "@squadbase/vantage/ui";
10
+ ```
11
+
12
+ Set the height (or width) via `className`. Vertical is the default; for horizontal scrolling add a
13
+ `ScrollBar orientation="horizontal"` child.
14
+
15
+ ```tsx
16
+ <ScrollArea className="w-96 whitespace-nowrap">
17
+ <div className="flex gap-3">…</div>
18
+ <ScrollBar orientation="horizontal" />
19
+ </ScrollArea>
20
+ ```
21
+
22
+ > [!NOTE]
23
+ > If you only want to hide the scrollbar, `theme.css` defines a `no-scrollbar` utility.
@@ -0,0 +1,63 @@
1
+ # Select
2
+
3
+ > The single-choice select. Note that onValueChange can hand you null.
4
+
5
+ Pick one option from a list. When there are many options and you want search, use
6
+ [`SearchableSelect`](parts/searchable-select); for a handful shown side by side,
7
+ [`SegmentedControl`](parts/segmented-control).
8
+
9
+ ```tsx
10
+ import {
11
+ Select,
12
+ SelectTrigger,
13
+ SelectValue,
14
+ SelectContent,
15
+ SelectGroup,
16
+ SelectLabel,
17
+ SelectItem,
18
+ SelectSeparator,
19
+ SelectScrollUpButton,
20
+ SelectScrollDownButton,
21
+ } from "@squadbase/vantage/ui";
22
+ ```
23
+
24
+ ## Parts
25
+
26
+ | Part | Role |
27
+ | --- | --- |
28
+ | `Select` | The state: `value` / `defaultValue` / `onValueChange` / `items` |
29
+ | `SelectTrigger` | The closed state. `size`: `default` \| `sm` |
30
+ | `SelectValue` | What's selected; `placeholder` covers "nothing yet" |
31
+ | `SelectContent` | The open list |
32
+ | `SelectGroup` + `SelectLabel` | A group with a heading |
33
+ | `SelectItem` | One option; `value` is required |
34
+
35
+ > [!WARNING]
36
+ > `onValueChange` hands you **`string | null`** — Base UI allows deselection. Always guard for `null`.
37
+ >
38
+ > ```tsx
39
+ > <Select onValueChange={(value) => value !== null && setRegion(value)}>
40
+ > ```
41
+
42
+ > [!WARNING]
43
+ > `SelectValue` shows the **raw selected `value`** by default — it never looks inside `SelectItem`.
44
+ > With `value="kanto"` the trigger reads `kanto`, not "Kanto". Give `Select` the value-to-label map
45
+ > via `items`.
46
+ >
47
+ > ```tsx
48
+ > const regions = { hokkaido: "Hokkaido", kanto: "Kanto", kansai: "Kansai" };
49
+ >
50
+ > <Select items={regions} value={region} onValueChange={…}>
51
+ > <SelectTrigger><SelectValue placeholder="Pick a region" /></SelectTrigger>
52
+ > …
53
+ > </Select>;
54
+ > ```
55
+ >
56
+ > If you'd rather not carry `items`, a function child on `SelectValue` does the same job.
57
+ >
58
+ > ```tsx
59
+ > <SelectValue>{(value) => regions[value] ?? "Pick a region"}</SelectValue>
60
+ > ```
61
+
62
+ `SelectContent` opens over the trigger with the selected item aligned to it. For a plain dropdown
63
+ below the trigger, pass `alignItemWithTrigger={false}`.
@@ -0,0 +1,15 @@
1
+ # Separator
2
+
3
+ > A single dividing rule.
4
+
5
+ A rule between sections. With `orientation="vertical"` the parent needs a height.
6
+
7
+ ```tsx
8
+ import { Separator } from "@squadbase/vantage/ui";
9
+ ```
10
+
11
+ | Prop | Type | Default | Description |
12
+ | --- | --- | --- | --- |
13
+ | `orientation` | `"horizontal" \| "vertical"` | `"horizontal"` | Which way the rule runs. |
14
+
15
+ It is decorative, so assistive technology skips it.
@@ -0,0 +1,28 @@
1
+ # Sheet
2
+
3
+ > A panel that slides in from an edge.
4
+
5
+ A panel that slides in from the edge of the screen — for a full set of filters, or an edit form that
6
+ wants more room than a modal.
7
+
8
+ ```tsx
9
+ import {
10
+ Sheet,
11
+ SheetTrigger,
12
+ SheetContent,
13
+ SheetHeader,
14
+ SheetTitle,
15
+ SheetDescription,
16
+ SheetFooter,
17
+ SheetClose,
18
+ } from "@squadbase/vantage/ui";
19
+ ```
20
+
21
+ The structure matches [`Dialog`](ui/dialog); only the direction differs.
22
+
23
+ | Prop | Type | Default | Description |
24
+ | --- | --- | --- | --- |
25
+ | `side` | `"top" \| "right" \| "bottom" \| "left"` | `"right"` | Goes on `SheetContent`. Which edge it enters from. |
26
+
27
+ `SheetTitle` is required for assistive technology. Keep it and add `className="sr-only"` if it
28
+ shouldn't be visible.
@@ -0,0 +1,92 @@
1
+ # Sidebar
2
+
3
+ > The full collapsible application sidebar kit.
4
+
5
+ A kit of twenty-odd parts for building an application's navigation. If you'd rather just hand over
6
+ an array of nav items, [`AppShell`](parts/app-shell) gets you there faster.
7
+
8
+ ```tsx
9
+ import {
10
+ Sidebar,
11
+ SidebarProvider,
12
+ SidebarInset,
13
+ SidebarTrigger,
14
+ SidebarHeader,
15
+ SidebarContent,
16
+ SidebarFooter,
17
+ SidebarGroup,
18
+ SidebarGroupLabel,
19
+ SidebarGroupContent,
20
+ SidebarGroupAction,
21
+ SidebarMenu,
22
+ SidebarMenuItem,
23
+ SidebarMenuButton,
24
+ SidebarMenuAction,
25
+ SidebarMenuBadge,
26
+ SidebarMenuSkeleton,
27
+ SidebarMenuSub,
28
+ SidebarMenuSubItem,
29
+ SidebarMenuSubButton,
30
+ SidebarSeparator,
31
+ SidebarInput,
32
+ SidebarRail,
33
+ useSidebar,
34
+ } from "@squadbase/vantage/ui";
35
+ ```
36
+
37
+ ## The skeleton
38
+
39
+ `SidebarProvider` owns the open/closed state; `Sidebar` and `SidebarInset` (the content side) sit
40
+ inside it.
41
+
42
+ ```tsx
43
+ <SidebarProvider>
44
+ <Sidebar>
45
+ <SidebarHeader>Acme Analytics</SidebarHeader>
46
+ <SidebarContent>
47
+ <SidebarGroup>
48
+ <SidebarGroupLabel>Analytics</SidebarGroupLabel>
49
+ <SidebarGroupContent>
50
+ <SidebarMenu>
51
+ <SidebarMenuItem>
52
+ <SidebarMenuButton isActive>Overview</SidebarMenuButton>
53
+ </SidebarMenuItem>
54
+ <SidebarMenuItem>
55
+ <SidebarMenuButton>Sales</SidebarMenuButton>
56
+ <SidebarMenuBadge>12</SidebarMenuBadge>
57
+ </SidebarMenuItem>
58
+ </SidebarMenu>
59
+ </SidebarGroupContent>
60
+ </SidebarGroup>
61
+ </SidebarContent>
62
+ <SidebarRail />
63
+ </Sidebar>
64
+
65
+ <SidebarInset>
66
+ <SidebarTrigger />
67
+ {children}
68
+ </SidebarInset>
69
+ </SidebarProvider>
70
+ ```
71
+
72
+ ## Worth knowing
73
+
74
+ | Thing | Effect |
75
+ | --- | --- |
76
+ | `isActive` on `SidebarMenuButton` | Highlights the current page |
77
+ | `tooltip` on `SidebarMenuButton` | Shows the label while collapsed |
78
+ | `render` on `SidebarMenuButton` | Swaps in a link component |
79
+ | `SidebarRail` | The thin strip you drag to collapse |
80
+ | `SidebarMenuSkeleton` | A loading menu |
81
+ | `useSidebar()` | Reads the open state and the mobile flag |
82
+
83
+ ## Making items links
84
+
85
+ ```tsx
86
+ import { Link } from "@squadbase/vantage/router";
87
+
88
+ <SidebarMenuButton render={<Link to="/sales" />}>Sales</SidebarMenuButton>;
89
+ ```
90
+
91
+ > [!NOTE]
92
+ > Base UI has no `asChild` — pass an element to `render`.
@@ -0,0 +1,16 @@
1
+ # Skeleton
2
+
3
+ > A box shaped like the content that will replace it.
4
+
5
+ A placeholder shaped like whatever is coming. Unlike [`Loading`](ui/loading)'s
6
+ full-panel spinner, it keeps the layout intact while you wait.
7
+
8
+ ```tsx
9
+ import { Skeleton } from "@squadbase/vantage/ui";
10
+ ```
11
+
12
+ Size it with `className` (`h-4 w-32` and friends). Match the height of the real element and the page
13
+ won't jump when the data lands.
14
+
15
+ For dashboard tiles, [`DashboardCardSkeleton`](parts/dashboard-card) is already the
16
+ right shape.
@@ -0,0 +1,21 @@
1
+ # Slider
2
+
3
+ > Pick a number by dragging. Ranges included.
4
+
5
+ Choose a number by dragging. Pass an array as `value` and you get one thumb per entry — a range.
6
+
7
+ ```tsx
8
+ import { Slider } from "@squadbase/vantage/ui";
9
+ ```
10
+
11
+ | Prop | Type | Default | Description |
12
+ | --- | --- | --- | --- |
13
+ | `value` | `number \| number[]` | | Thumb position(s). An array makes it a range. |
14
+ | `defaultValue` | `number \| number[]` | | Initial value when uncontrolled. |
15
+ | `onValueChange` | `(value: number \| number[]) => void` | | Fired on change, in the same shape you passed to `value`. |
16
+ | `min` | `number` | `0` | Lower bound. |
17
+ | `max` | `number` | `100` | Upper bound. |
18
+ | `step` | `number` | `1` | Increment. |
19
+ | `disabled` | `boolean` | | Disable interaction. |
20
+
21
+ Thumbs are aligned to the track's edges, so they never overhang it at `min` or `max`.
@@ -0,0 +1,14 @@
1
+ # Spinner
2
+
3
+ > The smallest waiting indicator.
4
+
5
+ Just a spinning icon — for tight spots like inside a button.
6
+
7
+ ```tsx
8
+ import { Spinner } from "@squadbase/vantage/ui";
9
+ ```
10
+
11
+ It is an `<svg>`, so `size-*` sets the size and `text-*` the colour.
12
+
13
+ For a whole panel use [`Loading`](ui/loading); to hold the layout while you wait,
14
+ [`Skeleton`](ui/skeleton).
@@ -0,0 +1,19 @@
1
+ # Switch
2
+
3
+ > A toggle for settings that take effect at once.
4
+
5
+ For a setting that applies immediately. If it only takes effect on submit,
6
+ [`Checkbox`](ui/checkbox) is the better fit.
7
+
8
+ ```tsx
9
+ import { Switch } from "@squadbase/vantage/ui";
10
+ ```
11
+
12
+ | Prop | Type | Default | Description |
13
+ | --- | --- | --- | --- |
14
+ | `checked` | `boolean` | | On or off. |
15
+ | `onCheckedChange` | `(checked: boolean) => void` | | Fired on change. |
16
+ | `size` | `"default" \| "sm"` | `"default"` | Scale. |
17
+ | `disabled` | `boolean` | | Disable interaction. |
18
+
19
+ Wrap it in a [`Label`](ui/label) so the text is clickable too.