@brumaombra/ui-vintage 0.7.13 → 0.8.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 (194) hide show
  1. package/COMPONENTS.md +3643 -0
  2. package/README.md +50 -10
  3. package/package.json +30 -8
  4. package/skills/ui-vintage/SKILL.md +42 -0
  5. package/src/components/blog/BlogFAQSection.vue +2 -2
  6. package/src/components/blog/BlogHeaderSection.vue +2 -2
  7. package/src/components/blog/BlogInfoSection.vue +3 -3
  8. package/src/components/blog/BlogProgressBar.vue +7 -6
  9. package/src/components/blog/BlogSectionTitle.vue +1 -1
  10. package/src/components/blog/BlogTagsSection.vue +22 -0
  11. package/src/components/blog/CategoryCard.vue +1 -1
  12. package/src/components/blog/HeaderCarousel.vue +6 -6
  13. package/src/components/blog/PostCard.vue +2 -2
  14. package/src/components/blog/SocialShareSidebar.vue +1 -1
  15. package/src/components/blog/TableOfContents.vue +6 -6
  16. package/src/components/blog/index.ts +1 -0
  17. package/src/components/busy-indicator/busy-indicator-state.ts +3 -2
  18. package/src/components/chip/Chip.vue +9 -5
  19. package/src/components/confirm-dialog/ConfirmDialog.vue +17 -6
  20. package/src/components/confirm-dialog/confirm-dialog-state.ts +4 -3
  21. package/src/components/content/BlogList.vue +3 -3
  22. package/src/components/content/BlogTable.vue +7 -7
  23. package/src/components/content/CodeBlock.vue +4 -4
  24. package/src/components/content/Flow.vue +3 -3
  25. package/src/components/content/ProseHr.vue +2 -2
  26. package/src/components/content/Terminal.vue +4 -4
  27. package/src/components/cookie-consent/CookieConsent.vue +82 -0
  28. package/src/components/cookie-consent/index.ts +3 -0
  29. package/src/components/cookie-consent/useCookieConsent.ts +55 -0
  30. package/src/components/dashboard-shell/DashboardShell.vue +3 -3
  31. package/src/components/empty-state-card/EmptyStateCard.vue +4 -4
  32. package/src/components/error-page/ErrorPage.vue +16 -14
  33. package/src/components/info-card/InfoCard.vue +1 -1
  34. package/src/components/landing/landing-navbar/LandingNavbar.vue +2 -1
  35. package/src/components/load-more-button/LoadMoreButton.vue +2 -2
  36. package/src/components/loading-state-card/LoadingStateCard.vue +4 -4
  37. package/src/components/message-dialog/MessageDialog.vue +4 -4
  38. package/src/components/message-toast/MessageToast.vue +222 -50
  39. package/src/components/message-toast/index.ts +2 -2
  40. package/src/components/message-toast/message-toast-state.ts +107 -81
  41. package/src/components/page-header/PageHeader.vue +1 -1
  42. package/src/components/progress-component/ProgressComponent.vue +4 -4
  43. package/src/components/single-value-card/SingleValueCard.vue +47 -11
  44. package/src/components/theme-selector/ThemeSelector.vue +20 -36
  45. package/src/components/theme-selector/index.ts +3 -1
  46. package/src/components/theme-selector/theme-transition.ts +86 -0
  47. package/src/components/ui/accordion/Accordion.vue +41 -26
  48. package/src/components/ui/alert-dialog/AlertDialogContent.vue +2 -2
  49. package/src/components/ui/alert-dialog/AlertDialogFooter.vue +1 -1
  50. package/src/components/ui/animated-number/AnimatedNumber.vue +102 -0
  51. package/src/components/ui/animated-number/index.ts +1 -0
  52. package/src/components/ui/avatar/Avatar.vue +66 -0
  53. package/src/components/ui/avatar/AvatarFallback.vue +31 -0
  54. package/src/components/ui/avatar/AvatarGroup.vue +75 -0
  55. package/src/components/ui/avatar/AvatarImage.vue +23 -0
  56. package/src/components/ui/avatar/index.ts +47 -0
  57. package/src/components/ui/badge/Badge.vue +13 -2
  58. package/src/components/ui/breadcrumb/Breadcrumb.vue +4 -1
  59. package/src/components/ui/breadcrumb/BreadcrumbEllipsis.vue +7 -1
  60. package/src/components/ui/busy/Busy.vue +45 -20
  61. package/src/components/ui/button/Button.vue +20 -3
  62. package/src/components/ui/button/index.ts +12 -2
  63. package/src/components/ui/card/Card.vue +21 -8
  64. package/src/components/ui/card/CardText.vue +1 -1
  65. package/src/components/ui/checkbox/Checkbox.vue +48 -0
  66. package/src/components/ui/checkbox/index.ts +1 -0
  67. package/src/components/ui/collapsible/Collapsible.vue +22 -0
  68. package/src/components/ui/collapsible/CollapsibleContent.vue +22 -0
  69. package/src/components/ui/collapsible/CollapsibleTrigger.vue +19 -0
  70. package/src/components/ui/collapsible/index.ts +3 -0
  71. package/src/components/ui/combobox/Combobox.vue +24 -0
  72. package/src/components/ui/combobox/ComboboxAnchor.vue +39 -0
  73. package/src/components/ui/combobox/ComboboxEmpty.vue +21 -0
  74. package/src/components/ui/combobox/ComboboxGroup.vue +26 -0
  75. package/src/components/ui/combobox/ComboboxInput.vue +28 -0
  76. package/src/components/ui/combobox/ComboboxItem.vue +39 -0
  77. package/src/components/ui/combobox/ComboboxList.vue +43 -0
  78. package/src/components/ui/combobox/ComboboxSelect.vue +162 -0
  79. package/src/components/ui/combobox/ComboboxSeparator.vue +16 -0
  80. package/src/components/ui/combobox/ComboboxTrigger.vue +28 -0
  81. package/src/components/ui/combobox/index.ts +11 -0
  82. package/src/components/ui/combobox/types.ts +16 -0
  83. package/src/components/ui/command/CommandDialog.vue +18 -16
  84. package/src/components/ui/command/CommandGroup.vue +1 -1
  85. package/src/components/ui/command/CommandInput.vue +2 -2
  86. package/src/components/ui/command/CommandItem.vue +7 -5
  87. package/src/components/ui/data-table/DataTable.vue +230 -0
  88. package/src/components/ui/data-table/index.ts +20 -0
  89. package/src/components/ui/date-picker/DatePicker.vue +11 -15
  90. package/src/components/ui/date-time-picker/DateTimePicker.vue +2 -7
  91. package/src/components/ui/dialog/DialogContent.vue +9 -4
  92. package/src/components/ui/dialog/DialogOverlay.vue +1 -1
  93. package/src/components/ui/dialog/DialogScrollContent.vue +10 -5
  94. package/src/components/ui/dropdown-menu/DropdownMenu.vue +18 -0
  95. package/src/components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue +34 -0
  96. package/src/components/ui/dropdown-menu/DropdownMenuContent.vue +39 -0
  97. package/src/components/ui/dropdown-menu/DropdownMenuGroup.vue +13 -0
  98. package/src/components/ui/dropdown-menu/DropdownMenuItem.vue +34 -0
  99. package/src/components/ui/dropdown-menu/DropdownMenuLabel.vue +26 -0
  100. package/src/components/ui/dropdown-menu/DropdownMenuPortal.vue +13 -0
  101. package/src/components/ui/dropdown-menu/DropdownMenuRadioGroup.vue +18 -0
  102. package/src/components/ui/dropdown-menu/DropdownMenuRadioItem.vue +32 -0
  103. package/src/components/ui/dropdown-menu/DropdownMenuSeparator.vue +16 -0
  104. package/src/components/ui/dropdown-menu/DropdownMenuShortcut.vue +15 -0
  105. package/src/components/ui/dropdown-menu/DropdownMenuSub.vue +18 -0
  106. package/src/components/ui/dropdown-menu/DropdownMenuSubContent.vue +39 -0
  107. package/src/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue +36 -0
  108. package/src/components/ui/dropdown-menu/DropdownMenuTrigger.vue +15 -0
  109. package/src/components/ui/dropdown-menu/classes.ts +24 -0
  110. package/src/components/ui/dropdown-menu/index.ts +15 -0
  111. package/src/components/ui/field/FieldDescription.vue +1 -1
  112. package/src/components/ui/field/FieldError.vue +4 -1
  113. package/src/components/ui/file-dropzone/FileDropzone.vue +250 -0
  114. package/src/components/ui/file-dropzone/index.ts +35 -0
  115. package/src/components/ui/hover-card/HoverCard.vue +21 -0
  116. package/src/components/ui/hover-card/HoverCardContent.vue +33 -0
  117. package/src/components/ui/hover-card/HoverCardTrigger.vue +13 -0
  118. package/src/components/ui/hover-card/index.ts +3 -0
  119. package/src/components/ui/input/Input.vue +5 -5
  120. package/src/components/ui/kbd/Kbd.vue +21 -0
  121. package/src/components/ui/kbd/KbdGroup.vue +72 -0
  122. package/src/components/ui/kbd/index.ts +2 -0
  123. package/src/components/ui/number-field/NumberField.vue +130 -0
  124. package/src/components/ui/number-field/index.ts +1 -0
  125. package/src/components/ui/pagination/Pagination.vue +27 -0
  126. package/src/components/ui/pagination/PaginationContent.vue +20 -0
  127. package/src/components/ui/pagination/PaginationEllipsis.vue +31 -0
  128. package/src/components/ui/pagination/PaginationFirst.vue +32 -0
  129. package/src/components/ui/pagination/PaginationItem.vue +41 -0
  130. package/src/components/ui/pagination/PaginationLast.vue +32 -0
  131. package/src/components/ui/pagination/PaginationNext.vue +32 -0
  132. package/src/components/ui/pagination/PaginationPrevious.vue +32 -0
  133. package/src/components/ui/pagination/SimplePagination.vue +49 -0
  134. package/src/components/ui/pagination/index.ts +9 -0
  135. package/src/components/ui/pin-input/PinInput.vue +48 -0
  136. package/src/components/ui/pin-input/PinInputInput.vue +49 -0
  137. package/src/components/ui/pin-input/context.ts +8 -0
  138. package/src/components/ui/pin-input/index.ts +2 -0
  139. package/src/components/ui/popover/PopoverContent.vue +1 -1
  140. package/src/components/ui/progress/Progress.vue +22 -7
  141. package/src/components/ui/radio-group/RadioGroup.vue +27 -0
  142. package/src/components/ui/radio-group/RadioGroupCard.vue +56 -0
  143. package/src/components/ui/radio-group/RadioGroupItem.vue +40 -0
  144. package/src/components/ui/radio-group/index.ts +3 -0
  145. package/src/components/ui/select/SelectContent.vue +1 -1
  146. package/src/components/ui/select/SelectItem.vue +2 -2
  147. package/src/components/ui/select/SelectItemContent.vue +1 -1
  148. package/src/components/ui/select/SelectTrigger.vue +6 -6
  149. package/src/components/ui/select/SelectValueContent.vue +1 -1
  150. package/src/components/ui/sheet/SheetContent.vue +5 -5
  151. package/src/components/ui/sheet/SheetOverlay.vue +1 -1
  152. package/src/components/ui/sidebar/Sidebar.vue +7 -5
  153. package/src/components/ui/sidebar/SidebarRail.vue +3 -1
  154. package/src/components/ui/sidebar/SidebarTrigger.vue +3 -1
  155. package/src/components/ui/skeleton/Skeleton.vue +4 -4
  156. package/src/components/ui/slider/Slider.vue +8 -6
  157. package/src/components/ui/spinner/Spinner.vue +47 -0
  158. package/src/components/ui/spinner/index.ts +1 -0
  159. package/src/components/ui/stepper/SimpleStepper.vue +56 -0
  160. package/src/components/ui/stepper/Stepper.vue +30 -0
  161. package/src/components/ui/stepper/StepperDescription.vue +20 -0
  162. package/src/components/ui/stepper/StepperIndicator.vue +41 -0
  163. package/src/components/ui/stepper/StepperItem.vue +21 -0
  164. package/src/components/ui/stepper/StepperSeparator.vue +34 -0
  165. package/src/components/ui/stepper/StepperTitle.vue +20 -0
  166. package/src/components/ui/stepper/StepperTrigger.vue +20 -0
  167. package/src/components/ui/stepper/index.ts +17 -0
  168. package/src/components/ui/switch/Switch.vue +8 -6
  169. package/src/components/ui/tabs/TabsContent.vue +1 -1
  170. package/src/components/ui/tabs/TabsList.vue +13 -5
  171. package/src/components/ui/tabs/TabsTrigger.vue +5 -3
  172. package/src/components/ui/tags-input/TagsInput.vue +49 -0
  173. package/src/components/ui/tags-input/TagsInputInput.vue +23 -0
  174. package/src/components/ui/tags-input/TagsInputItem.vue +35 -0
  175. package/src/components/ui/tags-input/TagsInputItemDelete.vue +31 -0
  176. package/src/components/ui/tags-input/TagsInputItemText.vue +21 -0
  177. package/src/components/ui/tags-input/index.ts +5 -0
  178. package/src/components/ui/textarea/Textarea.vue +4 -5
  179. package/src/components/ui/toggle-group/Toggle.vue +33 -0
  180. package/src/components/ui/toggle-group/ToggleGroup.vue +93 -0
  181. package/src/components/ui/toggle-group/ToggleGroupItem.vue +34 -0
  182. package/src/components/ui/toggle-group/index.ts +69 -0
  183. package/src/components/ui/tooltip/TooltipContent.vue +1 -1
  184. package/src/i18n/de.json +83 -0
  185. package/src/i18n/en.json +83 -0
  186. package/src/i18n/es.json +83 -0
  187. package/src/i18n/fr.json +83 -0
  188. package/src/i18n/it.json +83 -0
  189. package/src/i18n/ja.json +83 -0
  190. package/src/i18n/pt.json +83 -0
  191. package/src/i18n/ru.json +83 -0
  192. package/src/i18n/zh.json +83 -0
  193. package/src/lib/color-tokens.ts +14 -14
  194. package/src/styles.css +289 -5
package/COMPONENTS.md ADDED
@@ -0,0 +1,3643 @@
1
+ # UI Vintage component catalog
2
+
3
+ > Generated by `npm run docs:components` from the source of `@brumaombra/ui-vintage`. Do not edit by hand.
4
+
5
+ This file lists every public entry point of the package with its components, props, events, slots, and helpers. It ships inside the npm package, so it always matches the installed version: `node_modules/@brumaombra/ui-vintage/COMPONENTS.md`.
6
+
7
+ ## Ground rules
8
+
9
+ - Register the Nuxt module once in `nuxt.config`: `modules: ['@brumaombra/ui-vintage']`. It injects the stylesheet, installs `@nuxt/image`, and merges the library translations into vue-i18n.
10
+ - Import from explicit subpaths only (for example `@brumaombra/ui-vintage/button`). There is no root barrel, and `src/` paths are internal.
11
+ - Style with the semantic Tailwind tokens: `bg-background`, `bg-card`, `bg-surface`, `bg-accent`, `bg-primary`, `hover:bg-primary-hover`, `text-foreground`, `text-muted-foreground`, `border-border`, `border-border-strong`, `text-destructive`, `text-success`, `text-warning`, `text-info`. They switch automatically in dark mode, so do not add `dark:` color overrides.
12
+ - Reuse the motion utilities from the stylesheet instead of custom animations: `ease-spring`, `ease-bounce`, `ease-out-expo`, `ease-snappy`, `uv-floating-motion`, `uv-modal-motion`, `uv-overlay-motion`, `uv-collapsible-motion`, `uv-field`, `animate-uv-pop`, `animate-uv-fade-up`, `animate-uv-shake`, `animate-uv-shimmer`, `animate-uv-float`, `animate-uv-ping-soft`, and elevation via `shadow-elevated-sm|md|lg|xl` and `shadow-glow`. Tailwind v4 animates `scale`, `rotate`, and `translate` as separate properties, so name them (not `transform`) in custom transitions.
13
+ - Icons are Hugeicons definitions passed as values: `import { Rocket01Icon } from '@hugeicons/core-free-icons'` then `:icon="Rocket01Icon"`, or render one with `<HugeiconsIcon :icon="Rocket01Icon" />` from `@hugeicons/vue`.
14
+ - Every component accepts `class`, merged with `tailwind-merge`, so utility overrides win over the defaults.
15
+
16
+ ## Contents
17
+
18
+ - **Actions:** [button](#brumaombraui-vintagebutton), [dropdown-menu](#brumaombraui-vintagedropdown-menu), [kbd](#brumaombraui-vintagekbd), [load-more-button](#brumaombraui-vintageload-more-button), [text-link](#brumaombraui-vintagetext-link), [toggle-group](#brumaombraui-vintagetoggle-group)
19
+ - **Forms:** [calendar](#brumaombraui-vintagecalendar), [checkbox](#brumaombraui-vintagecheckbox), [combobox](#brumaombraui-vintagecombobox), [date-picker](#brumaombraui-vintagedate-picker), [date-time-picker](#brumaombraui-vintagedate-time-picker), [field](#brumaombraui-vintagefield), [file-dropzone](#brumaombraui-vintagefile-dropzone), [input](#brumaombraui-vintageinput), [label](#brumaombraui-vintagelabel), [native-select](#brumaombraui-vintagenative-select), [number-field](#brumaombraui-vintagenumber-field), [pin-input](#brumaombraui-vintagepin-input), [radio-group](#brumaombraui-vintageradio-group), [select](#brumaombraui-vintageselect), [slider](#brumaombraui-vintageslider), [slider-form-component](#brumaombraui-vintageslider-form-component), [switch](#brumaombraui-vintageswitch), [switch-form-component](#brumaombraui-vintageswitch-form-component), [tags-input](#brumaombraui-vintagetags-input), [textarea](#brumaombraui-vintagetextarea), [time-picker](#brumaombraui-vintagetime-picker)
20
+ - **Data display:** [animated-number](#brumaombraui-vintageanimated-number), [avatar](#brumaombraui-vintageavatar), [badge](#brumaombraui-vintagebadge), [card](#brumaombraui-vintagecard), [card-grid](#brumaombraui-vintagecard-grid), [chip](#brumaombraui-vintagechip), [data-list](#brumaombraui-vintagedata-list), [data-table](#brumaombraui-vintagedata-table), [info-card](#brumaombraui-vintageinfo-card), [progress](#brumaombraui-vintageprogress), [progress-component](#brumaombraui-vintageprogress-component), [scroll-area](#brumaombraui-vintagescroll-area), [separator](#brumaombraui-vintageseparator), [single-value-card](#brumaombraui-vintagesingle-value-card), [skeleton](#brumaombraui-vintageskeleton), [table](#brumaombraui-vintagetable)
21
+ - **Navigation:** [accordion](#brumaombraui-vintageaccordion), [breadcrumb](#brumaombraui-vintagebreadcrumb), [collapsible](#brumaombraui-vintagecollapsible), [pagination](#brumaombraui-vintagepagination), [sidebar](#brumaombraui-vintagesidebar), [stepper](#brumaombraui-vintagestepper), [tabs](#brumaombraui-vintagetabs)
22
+ - **Overlays:** [alert-dialog](#brumaombraui-vintagealert-dialog), [command](#brumaombraui-vintagecommand), [dialog](#brumaombraui-vintagedialog), [hover-card](#brumaombraui-vintagehover-card), [popover](#brumaombraui-vintagepopover), [sheet](#brumaombraui-vintagesheet), [tooltip](#brumaombraui-vintagetooltip)
23
+ - **Feedback:** [alert](#brumaombraui-vintagealert), [busy](#brumaombraui-vintagebusy), [busy-indicator](#brumaombraui-vintagebusy-indicator), [confirm-dialog](#brumaombraui-vintageconfirm-dialog), [cookie-consent](#brumaombraui-vintagecookie-consent), [empty-state-card](#brumaombraui-vintageempty-state-card), [loading-state-card](#brumaombraui-vintageloading-state-card), [message-dialog](#brumaombraui-vintagemessage-dialog), [message-toast](#brumaombraui-vintagemessage-toast), [spinner](#brumaombraui-vintagespinner)
24
+ - **Layouts and app shell:** [background-grid](#brumaombraui-vintagebackground-grid), [dashboard-shell](#brumaombraui-vintagedashboard-shell), [error-page](#brumaombraui-vintageerror-page), [landing](#brumaombraui-vintagelanding), [landing-content](#brumaombraui-vintagelanding-content), [landing-footer](#brumaombraui-vintagelanding-footer), [landing-navbar](#brumaombraui-vintagelanding-navbar), [landing-shell](#brumaombraui-vintagelanding-shell), [language-flag](#brumaombraui-vintagelanguage-flag), [language-selector](#brumaombraui-vintagelanguage-selector), [page-header](#brumaombraui-vintagepage-header), [theme-selector](#brumaombraui-vintagetheme-selector)
25
+ - **Content and blog:** [blog](#brumaombraui-vintageblog), [content](#brumaombraui-vintagecontent)
26
+ - **Utilities and types:** [common-types](#brumaombraui-vintagecommon-types), [utils](#brumaombraui-vintageutils)
27
+
28
+ ## Actions
29
+
30
+ Buttons, segmented controls, menus, and keyboard hints.
31
+
32
+ ### `@brumaombra/ui-vintage/button`
33
+
34
+ Button with solid, outline, ghost, link, and tone variants. Spring press feedback, a sheen on primary buttons, and a `loading` state that keeps the width stable. Use `as-child` to render a link.
35
+
36
+ ```ts
37
+ import { Button, buttonVariants } from '@brumaombra/ui-vintage/button';
38
+ import type { ButtonVariants } from '@brumaombra/ui-vintage/button';
39
+ ```
40
+
41
+ ```vue
42
+ <Button variant="secondary" size="sm" :loading="saving" @click="save">
43
+ <HugeiconsIcon :icon="SaveIcon" />
44
+ Save changes
45
+ </Button>
46
+
47
+ <Button as-child>
48
+ <NuxtLink to="/pricing">Pricing</NuxtLink>
49
+ </Button>
50
+ ```
51
+
52
+ #### `Button`
53
+
54
+ | Prop | Type | Default |
55
+ | --- | --- | --- |
56
+ | `variant` | `ButtonVariants['variant']` | |
57
+ | `size` | `ButtonVariants['size']` | |
58
+ | `loading` | `boolean` | `false` |
59
+ | `class` | `HTMLAttributes['class']` | |
60
+
61
+ - **Also accepts** all props of Reka `PrimitiveProps`.
62
+ - **Slots:** `default`.
63
+
64
+ #### Functions, constants, and types
65
+
66
+ ```ts
67
+ type ButtonVariants = { variant?: | 'primary' | 'secondary' | 'ghost' | 'link' | 'gray' | 'green' | 'red' | 'blue' | 'yellow' | null | undefined; size?: | 'default' | 'sm' | 'lg' | 'icon' | 'icon-sm' | 'icon-lg' | null | undefined }
68
+ const buttonVariants: (props?: ButtonVariants & ClassProp) => string
69
+ ```
70
+
71
+ ---
72
+
73
+ ### `@brumaombra/ui-vintage/dropdown-menu`
74
+
75
+ Menu of actions with items, checkbox and radio items, labels, shortcuts, destructive items, and submenus.
76
+
77
+ ```ts
78
+ import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger } from '@brumaombra/ui-vintage/dropdown-menu';
79
+ ```
80
+
81
+ ```vue
82
+ <DropdownMenu>
83
+ <DropdownMenuTrigger as-child>
84
+ <Button variant="secondary">Account</Button>
85
+ </DropdownMenuTrigger>
86
+ <DropdownMenuContent>
87
+ <DropdownMenuLabel>My account</DropdownMenuLabel>
88
+ <DropdownMenuItem @select="openProfile">Profile <DropdownMenuShortcut>⇧⌘P</DropdownMenuShortcut></DropdownMenuItem>
89
+ <DropdownMenuCheckboxItem v-model="showStatusBar">Status bar</DropdownMenuCheckboxItem>
90
+ <DropdownMenuSeparator />
91
+ <DropdownMenuItem variant="destructive" @select="logout">Log out</DropdownMenuItem>
92
+ </DropdownMenuContent>
93
+ </DropdownMenu>
94
+ ```
95
+
96
+ #### `DropdownMenu`
97
+
98
+ - **Also accepts** all props of Reka `DropdownMenuRootProps`.
99
+ - **Emits:** all events of Reka `DropdownMenuRootEmits`.
100
+ - **Slots:** `default`.
101
+
102
+ #### `DropdownMenuCheckboxItem`
103
+
104
+ - **Props:** `class`.
105
+ - **Also accepts** all props of Reka `DropdownMenuCheckboxItemProps`.
106
+ - **Emits:** all events of Reka `DropdownMenuCheckboxItemEmits`.
107
+ - **Slots:** `indicator-icon`, `default`.
108
+
109
+ #### `DropdownMenuContent`
110
+
111
+ - **Props:** `class`.
112
+ - **Also accepts** all props of Reka `DropdownMenuContentProps`.
113
+ - **Emits:** all events of Reka `DropdownMenuContentEmits`.
114
+ - **Slots:** `default`.
115
+
116
+ #### `DropdownMenuGroup`
117
+
118
+ - **Also accepts** all props of Reka `DropdownMenuGroupProps`.
119
+ - **Slots:** `default`.
120
+
121
+ #### `DropdownMenuItem`
122
+
123
+ | Prop | Type | Default |
124
+ | --- | --- | --- |
125
+ | `class` | `HTMLAttributes['class']` | |
126
+ | `inset` | `boolean` | |
127
+ | `variant` | `'default' \| 'destructive'` | `'default'` |
128
+
129
+ - **Also accepts** all props of Reka `DropdownMenuItemProps`.
130
+ - **Emits:** all events of Reka `DropdownMenuItemEmits`.
131
+ - **Slots:** `default`.
132
+
133
+ #### `DropdownMenuLabel`
134
+
135
+ | Prop | Type | Default |
136
+ | --- | --- | --- |
137
+ | `class` | `HTMLAttributes['class']` | |
138
+ | `inset` | `boolean` | |
139
+
140
+ - **Also accepts** all props of Reka `DropdownMenuLabelProps`.
141
+ - **Slots:** `default`.
142
+
143
+ #### `DropdownMenuPortal`
144
+
145
+ - **Also accepts** all props of Reka `DropdownMenuPortalProps`.
146
+ - **Slots:** `default`.
147
+
148
+ #### `DropdownMenuRadioGroup`
149
+
150
+ - **Also accepts** all props of Reka `DropdownMenuRadioGroupProps`.
151
+ - **Emits:** all events of Reka `DropdownMenuRadioGroupEmits`.
152
+ - **Slots:** `default`.
153
+
154
+ #### `DropdownMenuRadioItem`
155
+
156
+ - **Props:** `class`.
157
+ - **Also accepts** all props of Reka `DropdownMenuRadioItemProps`.
158
+ - **Emits:** all events of Reka `DropdownMenuRadioItemEmits`.
159
+ - **Slots:** `indicator-icon`, `default`.
160
+
161
+ #### `DropdownMenuSeparator`
162
+
163
+ - **Props:** `class`.
164
+ - **Also accepts** all props of Reka `DropdownMenuSeparatorProps`.
165
+
166
+ #### `DropdownMenuShortcut`
167
+
168
+ - **Props:** `class`.
169
+ - **Slots:** `default`.
170
+
171
+ #### `DropdownMenuSub`
172
+
173
+ - **Also accepts** all props of Reka `DropdownMenuSubProps`.
174
+ - **Emits:** all events of Reka `DropdownMenuSubEmits`.
175
+ - **Slots:** `default`.
176
+
177
+ #### `DropdownMenuSubContent`
178
+
179
+ - **Props:** `class`.
180
+ - **Also accepts** all props of Reka `DropdownMenuSubContentProps`.
181
+ - **Emits:** all events of Reka `DropdownMenuSubContentEmits`.
182
+ - **Slots:** `default`.
183
+
184
+ #### `DropdownMenuSubTrigger`
185
+
186
+ | Prop | Type | Default |
187
+ | --- | --- | --- |
188
+ | `class` | `HTMLAttributes['class']` | |
189
+ | `inset` | `boolean` | |
190
+
191
+ - **Also accepts** all props of Reka `DropdownMenuSubTriggerProps`.
192
+ - **Slots:** `default`.
193
+
194
+ #### `DropdownMenuTrigger`
195
+
196
+ - **Also accepts** all props of Reka `DropdownMenuTriggerProps`.
197
+ - **Slots:** `default`.
198
+
199
+ ---
200
+
201
+ ### `@brumaombra/ui-vintage/kbd`
202
+
203
+ Keycaps for keyboard shortcuts. In `KbdGroup`, `mod` renders ⌘ on macOS and Ctrl elsewhere.
204
+
205
+ ```ts
206
+ import { Kbd, KbdGroup } from '@brumaombra/ui-vintage/kbd';
207
+ ```
208
+
209
+ ```vue
210
+ <KbdGroup :keys="['mod', 'k']" />
211
+ <Kbd>Esc</Kbd>
212
+ ```
213
+
214
+ #### `Kbd`
215
+
216
+ | Prop | Type | Default |
217
+ | --- | --- | --- |
218
+ | `class` | `HTMLAttributes['class']` | |
219
+ | `pressed` | `boolean` | |
220
+
221
+ - **Slots:** `default`.
222
+
223
+ #### `KbdGroup`
224
+
225
+ | Prop | Type | Default |
226
+ | --- | --- | --- |
227
+ | `class` | `HTMLAttributes['class']` | |
228
+ | `keys` | `string[]` | |
229
+ | `pressed` | `boolean` | |
230
+
231
+ - **Slots:** `default`.
232
+
233
+ ---
234
+
235
+ ### `@brumaombra/ui-vintage/load-more-button`
236
+
237
+ Full-width "load more" button with a built-in busy state and localized labels.
238
+
239
+ ```ts
240
+ import { LoadMoreButton } from '@brumaombra/ui-vintage/load-more-button';
241
+ ```
242
+
243
+ #### `LoadMoreButton`
244
+
245
+ | Prop | Type | Default |
246
+ | --- | --- | --- |
247
+ | `busy` | `boolean` | `false` |
248
+ | `text` | `string` | `''` |
249
+ | `loadingText` | `string` | `''` |
250
+
251
+ - **Emits:** `load-more`.
252
+
253
+ ---
254
+
255
+ ### `@brumaombra/ui-vintage/text-link`
256
+
257
+ Inline text link that renders an anchor or a router link component (pass `NuxtLink` as `link-component`).
258
+
259
+ ```ts
260
+ import { TextLink } from '@brumaombra/ui-vintage/text-link';
261
+ ```
262
+
263
+ #### `TextLink`
264
+
265
+ | Prop | Type | Default |
266
+ | --- | --- | --- |
267
+ | `to` *(required)* | `string` | |
268
+ | `text` *(required)* | `string` | |
269
+ | `linkComponent` | `Component \| string` | `'a'` |
270
+
271
+ - **Emits:** `click` (event: MouseEvent).
272
+
273
+ ---
274
+
275
+ ### `@brumaombra/ui-vintage/toggle-group`
276
+
277
+ Segmented control (`type="single"`, with a sliding indicator) or multi-select toggle group, plus a standalone `Toggle`.
278
+
279
+ ```ts
280
+ import { Toggle, ToggleGroup, ToggleGroupItem, toggleVariants, toggleGroupItemVariants, toggleGroupContextKey } from '@brumaombra/ui-vintage/toggle-group';
281
+ import type { ToggleVariants, ToggleGroupSize } from '@brumaombra/ui-vintage/toggle-group';
282
+ ```
283
+
284
+ ```vue
285
+ <ToggleGroup v-model="view" type="single" highlight>
286
+ <ToggleGroupItem value="grid">Grid</ToggleGroupItem>
287
+ <ToggleGroupItem value="list">List</ToggleGroupItem>
288
+ </ToggleGroup>
289
+ ```
290
+
291
+ #### `Toggle`
292
+
293
+ | Prop | Type | Default |
294
+ | --- | --- | --- |
295
+ | `variant` | `ToggleVariants['variant']` | `'default'` |
296
+ | `size` | `ToggleVariants['size']` | `'default'` |
297
+ | `class` | `HTMLAttributes['class']` | |
298
+
299
+ - **Also accepts** all props of Reka `ToggleProps`.
300
+ - **Emits:** all events of Reka `ToggleEmits`.
301
+ - **Slots:** `default`.
302
+
303
+ #### `ToggleGroup`
304
+
305
+ | Prop | Type | Default |
306
+ | --- | --- | --- |
307
+ | `size` | `ToggleGroupSize` | `'default'` |
308
+ | `highlight` | `boolean` | `false` |
309
+ | `class` | `HTMLAttributes['class']` | |
310
+
311
+ - **Also accepts** all props of Reka `ToggleGroupRootProps`.
312
+ - **Emits:** all events of Reka `ToggleGroupRootEmits`.
313
+ - **Slots:** `default`.
314
+
315
+ #### `ToggleGroupItem`
316
+
317
+ | Prop | Type | Default |
318
+ | --- | --- | --- |
319
+ | `size` | `ToggleGroupSize` | |
320
+ | `class` | `HTMLAttributes['class']` | |
321
+
322
+ - **Also accepts** all props of Reka `ToggleGroupItemProps`.
323
+ - **Slots:** `default`.
324
+
325
+ #### Functions, constants, and types
326
+
327
+ ```ts
328
+ type ToggleVariants = { variant?: 'default' | 'outline' | null | undefined; size?: 'default' | 'sm' | 'lg' | null | undefined }
329
+ type ToggleGroupSize = 'default' | 'sm' | 'lg'
330
+ const toggleVariants: (props?: ToggleVariants & ClassProp) => string
331
+ const toggleGroupItemVariants: (props?: { size?: ToggleGroupSize | null } & ClassProp) => string
332
+ const toggleGroupContextKey: InjectionKey<{ size: Ref<ToggleGroupSize>; indicator: Ref<boolean> }>
333
+ ```
334
+
335
+ ## Forms
336
+
337
+ Inputs, pickers, and form layout. Text-like controls share the `uv-field` focus glow and shake on `aria-invalid`.
338
+
339
+ ### `@brumaombra/ui-vintage/calendar`
340
+
341
+ Month calendar (Reka) working with `@internationalized/date` values. Usually used through `DatePicker`.
342
+
343
+ ```ts
344
+ import { Calendar, CalendarCell, CalendarCellTrigger, CalendarGrid, CalendarGridBody, CalendarGridHead, CalendarGridRow, CalendarHeadCell, CalendarHeader, CalendarHeading, CalendarNextButton, CalendarPrevButton } from '@brumaombra/ui-vintage/calendar';
345
+ import type { LayoutTypes } from '@brumaombra/ui-vintage/calendar';
346
+ ```
347
+
348
+ #### `Calendar`
349
+
350
+ | Prop | Type | Default |
351
+ | --- | --- | --- |
352
+ | `class` | `HTMLAttributes['class']` | |
353
+ | `layout` | `LayoutTypes` | `undefined` |
354
+ | `yearRange` | `DateValue[]` | |
355
+
356
+ - **Also accepts** all props of Reka `CalendarRootProps`.
357
+ - **Emits:** all events of Reka `CalendarRootEmits`.
358
+ - **Slots:** `calendar-prev-icon`, `calendar-next-icon`, `calendar-heading`.
359
+
360
+ #### `CalendarCell`
361
+
362
+ - **Props:** `class`.
363
+ - **Also accepts** all props of Reka `CalendarCellProps`.
364
+ - **Slots:** `default`.
365
+
366
+ #### `CalendarCellTrigger`
367
+
368
+ - **Props:** `class`.
369
+ - **Also accepts** all props of Reka `CalendarCellTriggerProps`.
370
+ - **Slots:** `default`.
371
+
372
+ #### `CalendarGrid`
373
+
374
+ - **Props:** `class`.
375
+ - **Also accepts** all props of Reka `CalendarGridProps`.
376
+ - **Slots:** `default`.
377
+
378
+ #### `CalendarGridBody`
379
+
380
+ - **Also accepts** all props of Reka `CalendarGridBodyProps`.
381
+ - **Slots:** `default`.
382
+
383
+ #### `CalendarGridHead`
384
+
385
+ - **Props:** `class`.
386
+ - **Also accepts** all props of Reka `CalendarGridHeadProps`.
387
+ - **Slots:** `default`.
388
+
389
+ #### `CalendarGridRow`
390
+
391
+ - **Props:** `class`.
392
+ - **Also accepts** all props of Reka `CalendarGridRowProps`.
393
+ - **Slots:** `default`.
394
+
395
+ #### `CalendarHeadCell`
396
+
397
+ - **Props:** `class`.
398
+ - **Also accepts** all props of Reka `CalendarHeadCellProps`.
399
+ - **Slots:** `default`.
400
+
401
+ #### `CalendarHeader`
402
+
403
+ - **Props:** `class`.
404
+ - **Also accepts** all props of Reka `CalendarHeaderProps`.
405
+ - **Slots:** `default`.
406
+
407
+ #### `CalendarHeading`
408
+
409
+ - **Props:** `class`.
410
+ - **Also accepts** all props of Reka `CalendarHeadingProps`.
411
+ - **Slots:** `default`.
412
+
413
+ #### `CalendarNextButton`
414
+
415
+ - **Props:** `class`.
416
+ - **Also accepts** all props of Reka `CalendarNextProps`.
417
+ - **Slots:** `default`.
418
+
419
+ #### `CalendarPrevButton`
420
+
421
+ - **Props:** `class`.
422
+ - **Also accepts** all props of Reka `CalendarPrevProps`.
423
+ - **Slots:** `default`.
424
+
425
+ #### Functions, constants, and types
426
+
427
+ ```ts
428
+ type LayoutTypes = | 'month-and-year' | 'month-only' | 'year-only' | undefined
429
+ ```
430
+
431
+ ---
432
+
433
+ ### `@brumaombra/ui-vintage/checkbox`
434
+
435
+ Checkbox with a self-drawing check mark. `v-model` accepts `true`, `false`, or `'indeterminate'`.
436
+
437
+ ```ts
438
+ import { Checkbox } from '@brumaombra/ui-vintage/checkbox';
439
+ ```
440
+
441
+ ```vue
442
+ <Checkbox id="terms" v-model="accepted" />
443
+ <Label for="terms">I accept the terms</Label>
444
+ ```
445
+
446
+ #### `Checkbox`
447
+
448
+ - **Props:** `class`.
449
+ - **Also accepts** all props of Reka `CheckboxRootProps`.
450
+ - **Emits:** all events of Reka `CheckboxRootEmits`.
451
+ - **Slots:** `default`.
452
+
453
+ ---
454
+
455
+ ### `@brumaombra/ui-vintage/combobox`
456
+
457
+ Searchable select. Use `ComboboxSelect` for the common case (single or `multiple`, rich options); the other parts compose custom comboboxes.
458
+
459
+ ```ts
460
+ import { Combobox, ComboboxAnchor, ComboboxEmpty, ComboboxGroup, ComboboxInput, ComboboxItem, ComboboxList, ComboboxSelect, ComboboxSeparator, ComboboxTrigger } from '@brumaombra/ui-vintage/combobox';
461
+ import type { ComboboxSelectModelValue, ComboboxSelectOption, ComboboxSelectValue } from '@brumaombra/ui-vintage/combobox';
462
+ ```
463
+
464
+ ```vue
465
+ <ComboboxSelect v-model="framework" :options="[{ value: 'nuxt', label: 'Nuxt', description: 'The Vue framework' }]" placeholder="Search frameworks" />
466
+ <ComboboxSelect v-model="stack" :options="options" multiple placeholder="Pick your stack" />
467
+ ```
468
+
469
+ #### `Combobox`
470
+
471
+ - **Props:** `class`.
472
+ - **Also accepts** all props of Reka `ComboboxRootProps`.
473
+ - **Emits:** all events of Reka `ComboboxRootEmits`.
474
+ - **Slots:** `default`.
475
+
476
+ #### `ComboboxAnchor`
477
+
478
+ | Prop | Type | Default |
479
+ | --- | --- | --- |
480
+ | `class` | `HTMLAttributes['class']` | |
481
+ | `size` | `'sm' \| 'default'` | `'default'` |
482
+
483
+ - **Also accepts** all props of Reka `ComboboxAnchorProps`.
484
+ - **Slots:** `default`.
485
+
486
+ #### `ComboboxEmpty`
487
+
488
+ - **Props:** `class`.
489
+ - **Also accepts** all props of Reka `ComboboxEmptyProps`.
490
+ - **Slots:** `default`.
491
+
492
+ #### `ComboboxGroup`
493
+
494
+ | Prop | Type | Default |
495
+ | --- | --- | --- |
496
+ | `class` | `HTMLAttributes['class']` | |
497
+ | `heading` | `string` | |
498
+
499
+ - **Also accepts** all props of Reka `ComboboxGroupProps`.
500
+ - **Slots:** `heading`, `default`.
501
+
502
+ #### `ComboboxInput`
503
+
504
+ - **Props:** `class`.
505
+ - **Also accepts** all props of Reka `ComboboxInputProps`.
506
+ - **Emits:** all events of Reka `ComboboxInputEmits`.
507
+
508
+ #### `ComboboxItem`
509
+
510
+ - **Props:** `class`.
511
+ - **Also accepts** all props of Reka `ComboboxItemProps`.
512
+ - **Emits:** all events of Reka `ComboboxItemEmits`.
513
+ - **Slots:** `default`, `indicator-icon`.
514
+
515
+ #### `ComboboxList`
516
+
517
+ | Prop | Type | Default |
518
+ | --- | --- | --- |
519
+ | `class` | `HTMLAttributes['class']` | |
520
+ | `viewportClass` | `HTMLAttributes['class']` | |
521
+
522
+ - **Also accepts** all props of Reka `ComboboxContentProps`.
523
+ - **Emits:** all events of Reka `ComboboxContentEmits`.
524
+ - **Slots:** `default`.
525
+
526
+ #### `ComboboxSelect`
527
+
528
+ | Prop | Type | Default |
529
+ | --- | --- | --- |
530
+ | `modelValue` | `ComboboxSelectModelValue` | `undefined` |
531
+ | `options` *(required)* | `ComboboxSelectOption[]` | |
532
+ | `placeholder` | `string` | |
533
+ | `searchPlaceholder` | `string` | |
534
+ | `emptyText` | `string` | |
535
+ | `multiple` | `boolean` | `false` |
536
+ | `disabled` | `boolean` | `false` |
537
+ | `size` | `'sm' \| 'default'` | `'default'` |
538
+ | `class` | `HTMLAttributes['class']` | |
539
+ | `contentClass` | `HTMLAttributes['class']` | |
540
+
541
+ - **Emits:** `update:modelValue` (value: ComboboxSelectModelValue).
542
+
543
+ #### `ComboboxSeparator`
544
+
545
+ - **Props:** `class`.
546
+ - **Also accepts** all props of Reka `ComboboxSeparatorProps`.
547
+
548
+ #### `ComboboxTrigger`
549
+
550
+ - **Props:** `class`.
551
+ - **Also accepts** all props of Reka `ComboboxTriggerProps`.
552
+ - **Slots:** `default`.
553
+
554
+ #### Functions, constants, and types
555
+
556
+ ```ts
557
+ type ComboboxSelectModelValue = ComboboxSelectValue | ComboboxSelectValue[] | null | undefined
558
+ interface ComboboxSelectOption {
559
+ value: ComboboxSelectValue;
560
+ label: string;
561
+ description?: string;
562
+ icon?: HugeiconsIconDefinition;
563
+ disabled?: boolean;
564
+ }
565
+ type ComboboxSelectValue = string | number
566
+ ```
567
+
568
+ ---
569
+
570
+ ### `@brumaombra/ui-vintage/date-picker`
571
+
572
+ Date picker button with a calendar popover. `v-model` is a `DateValue` from `@internationalized/date`; labels follow the vue-i18n locale.
573
+
574
+ ```ts
575
+ import { DatePicker } from '@brumaombra/ui-vintage/date-picker';
576
+ ```
577
+
578
+ #### `DatePicker`
579
+
580
+ | Prop | Type | Default |
581
+ | --- | --- | --- |
582
+ | `defaultValue` | `DateValue` | |
583
+ | `modelValue` | `DateValue` | |
584
+ | `minValue` | `DateValue` | |
585
+ | `maxValue` | `DateValue` | |
586
+ | `placeholder` | `string` | |
587
+ | `disabled` | `boolean` | `false` |
588
+ | `class` | `HTMLAttributes['class']` | |
589
+ | `contentClass` | `HTMLAttributes['class']` | |
590
+
591
+ - **Emits:** `update:modelValue` (payload: DateValue \| undefined).
592
+
593
+ ---
594
+
595
+ ### `@brumaombra/ui-vintage/date-time-picker`
596
+
597
+ Date and time picker pair. `v-model` is a JavaScript `Date` or `null`.
598
+
599
+ ```ts
600
+ import { DateTimePicker } from '@brumaombra/ui-vintage/date-time-picker';
601
+ ```
602
+
603
+ #### `DateTimePicker`
604
+
605
+ | Prop | Type | Default |
606
+ | --- | --- | --- |
607
+ | `defaultValue` | `Date \| null` | `null` |
608
+ | `modelValue` | `Date \| null` | |
609
+ | `minDate` | `Date \| null` | `null` |
610
+ | `maxDate` | `Date \| null` | `null` |
611
+ | `step` | `string \| number` | `60` |
612
+ | `disabled` | `boolean` | `false` |
613
+ | `datePlaceholder` | `string` | |
614
+ | `class` | `HTMLAttributes['class']` | |
615
+ | `datePickerClass` | `HTMLAttributes['class']` | |
616
+ | `timePickerClass` | `HTMLAttributes['class']` | |
617
+ | `datePickerContentClass` | `HTMLAttributes['class']` | |
618
+
619
+ - **Emits:** `update:modelValue` (payload: Date \| null).
620
+
621
+ ---
622
+
623
+ ### `@brumaombra/ui-vintage/field`
624
+
625
+ Form layout primitives: label, description, error list, groups, and fieldsets. `FieldError` accepts strings or `{ message }` objects and hides itself when empty.
626
+
627
+ ```ts
628
+ import { fieldVariants, Field, FieldContent, FieldDescription, FieldError, FieldGroup, FieldLabel, FieldLegend, FieldSeparator, FieldSet, FieldTitle } from '@brumaombra/ui-vintage/field';
629
+ import type { FieldVariants } from '@brumaombra/ui-vintage/field';
630
+ ```
631
+
632
+ ```vue
633
+ <Field>
634
+ <FieldLabel for="email">Email</FieldLabel>
635
+ <FieldContent>
636
+ <Input id="email" v-model="email" :aria-invalid="!!emailError || undefined" />
637
+ <FieldError :errors="[emailError]" />
638
+ <FieldDescription>We will send the invite here.</FieldDescription>
639
+ </FieldContent>
640
+ </Field>
641
+ ```
642
+
643
+ #### `Field`
644
+
645
+ | Prop | Type | Default |
646
+ | --- | --- | --- |
647
+ | `class` | `HTMLAttributes['class']` | |
648
+ | `orientation` | `FieldVariants['orientation']` | |
649
+
650
+ - **Slots:** `default`.
651
+
652
+ #### `FieldContent`
653
+
654
+ - **Props:** `class`.
655
+ - **Slots:** `default`.
656
+
657
+ #### `FieldDescription`
658
+
659
+ - **Props:** `class`.
660
+ - **Slots:** `default`.
661
+
662
+ #### `FieldError`
663
+
664
+ | Prop | Type | Default |
665
+ | --- | --- | --- |
666
+ | `class` | `HTMLAttributes['class']` | |
667
+ | `errors` | `Array<string \| { message: string \| undefined } \| undefined>` | |
668
+
669
+ - **Slots:** `default`.
670
+
671
+ #### `FieldGroup`
672
+
673
+ - **Props:** `class`.
674
+ - **Slots:** `default`.
675
+
676
+ #### `FieldLabel`
677
+
678
+ - **Props:** `class`.
679
+ - **Slots:** `default`.
680
+
681
+ #### `FieldLegend`
682
+
683
+ | Prop | Type | Default |
684
+ | --- | --- | --- |
685
+ | `class` | `HTMLAttributes['class']` | |
686
+ | `variant` | `'legend' \| 'label'` | |
687
+
688
+ - **Slots:** `default`.
689
+
690
+ #### `FieldSeparator`
691
+
692
+ - **Props:** `class`.
693
+ - **Slots:** `default`.
694
+
695
+ #### `FieldSet`
696
+
697
+ - **Props:** `class`.
698
+ - **Slots:** `default`.
699
+
700
+ #### `FieldTitle`
701
+
702
+ - **Props:** `class`.
703
+ - **Slots:** `default`.
704
+
705
+ #### Functions, constants, and types
706
+
707
+ ```ts
708
+ type FieldVariants = { orientation?: 'vertical' | 'horizontal' | 'responsive' | null | undefined }
709
+ const fieldVariants: (props?: FieldVariants & ClassProp) => string
710
+ ```
711
+
712
+ ---
713
+
714
+ ### `@brumaombra/ui-vintage/file-dropzone`
715
+
716
+ Drag-and-drop file picker with type, size, and count limits, a rejection event, and an animated file list. `v-model` is a `File[]`.
717
+
718
+ ```ts
719
+ import { FileDropzone, formatFileSize, isFileAccepted } from '@brumaombra/ui-vintage/file-dropzone';
720
+ import type { FileRejectionReason, FileRejection } from '@brumaombra/ui-vintage/file-dropzone';
721
+ ```
722
+
723
+ ```vue
724
+ <FileDropzone v-model="files" accept="image/*,.pdf" :max-size="5 * 1024 * 1024" :max-files="4" @reject="onReject" />
725
+ ```
726
+
727
+ #### `FileDropzone`
728
+
729
+ | Prop | Type | Default |
730
+ | --- | --- | --- |
731
+ | `accept` | `string` | |
732
+ | `multiple` | `boolean` | `true` |
733
+ | `maxSize` | `number` | |
734
+ | `maxFiles` | `number` | |
735
+ | `disabled` | `boolean` | `false` |
736
+ | `title` | `string` | |
737
+ | `description` | `string` | |
738
+ | `class` | `HTMLAttributes['class']` | |
739
+
740
+ - **Emits:** `reject` (rejections: FileRejection[]).
741
+
742
+ #### Functions, constants, and types
743
+
744
+ ```ts
745
+ type FileRejectionReason = 'type' | 'size' | 'count'
746
+ type FileRejection = { file: File; reason: FileRejectionReason }
747
+ function formatFileSize(bytes: number): string
748
+ function isFileAccepted(file: File, accept: string | undefined): boolean
749
+ ```
750
+
751
+ ---
752
+
753
+ ### `@brumaombra/ui-vintage/input`
754
+
755
+ Text input with `v-model`. Set `aria-invalid` to show the error state.
756
+
757
+ ```ts
758
+ import { Input } from '@brumaombra/ui-vintage/input';
759
+ ```
760
+
761
+ #### `Input`
762
+
763
+ | Prop | Type | Default |
764
+ | --- | --- | --- |
765
+ | `defaultValue` | `string \| number` | |
766
+ | `modelValue` | `string \| number` | |
767
+ | `class` | `HTMLAttributes['class']` | |
768
+
769
+ - **Emits:** `update:modelValue` (payload: string \| number).
770
+
771
+ ---
772
+
773
+ ### `@brumaombra/ui-vintage/label`
774
+
775
+ Accessible form label (Reka `Label`).
776
+
777
+ ```ts
778
+ import { Label } from '@brumaombra/ui-vintage/label';
779
+ ```
780
+
781
+ #### `Label`
782
+
783
+ - **Props:** `class`.
784
+ - **Also accepts** all props of Reka `LabelProps`.
785
+ - **Slots:** `default`.
786
+
787
+ ---
788
+
789
+ ### `@brumaombra/ui-vintage/native-select`
790
+
791
+ Native `<select>` with the library styling, for simple or mobile-first forms.
792
+
793
+ ```ts
794
+ import { NativeSelect, NativeSelectOptGroup, NativeSelectOption } from '@brumaombra/ui-vintage/native-select';
795
+ ```
796
+
797
+ #### `NativeSelect`
798
+
799
+ | Prop | Type | Default |
800
+ | --- | --- | --- |
801
+ | `modelValue` | `AcceptableValue \| AcceptableValue[]` | |
802
+ | `class` | `HTMLAttributes['class']` | |
803
+
804
+ - **Emits:** `update:modelValue` (AcceptableValue).
805
+ - **Slots:** `default`.
806
+
807
+ #### `NativeSelectOptGroup`
808
+
809
+ - **Props:** `class`.
810
+ - **Slots:** `default`.
811
+
812
+ #### `NativeSelectOption`
813
+
814
+ - **Props:** `class`.
815
+ - **Slots:** `default`.
816
+
817
+ ---
818
+
819
+ ### `@brumaombra/ui-vintage/number-field`
820
+
821
+ Numeric input with increment and decrement buttons, bounds, and `Intl` formatting (`format-options`).
822
+
823
+ ```ts
824
+ import { NumberField } from '@brumaombra/ui-vintage/number-field';
825
+ ```
826
+
827
+ ```vue
828
+ <NumberField v-model="seats" :min="1" :max="50" />
829
+ <NumberField v-model="price" :step="0.1" :format-options="{ style: 'currency', currency: 'EUR' }" />
830
+ ```
831
+
832
+ #### `NumberField`
833
+
834
+ | Prop | Type | Default |
835
+ | --- | --- | --- |
836
+ | `placeholder` | `string` | |
837
+ | `decrementLabel` | `string` | |
838
+ | `incrementLabel` | `string` | |
839
+ | `class` | `HTMLAttributes['class']` | |
840
+ | `inputClass` | `HTMLAttributes['class']` | |
841
+
842
+ - **Also accepts** all props of Reka `NumberFieldRootProps`.
843
+ - **Emits:** all events of Reka `NumberFieldRootEmits`.
844
+ - **Slots:** `decrement-icon`, `increment-icon`, `default`.
845
+
846
+ ---
847
+
848
+ ### `@brumaombra/ui-vintage/pin-input`
849
+
850
+ One-time code input. Pass `length` to render the cells automatically; `v-model` is an array of characters.
851
+
852
+ ```ts
853
+ import { PinInput, PinInputInput } from '@brumaombra/ui-vintage/pin-input';
854
+ ```
855
+
856
+ ```vue
857
+ <PinInput v-model="code" :length="6" otp type="number" :separator-after="2" :invalid="codeInvalid" @complete="verify" />
858
+ ```
859
+
860
+ #### `PinInput`
861
+
862
+ | Prop | Type | Default |
863
+ | --- | --- | --- |
864
+ | `length` | `number` | |
865
+ | `invalid` | `boolean` | |
866
+ | `separatorAfter` | `number` | |
867
+ | `class` | `HTMLAttributes['class']` | |
868
+ | `inputClass` | `HTMLAttributes['class']` | |
869
+
870
+ - **Also accepts** all props of Reka `PinInputRootProps`.
871
+ - **Emits:** all events of Reka `PinInputRootEmits`.
872
+ - **Slots:** `default`.
873
+
874
+ #### `PinInputInput`
875
+
876
+ - **Props:** `class`.
877
+ - **Also accepts** all props of Reka `PinInputInputProps`.
878
+
879
+ ---
880
+
881
+ ### `@brumaombra/ui-vintage/radio-group`
882
+
883
+ Radio group with plain items or selectable `RadioGroupCard` rows (icon, label, description).
884
+
885
+ ```ts
886
+ import { RadioGroup, RadioGroupItem, RadioGroupCard } from '@brumaombra/ui-vintage/radio-group';
887
+ ```
888
+
889
+ ```vue
890
+ <RadioGroup v-model="plan">
891
+ <RadioGroupCard value="pro" label="Pro" description="Unlimited projects" :icon="Rocket01Icon" />
892
+ <RadioGroupCard value="team" label="Team" description="SSO and audit logs" />
893
+ </RadioGroup>
894
+ ```
895
+
896
+ #### `RadioGroup`
897
+
898
+ - **Props:** `class`.
899
+ - **Also accepts** all props of Reka `RadioGroupRootProps`.
900
+ - **Emits:** all events of Reka `RadioGroupRootEmits`.
901
+ - **Slots:** `default`.
902
+
903
+ #### `RadioGroupItem`
904
+
905
+ - **Props:** `class`.
906
+ - **Also accepts** all props of Reka `RadioGroupItemProps`.
907
+ - **Emits:** all events of Reka `RadioGroupItemEmits`.
908
+ - **Slots:** `default`.
909
+
910
+ #### `RadioGroupCard`
911
+
912
+ | Prop | Type | Default |
913
+ | --- | --- | --- |
914
+ | `value` *(required)* | `AcceptableValue` | |
915
+ | `label` *(required)* | `string` | |
916
+ | `description` | `string` | |
917
+ | `icon` | `HugeiconsIconDefinition` | |
918
+ | `disabled` | `boolean` | |
919
+ | `id` | `string` | |
920
+ | `class` | `HTMLAttributes['class']` | |
921
+
922
+ - **Slots:** `label`, `description`.
923
+
924
+ ---
925
+
926
+ ### `@brumaombra/ui-vintage/select`
927
+
928
+ Styled Reka select. `SelectValueContent` and `SelectItemContent` render an icon, label, and description.
929
+
930
+ ```ts
931
+ import { Select, SelectContent, SelectGroup, SelectItem, SelectItemContent, SelectItemText, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, SelectValueContent } from '@brumaombra/ui-vintage/select';
932
+ ```
933
+
934
+ ```vue
935
+ <Select v-model="region">
936
+ <SelectTrigger class="w-full">
937
+ <SelectValueContent placeholder="Choose a region" :label="selectedRegion?.label" />
938
+ </SelectTrigger>
939
+ <SelectContent>
940
+ <SelectItem v-for="option in regions" :key="option.value" :value="option.value" :text-value="option.label">
941
+ <SelectItemContent :icon="option.icon" :label="option.label" :description="option.description" />
942
+ </SelectItem>
943
+ </SelectContent>
944
+ </Select>
945
+ ```
946
+
947
+ #### `Select`
948
+
949
+ - **Also accepts** all props of Reka `SelectRootProps`.
950
+ - **Emits:** all events of Reka `SelectRootEmits`.
951
+ - **Slots:** `default`.
952
+
953
+ #### `SelectContent`
954
+
955
+ - **Props:** `class`.
956
+ - **Also accepts** all props of Reka `SelectContentProps`.
957
+ - **Emits:** all events of Reka `SelectContentEmits`.
958
+ - **Slots:** `default`.
959
+
960
+ #### `SelectGroup`
961
+
962
+ - **Also accepts** all props of Reka `SelectGroupProps`.
963
+ - **Slots:** `default`.
964
+
965
+ #### `SelectItem`
966
+
967
+ - **Props:** `class`.
968
+ - **Also accepts** all props of Reka `SelectItemProps`.
969
+ - **Slots:** `indicator-icon`, `default`.
970
+
971
+ #### `SelectItemContent`
972
+
973
+ | Prop | Type | Default |
974
+ | --- | --- | --- |
975
+ | `class` | `HTMLAttributes['class']` | |
976
+ | `icon` | `HugeiconsIconDefinition \| null` | |
977
+ | `label` | `string \| number \| null` | |
978
+ | `description` | `string \| number \| null` | |
979
+ | `iconClass` | `HTMLAttributes['class']` | |
980
+ | `textClass` | `HTMLAttributes['class']` | |
981
+ | `descriptionClass` | `HTMLAttributes['class']` | |
982
+
983
+ #### `SelectItemText`
984
+
985
+ - **Also accepts** all props of Reka `SelectItemTextProps`.
986
+ - **Slots:** `default`.
987
+
988
+ #### `SelectLabel`
989
+
990
+ - **Props:** `class`.
991
+ - **Also accepts** all props of Reka `SelectLabelProps`.
992
+ - **Slots:** `default`.
993
+
994
+ #### `SelectScrollDownButton`
995
+
996
+ - **Props:** `class`.
997
+ - **Also accepts** all props of Reka `SelectScrollDownButtonProps`.
998
+ - **Slots:** `default`.
999
+
1000
+ #### `SelectScrollUpButton`
1001
+
1002
+ - **Props:** `class`.
1003
+ - **Also accepts** all props of Reka `SelectScrollUpButtonProps`.
1004
+ - **Slots:** `default`.
1005
+
1006
+ #### `SelectSeparator`
1007
+
1008
+ - **Props:** `class`.
1009
+ - **Also accepts** all props of Reka `SelectSeparatorProps`.
1010
+
1011
+ #### `SelectTrigger`
1012
+
1013
+ | Prop | Type | Default |
1014
+ | --- | --- | --- |
1015
+ | `class` | `HTMLAttributes['class']` | |
1016
+ | `size` | `'sm' \| 'default'` | `'default'` |
1017
+
1018
+ - **Also accepts** all props of Reka `SelectTriggerProps`.
1019
+ - **Slots:** `default`.
1020
+
1021
+ #### `SelectValue`
1022
+
1023
+ - **Also accepts** all props of Reka `SelectValueProps`.
1024
+ - **Slots:** `default`.
1025
+
1026
+ #### `SelectValueContent`
1027
+
1028
+ | Prop | Type | Default |
1029
+ | --- | --- | --- |
1030
+ | `class` | `HTMLAttributes['class']` | |
1031
+ | `icon` | `HugeiconsIconDefinition \| null` | |
1032
+ | `label` | `string \| number \| null` | |
1033
+ | `description` | `string \| number \| null` | |
1034
+ | `iconClass` | `HTMLAttributes['class']` | |
1035
+ | `textClass` | `HTMLAttributes['class']` | |
1036
+ | `descriptionClass` | `HTMLAttributes['class']` | |
1037
+
1038
+ - **Also accepts** all props of Reka `SelectValueProps`.
1039
+
1040
+ ---
1041
+
1042
+ ### `@brumaombra/ui-vintage/slider`
1043
+
1044
+ Range slider. `v-model` is an array, one value per thumb (`[50]` or `[20, 80]`).
1045
+
1046
+ ```ts
1047
+ import { Slider } from '@brumaombra/ui-vintage/slider';
1048
+ ```
1049
+
1050
+ #### `Slider`
1051
+
1052
+ - **Props:** `class`.
1053
+ - **Also accepts** all props of Reka `SliderRootProps`.
1054
+ - **Emits:** all events of Reka `SliderRootEmits`.
1055
+
1056
+ ---
1057
+
1058
+ ### `@brumaombra/ui-vintage/slider-form-component`
1059
+
1060
+ Card with a label, description, value badge, and single-value slider (`v-model` is a number).
1061
+
1062
+ ```ts
1063
+ import { SliderFormComponent } from '@brumaombra/ui-vintage/slider-form-component';
1064
+ ```
1065
+
1066
+ #### `SliderFormComponent`
1067
+
1068
+ | Prop | Type | Default |
1069
+ | --- | --- | --- |
1070
+ | `id` | `string` | `undefined` |
1071
+ | `label` *(required)* | `string` | |
1072
+ | `description` | `string` | `''` |
1073
+ | `modelValue` *(required)* | `number` | |
1074
+ | `min` | `number` | `0` |
1075
+ | `max` | `number` | `100` |
1076
+ | `step` | `number` | `1` |
1077
+ | `valueText` | `string` | `''` |
1078
+
1079
+ - **Emits:** `update:modelValue` (value: number).
1080
+
1081
+ ---
1082
+
1083
+ ### `@brumaombra/ui-vintage/switch`
1084
+
1085
+ On/off switch with `v-model` (boolean).
1086
+
1087
+ ```ts
1088
+ import { Switch } from '@brumaombra/ui-vintage/switch';
1089
+ ```
1090
+
1091
+ #### `Switch`
1092
+
1093
+ - **Props:** `class`.
1094
+ - **Also accepts** all props of Reka `SwitchRootProps`.
1095
+ - **Emits:** all events of Reka `SwitchRootEmits`.
1096
+ - **Slots:** `thumb`.
1097
+
1098
+ ---
1099
+
1100
+ ### `@brumaombra/ui-vintage/switch-form-component`
1101
+
1102
+ Card row with a label, description, and switch, for settings pages.
1103
+
1104
+ ```ts
1105
+ import { SwitchFormComponent } from '@brumaombra/ui-vintage/switch-form-component';
1106
+ ```
1107
+
1108
+ #### `SwitchFormComponent`
1109
+
1110
+ | Prop | Type | Default |
1111
+ | --- | --- | --- |
1112
+ | `id` *(required)* | `string` | |
1113
+ | `label` *(required)* | `string` | |
1114
+ | `description` *(required)* | `string` | |
1115
+ | `modelValue` *(required)* | `boolean` | |
1116
+
1117
+ - **Emits:** `update:modelValue` (value: boolean).
1118
+
1119
+ ---
1120
+
1121
+ ### `@brumaombra/ui-vintage/tags-input`
1122
+
1123
+ Free-text tags input. Without a default slot it renders the tags from `v-model` and an input automatically.
1124
+
1125
+ ```ts
1126
+ import { TagsInput, TagsInputItem, TagsInputItemText, TagsInputItemDelete, TagsInputInput } from '@brumaombra/ui-vintage/tags-input';
1127
+ ```
1128
+
1129
+ ```vue
1130
+ <TagsInput v-model="skills" placeholder="Add a skill..." />
1131
+ ```
1132
+
1133
+ #### `TagsInput`
1134
+
1135
+ | Prop | Type | Default |
1136
+ | --- | --- | --- |
1137
+ | `placeholder` | `string` | |
1138
+ | `class` | `HTMLAttributes['class']` | |
1139
+ | `inputClass` | `HTMLAttributes['class']` | |
1140
+
1141
+ - **Also accepts** all props of Reka `TagsInputRootProps`.
1142
+ - **Emits:** all events of Reka `TagsInputRootEmits`.
1143
+ - **Slots:** `default`.
1144
+
1145
+ #### `TagsInputItem`
1146
+
1147
+ - **Props:** `class`.
1148
+ - **Also accepts** all props of Reka `TagsInputItemProps`.
1149
+ - **Slots:** `default`.
1150
+
1151
+ #### `TagsInputItemText`
1152
+
1153
+ - **Props:** `class`.
1154
+ - **Also accepts** all props of Reka `TagsInputItemTextProps`.
1155
+ - **Slots:** `default`.
1156
+
1157
+ #### `TagsInputItemDelete`
1158
+
1159
+ - **Props:** `class`.
1160
+ - **Also accepts** all props of Reka `TagsInputItemDeleteProps`.
1161
+ - **Slots:** `default`.
1162
+
1163
+ #### `TagsInputInput`
1164
+
1165
+ - **Props:** `class`.
1166
+ - **Also accepts** all props of Reka `TagsInputInputProps`.
1167
+
1168
+ ---
1169
+
1170
+ ### `@brumaombra/ui-vintage/textarea`
1171
+
1172
+ Auto-growing textarea with `v-model` (uses `field-sizing: content`).
1173
+
1174
+ ```ts
1175
+ import { Textarea } from '@brumaombra/ui-vintage/textarea';
1176
+ ```
1177
+
1178
+ #### `Textarea`
1179
+
1180
+ | Prop | Type | Default |
1181
+ | --- | --- | --- |
1182
+ | `class` | `HTMLAttributes['class']` | |
1183
+ | `defaultValue` | `string \| number` | |
1184
+ | `modelValue` | `string \| number` | |
1185
+
1186
+ - **Emits:** `update:modelValue` (payload: string \| number).
1187
+
1188
+ ---
1189
+
1190
+ ### `@brumaombra/ui-vintage/time-picker`
1191
+
1192
+ Time input with `v-model` as an `HH:mm` (or `HH:mm:ss`) string.
1193
+
1194
+ ```ts
1195
+ import { TimePicker } from '@brumaombra/ui-vintage/time-picker';
1196
+ ```
1197
+
1198
+ #### `TimePicker`
1199
+
1200
+ | Prop | Type | Default |
1201
+ | --- | --- | --- |
1202
+ | `defaultValue` | `string` | `''` |
1203
+ | `modelValue` | `string` | |
1204
+ | `step` | `string \| number` | `1` |
1205
+ | `min` | `string` | |
1206
+ | `max` | `string` | |
1207
+ | `disabled` | `boolean` | `false` |
1208
+ | `class` | `HTMLAttributes['class']` | |
1209
+ | `inputClass` | `HTMLAttributes['class']` | |
1210
+
1211
+ - **Emits:** `update:modelValue` (payload: string).
1212
+
1213
+ ## Data display
1214
+
1215
+ Surfaces, tables, stats, and status indicators.
1216
+
1217
+ ### `@brumaombra/ui-vintage/animated-number`
1218
+
1219
+ Number that counts up on mount and tweens to new values, formatted with `Intl.NumberFormat`.
1220
+
1221
+ ```ts
1222
+ import { AnimatedNumber } from '@brumaombra/ui-vintage/animated-number';
1223
+ ```
1224
+
1225
+ #### `AnimatedNumber`
1226
+
1227
+ | Prop | Type | Default |
1228
+ | --- | --- | --- |
1229
+ | `value` *(required)* | `number` | |
1230
+ | `duration` | `number` | `900` |
1231
+ | `locale` | `string` | `undefined` |
1232
+ | `formatOptions` | `Intl.NumberFormatOptions` | `undefined` |
1233
+ | `prefix` | `string` | `''` |
1234
+ | `suffix` | `string` | `''` |
1235
+ | `animateOnMount` | `boolean` | `true` |
1236
+ | `class` | `HTMLAttributes['class']` | |
1237
+
1238
+ ---
1239
+
1240
+ ### `@brumaombra/ui-vintage/avatar`
1241
+
1242
+ Avatar with image, generated initials (`AvatarFallback name`), sizes, shapes, and status dots. `AvatarGroup` stacks avatars with a `+N` overflow.
1243
+
1244
+ ```ts
1245
+ import { Avatar, AvatarFallback, AvatarGroup, AvatarImage, avatarSizeClasses, avatarTextClasses, avatarShapeClasses, avatarContextKey, getInitials } from '@brumaombra/ui-vintage/avatar';
1246
+ import type { AvatarSize, AvatarShape, AvatarStatus } from '@brumaombra/ui-vintage/avatar';
1247
+ ```
1248
+
1249
+ ```vue
1250
+ <AvatarGroup :max="3">
1251
+ <Avatar v-for="user in users" :key="user.id" status="online">
1252
+ <AvatarImage :src="user.avatar" :alt="user.name" />
1253
+ <AvatarFallback :name="user.name" />
1254
+ </Avatar>
1255
+ </AvatarGroup>
1256
+ ```
1257
+
1258
+ #### `Avatar`
1259
+
1260
+ | Prop | Type | Default |
1261
+ | --- | --- | --- |
1262
+ | `size` | `AvatarSize` | `'md'` |
1263
+ | `shape` | `AvatarShape` | `'circle'` |
1264
+ | `status` | `AvatarStatus` | |
1265
+ | `class` | `HTMLAttributes['class']` | |
1266
+
1267
+ - **Also accepts** all props of Reka `AvatarRootProps`.
1268
+ - **Slots:** `default`.
1269
+
1270
+ #### `AvatarFallback`
1271
+
1272
+ | Prop | Type | Default |
1273
+ | --- | --- | --- |
1274
+ | `name` | `string` | |
1275
+ | `class` | `HTMLAttributes['class']` | |
1276
+
1277
+ - **Also accepts** all props of Reka `AvatarFallbackProps`.
1278
+ - **Slots:** `default`.
1279
+
1280
+ #### `AvatarGroup`
1281
+
1282
+ | Prop | Type | Default |
1283
+ | --- | --- | --- |
1284
+ | `max` | `number` | |
1285
+ | `size` | `AvatarSize` | `'md'` |
1286
+ | `shape` | `AvatarShape` | `'circle'` |
1287
+ | `class` | `HTMLAttributes['class']` | |
1288
+
1289
+ #### `AvatarImage`
1290
+
1291
+ - **Props:** `class`.
1292
+ - **Also accepts** all props of Reka `AvatarImageProps`.
1293
+ - **Emits:** all events of Reka `AvatarImageEmits`.
1294
+
1295
+ #### Functions, constants, and types
1296
+
1297
+ ```ts
1298
+ type AvatarSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl'
1299
+ type AvatarShape = 'circle' | 'square'
1300
+ type AvatarStatus = 'online' | 'offline' | 'busy' | 'away'
1301
+ const avatarSizeClasses: Record<AvatarSize, string>
1302
+ const avatarTextClasses: Record<AvatarSize, string>
1303
+ const avatarShapeClasses: Record<AvatarShape, string>
1304
+ const avatarContextKey: InjectionKey<{ size: Ref<AvatarSize>; shape: Ref<AvatarShape> }>
1305
+ function getInitials(name: string | null | undefined): string
1306
+ ```
1307
+
1308
+ ---
1309
+
1310
+ ### `@brumaombra/ui-vintage/badge`
1311
+
1312
+ Small status label in five tones, with an optional icon, `dot`, or pulsing `pulse` indicator.
1313
+
1314
+ ```ts
1315
+ import { Badge } from '@brumaombra/ui-vintage/badge';
1316
+ ```
1317
+
1318
+ ```vue
1319
+ <Badge text="Operational" color="green" pulse />
1320
+ ```
1321
+
1322
+ #### `Badge`
1323
+
1324
+ | Prop | Type | Default |
1325
+ | --- | --- | --- |
1326
+ | `text` *(required)* | `string` | |
1327
+ | `icon` | `HugeiconsIconDefinition \| null` | `null` |
1328
+ | `color` | `ToneColor` | `'gray'` |
1329
+ | `dot` | `boolean` | `false` |
1330
+ | `pulse` | `boolean` | `false` |
1331
+ | `class` | `HTMLAttributes['class']` | |
1332
+
1333
+ ---
1334
+
1335
+ ### `@brumaombra/ui-vintage/card`
1336
+
1337
+ Surface container with header, title, description, content, footer, and action slots. `interactive` adds a hover lift and pointer spotlight; `color` switches to a tone surface.
1338
+
1339
+ ```ts
1340
+ import { Card, CardAction, CardContent, CardText, CardDescription, CardFooter, CardHeader, CardTitle } from '@brumaombra/ui-vintage/card';
1341
+ ```
1342
+
1343
+ ```vue
1344
+ <Card interactive>
1345
+ <CardHeader>
1346
+ <CardTitle>Deployments</CardTitle>
1347
+ <CardDescription>Ship previews for every branch.</CardDescription>
1348
+ </CardHeader>
1349
+ <CardContent>...</CardContent>
1350
+ </Card>
1351
+ ```
1352
+
1353
+ #### `Card`
1354
+
1355
+ | Prop | Type | Default |
1356
+ | --- | --- | --- |
1357
+ | `color` | `CardColor` | |
1358
+ | `interactive` | `boolean` | `false` |
1359
+ | `class` | `HTMLAttributes['class']` | |
1360
+
1361
+ - **Slots:** `default`.
1362
+
1363
+ #### `CardAction`
1364
+
1365
+ - **Props:** `class`.
1366
+ - **Slots:** `default`.
1367
+
1368
+ #### `CardContent`
1369
+
1370
+ - **Props:** `class`.
1371
+ - **Slots:** `default`.
1372
+
1373
+ #### `CardText`
1374
+
1375
+ - **Props:** `class`.
1376
+ - **Slots:** `default`.
1377
+
1378
+ #### `CardDescription`
1379
+
1380
+ - **Props:** `class`.
1381
+ - **Slots:** `default`.
1382
+
1383
+ #### `CardFooter`
1384
+
1385
+ - **Props:** `class`.
1386
+ - **Slots:** `default`.
1387
+
1388
+ #### `CardHeader`
1389
+
1390
+ - **Props:** `class`.
1391
+ - **Slots:** `default`.
1392
+
1393
+ #### `CardTitle`
1394
+
1395
+ | Prop | Type | Default |
1396
+ | --- | --- | --- |
1397
+ | `class` | `HTMLAttributes['class']` | |
1398
+ | `level` | `HeadingLevel` | `3` |
1399
+
1400
+ - **Slots:** `default`.
1401
+
1402
+ ---
1403
+
1404
+ ### `@brumaombra/ui-vintage/card-grid`
1405
+
1406
+ Responsive grid of cards with built-in loading, empty, and load-more states. Render each item in the `card` slot.
1407
+
1408
+ ```ts
1409
+ import { CardGrid } from '@brumaombra/ui-vintage/card-grid';
1410
+ ```
1411
+
1412
+ #### `CardGrid`
1413
+
1414
+ | Prop | Type | Default |
1415
+ | --- | --- | --- |
1416
+ | `items` | `T[]` | `[]` |
1417
+ | `busy` | `boolean` | `false` |
1418
+ | `loadMoreBusy` | `boolean` | `false` |
1419
+ | `hasMore` | `boolean` | `false` |
1420
+ | `emptyMessage` *(required)* | `string` | |
1421
+ | `emptyIcon` | `HugeiconsIconDefinition` | `PackageIcon` |
1422
+
1423
+ - **Emits:** `load-more`.
1424
+ - **Slots:** `card`.
1425
+
1426
+ ---
1427
+
1428
+ ### `@brumaombra/ui-vintage/chip`
1429
+
1430
+ Removable tag that emits `remove`.
1431
+
1432
+ ```ts
1433
+ import { Chip } from '@brumaombra/ui-vintage/chip';
1434
+ ```
1435
+
1436
+ #### `Chip`
1437
+
1438
+ | Prop | Type | Default |
1439
+ | --- | --- | --- |
1440
+ | `text` *(required)* | `string` | |
1441
+ | `color` | `ToneColor` | `'gray'` |
1442
+ | `removeLabel` | `string` | |
1443
+ | `class` | `HTMLAttributes['class']` | |
1444
+
1445
+ - **Emits:** `remove`.
1446
+
1447
+ ---
1448
+
1449
+ ### `@brumaombra/ui-vintage/data-list`
1450
+
1451
+ Key-value rows for detail panels.
1452
+
1453
+ ```ts
1454
+ import { DataList, DataListItem, DataListLabel, DataListText, DataListValue } from '@brumaombra/ui-vintage/data-list';
1455
+ ```
1456
+
1457
+ #### `DataList`
1458
+
1459
+ - **Props:** `class`.
1460
+ - **Slots:** `default`.
1461
+
1462
+ #### `DataListItem`
1463
+
1464
+ - **Props:** `class`.
1465
+ - **Slots:** `default`.
1466
+
1467
+ #### `DataListLabel`
1468
+
1469
+ - **Props:** `class`.
1470
+ - **Slots:** `default`.
1471
+
1472
+ #### `DataListText`
1473
+
1474
+ - **Props:** `class`.
1475
+ - **Slots:** `default`.
1476
+
1477
+ #### `DataListValue`
1478
+
1479
+ - **Props:** `class`.
1480
+ - **Slots:** `default`.
1481
+
1482
+ ---
1483
+
1484
+ ### `@brumaombra/ui-vintage/data-table`
1485
+
1486
+ Typed data table with client-side sorting (animated rows), row selection, skeleton loading, empty state, and `cell-<key>` / `header-<key>` slots. Set `manual-sort` to sort on the server.
1487
+
1488
+ ```ts
1489
+ import { DataTable } from '@brumaombra/ui-vintage/data-table';
1490
+ import type { DataTableSortDirection, DataTableSort, DataTableColumn } from '@brumaombra/ui-vintage/data-table';
1491
+ ```
1492
+
1493
+ ```vue
1494
+ <DataTable v-model:selected="selected" v-model:sort="sort" :columns="columns" :rows="customers" selectable :loading="loading">
1495
+ <template #cell-status="{ row }">
1496
+ <Badge :text="row.status" color="green" dot />
1497
+ </template>
1498
+ </DataTable>
1499
+ ```
1500
+
1501
+ #### `DataTable`
1502
+
1503
+ | Prop | Type | Default |
1504
+ | --- | --- | --- |
1505
+ | `columns` *(required)* | `DataTableColumn<T>[]` | |
1506
+ | `rows` *(required)* | `T[]` | |
1507
+ | `rowKey` | `keyof T \| ((row: T) => PropertyKey)` | `'id'` |
1508
+ | `selectable` | `boolean` | `false` |
1509
+ | `selected` | `PropertyKey[]` | `[]` |
1510
+ | `sort` | `DataTableSort \| null` | `null` |
1511
+ | `manualSort` | `boolean` | `false` |
1512
+ | `loading` | `boolean` | `false` |
1513
+ | `loadingRows` | `number` | `5` |
1514
+ | `emptyText` | `string` | `''` |
1515
+ | `rowClickable` | `boolean` | `false` |
1516
+ | `stickyHeader` | `boolean` | `false` |
1517
+ | `class` | `HTMLAttributes['class']` | |
1518
+
1519
+ - **Emits:** `update:selected` (value: PropertyKey[]), `update:sort` (value: DataTableSort \| null), `row-click` (row: T, event: MouseEvent).
1520
+ - **Slots:** `cell-${string}`, `header-${string}`, `empty`.
1521
+
1522
+ #### Functions, constants, and types
1523
+
1524
+ ```ts
1525
+ type DataTableSortDirection = 'asc' | 'desc'
1526
+ interface DataTableSort {
1527
+ key: string;
1528
+ direction: DataTableSortDirection;
1529
+ }
1530
+ interface DataTableColumn<T> {
1531
+ key: string;
1532
+ label: string;
1533
+ sortable?: boolean;
1534
+ align?: 'left' | 'center' | 'right';
1535
+ width?: string;
1536
+ class?: string;
1537
+ headerClass?: string;
1538
+ format?: (value: unknown, row: T) => string;
1539
+ sortValue?: (row: T) => string | number | null | undefined;
1540
+ }
1541
+ ```
1542
+
1543
+ ---
1544
+
1545
+ ### `@brumaombra/ui-vintage/info-card`
1546
+
1547
+ Horizontal card with an icon, title, description, and a `right` slot for actions or badges.
1548
+
1549
+ ```ts
1550
+ import { InfoCard } from '@brumaombra/ui-vintage/info-card';
1551
+ ```
1552
+
1553
+ #### `InfoCard`
1554
+
1555
+ | Prop | Type | Default |
1556
+ | --- | --- | --- |
1557
+ | `icon` *(required)* | `HugeiconsIconDefinition` | |
1558
+ | `title` | `string` | `''` |
1559
+ | `description` | `string \| number` | `''` |
1560
+ | `class` | `HTMLAttributes['class']` | |
1561
+
1562
+ - **Slots:** `right`.
1563
+
1564
+ ---
1565
+
1566
+ ### `@brumaombra/ui-vintage/progress`
1567
+
1568
+ Progress bar (`v-model` 0 to `max`) with an `indeterminate` mode.
1569
+
1570
+ ```ts
1571
+ import { Progress } from '@brumaombra/ui-vintage/progress';
1572
+ ```
1573
+
1574
+ #### `Progress`
1575
+
1576
+ | Prop | Type | Default |
1577
+ | --- | --- | --- |
1578
+ | `indeterminate` | `boolean` | `false` |
1579
+ | `class` | `HTMLAttributes['class']` | |
1580
+
1581
+ - **Also accepts** all props of Reka `ProgressRootProps`.
1582
+
1583
+ ---
1584
+
1585
+ ### `@brumaombra/ui-vintage/progress-component`
1586
+
1587
+ Progress bar with a title, a value/max readout, and optional bottom labels.
1588
+
1589
+ ```ts
1590
+ import { ProgressComponent } from '@brumaombra/ui-vintage/progress-component';
1591
+ ```
1592
+
1593
+ #### `ProgressComponent`
1594
+
1595
+ | Prop | Type | Default |
1596
+ | --- | --- | --- |
1597
+ | `title` *(required)* | `string` | |
1598
+ | `bottomLeftLabel` | `string` | `''` |
1599
+ | `bottomRightLabel` | `string` | `''` |
1600
+ | `value` *(required)* | `number` | |
1601
+ | `max` *(required)* | `number` | |
1602
+
1603
+ ---
1604
+
1605
+ ### `@brumaombra/ui-vintage/scroll-area`
1606
+
1607
+ Scroll container with custom scrollbars.
1608
+
1609
+ ```ts
1610
+ import { ScrollArea, ScrollBar } from '@brumaombra/ui-vintage/scroll-area';
1611
+ ```
1612
+
1613
+ #### `ScrollArea`
1614
+
1615
+ - **Props:** `class`.
1616
+ - **Also accepts** all props of Reka `ScrollAreaRootProps`.
1617
+ - **Slots:** `default`.
1618
+
1619
+ #### `ScrollBar`
1620
+
1621
+ - **Props:** `class`.
1622
+ - **Also accepts** all props of Reka `ScrollAreaScrollbarProps`.
1623
+
1624
+ ---
1625
+
1626
+ ### `@brumaombra/ui-vintage/separator`
1627
+
1628
+ Horizontal or vertical divider.
1629
+
1630
+ ```ts
1631
+ import { Separator } from '@brumaombra/ui-vintage/separator';
1632
+ ```
1633
+
1634
+ #### `Separator`
1635
+
1636
+ - **Props:** `class`.
1637
+ - **Also accepts** all props of Reka `SeparatorProps`.
1638
+
1639
+ ---
1640
+
1641
+ ### `@brumaombra/ui-vintage/single-value-card`
1642
+
1643
+ KPI card. Numeric values count up and tween on change; optional trend badge and description.
1644
+
1645
+ ```ts
1646
+ import { SingleValueCard } from '@brumaombra/ui-vintage/single-value-card';
1647
+ ```
1648
+
1649
+ ```vue
1650
+ <SingleValueCard label="Revenue" :value="48290" :icon="Money03Icon" :trend="12.4" trend-label="vs last month"
1651
+ :format-options="{ style: 'currency', currency: 'EUR', maximumFractionDigits: 0 }" />
1652
+ ```
1653
+
1654
+ #### `SingleValueCard`
1655
+
1656
+ | Prop | Type | Default |
1657
+ | --- | --- | --- |
1658
+ | `value` *(required)* | `string \| number` | |
1659
+ | `label` *(required)* | `string` | |
1660
+ | `icon` *(required)* | `HugeiconsIconDefinition` | |
1661
+ | `valueColor` | `'default' \| 'green' \| 'red' \| 'gray'` | `'default'` |
1662
+ | `trend` | `number \| null` | `null` |
1663
+ | `trendLabel` | `string` | `''` |
1664
+ | `description` | `string` | `''` |
1665
+ | `animate` | `boolean` | `true` |
1666
+ | `formatOptions` | `Intl.NumberFormatOptions` | `undefined` |
1667
+ | `class` | `HTMLAttributes['class']` | |
1668
+
1669
+ ---
1670
+
1671
+ ### `@brumaombra/ui-vintage/skeleton`
1672
+
1673
+ Shimmering loading placeholder. Size and shape it with classes.
1674
+
1675
+ ```ts
1676
+ import { Skeleton } from '@brumaombra/ui-vintage/skeleton';
1677
+ ```
1678
+
1679
+ #### `Skeleton`
1680
+
1681
+ - **Props:** `class`.
1682
+
1683
+ ---
1684
+
1685
+ ### `@brumaombra/ui-vintage/table`
1686
+
1687
+ Low-level table parts (header, body, row, cell, caption, footer, empty row) for fully custom tables.
1688
+
1689
+ ```ts
1690
+ import { Table, TableBody, TableCaption, TableCell, TableEmpty, TableFooter, TableHead, TableHeader, TableRow } from '@brumaombra/ui-vintage/table';
1691
+ ```
1692
+
1693
+ #### `Table`
1694
+
1695
+ - **Props:** `class`.
1696
+ - **Slots:** `default`.
1697
+
1698
+ #### `TableBody`
1699
+
1700
+ - **Props:** `class`.
1701
+ - **Slots:** `default`.
1702
+
1703
+ #### `TableCaption`
1704
+
1705
+ - **Props:** `class`.
1706
+ - **Slots:** `default`.
1707
+
1708
+ #### `TableCell`
1709
+
1710
+ - **Props:** `class`.
1711
+ - **Slots:** `default`.
1712
+
1713
+ #### `TableEmpty`
1714
+
1715
+ | Prop | Type | Default |
1716
+ | --- | --- | --- |
1717
+ | `class` | `HTMLAttributes['class']` | |
1718
+ | `colspan` | `number` | `1` |
1719
+
1720
+ - **Slots:** `default`.
1721
+
1722
+ #### `TableFooter`
1723
+
1724
+ - **Props:** `class`.
1725
+ - **Slots:** `default`.
1726
+
1727
+ #### `TableHead`
1728
+
1729
+ - **Props:** `class`.
1730
+ - **Slots:** `default`.
1731
+
1732
+ #### `TableHeader`
1733
+
1734
+ - **Props:** `class`.
1735
+ - **Slots:** `default`.
1736
+
1737
+ #### `TableRow`
1738
+
1739
+ - **Props:** `class`.
1740
+ - **Slots:** `default`.
1741
+
1742
+ ## Navigation
1743
+
1744
+ Tabs, steps, pagination, disclosures, and sidebars.
1745
+
1746
+ ### `@brumaombra/ui-vintage/accordion`
1747
+
1748
+ Single expandable card with a title and optional icon. Uncontrolled (`initially-expanded`) or controlled (`v-model:open`).
1749
+
1750
+ ```ts
1751
+ import { Accordion } from '@brumaombra/ui-vintage/accordion';
1752
+ ```
1753
+
1754
+ ```vue
1755
+ <Accordion title="What is UI Vintage?" :icon="InformationCircleIcon" initially-expanded>
1756
+ <p>A source-published Nuxt component library.</p>
1757
+ </Accordion>
1758
+ ```
1759
+
1760
+ #### `Accordion`
1761
+
1762
+ | Prop | Type | Default |
1763
+ | --- | --- | --- |
1764
+ | `title` *(required)* | `string` | |
1765
+ | `initiallyExpanded` | `boolean` | `false` |
1766
+ | `open` | `boolean` | `undefined` |
1767
+ | `icon` | `HugeiconsIconDefinition \| null` | |
1768
+ | `iconClass` | `HTMLAttributes['class']` | |
1769
+ | `class` | `HTMLAttributes['class']` | |
1770
+
1771
+ - **Emits:** `update:open` (value: boolean).
1772
+ - **Slots:** `default`.
1773
+
1774
+ ---
1775
+
1776
+ ### `@brumaombra/ui-vintage/breadcrumb`
1777
+
1778
+ Breadcrumb trail parts: list, item, link, current page, separator, and ellipsis.
1779
+
1780
+ ```ts
1781
+ import { Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator } from '@brumaombra/ui-vintage/breadcrumb';
1782
+ ```
1783
+
1784
+ #### `Breadcrumb`
1785
+
1786
+ - **Props:** `class`.
1787
+ - **Slots:** `default`.
1788
+
1789
+ #### `BreadcrumbEllipsis`
1790
+
1791
+ - **Props:** `class`.
1792
+ - **Slots:** `default`.
1793
+
1794
+ #### `BreadcrumbItem`
1795
+
1796
+ - **Props:** `class`.
1797
+ - **Slots:** `default`.
1798
+
1799
+ #### `BreadcrumbLink`
1800
+
1801
+ - **Props:** `class`.
1802
+ - **Also accepts** all props of Reka `PrimitiveProps`.
1803
+ - **Slots:** `default`.
1804
+
1805
+ #### `BreadcrumbList`
1806
+
1807
+ - **Props:** `class`.
1808
+ - **Slots:** `default`.
1809
+
1810
+ #### `BreadcrumbPage`
1811
+
1812
+ - **Props:** `class`.
1813
+ - **Slots:** `default`.
1814
+
1815
+ #### `BreadcrumbSeparator`
1816
+
1817
+ - **Props:** `class`.
1818
+ - **Slots:** `default`.
1819
+
1820
+ ---
1821
+
1822
+ ### `@brumaombra/ui-vintage/collapsible`
1823
+
1824
+ Show or hide content with an animated height (`v-model:open`).
1825
+
1826
+ ```ts
1827
+ import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@brumaombra/ui-vintage/collapsible';
1828
+ ```
1829
+
1830
+ #### `Collapsible`
1831
+
1832
+ - **Props:** `class`.
1833
+ - **Also accepts** all props of Reka `CollapsibleRootProps`.
1834
+ - **Emits:** all events of Reka `CollapsibleRootEmits`.
1835
+ - **Slots:** `default`.
1836
+
1837
+ #### `CollapsibleContent`
1838
+
1839
+ - **Props:** `class`.
1840
+ - **Also accepts** all props of Reka `CollapsibleContentProps`.
1841
+ - **Emits:** all events of Reka `CollapsibleContentEmits`.
1842
+ - **Slots:** `default`.
1843
+
1844
+ #### `CollapsibleTrigger`
1845
+
1846
+ - **Props:** `class`.
1847
+ - **Also accepts** all props of Reka `CollapsibleTriggerProps`.
1848
+ - **Slots:** `default`.
1849
+
1850
+ ---
1851
+
1852
+ ### `@brumaombra/ui-vintage/pagination`
1853
+
1854
+ Pagination controls. `SimplePagination` covers the common case; the parts compose custom layouts.
1855
+
1856
+ ```ts
1857
+ import { Pagination, PaginationContent, PaginationEllipsis, PaginationFirst, PaginationItem, PaginationLast, PaginationNext, PaginationPrevious, SimplePagination } from '@brumaombra/ui-vintage/pagination';
1858
+ ```
1859
+
1860
+ ```vue
1861
+ <SimplePagination v-model:page="page" :total="240" :items-per-page="20" />
1862
+ ```
1863
+
1864
+ #### `Pagination`
1865
+
1866
+ - **Props:** `class`.
1867
+ - **Also accepts** all props of Reka `PaginationRootProps`.
1868
+ - **Emits:** all events of Reka `PaginationRootEmits`.
1869
+ - **Slots:** `default`.
1870
+
1871
+ #### `PaginationContent`
1872
+
1873
+ - **Props:** `class`.
1874
+ - **Also accepts** all props of Reka `PaginationListProps`.
1875
+ - **Slots:** `default`.
1876
+
1877
+ #### `PaginationEllipsis`
1878
+
1879
+ - **Props:** `class`.
1880
+ - **Also accepts** all props of Reka `PaginationEllipsisProps`.
1881
+ - **Slots:** `default`.
1882
+
1883
+ #### `PaginationFirst`
1884
+
1885
+ | Prop | Type | Default |
1886
+ | --- | --- | --- |
1887
+ | `size` | `ButtonVariants['size']` | `'icon-sm'` |
1888
+ | `class` | `HTMLAttributes['class']` | |
1889
+
1890
+ - **Also accepts** all props of Reka `PaginationFirstProps`.
1891
+ - **Slots:** `default`.
1892
+
1893
+ #### `PaginationItem`
1894
+
1895
+ | Prop | Type | Default |
1896
+ | --- | --- | --- |
1897
+ | `size` | `ButtonVariants['size']` | `'icon-sm'` |
1898
+ | `class` | `HTMLAttributes['class']` | |
1899
+
1900
+ - **Also accepts** all props of Reka `PaginationListItemProps`.
1901
+ - **Slots:** `default`.
1902
+
1903
+ #### `PaginationLast`
1904
+
1905
+ | Prop | Type | Default |
1906
+ | --- | --- | --- |
1907
+ | `size` | `ButtonVariants['size']` | `'icon-sm'` |
1908
+ | `class` | `HTMLAttributes['class']` | |
1909
+
1910
+ - **Also accepts** all props of Reka `PaginationLastProps`.
1911
+ - **Slots:** `default`.
1912
+
1913
+ #### `PaginationNext`
1914
+
1915
+ | Prop | Type | Default |
1916
+ | --- | --- | --- |
1917
+ | `size` | `ButtonVariants['size']` | `'icon-sm'` |
1918
+ | `class` | `HTMLAttributes['class']` | |
1919
+
1920
+ - **Also accepts** all props of Reka `PaginationNextProps`.
1921
+ - **Slots:** `default`.
1922
+
1923
+ #### `PaginationPrevious`
1924
+
1925
+ | Prop | Type | Default |
1926
+ | --- | --- | --- |
1927
+ | `size` | `ButtonVariants['size']` | `'icon-sm'` |
1928
+ | `class` | `HTMLAttributes['class']` | |
1929
+
1930
+ - **Also accepts** all props of Reka `PaginationPrevProps`.
1931
+ - **Slots:** `default`.
1932
+
1933
+ #### `SimplePagination`
1934
+
1935
+ | Prop | Type | Default |
1936
+ | --- | --- | --- |
1937
+ | `total` *(required)* | `number` | |
1938
+ | `itemsPerPage` | `number` | `10` |
1939
+ | `siblingCount` | `number` | `1` |
1940
+ | `showEdges` | `boolean` | `true` |
1941
+ | `disabled` | `boolean` | `false` |
1942
+ | `class` | `HTMLAttributes['class']` | |
1943
+
1944
+ ---
1945
+
1946
+ ### `@brumaombra/ui-vintage/sidebar`
1947
+
1948
+ Low-level sidebar system (provider, collapsible desktop sidebar, mobile sheet, menus, `useSidebar`). Prefer `dashboard-shell`, which composes it.
1949
+
1950
+ ```ts
1951
+ import { Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, useSidebar, sidebarMenuButtonVariants } from '@brumaombra/ui-vintage/sidebar';
1952
+ import type { SidebarProps, SidebarMenuButtonVariants } from '@brumaombra/ui-vintage/sidebar';
1953
+ ```
1954
+
1955
+ #### `Sidebar`
1956
+
1957
+ | Prop | Type | Default |
1958
+ | --- | --- | --- |
1959
+ | `side` | `'left' \| 'right'` | `'left'` |
1960
+ | `variant` | `'sidebar' \| 'floating' \| 'inset'` | `'sidebar'` |
1961
+ | `collapsible` | `'offcanvas' \| 'icon' \| 'none'` | `'offcanvas'` |
1962
+ | `compact` | `boolean` | `false` |
1963
+ | `class` | `HTMLAttributes['class']` | |
1964
+
1965
+ - **Slots:** `default`.
1966
+
1967
+ #### `SidebarContent`
1968
+
1969
+ - **Props:** `class`.
1970
+ - **Slots:** `default`.
1971
+
1972
+ #### `SidebarFooter`
1973
+
1974
+ - **Props:** `class`.
1975
+ - **Slots:** `default`.
1976
+
1977
+ #### `SidebarGroup`
1978
+
1979
+ - **Props:** `class`.
1980
+ - **Slots:** `default`.
1981
+
1982
+ #### `SidebarGroupAction`
1983
+
1984
+ - **Props:** `class`.
1985
+ - **Also accepts** all props of Reka `PrimitiveProps`.
1986
+ - **Slots:** `default`.
1987
+
1988
+ #### `SidebarGroupContent`
1989
+
1990
+ - **Props:** `class`.
1991
+ - **Slots:** `default`.
1992
+
1993
+ #### `SidebarGroupLabel`
1994
+
1995
+ - **Props:** `class`.
1996
+ - **Also accepts** all props of Reka `PrimitiveProps`.
1997
+ - **Slots:** `default`.
1998
+
1999
+ #### `SidebarHeader`
2000
+
2001
+ - **Props:** `class`.
2002
+ - **Slots:** `default`.
2003
+
2004
+ #### `SidebarInput`
2005
+
2006
+ - **Props:** `class`.
2007
+ - **Slots:** `default`.
2008
+
2009
+ #### `SidebarInset`
2010
+
2011
+ - **Props:** `class`.
2012
+ - **Slots:** `default`.
2013
+
2014
+ #### `SidebarMenu`
2015
+
2016
+ - **Props:** `class`.
2017
+ - **Slots:** `default`.
2018
+
2019
+ #### `SidebarMenuAction`
2020
+
2021
+ | Prop | Type | Default |
2022
+ | --- | --- | --- |
2023
+ | `showOnHover` | `boolean` | |
2024
+ | `class` | `HTMLAttributes['class']` | |
2025
+
2026
+ - **Also accepts** all props of Reka `PrimitiveProps`.
2027
+ - **Slots:** `default`.
2028
+
2029
+ #### `SidebarMenuBadge`
2030
+
2031
+ - **Props:** `class`.
2032
+ - **Slots:** `default`.
2033
+
2034
+ #### `SidebarMenuButton`
2035
+
2036
+ | Prop | Type | Default |
2037
+ | --- | --- | --- |
2038
+ | `variant` | `SidebarMenuButtonVariants['variant']` | `'default'` |
2039
+ | `size` | `SidebarMenuButtonVariants['size']` | `'default'` |
2040
+ | `isActive` | `boolean` | |
2041
+ | `class` | `HTMLAttributes['class']` | |
2042
+ | `tooltip` | `string \| Component` | |
2043
+
2044
+ - **Also accepts** all props of Reka `PrimitiveProps`.
2045
+ - **Slots:** `default`.
2046
+
2047
+ #### `SidebarMenuItem`
2048
+
2049
+ - **Props:** `class`.
2050
+ - **Slots:** `default`.
2051
+
2052
+ #### `SidebarMenuSkeleton`
2053
+
2054
+ | Prop | Type | Default |
2055
+ | --- | --- | --- |
2056
+ | `showIcon` | `boolean` | |
2057
+ | `class` | `HTMLAttributes['class']` | |
2058
+
2059
+ #### `SidebarMenuSub`
2060
+
2061
+ - **Props:** `class`.
2062
+ - **Slots:** `default`.
2063
+
2064
+ #### `SidebarMenuSubButton`
2065
+
2066
+ | Prop | Type | Default |
2067
+ | --- | --- | --- |
2068
+ | `size` | `'sm' \| 'md'` | `'md'` |
2069
+ | `isActive` | `boolean` | |
2070
+ | `class` | `HTMLAttributes['class']` | |
2071
+
2072
+ - **Also accepts** all props of Reka `PrimitiveProps`.
2073
+ - **Slots:** `default`.
2074
+
2075
+ #### `SidebarMenuSubItem`
2076
+
2077
+ - **Props:** `class`.
2078
+ - **Slots:** `default`.
2079
+
2080
+ #### `SidebarProvider`
2081
+
2082
+ | Prop | Type | Default |
2083
+ | --- | --- | --- |
2084
+ | `defaultOpen` | `boolean` | `!defaultDocument?.cookie.includes(`${SIDEBAR_COOKIE_NAME}=false`)` |
2085
+ | `open` | `boolean` | `undefined` |
2086
+ | `compact` | `boolean` | `false` |
2087
+ | `class` | `HTMLAttributes['class']` | |
2088
+
2089
+ - **Emits:** `update:open` (open: boolean).
2090
+ - **Slots:** `default`.
2091
+
2092
+ #### `SidebarRail`
2093
+
2094
+ - **Props:** `class`.
2095
+ - **Slots:** `default`.
2096
+
2097
+ #### `SidebarSeparator`
2098
+
2099
+ - **Props:** `class`.
2100
+ - **Slots:** `default`.
2101
+
2102
+ #### `SidebarTrigger`
2103
+
2104
+ - **Props:** `class`.
2105
+
2106
+ #### Functions, constants, and types
2107
+
2108
+ ```ts
2109
+ value useSidebar
2110
+ interface SidebarProps {
2111
+ side?: 'left' | 'right';
2112
+ variant?: 'sidebar' | 'floating' | 'inset';
2113
+ collapsible?: 'offcanvas' | 'icon' | 'none';
2114
+ compact?: boolean;
2115
+ class?: HTMLAttributes['class'];
2116
+ }
2117
+ type SidebarMenuButtonVariants = { variant?: 'default' | 'outline' | null | undefined; size?: 'default' | 'sm' | 'lg' | null | undefined }
2118
+ const sidebarMenuButtonVariants: ( props?: SidebarMenuButtonVariants & ClassProp ) => string
2119
+ ```
2120
+
2121
+ ---
2122
+
2123
+ ### `@brumaombra/ui-vintage/stepper`
2124
+
2125
+ Step indicator for wizards. `SimpleStepper` renders a whole stepper from a `steps` array; the other parts compose custom layouts.
2126
+
2127
+ ```ts
2128
+ import { SimpleStepper, Stepper, StepperDescription, StepperIndicator, StepperItem, StepperSeparator, StepperTitle, StepperTrigger } from '@brumaombra/ui-vintage/stepper';
2129
+ import type { StepperStep } from '@brumaombra/ui-vintage/stepper';
2130
+ ```
2131
+
2132
+ ```vue
2133
+ <SimpleStepper v-model="step" :steps="[{ title: 'Account' }, { title: 'Billing', description: 'Pick a plan' }, { title: 'Launch' }]" />
2134
+ ```
2135
+
2136
+ #### `SimpleStepper`
2137
+
2138
+ | Prop | Type | Default |
2139
+ | --- | --- | --- |
2140
+ | `steps` *(required)* | `StepperStep[]` | |
2141
+ | `orientation` | `'horizontal' \| 'vertical'` | `'horizontal'` |
2142
+ | `linear` | `boolean` | `true` |
2143
+ | `class` | `HTMLAttributes['class']` | |
2144
+
2145
+ #### `Stepper`
2146
+
2147
+ - **Props:** `class`.
2148
+ - **Also accepts** all props of Reka `StepperRootProps`.
2149
+ - **Emits:** all events of Reka `StepperRootEmits`.
2150
+ - **Slots:** `default`.
2151
+
2152
+ #### `StepperDescription`
2153
+
2154
+ - **Props:** `class`.
2155
+ - **Also accepts** all props of Reka `StepperDescriptionProps`.
2156
+ - **Slots:** `default`.
2157
+
2158
+ #### `StepperIndicator`
2159
+
2160
+ - **Props:** `class`.
2161
+ - **Also accepts** all props of Reka `StepperIndicatorProps`.
2162
+ - **Slots:** `default`.
2163
+
2164
+ #### `StepperItem`
2165
+
2166
+ - **Props:** `class`.
2167
+ - **Also accepts** all props of Reka `StepperItemProps`.
2168
+ - **Slots:** `default`.
2169
+
2170
+ #### `StepperSeparator`
2171
+
2172
+ - **Props:** `class`.
2173
+ - **Also accepts** all props of Reka `StepperSeparatorProps`.
2174
+
2175
+ #### `StepperTitle`
2176
+
2177
+ - **Props:** `class`.
2178
+ - **Also accepts** all props of Reka `StepperTitleProps`.
2179
+ - **Slots:** `default`.
2180
+
2181
+ #### `StepperTrigger`
2182
+
2183
+ - **Props:** `class`.
2184
+ - **Also accepts** all props of Reka `StepperTriggerProps`.
2185
+ - **Slots:** `default`.
2186
+
2187
+ #### Functions, constants, and types
2188
+
2189
+ ```ts
2190
+ type StepperStep = { title: string; description?: string; icon?: HugeiconsIconDefinition }
2191
+ ```
2192
+
2193
+ ---
2194
+
2195
+ ### `@brumaombra/ui-vintage/tabs`
2196
+
2197
+ Tabs with a sliding active indicator (horizontal or vertical) and animated panels.
2198
+
2199
+ ```ts
2200
+ import { Tabs, TabsContent, TabsList, TabsTrigger } from '@brumaombra/ui-vintage/tabs';
2201
+ ```
2202
+
2203
+ ```vue
2204
+ <Tabs default-value="overview">
2205
+ <TabsList>
2206
+ <TabsTrigger value="overview">Overview</TabsTrigger>
2207
+ <TabsTrigger value="settings">Settings</TabsTrigger>
2208
+ </TabsList>
2209
+ <TabsContent value="overview">...</TabsContent>
2210
+ <TabsContent value="settings">...</TabsContent>
2211
+ </Tabs>
2212
+ ```
2213
+
2214
+ #### `Tabs`
2215
+
2216
+ - **Props:** `class`.
2217
+ - **Also accepts** all props of Reka `TabsRootProps`.
2218
+ - **Emits:** all events of Reka `TabsRootEmits`.
2219
+ - **Slots:** `default`.
2220
+
2221
+ #### `TabsContent`
2222
+
2223
+ - **Props:** `class`.
2224
+ - **Also accepts** all props of Reka `TabsContentProps`.
2225
+ - **Slots:** `default`.
2226
+
2227
+ #### `TabsList`
2228
+
2229
+ | Prop | Type | Default |
2230
+ | --- | --- | --- |
2231
+ | `class` | `HTMLAttributes['class']` | |
2232
+ | `indicatorClass` | `HTMLAttributes['class']` | |
2233
+
2234
+ - **Also accepts** all props of Reka `TabsListProps`.
2235
+ - **Slots:** `default`.
2236
+
2237
+ #### `TabsTrigger`
2238
+
2239
+ - **Props:** `class`.
2240
+ - **Also accepts** all props of Reka `TabsTriggerProps`.
2241
+ - **Slots:** `default`.
2242
+
2243
+ ## Overlays
2244
+
2245
+ Modals, sheets, and floating surfaces built on Reka UI.
2246
+
2247
+ ### `@brumaombra/ui-vintage/alert-dialog`
2248
+
2249
+ Modal that requires an explicit choice. For simple confirmations prefer `showConfirmDialog` from `confirm-dialog`.
2250
+
2251
+ ```ts
2252
+ import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger } from '@brumaombra/ui-vintage/alert-dialog';
2253
+ ```
2254
+
2255
+ #### `AlertDialog`
2256
+
2257
+ - **Also accepts** all props of Reka `AlertDialogProps`.
2258
+ - **Emits:** all events of Reka `AlertDialogEmits`.
2259
+ - **Slots:** `default`.
2260
+
2261
+ #### `AlertDialogAction`
2262
+
2263
+ - **Props:** `class`.
2264
+ - **Also accepts** all props of Reka `AlertDialogActionProps`.
2265
+ - **Slots:** `default`.
2266
+
2267
+ #### `AlertDialogCancel`
2268
+
2269
+ - **Props:** `class`.
2270
+ - **Also accepts** all props of Reka `AlertDialogCancelProps`.
2271
+ - **Slots:** `default`.
2272
+
2273
+ #### `AlertDialogContent`
2274
+
2275
+ - **Props:** `class`.
2276
+ - **Also accepts** all props of Reka `AlertDialogContentProps`.
2277
+ - **Emits:** all events of Reka `AlertDialogContentEmits`.
2278
+ - **Slots:** `default`.
2279
+
2280
+ #### `AlertDialogDescription`
2281
+
2282
+ - **Props:** `class`.
2283
+ - **Also accepts** all props of Reka `AlertDialogDescriptionProps`.
2284
+ - **Slots:** `default`.
2285
+
2286
+ #### `AlertDialogFooter`
2287
+
2288
+ - **Props:** `class`.
2289
+ - **Slots:** `default`.
2290
+
2291
+ #### `AlertDialogHeader`
2292
+
2293
+ - **Props:** `class`.
2294
+ - **Slots:** `default`.
2295
+
2296
+ #### `AlertDialogTitle`
2297
+
2298
+ - **Props:** `class`.
2299
+ - **Also accepts** all props of Reka `AlertDialogTitleProps`.
2300
+ - **Slots:** `default`.
2301
+
2302
+ #### `AlertDialogTrigger`
2303
+
2304
+ - **Also accepts** all props of Reka `AlertDialogTriggerProps`.
2305
+ - **Slots:** `default`.
2306
+
2307
+ ---
2308
+
2309
+ ### `@brumaombra/ui-vintage/command`
2310
+
2311
+ Command palette list with filtering. A string `value` on `CommandItem` adds search keywords. Use `CommandDialog` for a modal palette.
2312
+
2313
+ ```ts
2314
+ import { Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, [useCommand, provideCommandContext], [useCommandGroup, provideCommandGroupContext] } from '@brumaombra/ui-vintage/command';
2315
+ ```
2316
+
2317
+ ```vue
2318
+ <CommandDialog v-model:open="open">
2319
+ <CommandInput placeholder="Search..." />
2320
+ <CommandList>
2321
+ <CommandEmpty>No results.</CommandEmpty>
2322
+ <CommandGroup heading="Pages">
2323
+ <CommandItem value="settings preferences" @select="go('/settings')">Settings</CommandItem>
2324
+ </CommandGroup>
2325
+ </CommandList>
2326
+ </CommandDialog>
2327
+ ```
2328
+
2329
+ #### `Command`
2330
+
2331
+ - **Props:** `class`.
2332
+ - **Also accepts** all props of Reka `ListboxRootProps`.
2333
+ - **Emits:** all events of Reka `ListboxRootEmits`.
2334
+ - **Slots:** `default`.
2335
+
2336
+ #### `CommandDialog`
2337
+
2338
+ | Prop | Type | Default |
2339
+ | --- | --- | --- |
2340
+ | `title` | `string` | |
2341
+ | `description` | `string` | |
2342
+ | `contentClass` | `HTMLAttributes['class']` | |
2343
+
2344
+ - **Also accepts** all props of Reka `DialogRootProps`.
2345
+ - **Emits:** all events of Reka `DialogRootEmits`.
2346
+ - **Slots:** `default`.
2347
+
2348
+ #### `CommandEmpty`
2349
+
2350
+ - **Props:** `class`.
2351
+ - **Also accepts** all props of Reka `PrimitiveProps`.
2352
+ - **Slots:** `default`.
2353
+
2354
+ #### `CommandGroup`
2355
+
2356
+ | Prop | Type | Default |
2357
+ | --- | --- | --- |
2358
+ | `class` | `HTMLAttributes['class']` | |
2359
+ | `heading` | `string` | |
2360
+
2361
+ - **Also accepts** all props of Reka `ListboxGroupProps`.
2362
+ - **Slots:** `default`.
2363
+
2364
+ #### `CommandInput`
2365
+
2366
+ - **Props:** `class`.
2367
+ - **Also accepts** all props of Reka `ListboxFilterProps`.
2368
+
2369
+ #### `CommandItem`
2370
+
2371
+ - **Props:** `class`.
2372
+ - **Also accepts** all props of Reka `ListboxItemProps`.
2373
+ - **Emits:** all events of Reka `ListboxItemEmits`.
2374
+ - **Slots:** `default`.
2375
+
2376
+ #### `CommandList`
2377
+
2378
+ - **Props:** `class`.
2379
+ - **Also accepts** all props of Reka `ListboxContentProps`.
2380
+ - **Slots:** `default`.
2381
+
2382
+ #### `CommandSeparator`
2383
+
2384
+ - **Props:** `class`.
2385
+ - **Also accepts** all props of Reka `SeparatorProps`.
2386
+ - **Slots:** `default`.
2387
+
2388
+ #### `CommandShortcut`
2389
+
2390
+ - **Props:** `class`.
2391
+ - **Slots:** `default`.
2392
+
2393
+ #### Functions, constants, and types
2394
+
2395
+ ```ts
2396
+ value [useCommand, provideCommandContext]
2397
+ value [useCommandGroup, provideCommandGroupContext]
2398
+ ```
2399
+
2400
+ ---
2401
+
2402
+ ### `@brumaombra/ui-vintage/dialog`
2403
+
2404
+ Modal dialog. `DialogContent` accepts `show-close-button`; use `DialogScrollContent` for long content.
2405
+
2406
+ ```ts
2407
+ import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogScrollContent, DialogTitle, DialogTrigger } from '@brumaombra/ui-vintage/dialog';
2408
+ ```
2409
+
2410
+ ```vue
2411
+ <Dialog>
2412
+ <DialogTrigger as-child>
2413
+ <Button>Edit profile</Button>
2414
+ </DialogTrigger>
2415
+ <DialogContent show-close-button>
2416
+ <DialogHeader>
2417
+ <DialogTitle>Edit profile</DialogTitle>
2418
+ <DialogDescription>Make changes to your profile.</DialogDescription>
2419
+ </DialogHeader>
2420
+ ...
2421
+ <DialogFooter>
2422
+ <DialogClose as-child><Button variant="secondary">Cancel</Button></DialogClose>
2423
+ </DialogFooter>
2424
+ </DialogContent>
2425
+ </Dialog>
2426
+ ```
2427
+
2428
+ #### `Dialog`
2429
+
2430
+ - **Also accepts** all props of Reka `DialogRootProps`.
2431
+ - **Emits:** all events of Reka `DialogRootEmits`.
2432
+ - **Slots:** `default`.
2433
+
2434
+ #### `DialogClose`
2435
+
2436
+ - **Also accepts** all props of Reka `DialogCloseProps`.
2437
+ - **Slots:** `default`.
2438
+
2439
+ #### `DialogContent`
2440
+
2441
+ | Prop | Type | Default |
2442
+ | --- | --- | --- |
2443
+ | `class` | `HTMLAttributes['class']` | |
2444
+ | `showCloseButton` | `boolean` | `false` |
2445
+
2446
+ - **Also accepts** all props of Reka `DialogContentProps`.
2447
+ - **Emits:** all events of Reka `DialogContentEmits`.
2448
+ - **Slots:** `default`.
2449
+
2450
+ #### `DialogDescription`
2451
+
2452
+ - **Props:** `class`.
2453
+ - **Also accepts** all props of Reka `DialogDescriptionProps`.
2454
+ - **Slots:** `default`.
2455
+
2456
+ #### `DialogFooter`
2457
+
2458
+ - **Props:** `class`.
2459
+ - **Slots:** `default`.
2460
+
2461
+ #### `DialogHeader`
2462
+
2463
+ - **Props:** `class`.
2464
+ - **Slots:** `default`.
2465
+
2466
+ #### `DialogOverlay`
2467
+
2468
+ - **Props:** `class`.
2469
+ - **Also accepts** all props of Reka `DialogOverlayProps`.
2470
+ - **Slots:** `default`.
2471
+
2472
+ #### `DialogScrollContent`
2473
+
2474
+ | Prop | Type | Default |
2475
+ | --- | --- | --- |
2476
+ | `class` | `HTMLAttributes['class']` | |
2477
+ | `showCloseButton` | `boolean` | `false` |
2478
+
2479
+ - **Also accepts** all props of Reka `DialogContentProps`.
2480
+ - **Emits:** all events of Reka `DialogContentEmits`.
2481
+ - **Slots:** `default`.
2482
+
2483
+ #### `DialogTitle`
2484
+
2485
+ - **Props:** `class`.
2486
+ - **Also accepts** all props of Reka `DialogTitleProps`.
2487
+ - **Slots:** `default`.
2488
+
2489
+ #### `DialogTrigger`
2490
+
2491
+ - **Also accepts** all props of Reka `DialogTriggerProps`.
2492
+ - **Slots:** `default`.
2493
+
2494
+ ---
2495
+
2496
+ ### `@brumaombra/ui-vintage/hover-card`
2497
+
2498
+ Rich preview shown on hover (for example a user profile behind a link).
2499
+
2500
+ ```ts
2501
+ import { HoverCard, HoverCardContent, HoverCardTrigger } from '@brumaombra/ui-vintage/hover-card';
2502
+ ```
2503
+
2504
+ #### `HoverCard`
2505
+
2506
+ - **Also accepts** all props of Reka `HoverCardRootProps`.
2507
+ - **Emits:** all events of Reka `HoverCardRootEmits`.
2508
+ - **Slots:** `default`.
2509
+
2510
+ #### `HoverCardContent`
2511
+
2512
+ - **Props:** `class`.
2513
+ - **Also accepts** all props of Reka `HoverCardContentProps`.
2514
+ - **Slots:** `default`.
2515
+
2516
+ #### `HoverCardTrigger`
2517
+
2518
+ - **Also accepts** all props of Reka `HoverCardTriggerProps`.
2519
+ - **Slots:** `default`.
2520
+
2521
+ ---
2522
+
2523
+ ### `@brumaombra/ui-vintage/popover`
2524
+
2525
+ Floating panel anchored to a trigger.
2526
+
2527
+ ```ts
2528
+ import { Popover, PopoverAnchor, PopoverContent, PopoverTrigger } from '@brumaombra/ui-vintage/popover';
2529
+ ```
2530
+
2531
+ #### `Popover`
2532
+
2533
+ - **Also accepts** all props of Reka `PopoverRootProps`.
2534
+ - **Emits:** all events of Reka `PopoverRootEmits`.
2535
+ - **Slots:** `default`.
2536
+
2537
+ #### `PopoverAnchor`
2538
+
2539
+ - **Also accepts** all props of Reka `PopoverAnchorProps`.
2540
+ - **Slots:** `default`.
2541
+
2542
+ #### `PopoverContent`
2543
+
2544
+ - **Props:** `class`.
2545
+ - **Also accepts** all props of Reka `PopoverContentProps`.
2546
+ - **Emits:** all events of Reka `PopoverContentEmits`.
2547
+ - **Slots:** `default`.
2548
+
2549
+ #### `PopoverTrigger`
2550
+
2551
+ - **Also accepts** all props of Reka `PopoverTriggerProps`.
2552
+ - **Slots:** `default`.
2553
+
2554
+ ---
2555
+
2556
+ ### `@brumaombra/ui-vintage/sheet`
2557
+
2558
+ Side panel that slides in from `top`, `right`, `bottom`, or `left`.
2559
+
2560
+ ```ts
2561
+ import { Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger } from '@brumaombra/ui-vintage/sheet';
2562
+ ```
2563
+
2564
+ ```vue
2565
+ <Sheet>
2566
+ <SheetTrigger as-child><Button variant="secondary">Settings</Button></SheetTrigger>
2567
+ <SheetContent side="right">
2568
+ <SheetHeader>
2569
+ <SheetTitle>Settings</SheetTitle>
2570
+ <SheetDescription>Workspace preferences.</SheetDescription>
2571
+ </SheetHeader>
2572
+ </SheetContent>
2573
+ </Sheet>
2574
+ ```
2575
+
2576
+ #### `Sheet`
2577
+
2578
+ - **Also accepts** all props of Reka `DialogRootProps`.
2579
+ - **Emits:** all events of Reka `DialogRootEmits`.
2580
+ - **Slots:** `default`.
2581
+
2582
+ #### `SheetClose`
2583
+
2584
+ - **Also accepts** all props of Reka `DialogCloseProps`.
2585
+ - **Slots:** `default`.
2586
+
2587
+ #### `SheetContent`
2588
+
2589
+ | Prop | Type | Default |
2590
+ | --- | --- | --- |
2591
+ | `class` | `HTMLAttributes['class']` | |
2592
+ | `side` | `'top' \| 'right' \| 'bottom' \| 'left'` | `'right'` |
2593
+
2594
+ - **Also accepts** all props of Reka `DialogContentProps`.
2595
+ - **Emits:** all events of Reka `DialogContentEmits`.
2596
+ - **Slots:** `default`.
2597
+
2598
+ #### `SheetDescription`
2599
+
2600
+ - **Props:** `class`.
2601
+ - **Also accepts** all props of Reka `DialogDescriptionProps`.
2602
+ - **Slots:** `default`.
2603
+
2604
+ #### `SheetFooter`
2605
+
2606
+ - **Props:** `class`.
2607
+ - **Slots:** `default`.
2608
+
2609
+ #### `SheetHeader`
2610
+
2611
+ - **Props:** `class`.
2612
+ - **Slots:** `default`.
2613
+
2614
+ #### `SheetTitle`
2615
+
2616
+ - **Props:** `class`.
2617
+ - **Also accepts** all props of Reka `DialogTitleProps`.
2618
+ - **Slots:** `default`.
2619
+
2620
+ #### `SheetTrigger`
2621
+
2622
+ - **Also accepts** all props of Reka `DialogTriggerProps`.
2623
+ - **Slots:** `default`.
2624
+
2625
+ ---
2626
+
2627
+ ### `@brumaombra/ui-vintage/tooltip`
2628
+
2629
+ Hover and focus hint. Wrap the app (or layout) in `TooltipProvider` once; `DashboardShell` already provides one.
2630
+
2631
+ ```ts
2632
+ import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@brumaombra/ui-vintage/tooltip';
2633
+ ```
2634
+
2635
+ ```vue
2636
+ <Tooltip>
2637
+ <TooltipTrigger as-child><Button variant="ghost" size="icon">?</Button></TooltipTrigger>
2638
+ <TooltipContent side="right">Helpful hint</TooltipContent>
2639
+ </Tooltip>
2640
+ ```
2641
+
2642
+ #### `Tooltip`
2643
+
2644
+ - **Also accepts** all props of Reka `TooltipRootProps`.
2645
+ - **Emits:** all events of Reka `TooltipRootEmits`.
2646
+ - **Slots:** `default`.
2647
+
2648
+ #### `TooltipContent`
2649
+
2650
+ - **Props:** `class`.
2651
+ - **Also accepts** all props of Reka `TooltipContentProps`.
2652
+ - **Emits:** all events of Reka `TooltipContentEmits`.
2653
+ - **Slots:** `default`.
2654
+
2655
+ #### `TooltipProvider`
2656
+
2657
+ - **Also accepts** all props of Reka `TooltipProviderProps`.
2658
+ - **Slots:** `default`.
2659
+
2660
+ #### `TooltipTrigger`
2661
+
2662
+ - **Also accepts** all props of Reka `TooltipTriggerProps`.
2663
+ - **Slots:** `default`.
2664
+
2665
+ ## Feedback
2666
+
2667
+ Toasts, promise-based dialogs, the busy overlay, alerts, and empty or loading states. The runtime flows mount themselves lazily, so no component needs to be placed in the app.
2668
+
2669
+ ### `@brumaombra/ui-vintage/alert`
2670
+
2671
+ Inline callout in five tones. Put an icon first, then `AlertTitle` and `AlertDescription`.
2672
+
2673
+ ```ts
2674
+ import { Alert, AlertDescription, AlertTitle, alertClasses } from '@brumaombra/ui-vintage/alert';
2675
+ import type { AlertColors } from '@brumaombra/ui-vintage/alert';
2676
+ ```
2677
+
2678
+ ```vue
2679
+ <Alert color="yellow">
2680
+ <HugeiconsIcon :icon="Alert02Icon" />
2681
+ <AlertTitle>Approaching limit</AlertTitle>
2682
+ <AlertDescription>You have used 92% of your build minutes.</AlertDescription>
2683
+ </Alert>
2684
+ ```
2685
+
2686
+ #### `Alert`
2687
+
2688
+ | Prop | Type | Default |
2689
+ | --- | --- | --- |
2690
+ | `class` | `HTMLAttributes['class']` | |
2691
+ | `color` | `AlertColors['color']` | |
2692
+
2693
+ - **Slots:** `default`.
2694
+
2695
+ #### `AlertDescription`
2696
+
2697
+ - **Props:** `class`.
2698
+ - **Slots:** `default`.
2699
+
2700
+ #### `AlertTitle`
2701
+
2702
+ - **Props:** `class`.
2703
+ - **Slots:** `default`.
2704
+
2705
+ #### Functions, constants, and types
2706
+
2707
+ ```ts
2708
+ type AlertColors = { color?: ToneColor | null | undefined }
2709
+ const alertClasses: (props?: ClassProp) => string
2710
+ ```
2711
+
2712
+ ---
2713
+
2714
+ ### `@brumaombra/ui-vintage/busy`
2715
+
2716
+ Busy overlay component for local use (`show` prop). For a global overlay use `busy-indicator`.
2717
+
2718
+ ```ts
2719
+ import { Busy } from '@brumaombra/ui-vintage/busy';
2720
+ ```
2721
+
2722
+ #### `Busy`
2723
+
2724
+ | Prop | Type | Default |
2725
+ | --- | --- | --- |
2726
+ | `show` | `boolean` | `false` |
2727
+ | `label` | `string` | |
2728
+ | `class` | `HTMLAttributes['class']` | |
2729
+ | `overlayClass` | `HTMLAttributes['class']` | |
2730
+
2731
+ - **Slots:** `default`.
2732
+
2733
+ ---
2734
+
2735
+ ### `@brumaombra/ui-vintage/busy-indicator`
2736
+
2737
+ Global busy overlay controlled with `setBusy(show, options)`.
2738
+
2739
+ ```ts
2740
+ import { BusyIndicator, busyIndicatorState, setBusy } from '@brumaombra/ui-vintage/busy-indicator';
2741
+ import type { SetBusyOptions } from '@brumaombra/ui-vintage/busy-indicator';
2742
+ ```
2743
+
2744
+ ```ts
2745
+ setBusy(true, { label: 'Generating report...' });
2746
+ await generateReport();
2747
+ setBusy(false);
2748
+ ```
2749
+
2750
+ #### `BusyIndicator`
2751
+
2752
+ - **Props:** none.
2753
+
2754
+ #### Functions, constants, and types
2755
+
2756
+ ```ts
2757
+ const busyIndicatorState: BusyIndicatorState
2758
+ function setBusy(show: boolean, options: SetBusyOptions = {})
2759
+ interface SetBusyOptions {
2760
+ label?: string;
2761
+ class?: HTMLAttributes['class'];
2762
+ overlayClass?: HTMLAttributes['class'];
2763
+ }
2764
+ ```
2765
+
2766
+ ---
2767
+
2768
+ ### `@brumaombra/ui-vintage/confirm-dialog`
2769
+
2770
+ Promise-based confirmation dialog. Resolves to `true` or `false`; an async `onConfirm` shows a spinner on the confirm button until it settles.
2771
+
2772
+ ```ts
2773
+ import { ConfirmDialog, cancelActiveConfirmDialog, closeConfirmDialog, confirmActiveDialog, confirmDialogState, showConfirmDialog } from '@brumaombra/ui-vintage/confirm-dialog';
2774
+ import type { DialogButtonVariant, ShowConfirmDialogOptions } from '@brumaombra/ui-vintage/confirm-dialog';
2775
+ ```
2776
+
2777
+ ```ts
2778
+ const confirmed = await showConfirmDialog({
2779
+ title: 'Delete project?',
2780
+ message: 'This action cannot be undone.',
2781
+ confirmText: 'Delete',
2782
+ confirmButtonType: 'red',
2783
+ onConfirm: () => api.deleteProject(id)
2784
+ });
2785
+ ```
2786
+
2787
+ #### `ConfirmDialog`
2788
+
2789
+ - **Props:** none.
2790
+
2791
+ #### Functions, constants, and types
2792
+
2793
+ ```ts
2794
+ async function cancelActiveConfirmDialog()
2795
+ function closeConfirmDialog()
2796
+ async function confirmActiveDialog()
2797
+ const confirmDialogState: ConfirmDialogState
2798
+ function showConfirmDialog(options: ShowConfirmDialogOptions)
2799
+ type DialogButtonVariant = NonNullable<ButtonVariants['variant']>
2800
+ interface ShowConfirmDialogOptions {
2801
+ title?: string;
2802
+ message: string;
2803
+ confirmText?: string;
2804
+ cancelText?: string;
2805
+ confirmButtonType?: DialogButtonVariant;
2806
+ cancelButtonType?: DialogButtonVariant;
2807
+ icon?: HugeiconsIconDefinition | null;
2808
+ confirmButtonIcon?: HugeiconsIconDefinition | null;
2809
+ cancelButtonIcon?: HugeiconsIconDefinition | null;
2810
+ onConfirm?: (() => void | Promise<void>) | null;
2811
+ onCancel?: (() => void | Promise<void>) | null;
2812
+ }
2813
+ ```
2814
+
2815
+ ---
2816
+
2817
+ ### `@brumaombra/ui-vintage/cookie-consent`
2818
+
2819
+ Cookie consent banner fixed to the bottom of the page, shown in the browser until the visitor accepts or declines. The choice is saved in `localStorage` under `storage-key`; `useCookieConsent(storageKey)` shares it, so optional scripts (analytics, ads) can wait for `consent.value === "granted"` and a settings page can call `reset()` to ask again. Texts have translated defaults, `policy-to` adds a link to the cookie policy.
2820
+
2821
+ ```ts
2822
+ import { CookieConsent, useCookieConsent } from '@brumaombra/ui-vintage/cookie-consent';
2823
+ import type { CookieConsentValue } from '@brumaombra/ui-vintage/cookie-consent';
2824
+ ```
2825
+
2826
+ ```vue
2827
+ <CookieConsent storage-key="analyticsConsent" policy-to="/cookie-policy" @accept="loadAnalytics" />
2828
+
2829
+ <script setup>
2830
+ const { consent, reset } = useCookieConsent('analyticsConsent');
2831
+ watch(consent, value => value === 'granted' && loadAnalytics(), { immediate: true });
2832
+ </script>
2833
+ ```
2834
+
2835
+ #### `CookieConsent`
2836
+
2837
+ | Prop | Type | Default |
2838
+ | --- | --- | --- |
2839
+ | `storageKey` | `string` | `'cookieConsent'` |
2840
+ | `message` | `string` | `undefined` |
2841
+ | `policyTo` | `string` | `undefined` |
2842
+ | `policyLabel` | `string` | `undefined` |
2843
+ | `acceptLabel` | `string` | `undefined` |
2844
+ | `declineLabel` | `string` | `undefined` |
2845
+ | `class` | `HTMLAttributes['class']` | `undefined` |
2846
+
2847
+ - **Emits:** `accept`, `decline`.
2848
+
2849
+ #### Functions, constants, and types
2850
+
2851
+ ```ts
2852
+ function useCookieConsent(storageKey = 'cookieConsent')
2853
+ type CookieConsentValue = 'granted' | 'denied' | null
2854
+ ```
2855
+
2856
+ ---
2857
+
2858
+ ### `@brumaombra/ui-vintage/empty-state-card`
2859
+
2860
+ Empty state with an icon, title, description, and an `action` slot. Falls back to localized default copy.
2861
+
2862
+ ```ts
2863
+ import { EmptyStateCard } from '@brumaombra/ui-vintage/empty-state-card';
2864
+ ```
2865
+
2866
+ #### `EmptyStateCard`
2867
+
2868
+ | Prop | Type | Default |
2869
+ | --- | --- | --- |
2870
+ | `icon` | `HugeiconsIconDefinition` | `PackageIcon` |
2871
+ | `title` | `string` | `''` |
2872
+ | `description` | `string` | `''` |
2873
+ | `titleKey` | `string` | `''` |
2874
+ | `descriptionKey` | `string` | `''` |
2875
+ | `level` | `HeadingLevel` | `3` |
2876
+
2877
+ - **Slots:** `action`.
2878
+
2879
+ ---
2880
+
2881
+ ### `@brumaombra/ui-vintage/loading-state-card`
2882
+
2883
+ Loading state card with a spinning icon and localized default copy.
2884
+
2885
+ ```ts
2886
+ import { LoadingStateCard } from '@brumaombra/ui-vintage/loading-state-card';
2887
+ ```
2888
+
2889
+ #### `LoadingStateCard`
2890
+
2891
+ | Prop | Type | Default |
2892
+ | --- | --- | --- |
2893
+ | `icon` | `HugeiconsIconDefinition` | `Loading03Icon` |
2894
+ | `title` | `string` | `''` |
2895
+ | `description` | `string` | `''` |
2896
+ | `level` | `HeadingLevel` | `3` |
2897
+
2898
+ - **Slots:** `default`.
2899
+
2900
+ ---
2901
+
2902
+ ### `@brumaombra/ui-vintage/message-dialog`
2903
+
2904
+ Promise-based message dialog for success, info, warning, and error messages.
2905
+
2906
+ ```ts
2907
+ import { MessageDialog, closeMessageDialog, messageDialogState, resolveActiveMessageDialog, showMessageDialog } from '@brumaombra/ui-vintage/message-dialog';
2908
+ import type { DialogMessageType, ShowMessageDialogOptions } from '@brumaombra/ui-vintage/message-dialog';
2909
+ ```
2910
+
2911
+ ```ts
2912
+ await showMessageDialog({ type: 'success', message: 'Your account is verified.' });
2913
+ ```
2914
+
2915
+ #### `MessageDialog`
2916
+
2917
+ - **Props:** none.
2918
+
2919
+ #### Functions, constants, and types
2920
+
2921
+ ```ts
2922
+ function closeMessageDialog()
2923
+ const messageDialogState: MessageDialogState
2924
+ function resolveActiveMessageDialog()
2925
+ function showMessageDialog(options: ShowMessageDialogOptions)
2926
+ type DialogMessageType = 'error' | 'success' | 'info' | 'warning'
2927
+ interface ShowMessageDialogOptions {
2928
+ type?: DialogMessageType;
2929
+ title?: string;
2930
+ message: string;
2931
+ closeText?: string;
2932
+ icon?: HugeiconsIconDefinition | null;
2933
+ closeButtonIcon?: HugeiconsIconDefinition | null;
2934
+ }
2935
+ ```
2936
+
2937
+ ---
2938
+
2939
+ ### `@brumaombra/ui-vintage/message-toast`
2940
+
2941
+ Stacked toasts (hover to expand and pause, swipe to dismiss) with titles and actions. `showMessageToast` returns an id for `closeMessageToast(id)`; `duration: 0` keeps a toast open.
2942
+
2943
+ ```ts
2944
+ import { closeMessageToast, messageToastState, pauseMessageToasts, resumeMessageToasts, showMessageToast } from '@brumaombra/ui-vintage/message-toast';
2945
+ import type { MessageToastAction, MessageToastItem, MessageToastType, ShowMessageToastOptions } from '@brumaombra/ui-vintage/message-toast';
2946
+ ```
2947
+
2948
+ ```ts
2949
+ showMessageToast({ title: 'Saved', message: 'Your changes are live.', type: 'success' });
2950
+
2951
+ const id = showMessageToast({ message: 'Publishing...', type: 'info', duration: 0, dismissible: false });
2952
+ closeMessageToast(id);
2953
+ ```
2954
+
2955
+ #### Functions, constants, and types
2956
+
2957
+ ```ts
2958
+ function closeMessageToast(id?: number)
2959
+ const messageToastState: MessageToastState
2960
+ function pauseMessageToasts()
2961
+ function resumeMessageToasts()
2962
+ function showMessageToast(options: ShowMessageToastOptions)
2963
+ interface MessageToastAction {
2964
+ label: string;
2965
+ onClick: () => void | Promise<void>;
2966
+ }
2967
+ interface MessageToastItem {
2968
+ id: number;
2969
+ message: string;
2970
+ type: MessageToastType;
2971
+ title: string;
2972
+ icon: HugeiconsIconDefinition | null;
2973
+ action: MessageToastAction | null;
2974
+ dismissible: boolean;
2975
+ duration: number;
2976
+ }
2977
+ type MessageToastType = 'success' | 'info' | 'warning' | 'error'
2978
+ interface ShowMessageToastOptions {
2979
+ message: string;
2980
+ type?: MessageToastType;
2981
+ duration?: number;
2982
+ title?: string;
2983
+ icon?: HugeiconsIconDefinition | null;
2984
+ action?: MessageToastAction | null;
2985
+ dismissible?: boolean;
2986
+ }
2987
+ ```
2988
+
2989
+ ---
2990
+
2991
+ ### `@brumaombra/ui-vintage/spinner`
2992
+
2993
+ Loading spinner in five sizes; inherits the text color.
2994
+
2995
+ ```ts
2996
+ import { Spinner } from '@brumaombra/ui-vintage/spinner';
2997
+ ```
2998
+
2999
+ #### `Spinner`
3000
+
3001
+ | Prop | Type | Default |
3002
+ | --- | --- | --- |
3003
+ | `size` | `'xs' \| 'sm' \| 'md' \| 'lg' \| 'xl'` | `'md'` |
3004
+ | `label` | `string` | `''` |
3005
+ | `class` | `HTMLAttributes['class']` | |
3006
+
3007
+ ## Layouts and app shell
3008
+
3009
+ Application shells, page headers, error pages, and theme or language controls.
3010
+
3011
+ ### `@brumaombra/ui-vintage/background-grid`
3012
+
3013
+ Decorative grid background for app shells.
3014
+
3015
+ ```ts
3016
+ import { BackgroundGrid } from '@brumaombra/ui-vintage/background-grid';
3017
+ ```
3018
+
3019
+ #### `BackgroundGrid`
3020
+
3021
+ - **Props:** `class`.
3022
+
3023
+ ---
3024
+
3025
+ ### `@brumaombra/ui-vintage/dashboard-shell`
3026
+
3027
+ Complete dashboard layout: collapsible sidebar built from `sidebar-sections`, mobile sheet, sticky topbar, and grid background. Pass `NuxtLink` as `sidebar-link-component` for client-side navigation.
3028
+
3029
+ ```ts
3030
+ import { DashboardShell } from '@brumaombra/ui-vintage/dashboard-shell';
3031
+ ```
3032
+
3033
+ ```vue
3034
+ <DashboardShell title="Projects" :sidebar-sections="sections" :sidebar-link-component="NuxtLink">
3035
+ <template #topbar-trailing>
3036
+ <ThemeSelector />
3037
+ </template>
3038
+ <slot />
3039
+ </DashboardShell>
3040
+ ```
3041
+
3042
+ #### `DashboardShell`
3043
+
3044
+ | Prop | Type | Default |
3045
+ | --- | --- | --- |
3046
+ | `appName` | `string` | `''` |
3047
+ | `appLogo` | `string` | `''` |
3048
+ | `appLinkTo` | `string` | `'/'` |
3049
+ | `title` | `string` | `''` |
3050
+ | `description` | `string` | `''` |
3051
+ | `collapsible` | `'offcanvas' \| 'icon' \| 'none'` | `'offcanvas'` |
3052
+ | `compact` | `boolean` | `false` |
3053
+ | `sidebarSections` | `Array<{ id: string; label?: string; items: Array<{ id: string; label: string; description?: string; icon?: HugeiconsIconDefinition \| null; href?: string; to?: unknown; active?: boolean; newTab?: boolean }> }>` | `[]` |
3054
+ | `sidebarLinkComponent` | `Component \| string` | `'a'` |
3055
+ | `showBackground` | `boolean` | `true` |
3056
+ | `insetClass` | `HTMLAttributes['class']` | |
3057
+ | `topbarClass` | `HTMLAttributes['class']` | |
3058
+ | `contentContainerClass` | `HTMLAttributes['class']` | |
3059
+
3060
+ - **Slots:** `sidebar-header`, `sidebar-footer`, `topbar-leading`, `topbar-trailing`, `default`, `footer`.
3061
+
3062
+ ---
3063
+
3064
+ ### `@brumaombra/ui-vintage/error-page`
3065
+
3066
+ Branded 404/500 page for `error.vue`, with `toolbar` and `brand` slots and an `action` event.
3067
+
3068
+ ```ts
3069
+ import { ErrorPage } from '@brumaombra/ui-vintage/error-page';
3070
+ ```
3071
+
3072
+ #### `ErrorPage`
3073
+
3074
+ | Prop | Type | Default |
3075
+ | --- | --- | --- |
3076
+ | `statusCode` | `number \| string` | `500` |
3077
+ | `label` | `string` | |
3078
+ | `title` | `string` | `undefined` |
3079
+ | `message` | `string` | `undefined` |
3080
+ | `actionLabel` | `string` | |
3081
+ | `showBackground` | `boolean` | `true` |
3082
+ | `showDefaultAction` | `boolean` | `true` |
3083
+ | `class` | `HTMLAttributes['class']` | `undefined` |
3084
+ | `cardClass` | `HTMLAttributes['class']` | `undefined` |
3085
+ | `contentClass` | `HTMLAttributes['class']` | `undefined` |
3086
+ | `footerClass` | `HTMLAttributes['class']` | `undefined` |
3087
+
3088
+ - **Emits:** `action`.
3089
+ - **Slots:** `toolbar`, `brand`, `actions`.
3090
+
3091
+ ---
3092
+
3093
+ ### `@brumaombra/ui-vintage/landing`
3094
+
3095
+ All landing layout parts in one entry point (shell, navbar, content, footer).
3096
+
3097
+ ```ts
3098
+ import { LandingContent, LandingShell, LandingNavbar, LandingFooter } from '@brumaombra/ui-vintage/landing';
3099
+ import type { LandingFooterLink, LandingFooterSection } from '@brumaombra/ui-vintage/landing';
3100
+ ```
3101
+
3102
+ #### `LandingContent`
3103
+
3104
+ - **Props:** `class`.
3105
+ - **Slots:** `default`.
3106
+
3107
+ #### `LandingShell`
3108
+
3109
+ | Prop | Type | Default |
3110
+ | --- | --- | --- |
3111
+ | `showBackground` | `boolean` | `true` |
3112
+ | `rootClass` | `HTMLAttributes['class']` | |
3113
+ | `navbarClass` | `HTMLAttributes['class']` | |
3114
+ | `mainClass` | `HTMLAttributes['class']` | |
3115
+ | `footerClass` | `HTMLAttributes['class']` | |
3116
+
3117
+ - **Slots:** `navbar`, `content`, `default`, `footer`.
3118
+
3119
+ #### `LandingNavbar`
3120
+
3121
+ | Prop | Type | Default |
3122
+ | --- | --- | --- |
3123
+ | `appName` | `string` | `''` |
3124
+ | `appLogo` | `string` | `''` |
3125
+ | `appLinkTo` | `string` | `'/'` |
3126
+ | `logoClass` | `HTMLAttributes['class']` | |
3127
+ | `class` | `HTMLAttributes['class']` | |
3128
+ | `containerClass` | `HTMLAttributes['class']` | |
3129
+ | `leftClass` | `HTMLAttributes['class']` | |
3130
+ | `rightClass` | `HTMLAttributes['class']` | |
3131
+ | `showProgress` | `boolean` | `false` |
3132
+
3133
+ - **Slots:** `left`, `right`.
3134
+
3135
+ #### `LandingFooter`
3136
+
3137
+ | Prop | Type | Default |
3138
+ | --- | --- | --- |
3139
+ | `appName` *(required)* | `string` | |
3140
+ | `appLogo` | `string` | |
3141
+ | `appLinkTo` | `string` | `'/'` |
3142
+ | `logoClass` | `HTMLAttributes['class']` | |
3143
+ | `appDescription` | `string` | `''` |
3144
+ | `sections` | `LandingFooterSection[]` | `[]` |
3145
+ | `linkComponent` | `Component \| string` | `'a'` |
3146
+ | `authorName` | `string` | `''` |
3147
+ | `authorLink` | `string` | `''` |
3148
+ | `year` | `number` | `new Date().getFullYear()` |
3149
+ | `showBottomBar` | `boolean` | `true` |
3150
+ | `level` | `HeadingLevel` | `3` |
3151
+ | `class` | `HTMLAttributes['class']` | |
3152
+ | `containerClass` | `HTMLAttributes['class']` | |
3153
+ | `brandClass` | `HTMLAttributes['class']` | |
3154
+ | `sectionsClass` | `HTMLAttributes['class']` | |
3155
+ | `bottomBarClass` | `HTMLAttributes['class']` | |
3156
+
3157
+ #### Functions, constants, and types
3158
+
3159
+ ```ts
3160
+ interface LandingFooterLink {
3161
+ id: string;
3162
+ label: string;
3163
+ href?: string;
3164
+ to?: unknown;
3165
+ newTab?: boolean;
3166
+ }
3167
+ interface LandingFooterSection {
3168
+ id: string;
3169
+ title: string;
3170
+ links: LandingFooterLink[];
3171
+ }
3172
+ ```
3173
+
3174
+ ---
3175
+
3176
+ ### `@brumaombra/ui-vintage/landing-content`
3177
+
3178
+ Centered content column for landing and blog pages.
3179
+
3180
+ ```ts
3181
+ import { LandingContent } from '@brumaombra/ui-vintage/landing-content';
3182
+ ```
3183
+
3184
+ #### `LandingContent`
3185
+
3186
+ - **Props:** `class`.
3187
+ - **Slots:** `default`.
3188
+
3189
+ ---
3190
+
3191
+ ### `@brumaombra/ui-vintage/landing-footer`
3192
+
3193
+ Landing footer with link sections, app description, and author credit.
3194
+
3195
+ ```ts
3196
+ import { LandingFooter } from '@brumaombra/ui-vintage/landing-footer';
3197
+ import type { LandingFooterLink, LandingFooterSection } from '@brumaombra/ui-vintage/landing-footer';
3198
+ ```
3199
+
3200
+ #### `LandingFooter`
3201
+
3202
+ | Prop | Type | Default |
3203
+ | --- | --- | --- |
3204
+ | `appName` *(required)* | `string` | |
3205
+ | `appLogo` | `string` | |
3206
+ | `appLinkTo` | `string` | `'/'` |
3207
+ | `logoClass` | `HTMLAttributes['class']` | |
3208
+ | `appDescription` | `string` | `''` |
3209
+ | `sections` | `LandingFooterSection[]` | `[]` |
3210
+ | `linkComponent` | `Component \| string` | `'a'` |
3211
+ | `authorName` | `string` | `''` |
3212
+ | `authorLink` | `string` | `''` |
3213
+ | `year` | `number` | `new Date().getFullYear()` |
3214
+ | `showBottomBar` | `boolean` | `true` |
3215
+ | `level` | `HeadingLevel` | `3` |
3216
+ | `class` | `HTMLAttributes['class']` | |
3217
+ | `containerClass` | `HTMLAttributes['class']` | |
3218
+ | `brandClass` | `HTMLAttributes['class']` | |
3219
+ | `sectionsClass` | `HTMLAttributes['class']` | |
3220
+ | `bottomBarClass` | `HTMLAttributes['class']` | |
3221
+
3222
+ #### Functions, constants, and types
3223
+
3224
+ ```ts
3225
+ interface LandingFooterLink {
3226
+ id: string;
3227
+ label: string;
3228
+ href?: string;
3229
+ to?: unknown;
3230
+ newTab?: boolean;
3231
+ }
3232
+ interface LandingFooterSection {
3233
+ id: string;
3234
+ title: string;
3235
+ links: LandingFooterLink[];
3236
+ }
3237
+ ```
3238
+
3239
+ ---
3240
+
3241
+ ### `@brumaombra/ui-vintage/landing-navbar`
3242
+
3243
+ Landing navbar with app name or logo, an optional reading progress bar, and a `right` slot.
3244
+
3245
+ ```ts
3246
+ import { LandingNavbar } from '@brumaombra/ui-vintage/landing-navbar';
3247
+ ```
3248
+
3249
+ #### `LandingNavbar`
3250
+
3251
+ | Prop | Type | Default |
3252
+ | --- | --- | --- |
3253
+ | `appName` | `string` | `''` |
3254
+ | `appLogo` | `string` | `''` |
3255
+ | `appLinkTo` | `string` | `'/'` |
3256
+ | `logoClass` | `HTMLAttributes['class']` | |
3257
+ | `class` | `HTMLAttributes['class']` | |
3258
+ | `containerClass` | `HTMLAttributes['class']` | |
3259
+ | `leftClass` | `HTMLAttributes['class']` | |
3260
+ | `rightClass` | `HTMLAttributes['class']` | |
3261
+ | `showProgress` | `boolean` | `false` |
3262
+
3263
+ - **Slots:** `left`, `right`.
3264
+
3265
+ ---
3266
+
3267
+ ### `@brumaombra/ui-vintage/landing-shell`
3268
+
3269
+ Landing page frame with `navbar`, `content`, and `footer` slots.
3270
+
3271
+ ```ts
3272
+ import { LandingShell } from '@brumaombra/ui-vintage/landing-shell';
3273
+ ```
3274
+
3275
+ #### `LandingShell`
3276
+
3277
+ | Prop | Type | Default |
3278
+ | --- | --- | --- |
3279
+ | `showBackground` | `boolean` | `true` |
3280
+ | `rootClass` | `HTMLAttributes['class']` | |
3281
+ | `navbarClass` | `HTMLAttributes['class']` | |
3282
+ | `mainClass` | `HTMLAttributes['class']` | |
3283
+ | `footerClass` | `HTMLAttributes['class']` | |
3284
+
3285
+ - **Slots:** `navbar`, `content`, `default`, `footer`.
3286
+
3287
+ ---
3288
+
3289
+ ### `@brumaombra/ui-vintage/language-flag`
3290
+
3291
+ Flag icons for the supported locales.
3292
+
3293
+ ```ts
3294
+ import { LanguageFlag, EnglishFlag, FrenchFlag, GermanFlag, ItalianFlag, ChineseFlag, JapaneseFlag, RussianFlag, SpanishFlag } from '@brumaombra/ui-vintage/language-flag';
3295
+ import type { SupportedLanguageCode } from '@brumaombra/ui-vintage/language-flag';
3296
+ ```
3297
+
3298
+ #### `LanguageFlag`
3299
+
3300
+ | Prop | Type | Default |
3301
+ | --- | --- | --- |
3302
+ | `code` | `SupportedLanguageCode` | `'en'` |
3303
+
3304
+ #### `EnglishFlag`
3305
+
3306
+ - **Props:** none.
3307
+
3308
+ #### `FrenchFlag`
3309
+
3310
+ - **Props:** none.
3311
+
3312
+ #### `GermanFlag`
3313
+
3314
+ - **Props:** none.
3315
+
3316
+ #### `ItalianFlag`
3317
+
3318
+ - **Props:** none.
3319
+
3320
+ #### `ChineseFlag`
3321
+
3322
+ - **Props:** none.
3323
+
3324
+ #### `JapaneseFlag`
3325
+
3326
+ - **Props:** none.
3327
+
3328
+ #### `RussianFlag`
3329
+
3330
+ - **Props:** none.
3331
+
3332
+ #### `SpanishFlag`
3333
+
3334
+ - **Props:** none.
3335
+
3336
+ #### Functions, constants, and types
3337
+
3338
+ ```ts
3339
+ type SupportedLanguageCode = keyof typeof supportedFlagLoaders
3340
+ ```
3341
+
3342
+ ---
3343
+
3344
+ ### `@brumaombra/ui-vintage/language-selector`
3345
+
3346
+ Language menu with flags. Pass the locale codes; handle `select` to call `setLocale`.
3347
+
3348
+ ```ts
3349
+ import { LanguageSelector } from '@brumaombra/ui-vintage/language-selector';
3350
+ import type { LanguageSelectorCode } from '@brumaombra/ui-vintage/language-selector';
3351
+ ```
3352
+
3353
+ #### `LanguageSelector`
3354
+
3355
+ | Prop | Type | Default |
3356
+ | --- | --- | --- |
3357
+ | `modelValue` | `string` | `''` |
3358
+ | `languages` | `LanguageSelectorCode[]` | `['en', 'it']` |
3359
+
3360
+ - **Emits:** `update:modelValue` (value: string), `select` (value: string).
3361
+
3362
+ #### Functions, constants, and types
3363
+
3364
+ ```ts
3365
+ type LanguageSelectorCode = string
3366
+ ```
3367
+
3368
+ ---
3369
+
3370
+ ### `@brumaombra/ui-vintage/page-header`
3371
+
3372
+ Page title row with an optional actions slot, in three sizes.
3373
+
3374
+ ```ts
3375
+ import { PageHeader } from '@brumaombra/ui-vintage/page-header';
3376
+ ```
3377
+
3378
+ #### `PageHeader`
3379
+
3380
+ | Prop | Type | Default |
3381
+ | --- | --- | --- |
3382
+ | `title` *(required)* | `string` | |
3383
+ | `headingLevel` | `number` | `1` |
3384
+ | `size` | `'small' \| 'medium' \| 'large'` | `'large'` |
3385
+
3386
+ - **Slots:** `default`.
3387
+
3388
+ ---
3389
+
3390
+ ### `@brumaombra/ui-vintage/theme-selector`
3391
+
3392
+ Light, dark, and auto theme menu with a circular reveal (View Transitions API). `applyThemeWithTransition` switches themes from your own controls.
3393
+
3394
+ ```ts
3395
+ import { ThemeSelector, applyTheme, applyThemeWithTransition, getStoredTheme, isDarkTheme } from '@brumaombra/ui-vintage/theme-selector';
3396
+ import type { ThemeMode, ThemeTransitionOrigin } from '@brumaombra/ui-vintage/theme-selector';
3397
+ ```
3398
+
3399
+ ```vue
3400
+ <ThemeSelector />
3401
+ ```
3402
+
3403
+ #### `ThemeSelector`
3404
+
3405
+ - **Props:** none.
3406
+
3407
+ #### Functions, constants, and types
3408
+
3409
+ ```ts
3410
+ function applyTheme(theme: ThemeMode)
3411
+ async function applyThemeWithTransition(theme: ThemeMode, origin?: ThemeTransitionOrigin | Element | null)
3412
+ function getStoredTheme(): ThemeMode
3413
+ function isDarkTheme(theme: ThemeMode)
3414
+ type ThemeMode = 'light' | 'dark' | 'auto'
3415
+ interface ThemeTransitionOrigin {
3416
+ x: number;
3417
+ y: number;
3418
+ }
3419
+ ```
3420
+
3421
+ ## Content and blog
3422
+
3423
+ Components for Nuxt Content pages and a complete blog.
3424
+
3425
+ ### `@brumaombra/ui-vintage/blog`
3426
+
3427
+ Blog building blocks: header carousel, post cards and lists, categories, tags, table of contents, reading progress, FAQ, share sidebar, and the content renderer.
3428
+
3429
+ ```ts
3430
+ import { AllPostsSection, BlogContentRenderer, BlogFAQSection, BlogInfoSection, BlogHeaderSection, BlogSectionTitle, BlogTagsSection, CategoriesList, CategoriesSection, CategoryCard, HeaderCarousel, PostCard, PostsList, SocialShareSidebar, TableOfContents } from '@brumaombra/ui-vintage/blog';
3431
+ ```
3432
+
3433
+ #### `AllPostsSection`
3434
+
3435
+ | Prop | Type | Default |
3436
+ | --- | --- | --- |
3437
+ | `posts` | `Array<{ path: string; title: string; description?: string; image?: string; categoryText?: string; categoryPath?: string }>` | `[]` |
3438
+ | `currentPage` | `number` | `1` |
3439
+ | `postsPerPage` | `number` | `9` |
3440
+ | `totalPosts` | `number` | `0` |
3441
+ | `hasMorePosts` | `boolean` | `false` |
3442
+ | `isLoading` | `boolean` | `false` |
3443
+
3444
+ - **Emits:** `load-more`.
3445
+
3446
+ #### `BlogContentRenderer`
3447
+
3448
+ | Prop | Type | Default |
3449
+ | --- | --- | --- |
3450
+ | `value` *(required)* | `Record<string, unknown>` | |
3451
+
3452
+ #### `BlogFAQSection`
3453
+
3454
+ | Prop | Type | Default |
3455
+ | --- | --- | --- |
3456
+ | `faqs` | `Array<{ question: string; answer: string }>` | `[]` |
3457
+
3458
+ #### `BlogInfoSection`
3459
+
3460
+ | Prop | Type | Default |
3461
+ | --- | --- | --- |
3462
+ | `author` *(required)* | `string` | |
3463
+ | `authorUrl` *(required)* | `string` | |
3464
+ | `authorImageUrl` *(required)* | `string` | |
3465
+ | `datePublished` *(required)* | `string` | |
3466
+ | `dateModified` | `string \| null` | `null` |
3467
+
3468
+ #### `BlogHeaderSection`
3469
+
3470
+ | Prop | Type | Default |
3471
+ | --- | --- | --- |
3472
+ | `badges` | `Array<{ color: ToneColor; text: string }>` | `[]` |
3473
+ | `title` *(required)* | `string` | |
3474
+ | `description` *(required)* | `string` | |
3475
+
3476
+ #### `BlogSectionTitle`
3477
+
3478
+ | Prop | Type | Default |
3479
+ | --- | --- | --- |
3480
+ | `title` *(required)* | `string` | |
3481
+
3482
+ #### `BlogTagsSection`
3483
+
3484
+ | Prop | Type | Default |
3485
+ | --- | --- | --- |
3486
+ | `tags` | `Array<{ name: string; slug: string; count: number }>` | `[]` |
3487
+
3488
+ #### `CategoriesList`
3489
+
3490
+ | Prop | Type | Default |
3491
+ | --- | --- | --- |
3492
+ | `categories` | `Array<{ path: string; slug?: string; name: string; image?: string; count: number }>` | `[]` |
3493
+
3494
+ #### `CategoriesSection`
3495
+
3496
+ | Prop | Type | Default |
3497
+ | --- | --- | --- |
3498
+ | `categories` | `Array<{ path: string; slug?: string; name: string; image?: string; count: number }>` | `[]` |
3499
+
3500
+ #### `CategoryCard`
3501
+
3502
+ | Prop | Type | Default |
3503
+ | --- | --- | --- |
3504
+ | `name` *(required)* | `string` | |
3505
+ | `image` | `string` | `''` |
3506
+ | `count` *(required)* | `number` | |
3507
+
3508
+ #### `HeaderCarousel`
3509
+
3510
+ | Prop | Type | Default |
3511
+ | --- | --- | --- |
3512
+ | `featuredPosts` | `Array<{ path: string; title: string; description?: string; image?: string; categoryText?: string; categoryPath?: string }>` | `[]` |
3513
+
3514
+ #### `PostCard`
3515
+
3516
+ | Prop | Type | Default |
3517
+ | --- | --- | --- |
3518
+ | `image` | `string` | `''` |
3519
+ | `category` | `string` | `''` |
3520
+ | `title` | `string` | `''` |
3521
+ | `description` | `string` | `''` |
3522
+
3523
+ #### `PostsList`
3524
+
3525
+ | Prop | Type | Default |
3526
+ | --- | --- | --- |
3527
+ | `posts` | `Array<{ path: string; title: string; description?: string; image?: string; categoryText?: string; categoryPath?: string }>` | `[]` |
3528
+
3529
+ #### `SocialShareSidebar`
3530
+
3531
+ | Prop | Type | Default |
3532
+ | --- | --- | --- |
3533
+ | `title` *(required)* | `string` | |
3534
+ | `url` *(required)* | `string` | |
3535
+
3536
+ #### `TableOfContents`
3537
+
3538
+ | Prop | Type | Default |
3539
+ | --- | --- | --- |
3540
+ | `content` *(required)* | `{ body?: { toc?: { links?: BlogTocLink[] } }; toc?: { links?: BlogTocLink[] } }` | |
3541
+
3542
+ ---
3543
+
3544
+ ### `@brumaombra/ui-vintage/content`
3545
+
3546
+ Prose components for Nuxt Content (MDC): code blocks highlighted with shiki, terminals, lists, tables, flows, and dividers.
3547
+
3548
+ ```ts
3549
+ import { Terminal, CodeBlock, ProsePre, BlogList, BlogTable, Flow, ProseHr } from '@brumaombra/ui-vintage/content';
3550
+ ```
3551
+
3552
+ #### `Terminal`
3553
+
3554
+ | Prop | Type | Default |
3555
+ | --- | --- | --- |
3556
+ | `commands` | `string[]` | `[]` |
3557
+ | `title` | `string` | `''` |
3558
+ | `prompt` | `string` | `'$'` |
3559
+ | `copyable` | `boolean` | `true` |
3560
+
3561
+ #### `CodeBlock`
3562
+
3563
+ | Prop | Type | Default |
3564
+ | --- | --- | --- |
3565
+ | `code` | `string` | `''` |
3566
+ | `language` | `CodeLanguage` | `'text'` |
3567
+ | `title` | `string` | `''` |
3568
+ | `copyable` | `boolean` | `true` |
3569
+
3570
+ #### `ProsePre`
3571
+
3572
+ | Prop | Type | Default |
3573
+ | --- | --- | --- |
3574
+ | `code` | `string` | `''` |
3575
+ | `language` | `string` | `''` |
3576
+
3577
+ - **Slots:** `default`.
3578
+
3579
+ #### `BlogList`
3580
+
3581
+ | Prop | Type | Default |
3582
+ | --- | --- | --- |
3583
+ | `items` | `string[]` | `[]` |
3584
+ | `variant` | `'circle' \| 'checkmark' \| 'numbered' \| 'cross'` | `'checkmark'` |
3585
+
3586
+ #### `BlogTable`
3587
+
3588
+ | Prop | Type | Default |
3589
+ | --- | --- | --- |
3590
+ | `headers` | `string[]` | `[]` |
3591
+ | `rows` | `string[][]` | `[]` |
3592
+ | `highlightCol` | `number` | `-1` |
3593
+
3594
+ #### `Flow`
3595
+
3596
+ | Prop | Type | Default |
3597
+ | --- | --- | --- |
3598
+ | `title` | `string` | `''` |
3599
+ | `description` | `string` | `''` |
3600
+ | `items` | `FlowItem[]` | `[]` |
3601
+ | `orientation` | `'horizontal' \| 'vertical'` | `'horizontal'` |
3602
+
3603
+ #### `ProseHr`
3604
+
3605
+ | Prop | Type | Default |
3606
+ | --- | --- | --- |
3607
+ | `icon` | `HugeiconsIconDefinition` | `ChartLineData02Icon` |
3608
+
3609
+ ## Utilities and types
3610
+
3611
+ Helpers shared by the components.
3612
+
3613
+ ### `@brumaombra/ui-vintage/common-types`
3614
+
3615
+ Shared types used in component props.
3616
+
3617
+ ```ts
3618
+ import type { HugeiconsIconDefinition, HeadingLevel } from '@brumaombra/ui-vintage/common-types';
3619
+ ```
3620
+
3621
+ #### Functions, constants, and types
3622
+
3623
+ ```ts
3624
+ type HugeiconsIconDefinition = readonly (readonly [string, { readonly [key: string]: string | number }])[]
3625
+ type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6
3626
+ ```
3627
+
3628
+ ---
3629
+
3630
+ ### `@brumaombra/ui-vintage/utils`
3631
+
3632
+ Class merging (`cn`) and formatting helpers.
3633
+
3634
+ ```ts
3635
+ import { cn, formatDateLongItalyTimezone } from '@brumaombra/ui-vintage/utils';
3636
+ ```
3637
+
3638
+ #### Functions, constants, and types
3639
+
3640
+ ```ts
3641
+ function cn(...inputs: ClassValue[])
3642
+ function formatDateLongItalyTimezone(date: string | number | Date | null | undefined, locale: string)
3643
+ ```