@skunkworksai/ui-kit 0.1.18

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 (274) hide show
  1. package/AGENTS.md +250 -0
  2. package/README.md +429 -0
  3. package/dist/assets/Service-applets-apps/audience-measurement.png +0 -0
  4. package/dist/assets/Service-applets-apps/coatro-app.png +0 -0
  5. package/dist/assets/Service-applets-apps/content-effectiveness.png +0 -0
  6. package/dist/assets/Service-applets-apps/hop-tracking.png +0 -0
  7. package/dist/assets/Service-applets-apps/index.ts +13 -0
  8. package/dist/assets/Service-applets-apps/journeys-app.png +0 -0
  9. package/dist/assets/Service-applets-apps/people-counting.png +0 -0
  10. package/dist/assets/Service-applets-apps/petra.png +0 -0
  11. package/dist/assets/Service-applets-apps/sam-generic.png +0 -0
  12. package/dist/assets/Service-applets-apps/sami-for-environment.png +0 -0
  13. package/dist/assets/Service-applets-apps/shelf-engagement.png +0 -0
  14. package/dist/assets/Service-applets-apps/traffic-management.png +0 -0
  15. package/dist/assets/Service-applets-apps/viana.png +0 -0
  16. package/dist/assets/Service-applets-apps/zone-engagement.png +0 -0
  17. package/dist/assets/icons/Dashboard-active.svg +29 -0
  18. package/dist/assets/icons/Dashboard.svg +25 -0
  19. package/dist/assets/icons/DashboardActiveIcon.tsx +35 -0
  20. package/dist/assets/icons/DashboardIcon.tsx +31 -0
  21. package/dist/assets/icons/Devices-active.svg +27 -0
  22. package/dist/assets/icons/Devices.svg +20 -0
  23. package/dist/assets/icons/DevicesActiveIcon.tsx +33 -0
  24. package/dist/assets/icons/DevicesIcon.tsx +26 -0
  25. package/dist/assets/icons/Installer-active.svg +29 -0
  26. package/dist/assets/icons/Installer.svg +17 -0
  27. package/dist/assets/icons/InstallerActiveIcon.tsx +35 -0
  28. package/dist/assets/icons/InstallerIcon.tsx +23 -0
  29. package/dist/assets/icons/Manifest-active.svg +49 -0
  30. package/dist/assets/icons/Manifest.svg +49 -0
  31. package/dist/assets/icons/ManifestActiveIcon.tsx +55 -0
  32. package/dist/assets/icons/ManifestIcon.tsx +55 -0
  33. package/dist/assets/icons/Sensor-active.svg +15 -0
  34. package/dist/assets/icons/Sensor.svg +11 -0
  35. package/dist/assets/icons/SensorActiveIcon.tsx +21 -0
  36. package/dist/assets/icons/SensorIcon.tsx +17 -0
  37. package/dist/assets/icons/Site-active.svg +14 -0
  38. package/dist/assets/icons/Site.svg +10 -0
  39. package/dist/assets/icons/SiteActiveIcon.tsx +20 -0
  40. package/dist/assets/icons/SiteIcon.tsx +16 -0
  41. package/dist/assets/icons/X-ray-active.svg +199 -0
  42. package/dist/assets/icons/X-ray.svg +47 -0
  43. package/dist/assets/icons/XrayActiveIcon.tsx +205 -0
  44. package/dist/assets/icons/XrayIcon.tsx +53 -0
  45. package/dist/assets/icons/index.ts +14 -0
  46. package/dist/assets/logos/DarkLogo.tsx +28 -0
  47. package/dist/assets/logos/DarkSymbol.tsx +9 -0
  48. package/dist/assets/logos/PrimaryLogo.tsx +28 -0
  49. package/dist/assets/logos/PrimarySymbol.tsx +9 -0
  50. package/dist/assets/logos/WhiteLogo.tsx +28 -0
  51. package/dist/assets/logos/WhiteSymbol.tsx +9 -0
  52. package/dist/assets/logos/dark_logo.svg +22 -0
  53. package/dist/assets/logos/dark_symbol.svg +3 -0
  54. package/dist/assets/logos/index.ts +6 -0
  55. package/dist/assets/logos/primary-logo.svg +22 -0
  56. package/dist/assets/logos/primary_logo.svg +22 -0
  57. package/dist/assets/logos/primary_symbol.svg +3 -0
  58. package/dist/assets/logos/white_symbol.svg +3 -0
  59. package/dist/index.cjs +160 -0
  60. package/dist/index.cjs.map +1 -0
  61. package/dist/index.js +45276 -0
  62. package/dist/index.js.map +1 -0
  63. package/dist/tokens-source.css +121 -0
  64. package/dist/types/assets/Service-applets-apps/index.d.ts +13 -0
  65. package/dist/types/assets/icons/DashboardActiveIcon.d.ts +2 -0
  66. package/dist/types/assets/icons/DashboardIcon.d.ts +2 -0
  67. package/dist/types/assets/icons/DevicesActiveIcon.d.ts +2 -0
  68. package/dist/types/assets/icons/DevicesIcon.d.ts +2 -0
  69. package/dist/types/assets/icons/InstallerActiveIcon.d.ts +2 -0
  70. package/dist/types/assets/icons/InstallerIcon.d.ts +2 -0
  71. package/dist/types/assets/icons/ManifestActiveIcon.d.ts +2 -0
  72. package/dist/types/assets/icons/ManifestIcon.d.ts +2 -0
  73. package/dist/types/assets/icons/SensorActiveIcon.d.ts +2 -0
  74. package/dist/types/assets/icons/SensorIcon.d.ts +2 -0
  75. package/dist/types/assets/icons/SiteActiveIcon.d.ts +2 -0
  76. package/dist/types/assets/icons/SiteIcon.d.ts +2 -0
  77. package/dist/types/assets/icons/XrayActiveIcon.d.ts +2 -0
  78. package/dist/types/assets/icons/XrayIcon.d.ts +2 -0
  79. package/dist/types/assets/icons/index.d.ts +14 -0
  80. package/dist/types/assets/logos/DarkLogo.d.ts +2 -0
  81. package/dist/types/assets/logos/DarkSymbol.d.ts +2 -0
  82. package/dist/types/assets/logos/PrimaryLogo.d.ts +2 -0
  83. package/dist/types/assets/logos/PrimarySymbol.d.ts +2 -0
  84. package/dist/types/assets/logos/WhiteLogo.d.ts +2 -0
  85. package/dist/types/assets/logos/WhiteSymbol.d.ts +2 -0
  86. package/dist/types/assets/logos/index.d.ts +6 -0
  87. package/dist/types/components/blocks/AppBentoMenu.d.ts +31 -0
  88. package/dist/types/components/blocks/AppDashboard.d.ts +121 -0
  89. package/dist/types/components/blocks/AppHeader.d.ts +198 -0
  90. package/dist/types/components/blocks/AppLocationTreeFilter.d.ts +44 -0
  91. package/dist/types/components/blocks/AppNotificationsMenu.d.ts +50 -0
  92. package/dist/types/components/blocks/AppPageTitle.d.ts +86 -0
  93. package/dist/types/components/blocks/AppProfile.d.ts +53 -0
  94. package/dist/types/components/blocks/TableManager.d.ts +194 -0
  95. package/dist/types/components/blocks/backgrounds/AppDashboardBackgroundDots.d.ts +14 -0
  96. package/dist/types/components/blocks/backgrounds/AppDashboardBackgroundWave.d.ts +14 -0
  97. package/dist/types/components/blocks/backgrounds/index.d.ts +3 -0
  98. package/dist/types/components/blocks/backgrounds/types.d.ts +13 -0
  99. package/dist/types/components/blocks/index.d.ts +9 -0
  100. package/dist/types/components/primitives/AppAccordion.d.ts +22 -0
  101. package/dist/types/components/primitives/AppAlert.d.ts +33 -0
  102. package/dist/types/components/primitives/AppAlertDialog.d.ts +79 -0
  103. package/dist/types/components/primitives/AppAspectRatio.d.ts +7 -0
  104. package/dist/types/components/primitives/AppAvatar.d.ts +17 -0
  105. package/dist/types/components/primitives/AppBadge.d.ts +9 -0
  106. package/dist/types/components/primitives/AppBreadcrumb.d.ts +45 -0
  107. package/dist/types/components/primitives/AppButton.d.ts +24 -0
  108. package/dist/types/components/primitives/AppButtonGroup.d.ts +10 -0
  109. package/dist/types/components/primitives/AppCalendar.d.ts +51 -0
  110. package/dist/types/components/primitives/AppCard.d.ts +41 -0
  111. package/dist/types/components/primitives/AppCarousel.d.ts +26 -0
  112. package/dist/types/components/primitives/AppChart.d.ts +27 -0
  113. package/dist/types/components/primitives/AppCheckbox.d.ts +9 -0
  114. package/dist/types/components/primitives/AppCollapsible.d.ts +20 -0
  115. package/dist/types/components/primitives/AppCombobox.d.ts +37 -0
  116. package/dist/types/components/primitives/AppCommand.d.ts +47 -0
  117. package/dist/types/components/primitives/AppContextMenu.d.ts +82 -0
  118. package/dist/types/components/primitives/AppDataTable.d.ts +23 -0
  119. package/dist/types/components/primitives/AppDatePicker.d.ts +26 -0
  120. package/dist/types/components/primitives/AppDialog.d.ts +40 -0
  121. package/dist/types/components/primitives/AppDrawer.d.ts +58 -0
  122. package/dist/types/components/primitives/AppDropdownMenu.d.ts +85 -0
  123. package/dist/types/components/primitives/AppEmpty.d.ts +35 -0
  124. package/dist/types/components/primitives/AppField.d.ts +65 -0
  125. package/dist/types/components/primitives/AppForm.d.ts +58 -0
  126. package/dist/types/components/primitives/AppHoverCard.d.ts +19 -0
  127. package/dist/types/components/primitives/AppInput.d.ts +21 -0
  128. package/dist/types/components/primitives/AppKbd.d.ts +18 -0
  129. package/dist/types/components/primitives/AppLabel.d.ts +8 -0
  130. package/dist/types/components/primitives/AppMenubar.d.ts +83 -0
  131. package/dist/types/components/primitives/AppNavigationMenu.d.ts +51 -0
  132. package/dist/types/components/primitives/AppPagination.d.ts +46 -0
  133. package/dist/types/components/primitives/AppPopover.d.ts +20 -0
  134. package/dist/types/components/primitives/AppProgress.d.ts +9 -0
  135. package/dist/types/components/primitives/AppRadioGroup.d.ts +15 -0
  136. package/dist/types/components/primitives/AppScrollArea.d.ts +12 -0
  137. package/dist/types/components/primitives/AppScrollText.d.ts +7 -0
  138. package/dist/types/components/primitives/AppSelect.d.ts +46 -0
  139. package/dist/types/components/primitives/AppSeparator.d.ts +8 -0
  140. package/dist/types/components/primitives/AppSheet.d.ts +32 -0
  141. package/dist/types/components/primitives/AppSidebar.d.ts +59 -0
  142. package/dist/types/components/primitives/AppSkeleton.d.ts +6 -0
  143. package/dist/types/components/primitives/AppSpinner.d.ts +13 -0
  144. package/dist/types/components/primitives/AppSwitch.d.ts +8 -0
  145. package/dist/types/components/primitives/AppTable.d.ts +53 -0
  146. package/dist/types/components/primitives/AppTabs.d.ts +10 -0
  147. package/dist/types/components/primitives/AppTextarea.d.ts +9 -0
  148. package/dist/types/components/primitives/AppThemeProvider.d.ts +46 -0
  149. package/dist/types/components/primitives/AppToaster.d.ts +7 -0
  150. package/dist/types/components/primitives/AppToggle.d.ts +9 -0
  151. package/dist/types/components/primitives/AppToggleGroup.d.ts +18 -0
  152. package/dist/types/components/primitives/AppTooltip.d.ts +26 -0
  153. package/dist/types/components/primitives/AppTypography.d.ts +80 -0
  154. package/dist/types/components/primitives/index.d.ts +57 -0
  155. package/dist/types/components/ui/accordion.d.ts +7 -0
  156. package/dist/types/components/ui/alert-dialog.d.ts +20 -0
  157. package/dist/types/components/ui/alert.d.ts +8 -0
  158. package/dist/types/components/ui/aspect-ratio.d.ts +4 -0
  159. package/dist/types/components/ui/avatar.d.ts +6 -0
  160. package/dist/types/components/ui/badge.d.ts +9 -0
  161. package/dist/types/components/ui/breadcrumb.d.ts +19 -0
  162. package/dist/types/components/ui/button.d.ts +13 -0
  163. package/dist/types/components/ui/calendar.d.ts +8 -0
  164. package/dist/types/components/ui/card.d.ts +11 -0
  165. package/dist/types/components/ui/carousel.d.ts +28 -0
  166. package/dist/types/components/ui/chart.d.ts +48 -0
  167. package/dist/types/components/ui/checkbox.d.ts +4 -0
  168. package/dist/types/components/ui/collapsible.d.ts +6 -0
  169. package/dist/types/components/ui/combobox.d.ts +83 -0
  170. package/dist/types/components/ui/command.d.ts +82 -0
  171. package/dist/types/components/ui/context-menu.d.ts +27 -0
  172. package/dist/types/components/ui/dialog.d.ts +19 -0
  173. package/dist/types/components/ui/drawer.d.ts +23 -0
  174. package/dist/types/components/ui/dropdown-menu.d.ts +27 -0
  175. package/dist/types/components/ui/empty.d.ts +14 -0
  176. package/dist/types/components/ui/field.d.ts +40 -0
  177. package/dist/types/components/ui/form.d.ts +22 -0
  178. package/dist/types/components/ui/hover-card.d.ts +6 -0
  179. package/dist/types/components/ui/input.d.ts +3 -0
  180. package/dist/types/components/ui/kbd.d.ts +4 -0
  181. package/dist/types/components/ui/label.d.ts +4 -0
  182. package/dist/types/components/ui/menubar.d.ts +30 -0
  183. package/dist/types/components/ui/navigation-menu.d.ts +12 -0
  184. package/dist/types/components/ui/pagination.d.ts +28 -0
  185. package/dist/types/components/ui/popover.d.ts +6 -0
  186. package/dist/types/components/ui/progress.d.ts +4 -0
  187. package/dist/types/components/ui/radio-group.d.ts +5 -0
  188. package/dist/types/components/ui/scroll-area.d.ts +5 -0
  189. package/dist/types/components/ui/scroll-text.d.ts +6 -0
  190. package/dist/types/components/ui/select.d.ts +13 -0
  191. package/dist/types/components/ui/separator.d.ts +4 -0
  192. package/dist/types/components/ui/sheet.d.ts +25 -0
  193. package/dist/types/components/ui/sidebar.d.ts +69 -0
  194. package/dist/types/components/ui/skeleton.d.ts +2 -0
  195. package/dist/types/components/ui/sonner.d.ts +2 -0
  196. package/dist/types/components/ui/switch.d.ts +4 -0
  197. package/dist/types/components/ui/table.d.ts +10 -0
  198. package/dist/types/components/ui/tabs.d.ts +19 -0
  199. package/dist/types/components/ui/textarea.d.ts +5 -0
  200. package/dist/types/components/ui/toggle-group.d.ts +15 -0
  201. package/dist/types/components/ui/toggle.d.ts +12 -0
  202. package/dist/types/components/ui/tooltip.d.ts +7 -0
  203. package/dist/types/hooks/use-mobile.d.ts +13 -0
  204. package/dist/types/hooks/use-page-title.d.ts +23 -0
  205. package/dist/types/index.d.ts +2 -0
  206. package/dist/types/lib/utils.d.ts +2 -0
  207. package/dist/ui-kit.css +1 -0
  208. package/package.json +117 -0
  209. package/rules/accordion.md +60 -0
  210. package/rules/alert-dialog.md +62 -0
  211. package/rules/alert.md +61 -0
  212. package/rules/aspect-ratio.md +47 -0
  213. package/rules/avatar.md +52 -0
  214. package/rules/badge.md +55 -0
  215. package/rules/bento-menu.md +86 -0
  216. package/rules/breadcrumb.md +80 -0
  217. package/rules/button-group.md +58 -0
  218. package/rules/button.md +66 -0
  219. package/rules/calendar.md +97 -0
  220. package/rules/card.md +84 -0
  221. package/rules/carousel.md +113 -0
  222. package/rules/chart.md +125 -0
  223. package/rules/checkbox.md +49 -0
  224. package/rules/collapsible.md +57 -0
  225. package/rules/combobox.md +133 -0
  226. package/rules/command.md +73 -0
  227. package/rules/context-menu.md +65 -0
  228. package/rules/dashboard.md +368 -0
  229. package/rules/data-table.md +91 -0
  230. package/rules/date-picker.md +65 -0
  231. package/rules/dialog.md +60 -0
  232. package/rules/drawer.md +65 -0
  233. package/rules/dropdown-menu.md +72 -0
  234. package/rules/empty.md +110 -0
  235. package/rules/field.md +149 -0
  236. package/rules/form.md +60 -0
  237. package/rules/header.md +245 -0
  238. package/rules/hover-card.md +53 -0
  239. package/rules/icons.md +141 -0
  240. package/rules/input.md +66 -0
  241. package/rules/kbd.md +58 -0
  242. package/rules/label.md +30 -0
  243. package/rules/location-tree-filter.md +165 -0
  244. package/rules/logo.md +58 -0
  245. package/rules/menubar.md +75 -0
  246. package/rules/navigation-menu.md +68 -0
  247. package/rules/notifications-menu.md +137 -0
  248. package/rules/pagetitle.md +160 -0
  249. package/rules/pagination.md +71 -0
  250. package/rules/popover.md +48 -0
  251. package/rules/profile.md +125 -0
  252. package/rules/progress.md +41 -0
  253. package/rules/radio-group.md +44 -0
  254. package/rules/scroll-area.md +32 -0
  255. package/rules/scroll-text.md +40 -0
  256. package/rules/select.md +86 -0
  257. package/rules/separator.md +43 -0
  258. package/rules/sheet.md +76 -0
  259. package/rules/sidebar.md +442 -0
  260. package/rules/skeleton.md +46 -0
  261. package/rules/spinner.md +43 -0
  262. package/rules/switch.md +46 -0
  263. package/rules/table-manager.md +306 -0
  264. package/rules/table.md +177 -0
  265. package/rules/tabs.md +82 -0
  266. package/rules/text.md +3 -0
  267. package/rules/textarea.md +38 -0
  268. package/rules/toaster.md +58 -0
  269. package/rules/toggle-group.md +50 -0
  270. package/rules/toggle.md +40 -0
  271. package/rules/tokens.md +88 -0
  272. package/rules/tooltip.md +78 -0
  273. package/rules/typography.md +81 -0
  274. package/scripts/scaffold.mjs +28 -0
@@ -0,0 +1,442 @@
1
+ # AppSidebar
2
+
3
+ > Docs: https://ui-kit.vercel.app/docs/components/sidebar
4
+
5
+ ```tsx
6
+ import {
7
+ AppSidebarProvider,
8
+ AppSidebar,
9
+ AppSidebarBrand,
10
+ AppSidebarTrigger,
11
+ AppSidebarRail,
12
+ AppSidebarInset,
13
+ AppSidebarHeader,
14
+ AppSidebarContent,
15
+ AppSidebarFooter,
16
+ AppSidebarSeparator,
17
+ AppSidebarInput,
18
+ AppSidebarGroup,
19
+ AppSidebarGroupLabel,
20
+ AppSidebarGroupAction,
21
+ AppSidebarGroupContent,
22
+ AppSidebarMenu,
23
+ AppSidebarMenuItem,
24
+ AppSidebarMenuButton,
25
+ AppSidebarMenuAction,
26
+ AppSidebarMenuBadge,
27
+ AppSidebarMenuSkeleton,
28
+ AppSidebarMenuSub,
29
+ AppSidebarMenuSubItem,
30
+ AppSidebarMenuSubButton,
31
+ useSidebar,
32
+ } from "@/components/primitives/AppSidebar"
33
+ ```
34
+
35
+ ## AppSidebarProvider
36
+
37
+ | Prop | Type | Default | Description |
38
+ | :--- | :--- | :--- | :--- |
39
+ | `defaultOpen` | `boolean` | `true` | Initial open state (uncontrolled). |
40
+ | `open` | `boolean` | — | Controlled open state. |
41
+ | `onOpenChange` | `(open: boolean) => void` | — | Callback for open state changes. |
42
+
43
+ ## AppSidebar
44
+
45
+ | Prop | Type | Default | Description |
46
+ | :--- | :--- | :--- | :--- |
47
+ | `side` | `"left" \| "right"` | `"left"` | Which edge the sidebar is anchored to. |
48
+ | `variant` | `"sidebar" \| "floating" \| "inset"` | `"sidebar"` | Visual presentation style. |
49
+ | `collapsible` | `"offcanvas" \| "icon" \| "none"` | `"offcanvas"` | How the sidebar collapses. |
50
+
51
+ ## AppSidebarBrand
52
+
53
+ Place as the first child of `AppSidebarHeader`. The logo is always **horizontally centered**. When a `dropdown` is provided, the chevron is absolutely positioned to the right edge so it does not shift the logo off-center.
54
+
55
+ | Prop | Type | Default | Description |
56
+ | :--- | :--- | :--- | :--- |
57
+ | `logo` | `string \| ReactNode` | `<WhiteLogo width={90} height={28} />` | Text label or logo component. Defaults to the white UI Kit logo for dark backgrounds. |
58
+ | `collapsedLogo` | `ReactNode` | `<WhiteSymbol width={24} height={24} />` | Icon shown when the sidebar is collapsed to icon mode. |
59
+ | `dropdown` | `AppSidebarBrandDropdownItem[]` | — | When provided, wraps the brand in a dropdown trigger. Omit for a non-interactive header. |
60
+ | `showChevron` | `boolean` | `true` | Show the caret icon. Only applies when `dropdown` is set. |
61
+ | `className` | `string` | — | Additional classes for the brand container. Supports `--sidebar-brand-px` CSS variable (see below). |
62
+
63
+ ### Collapsed brand padding
64
+
65
+ The brand container uses `--sidebar-brand-px` (default `0.5rem` = `px-2`) for horizontal padding. Override via `className` to make the symbol flush when collapsed:
66
+
67
+ ```tsx
68
+ // Zero padding — symbol fills the full icon-mode width
69
+ <AppSidebarBrand className="[--sidebar-brand-px:0]" />
70
+
71
+ // Or via AppDashboard brand prop
72
+ <AppDashboard brand={{ className: "[--sidebar-brand-px:0]" }}>...</AppDashboard>
73
+ ```
74
+
75
+ The `data-sidebar-brand` attribute is present on the wrapper for CSS selector hooks if needed.
76
+
77
+ ### AppSidebarBrandDropdownItem
78
+
79
+ Two shapes are accepted in the same array:
80
+
81
+ ```ts
82
+ // Regular item
83
+ { label: string; onClick?: () => void; icon?: ReactNode; disabled?: boolean }
84
+
85
+ // Separator
86
+ { separator: true }
87
+ ```
88
+
89
+ ## DEFAULT_NAV
90
+
91
+ A built-in navigation constant exported from `AppSidebar`. It pre-wires the four standard UI Kit nav sections with custom inline SVG icons and active/default icon pairs — no manual setup required.
92
+
93
+ ```ts
94
+ import { DEFAULT_NAV } from "@/components/primitives/AppSidebar"
95
+ ```
96
+
97
+ ### Structure
98
+
99
+ | Group label | Menu item |
100
+ |---|---|
101
+ | *(no label)* | Dashboard |
102
+ | MANAGE | Site, Devices, Sensor |
103
+ | INSIGHTS | X-ray, Manifest |
104
+ | DOWNLOADS | Installers |
105
+
106
+ All `href` values default to `"#"`. Override by passing a custom `nav` prop to `AppDashboard`, or by iterating `DEFAULT_NAV` and replacing `href` values in your app.
107
+
108
+ ### Using DEFAULT_NAV directly
109
+
110
+ ```tsx
111
+ import { DEFAULT_NAV } from "@/components/primitives/AppSidebar"
112
+
113
+ <AppSidebarContent>
114
+ {DEFAULT_NAV.map((section, i) => (
115
+ <AppSidebarGroup key={i}>
116
+ {section.label && (
117
+ <AppSidebarGroupLabel>{section.label}</AppSidebarGroupLabel>
118
+ )}
119
+ <AppSidebarGroupContent>
120
+ <AppSidebarMenu>
121
+ {section.items.map((item) => (
122
+ <AppSidebarMenuItem key={item.title}>
123
+ <AppSidebarMenuButton
124
+ isActive={item.title === "Dashboard"}
125
+ tooltip={item.title}
126
+ >
127
+ <item.icon />
128
+ <span>{item.title}</span>
129
+ </AppSidebarMenuButton>
130
+ </AppSidebarMenuItem>
131
+ ))}
132
+ </AppSidebarMenu>
133
+ </AppSidebarGroupContent>
134
+ </AppSidebarGroup>
135
+ ))}
136
+ </AppSidebarContent>
137
+ ```
138
+
139
+ When using `AppDashboard`, the default nav renders automatically — no prop needed. See [AppDashboard rules](/rules/dashboard.md).
140
+
141
+ ---
142
+
143
+ ## Active/default icon swap
144
+
145
+ Each `DEFAULT_NAV` icon component renders **two** icon variants simultaneously — the default state icon and the active state icon. Visibility is controlled entirely by CSS using the `group/menu-button` data attribute on `AppSidebarMenuButton`:
146
+
147
+ ```
148
+ default state → group-data-[active=true]/menu-button:hidden (visible by default, hidden when active)
149
+ active state → hidden group-data-[active=true]/menu-button:block (hidden by default, shown when active)
150
+ ```
151
+
152
+ This mechanism is internal to the nav-icon components and requires no code from consumers. Simply pass `isActive={true}` to `AppSidebarMenuButton` and both the background fill and the icon variant update automatically.
153
+
154
+ **Custom icon with active swap:**
155
+
156
+ ```tsx
157
+ function MyNavIcon() {
158
+ return (
159
+ <>
160
+ <span className="group-data-[active=true]/menu-button:hidden">
161
+ <MyDefaultIcon />
162
+ </span>
163
+ <span className="hidden group-data-[active=true]/menu-button:block">
164
+ <MyActiveIcon />
165
+ </span>
166
+ </>
167
+ )
168
+ }
169
+
170
+ <AppSidebarMenuButton isActive={isCurrentRoute} tooltip="My Section">
171
+ <MyNavIcon />
172
+ <span>My Section</span>
173
+ </AppSidebarMenuButton>
174
+ ```
175
+
176
+ SVG icons must be rendered as React components (inline SVG), not `<img>` tags, so they respond to CSS.
177
+
178
+ ---
179
+
180
+ ## AppSidebarMenuButton
181
+
182
+ No background fill by default or on hover. The **primary brand color** background is applied **only when `isActive={true}`** — using `bg-primary` and `text-primary-foreground`.
183
+
184
+ > **Note:** Tailwind v4 compiles `data-active:` to the CSS selector `[data-active]`, which matches all buttons (the attribute is always present). `AppSidebarMenuButton` corrects this by overriding with `data-active:bg-transparent` and re-applying the primary color only via `data-[active=true]:bg-primary data-[active=true]:text-primary-foreground`.
185
+
186
+ **Size overrides:** `AppSidebarMenuButton` bumps the shadcn defaults for a slightly larger feel:
187
+ - Icons: `[&_svg]:size-5` (20 px vs shadcn's 16 px)
188
+ - Font: `text-base` (16 px vs shadcn's 14 px)
189
+
190
+ | Prop | Type | Default | Description |
191
+ | :--- | :--- | :--- | :--- |
192
+ | `asChild` | `boolean` | `false` | Render as child element (e.g. a router Link). |
193
+ | `isActive` | `boolean` | `false` | Marks this item as the active route. Applies accent background + medium font weight + active icon variant. |
194
+ | `variant` | `"default" \| "outline"` | `"default"` | Visual style. |
195
+ | `size` | `"default" \| "sm" \| "lg"` | `"default"` | Height and text size. |
196
+ | `tooltip` | `string \| TooltipContentProps` | — | Tooltip shown when sidebar is collapsed to icon mode. |
197
+
198
+ ## AppSidebarMenuSubButton
199
+
200
+ | Prop | Type | Default | Description |
201
+ | :--- | :--- | :--- | :--- |
202
+ | `asChild` | `boolean` | `false` | Render as child element. |
203
+ | `isActive` | `boolean` | `false` | Marks the sub-item as active. |
204
+ | `size` | `"sm" \| "md"` | `"md"` | Text size. |
205
+
206
+ ## AppSidebarMenuSkeleton
207
+
208
+ | Prop | Type | Default | Description |
209
+ | :--- | :--- | :--- | :--- |
210
+ | `showIcon` | `boolean` | `false` | Show a skeleton icon placeholder. |
211
+
212
+ ## useSidebar
213
+
214
+ Returns `{ state, open, setOpen, openMobile, setOpenMobile, isMobile, toggleSidebar }`.
215
+
216
+ Must be called inside an `AppSidebarProvider`.
217
+
218
+ ---
219
+
220
+ ## Usage
221
+
222
+ ### Default (App logo, no dropdown)
223
+
224
+ ```tsx
225
+ <AppSidebarHeader>
226
+ <AppSidebarBrand />
227
+ </AppSidebarHeader>
228
+ ```
229
+
230
+ ### Text logo
231
+
232
+ ```tsx
233
+ <AppSidebarHeader>
234
+ <AppSidebarBrand logo="My App" />
235
+ </AppSidebarHeader>
236
+ ```
237
+
238
+ ### Image logo
239
+
240
+ ```tsx
241
+ import { WhiteLogo } from "@/assets/logos"
242
+
243
+ <AppSidebarHeader>
244
+ <AppSidebarBrand logo={<WhiteLogo width={90} height={28} />} />
245
+ </AppSidebarHeader>
246
+ ```
247
+
248
+ ### With workspace dropdown
249
+
250
+ ```tsx
251
+ <AppSidebarBrand
252
+ dropdown={[
253
+ { label: "Acme Corp", onClick: () => switchWorkspace("acme") },
254
+ { label: "Personal", onClick: () => switchWorkspace("personal") },
255
+ { separator: true },
256
+ { label: "Create workspace", onClick: openCreateModal },
257
+ ]}
258
+ />
259
+ ```
260
+
261
+ ### Dropdown with icons
262
+
263
+ ```tsx
264
+ import { UserIcon, CreditCardIcon, LogOutIcon } from "lucide-react"
265
+
266
+ <AppSidebarBrand
267
+ dropdown={[
268
+ { label: "Profile", icon: <UserIcon className="size-4" />, onClick: goToProfile },
269
+ { label: "Billing", icon: <CreditCardIcon className="size-4" />, onClick: goToBilling },
270
+ { separator: true },
271
+ { label: "Log out", icon: <LogOutIcon className="size-4" />, onClick: logout },
272
+ ]}
273
+ />
274
+ ```
275
+
276
+ ### Disable the chevron
277
+
278
+ ```tsx
279
+ <AppSidebarBrand dropdown={items} showChevron={false} />
280
+ ```
281
+
282
+ Use `showChevron={false}` when the logo itself already communicates the affordance, or for a minimal header style. The dropdown still works — the entire brand area remains clickable.
283
+
284
+ ### Full layout with DEFAULT_NAV
285
+
286
+ Use the built-in nav — no icons to import, no sections to define:
287
+
288
+ ```tsx
289
+ import { DEFAULT_NAV } from "@/components/primitives/AppSidebar"
290
+
291
+ <AppSidebarProvider>
292
+ <AppSidebar collapsible="icon">
293
+ <AppSidebarHeader>
294
+ <AppSidebarBrand dropdown={workspaces} />
295
+ </AppSidebarHeader>
296
+ <AppSidebarContent>
297
+ {DEFAULT_NAV.map((section, i) => (
298
+ <AppSidebarGroup key={i}>
299
+ {section.label && (
300
+ <AppSidebarGroupLabel>{section.label}</AppSidebarGroupLabel>
301
+ )}
302
+ <AppSidebarGroupContent>
303
+ <AppSidebarMenu>
304
+ {section.items.map((item) => (
305
+ <AppSidebarMenuItem key={item.title}>
306
+ <AppSidebarMenuButton
307
+ isActive={item.title === "Dashboard"}
308
+ tooltip={item.title}
309
+ >
310
+ <item.icon />
311
+ <span>{item.title}</span>
312
+ </AppSidebarMenuButton>
313
+ </AppSidebarMenuItem>
314
+ ))}
315
+ </AppSidebarMenu>
316
+ </AppSidebarGroupContent>
317
+ </AppSidebarGroup>
318
+ ))}
319
+ </AppSidebarContent>
320
+ <AppSidebarFooter>
321
+ <span className="text-xs text-sidebar-foreground/50">v1.0.0</span>
322
+ </AppSidebarFooter>
323
+ <AppSidebarRail />
324
+ </AppSidebar>
325
+ <AppSidebarInset>
326
+ <header className="flex items-center gap-2 border-b border-border px-4 py-3">
327
+ <AppSidebarTrigger />
328
+ </header>
329
+ <main>Page content</main>
330
+ </AppSidebarInset>
331
+ </AppSidebarProvider>
332
+ ```
333
+
334
+ ### Full layout with custom nav sections
335
+
336
+ To use your own icons and items instead of DEFAULT_NAV:
337
+
338
+ ```tsx
339
+ function MyDashboardNavIcon() {
340
+ return (
341
+ <>
342
+ <span className="group-data-[active=true]/menu-button:hidden">
343
+ <MyDefaultIcon />
344
+ </span>
345
+ <span className="hidden group-data-[active=true]/menu-button:block">
346
+ <MyActiveIcon />
347
+ </span>
348
+ </>
349
+ )
350
+ }
351
+
352
+ const myNav = [
353
+ { items: [{ title: "Home", icon: MyDashboardNavIcon }] },
354
+ ]
355
+
356
+ <AppSidebarProvider>
357
+ <AppSidebar collapsible="icon">
358
+ ...
359
+ <AppSidebarContent>
360
+ {myNav.map((section, i) => (
361
+ <AppSidebarGroup key={i}>
362
+ <AppSidebarGroupContent>
363
+ <AppSidebarMenu>
364
+ {section.items.map((item) => (
365
+ <AppSidebarMenuItem key={item.title}>
366
+ <AppSidebarMenuButton isActive tooltip={item.title}>
367
+ <item.icon />
368
+ <span>{item.title}</span>
369
+ </AppSidebarMenuButton>
370
+ </AppSidebarMenuItem>
371
+ ))}
372
+ </AppSidebarMenu>
373
+ </AppSidebarGroupContent>
374
+ </AppSidebarGroup>
375
+ ))}
376
+ </AppSidebarContent>
377
+ </AppSidebar>
378
+ </AppSidebarProvider>
379
+ ```
380
+
381
+ ### Menu button as link
382
+
383
+ ```tsx
384
+ <AppSidebarMenuButton asChild isActive>
385
+ <a href="/dashboard">Dashboard</a>
386
+ </AppSidebarMenuButton>
387
+ ```
388
+
389
+ ### With submenu
390
+
391
+ ```tsx
392
+ <AppSidebarMenu>
393
+ <AppSidebarMenuItem>
394
+ <AppSidebarMenuButton>Projects</AppSidebarMenuButton>
395
+ <AppSidebarMenuSub>
396
+ <AppSidebarMenuSubItem>
397
+ <AppSidebarMenuSubButton asChild>
398
+ <a href="/projects/alpha">Alpha</a>
399
+ </AppSidebarMenuSubButton>
400
+ </AppSidebarMenuSubItem>
401
+ </AppSidebarMenuSub>
402
+ </AppSidebarMenuItem>
403
+ </AppSidebarMenu>
404
+ ```
405
+
406
+ ### Containing sidebar inside a preview box
407
+
408
+ When embedding a sidebar inside a fixed-height container (e.g. a component preview), the sidebar uses `position: fixed` which breaks out of the parent. Add `[contain:layout]` to the wrapper to create a containing block. The sidebar has a transparent background, so the wrapper must provide a dark background:
409
+
410
+ ```tsx
411
+ <div className="dark relative h-96 overflow-hidden rounded-lg border bg-linear-to-br from-background via-muted to-card [contain:layout]">
412
+ <AppSidebarProvider className="min-h-0 h-full">
413
+ <AppSidebar collapsible="icon">...</AppSidebar>
414
+ <AppSidebarInset>...</AppSidebarInset>
415
+ </AppSidebarProvider>
416
+ </div>
417
+ ```
418
+
419
+ ---
420
+
421
+ ## Rules
422
+
423
+ - **Do** use `DEFAULT_NAV` as the starting point — it pre-wires all standard UI Kit nav sections with correct icons and active/default swap.
424
+ - **Do** always include an icon and a `<span>` label inside each `AppSidebarMenuButton` — both are required for icon-only collapsed mode.
425
+ - **Do** place the sidebar inside a dark container (e.g. `AppDashboard` or a dark gradient wrapper) — the sidebar background is transparent by default with light text.
426
+ - **Do** wrap the entire page layout in `AppSidebarProvider` — it manages state for all children.
427
+ - **Do** use `AppSidebarInset` as the wrapper for your main content area.
428
+ - **Do** add `AppSidebarRail` inside `AppSidebar` to allow drag-to-resize on desktop.
429
+ - **Do** place `AppSidebarBrand` inside `AppSidebarHeader` as the first child.
430
+ - **Do** pass a `tooltip` to `AppSidebarMenuButton` when using `collapsible="icon"` so labels remain accessible.
431
+ - **Do** use `AppSidebarMenuButton asChild` with a router `<Link>` for navigation items.
432
+ - **Do** use `isActive` to mark the current route — never apply manual background classes to menu items.
433
+ - **Do** render custom icons as React components (inline SVG) — not `<img>` tags — so they respond to CSS for the active icon swap.
434
+ - **Don't** nest `AppSidebarProvider` — one per layout root.
435
+ - **Don't** use raw `<button>` or `<a>` tags for menu items; always go through `AppSidebarMenuButton`.
436
+ - **Don't** use `AppSidebarMenuSub` more than one level deep.
437
+ - **Don't** skip `AppSidebarBrand` and wire up a logo manually — use the component for consistent centering and interaction.
438
+ - **Don't** add `hover:bg-*` or `bg-*` classes to `AppSidebarMenuButton` — the fill behaviour is intentionally controlled by `isActive` only.
439
+ - **Don't** import `DashboardNavIcon`, `SiteNavIcon`, or other internal nav-icon wrapper components — they are not exported. Use `DEFAULT_NAV` or build your own using the active/default swap pattern above.
440
+ - **Don't** add global CSS or `!important` overrides to change sidebar brand padding — use `className="[--sidebar-brand-px:0]"` on `AppSidebarBrand` instead.
441
+
442
+ If a prop you need is missing, stop and inform the design team.
@@ -0,0 +1,46 @@
1
+ # AppSkeleton
2
+
3
+ > Docs: https://ui-kit.vercel.app/docs/components/skeleton
4
+
5
+ ```tsx
6
+ import { AppSkeleton } from "@/components/primitives/AppSkeleton"
7
+ ```
8
+
9
+ ## AppSkeleton
10
+
11
+ | Prop | Type | Default | Description |
12
+ | :--- | :--- | :--- | :--- |
13
+ | `className` | `string` | - | Used to set dimensions and shape (e.g. `h-10 w-10 rounded-full`). |
14
+
15
+ ## Usage
16
+
17
+ ### Simple Card Skeleton
18
+ ```tsx
19
+ <div className="flex items-center space-x-4">
20
+ <AppSkeleton className="h-12 w-12 rounded-full" />
21
+ <div className="space-y-2">
22
+ <AppSkeleton className="h-4 w-[250px]" />
23
+ <AppSkeleton className="h-4 w-[200px]" />
24
+ </div>
25
+ </div>
26
+ ```
27
+
28
+ ### Profile Skeleton
29
+ ```tsx
30
+ <div className="flex flex-col space-y-3">
31
+ <AppSkeleton className="h-[125px] w-[250px] rounded-xl" />
32
+ <div className="space-y-2">
33
+ <AppSkeleton className="h-4 w-[250px]" />
34
+ <AppSkeleton className="h-4 w-[200px]" />
35
+ </div>
36
+ </div>
37
+ ```
38
+
39
+ ## Rules
40
+
41
+ - **Do** use `AppSkeleton` to indicate content is loading, mirroring the actual layout.
42
+ - **Do** use consistent spacing and sizing that matches the final component.
43
+ - **Don't** use `AppSkeleton` for purely decorative elements.
44
+ - **Don't** use too many skeletons at once if it causes excessive flickering on fast connections.
45
+
46
+ If a prop you need is missing, stop and inform the design team.
@@ -0,0 +1,43 @@
1
+ # AppSpinner
2
+
3
+ > Docs: https://ui-kit.vercel.app/docs/components/spinner
4
+
5
+ ```tsx
6
+ import { AppSpinner } from "@/components/primitives/AppSpinner"
7
+ ```
8
+
9
+ ## AppSpinner
10
+
11
+ | Prop | Type | Default | Description |
12
+ | :--- | :--- | :--- | :--- |
13
+ | `label` | `string` | `"Loading..."` | The accessible label for screen readers. |
14
+ | `className` | `string` | - | Used to set size (`h-x w-x`) and color (`text-x`). |
15
+
16
+ ## Usage
17
+
18
+ ### Default Spinner
19
+ ```tsx
20
+ <AppSpinner />
21
+ ```
22
+
23
+ ### Colored and Sized Spinner
24
+ ```tsx
25
+ <AppSpinner className="h-8 w-8 text-primary" label="Uploading..." />
26
+ ```
27
+
28
+ ### Spinner in Button
29
+ ```tsx
30
+ <AppButton disabled>
31
+ <AppSpinner className="h-4 w-4" />
32
+ Saving...
33
+ </AppButton>
34
+ ```
35
+
36
+ ## Rules
37
+
38
+ - **Do** use `AppSpinner` for discrete loading states within components.
39
+ - **Do** provide a descriptive `label` if the loading context isn't obvious.
40
+ - **Don't** use `AppSpinner` for full-page loading if a skeleton is more appropriate.
41
+ - **Don't** forget to disable interaction on buttons when showing a spinner inside them.
42
+
43
+ If a prop you need is missing, stop and inform the design team.
@@ -0,0 +1,46 @@
1
+ # AppSwitch
2
+
3
+ > Docs: https://ui-kit.vercel.app/docs/components/switch
4
+
5
+ ```tsx
6
+ import { AppSwitch } from "@/components/primitives/AppSwitch"
7
+ ```
8
+
9
+ ## AppSwitch
10
+
11
+ | Prop | Type | Default | Description |
12
+ | :--- | :--- | :--- | :--- |
13
+ | `checked` | `boolean` | - | Controlled checked state. |
14
+ | `defaultChecked` | `boolean` | - | Initial checked state. |
15
+ | `onCheckedChange` | `(checked: boolean) => void` | - | Callback for checked state changes. |
16
+ | `disabled` | `boolean` | `false` | When `true`, prevents the user from interacting with the switch. |
17
+
18
+ ## Usage
19
+
20
+ ### Basic Switch
21
+ ```tsx
22
+ <div className="flex items-center space-x-2">
23
+ <AppSwitch id="airplane-mode" />
24
+ <AppLabel htmlFor="airplane-mode">Airplane Mode</AppLabel>
25
+ </div>
26
+ ```
27
+
28
+ ### Controlled Switch
29
+ ```tsx
30
+ const [enabled, setEnabled] = useState(false);
31
+
32
+ return (
33
+ <AppSwitch
34
+ checked={enabled}
35
+ onCheckedChange={setEnabled}
36
+ />
37
+ );
38
+ ```
39
+
40
+ ## Rules
41
+
42
+ - **Do** use `AppSwitch` for toggling settings that take effect immediately.
43
+ - **Do** always pair `AppSwitch` with a label for accessibility.
44
+ - **Don't** use `AppSwitch` for multiple selection; use `AppCheckbox` instead.
45
+
46
+ If a prop you need is missing, stop and inform the design team.