shapes-ui 0.4.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (149) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.yml +47 -0
  2. package/.github/ISSUE_TEMPLATE/config.yml +1 -0
  3. package/.github/ISSUE_TEMPLATE/feature_request.yml +31 -0
  4. package/.github/pull_request_template.md +14 -0
  5. package/.github/workflows/pr-preview.yml +68 -0
  6. package/.github/workflows/release.yml +8 -0
  7. package/.idea/compiler.xml +6 -0
  8. package/.idea/copilot.data.migration.ask2agent.xml +6 -0
  9. package/.idea/vcs.xml +6 -0
  10. package/CHANGELOG.md +31 -0
  11. package/CODE_OF_CONDUCT.md +41 -0
  12. package/CONTRIBUTING.md +52 -0
  13. package/README.md +5 -0
  14. package/SECURITY.md +0 -0
  15. package/content/components/field.mdx +2 -2
  16. package/content/components/fieldset.mdx +1 -1
  17. package/content/components/menubar.mdx +4 -2
  18. package/content/components/meter.mdx +13 -1
  19. package/content/components/navigation-menu.mdx +6 -0
  20. package/content/components/number-field.mdx +24 -0
  21. package/content/components/popover.mdx +20 -0
  22. package/content/components/preview-card.mdx +11 -0
  23. package/content/components/progress.mdx +2 -0
  24. package/content/components/radio.mdx +20 -0
  25. package/content/components/select.mdx +30 -0
  26. package/content/components/slider.mdx +48 -0
  27. package/content/components/switch.mdx +26 -0
  28. package/content/components/tabs.mdx +32 -0
  29. package/content/components/toast.mdx +60 -0
  30. package/content/components/toggle.mdx +34 -2
  31. package/content/components/toolbar.mdx +26 -0
  32. package/content/components/tooltip.mdx +25 -0
  33. package/content-collections.ts +1 -1
  34. package/examples/__index.tsx +231 -0
  35. package/examples/checkbox-demo.tsx +1 -1
  36. package/examples/checkbox-form.tsx +3 -3
  37. package/examples/field-custom-control.tsx +33 -9
  38. package/examples/form-demo.tsx +5 -10
  39. package/examples/menu-advanced.tsx +1 -3
  40. package/examples/menu-align.tsx +19 -16
  41. package/examples/menu-checkbox.tsx +2 -3
  42. package/examples/menu-demo.tsx +1 -3
  43. package/examples/menu-group.tsx +1 -3
  44. package/examples/menu-radio.tsx +1 -3
  45. package/examples/menu-submenu.tsx +2 -3
  46. package/examples/menubar-advanced.tsx +91 -0
  47. package/examples/meter-demo.tsx +8 -21
  48. package/examples/meter-flip.tsx +13 -0
  49. package/examples/meter-no-label.tsx +12 -0
  50. package/examples/meter-no-value.tsx +12 -0
  51. package/examples/navigation-menu-demo.tsx +113 -1
  52. package/examples/number-field-buttons-end.tsx +20 -0
  53. package/examples/number-field-demo.tsx +17 -1
  54. package/examples/number-field-scrub.tsx +38 -0
  55. package/examples/popover-demo.tsx +18 -1
  56. package/examples/popover-form.tsx +46 -0
  57. package/examples/popover-positions.tsx +54 -0
  58. package/examples/preview-card-demo.tsx +26 -1
  59. package/examples/preview-card-links.tsx +38 -0
  60. package/examples/progress-demo.tsx +33 -1
  61. package/examples/radio-card.tsx +28 -0
  62. package/examples/radio-demo.tsx +19 -1
  63. package/examples/radio-description.tsx +26 -0
  64. package/examples/radio-orientation.tsx +21 -0
  65. package/examples/select-alignment.tsx +51 -0
  66. package/examples/select-demo.tsx +36 -1
  67. package/examples/select-disabled.tsx +38 -0
  68. package/examples/select-groups.tsx +54 -0
  69. package/examples/select-invalid.tsx +41 -0
  70. package/examples/select-scrollable.tsx +112 -0
  71. package/examples/slider-controlled.tsx +28 -0
  72. package/examples/slider-demo.tsx +3 -1
  73. package/examples/slider-disabled.tsx +7 -0
  74. package/examples/slider-edge.tsx +13 -0
  75. package/examples/slider-multiple.tsx +7 -0
  76. package/examples/slider-range.tsx +5 -0
  77. package/examples/slider-vertical.tsx +10 -0
  78. package/examples/switch-demo.tsx +19 -1
  79. package/examples/switch-disabled.tsx +20 -0
  80. package/examples/switch-sizes.tsx +24 -0
  81. package/examples/switch-with-label.tsx +16 -0
  82. package/examples/tabs-demo.tsx +14 -1
  83. package/examples/tabs-disabled.tsx +21 -0
  84. package/examples/tabs-line.tsx +18 -0
  85. package/examples/tabs-vertical.tsx +13 -0
  86. package/examples/toast-action.tsx +39 -0
  87. package/examples/toast-anchored.tsx +36 -0
  88. package/examples/toast-demo.tsx +27 -1
  89. package/examples/toast-positions.tsx +54 -0
  90. package/examples/toast-promise.tsx +51 -0
  91. package/examples/toast-stacked.tsx +30 -0
  92. package/examples/toast-timeout.tsx +43 -0
  93. package/examples/toast-update.tsx +38 -0
  94. package/examples/toast-variants.tsx +54 -0
  95. package/examples/toggle-controlled.tsx +20 -0
  96. package/examples/toggle-demo.tsx +7 -51
  97. package/examples/toggle-group-demo.tsx +19 -0
  98. package/examples/toggle-group-multiple.tsx +19 -0
  99. package/examples/toggle-icon-fill.tsx +12 -0
  100. package/examples/toolbar-demo.tsx +45 -21
  101. package/examples/toolbar-input-link.tsx +35 -0
  102. package/examples/toolbar-menu.tsx +53 -0
  103. package/examples/tooltip-demo.tsx +48 -0
  104. package/examples/tooltip-positions.tsx +60 -0
  105. package/package.json +8 -8
  106. package/public/r/drawer.json +1 -1
  107. package/public/r/field.json +1 -1
  108. package/public/r/menubar.json +1 -1
  109. package/public/r/meter.json +1 -1
  110. package/public/r/navigation-menu.json +1 -1
  111. package/public/r/number-field.json +4 -2
  112. package/public/r/popover.json +1 -1
  113. package/public/r/preview-card.json +1 -1
  114. package/public/r/progress.json +1 -1
  115. package/public/r/radio.json +1 -1
  116. package/public/r/select.json +1 -1
  117. package/public/r/slider.json +1 -1
  118. package/public/r/switch.json +1 -1
  119. package/public/r/tabs.json +1 -1
  120. package/public/r/toast.json +2 -1
  121. package/public/r/toggle.json +1 -1
  122. package/public/r/toolbar.json +1 -1
  123. package/public/r/tooltip.json +15 -0
  124. package/src/components/docs/layout/header.tsx +4 -14
  125. package/src/components/docs/layout/mobile-menu.tsx +27 -78
  126. package/src/components/docs/layout/nav-list.tsx +27 -21
  127. package/src/components/docs/layout/split-layout.tsx +6 -3
  128. package/src/components/ui/badge.tsx +1 -1
  129. package/src/components/ui/checkbox.tsx +1 -1
  130. package/src/components/ui/drawer.tsx +1 -1
  131. package/src/components/ui/field.tsx +9 -28
  132. package/src/components/ui/form.tsx +1 -1
  133. package/src/components/ui/menubar.tsx +52 -18
  134. package/src/components/ui/meter.tsx +12 -24
  135. package/src/components/ui/navigation-menu.tsx +121 -38
  136. package/src/components/ui/number-field.tsx +42 -46
  137. package/src/components/ui/popover.tsx +7 -2
  138. package/src/components/ui/preview-card.tsx +4 -2
  139. package/src/components/ui/progress.tsx +7 -18
  140. package/src/components/ui/radio.tsx +32 -19
  141. package/src/components/ui/select.tsx +6 -6
  142. package/src/components/ui/slider.tsx +8 -5
  143. package/src/components/ui/switch.tsx +13 -17
  144. package/src/components/ui/tabs.tsx +23 -10
  145. package/src/components/ui/toast.tsx +190 -29
  146. package/src/components/ui/toggle.tsx +1 -1
  147. package/src/components/ui/toolbar.tsx +17 -4
  148. package/src/components/ui/tooltip.tsx +54 -0
  149. package/src/routes/__root.tsx +3 -5
@@ -9,7 +9,7 @@
9
9
  "files": [
10
10
  {
11
11
  "path": "tabs.tsx",
12
- "content": "\"use client\";\n\nimport { Tabs as TabsPrimitive } from \"@base-ui/react/tabs\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"@/lib/utils\";\n\nfunction Tabs({ className, orientation = \"horizontal\", ...props }: TabsPrimitive.Root.Props) {\n return (\n <TabsPrimitive.Root\n data-slot=\"tabs\"\n data-orientation={orientation}\n className={cn(\"group/tabs flex gap-2 data-horizontal:flex-col\", className)}\n {...props}\n />\n );\n}\n\nconst tabsListVariants = cva(\n \"group/tabs-list inline-flex w-fit items-center justify-center rounded-lg p-[3px] text-muted-foreground group-data-horizontal/tabs:h-8 group-data-vertical/tabs:h-fit group-data-vertical/tabs:flex-col data-[variant=line]:rounded-none\",\n {\n variants: {\n variant: {\n default: \"bg-muted\",\n line: \"gap-1 bg-transparent\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n },\n);\n\nfunction TabsList({\n className,\n variant = \"default\",\n ...props\n}: TabsPrimitive.List.Props & VariantProps<typeof tabsListVariants>) {\n return (\n <TabsPrimitive.List\n data-slot=\"tabs-list\"\n data-variant={variant}\n className={cn(tabsListVariants({ variant }), className)}\n {...props}\n />\n );\n}\n\nfunction TabsTrigger({ className, ...props }: TabsPrimitive.Tab.Props) {\n return (\n <TabsPrimitive.Tab\n data-slot=\"tabs-trigger\"\n className={cn(\n \"relative inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-1.5 py-0.5 text-sm font-medium whitespace-nowrap text-foreground/60 transition-all group-data-vertical/tabs:w-full group-data-vertical/tabs:justify-start hover:text-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-1 focus-visible:outline-ring disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 group-data-[variant=default]/tabs-list:data-active:shadow-sm group-data-[variant=line]/tabs-list:data-active:shadow-none dark:text-muted-foreground dark:hover:text-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n \"group-data-[variant=line]/tabs-list:bg-transparent group-data-[variant=line]/tabs-list:data-active:bg-transparent dark:group-data-[variant=line]/tabs-list:data-active:border-transparent dark:group-data-[variant=line]/tabs-list:data-active:bg-transparent\",\n \"data-active:bg-background data-active:text-foreground dark:data-active:border-input dark:data-active:bg-input/30 dark:data-active:text-foreground\",\n \"after:absolute after:bg-foreground after:opacity-0 after:transition-opacity group-data-horizontal/tabs:after:inset-x-0 group-data-horizontal/tabs:after:bottom-[-5px] group-data-horizontal/tabs:after:h-0.5 group-data-vertical/tabs:after:inset-y-0 group-data-vertical/tabs:after:-right-1 group-data-vertical/tabs:after:w-0.5 group-data-[variant=line]/tabs-list:data-active:after:opacity-100\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction TabsContent({ className, ...props }: TabsPrimitive.Panel.Props) {\n return (\n <TabsPrimitive.Panel\n data-slot=\"tabs-content\"\n className={cn(\"flex-1 text-sm outline-none\", className)}\n {...props}\n />\n );\n}\n\nexport { Tabs, TabsList, TabsTrigger, TabsContent, tabsListVariants };\n",
12
+ "content": "\"use client\";\n\nimport { Tabs as TabsPrimitive } from \"@base-ui/react/tabs\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"@/lib/utils\";\n\nfunction Tabs({ className, orientation = \"horizontal\", ...props }: TabsPrimitive.Root.Props) {\n return (\n <TabsPrimitive.Root\n data-slot=\"tabs\"\n data-orientation={orientation}\n className={cn(\n \"group/tabs flex gap-2 data-[orientation=horizontal]:flex-col data-[orientation=vertical]:flex-row data-[orientation=horizontal]:**:data-[slot=tabs-list]:h-8 data-[orientation=horizontal]:**:data-[slot=tabs-list]:flex-row data-[orientation=vertical]:**:data-[slot=tabs-list]:h-fit data-[orientation=vertical]:**:data-[slot=tabs-list]:flex-col\",\n className,\n )}\n {...props}\n />\n );\n}\n\nconst tabsListVariants = cva(\n \"group/tabs-list relative inline-flex w-max overflow-hidden rounded-2xl p-0.5 text-muted-foreground group-data-[orientation=horizontal]/tabs:items-center group-data-[orientation=horizontal]/tabs:justify-center group-data-[orientation=vertical]/tabs:items-stretch group-data-[orientation=vertical]/tabs:justify-start data-[orientation=horizontal]:items-center data-[orientation=horizontal]:justify-center data-[orientation=vertical]:items-stretch data-[orientation=vertical]:justify-start data-[variant=line]:rounded-none\",\n {\n variants: {\n variant: {\n default: \"bg-muted\",\n line: \"gap-1 bg-transparent\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n },\n);\n\nfunction TabsList({\n children,\n className,\n variant = \"default\",\n ...props\n}: TabsPrimitive.List.Props & VariantProps<typeof tabsListVariants>) {\n return (\n <TabsPrimitive.List\n data-slot=\"tabs-list\"\n data-variant={variant}\n className={cn(tabsListVariants({ variant }), className)}\n {...props}\n >\n {children}\n <TabsPrimitive.Indicator\n className={cn(\n \"pointer-events-none absolute rounded-xl border border-input bg-card shadow-sm transition-[left,right,top,bottom,width,height,transform] duration-300 ease-[cubic-bezier(0.22,1,0.36,1)]\",\n \"data-[orientation=horizontal]:top-(--active-tab-top) data-[orientation=horizontal]:left-(--active-tab-left) data-[orientation=horizontal]:h-(--active-tab-height) data-[orientation=horizontal]:w-(--active-tab-width)\",\n \"data-[orientation=vertical]:top-(--active-tab-top) data-[orientation=vertical]:left-(--active-tab-left) data-[orientation=vertical]:h-(--active-tab-height) data-[orientation=vertical]:w-(--active-tab-width)\",\n \"group-data-[variant=line]/tabs-list:rounded-none group-data-[variant=line]/tabs-list:border-0 group-data-[variant=line]/tabs-list:bg-foreground group-data-[variant=line]/tabs-list:shadow-none\",\n \"group-data-[variant=line]/tabs-list:data-[orientation=horizontal]:top-auto group-data-[variant=line]/tabs-list:data-[orientation=horizontal]:bottom-0 group-data-[variant=line]/tabs-list:data-[orientation=horizontal]:h-0.5\",\n \"group-data-[variant=line]/tabs-list:data-[orientation=vertical]:right-auto group-data-[variant=line]/tabs-list:data-[orientation=vertical]:left-0 group-data-[variant=line]/tabs-list:data-[orientation=vertical]:w-0.5\",\n )}\n />\n </TabsPrimitive.List>\n );\n}\n\nfunction TabsTrigger({ className, ...props }: TabsPrimitive.Tab.Props) {\n return (\n <TabsPrimitive.Tab\n data-slot=\"tabs-trigger\"\n className={cn(\n \"relative z-10 inline-flex h-7 flex-none items-center justify-center rounded-xl border border-transparent px-2 py-0.5 text-center text-sm font-medium whitespace-nowrap text-muted-foreground transition-[color,transform,opacity] duration-200 ease-out group-data-[orientation=vertical]/tabs:w-full group-data-[variant=line]/tabs-list:rounded-none group-data-[variant=line]/tabs-list:border-0 group-data-[variant=line]/tabs-list:bg-transparent hover:text-foreground focus-visible:border-ring focus-visible:ring-1 focus-visible:ring-ring/50 focus-visible:outline-1 focus-visible:outline-ring group-data-[variant=line]/tabs-list:focus-visible:border-transparent group-data-[variant=line]/tabs-list:focus-visible:ring-0 group-data-[variant=line]/tabs-list:focus-visible:outline-none disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-active:text-card-foreground data-[orientation=vertical]:h-fit data-[orientation=vertical]:w-full [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction TabsPanel({ className, ...props }: TabsPrimitive.Panel.Props) {\n return (\n <TabsPrimitive.Panel\n data-slot=\"tabs-panel\"\n className={cn(\"flex-1 text-sm outline-none\", className)}\n {...props}\n />\n );\n}\n\nexport { Tabs, TabsList, TabsTrigger, TabsPanel, tabsListVariants };\n",
13
13
  "type": "registry:ui"
14
14
  }
15
15
  ]
@@ -3,13 +3,14 @@
3
3
  "type": "registry:ui",
4
4
  "dependencies": [
5
5
  "@base-ui/react",
6
+ "class-variance-authority",
6
7
  "lucide-react"
7
8
  ],
8
9
  "registryDependencies": [],
9
10
  "files": [
10
11
  {
11
12
  "path": "toast.tsx",
12
- "content": "\"use client\";\n\nimport { Toast as ToastPrimitive } from \"@base-ui/react/toast\";\nimport { AlertCircle, CheckCircle2 } from \"lucide-react\";\n\nimport { cn } from \"@/lib/utils\";\n\ntype ToastTypes = \"default\" | \"success\" | \"error\";\n\nconst globalToastManager = ToastPrimitive.createToastManager();\nexport const toast = globalToastManager;\n\nexport function ToastProvider({ children }: { children: React.ReactNode }) {\n return (\n <ToastPrimitive.Provider toastManager={globalToastManager} limit={5} timeout={5000}>\n {children}\n <ToastPrimitive.Portal>\n <ToastPrimitive.Viewport className=\"fixed right-4 bottom-4 z-50 flex flex-col gap-2\">\n <ToastViewportConsumer />\n </ToastPrimitive.Viewport>\n </ToastPrimitive.Portal>\n </ToastPrimitive.Provider>\n );\n}\n\nfunction ToastViewportConsumer() {\n const { toasts } = ToastPrimitive.useToastManager();\n return (\n <>\n {toasts.map((toast) => (\n <Toast key={toast.id} toast={toast} />\n ))}\n </>\n );\n}\n\nfunction Toast({ className, toast, ...props }: ToastPrimitive.Root.Props) {\n let icon;\n\n switch (toast.type as ToastTypes) {\n case \"success\":\n icon = <CheckCircle2 className=\"h-4 w-4 text-green-600\" />;\n break;\n case \"error\":\n icon = <AlertCircle className=\"h-4 w-4 text-red-600\" />;\n break;\n default:\n icon = null;\n break;\n }\n\n return (\n <ToastPrimitive.Root\n toast={toast}\n className={cn(\n \"flex w-80 items-center gap-3 rounded-lg border bg-popup p-4 shadow-md\",\n className,\n )}\n {...props}\n >\n {icon && <div>{icon}</div>}\n <div className=\"flex flex-1 flex-col\">\n {toast.title && (\n <ToastPrimitive.Title className=\"text-sm font-medium\">{toast.title}</ToastPrimitive.Title>\n )}\n {toast.description && (\n <ToastPrimitive.Description className=\"text-sm text-muted-foreground\">\n {toast.description}\n </ToastPrimitive.Description>\n )}\n </div>\n </ToastPrimitive.Root>\n );\n}\n\nexport { ToastProvider as Toast };\n",
13
+ "content": "\"use client\";\n\nimport { Toast as ToastPrimitive } from \"@base-ui/react/toast\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { AlertCircle, CheckCircle2 } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\ntype ToastTypes = \"default\" | \"success\" | \"error\";\n\nconst toastViewportVariants = cva(\"fixed z-50 w-80 outline-none\", {\n variants: {\n position: {\n \"top-left\": \"top-4 right-auto bottom-auto left-4\",\n \"top-center\": \"top-4 right-0 bottom-auto left-0 mx-auto\",\n \"top-right\": \"top-4 right-4 bottom-auto left-auto\",\n \"bottom-left\": \"top-auto right-auto bottom-4 left-4\",\n \"bottom-center\": \"top-auto right-0 bottom-4 left-0 mx-auto\",\n \"bottom-right\": \"top-auto right-4 bottom-4 left-auto\",\n },\n },\n defaultVariants: {\n position: \"bottom-right\",\n },\n});\n\nconst stackedToastVariants = cva(\n \"absolute z-[calc(1000-var(--toast-index))] h-(--height) w-full rounded-lg border bg-popup bg-clip-padding p-4 select-none [--gap:0.75rem] [--height:var(--toast-frontmost-height,var(--toast-height))] [--peek:0.75rem] [--scale:calc(max(0,1-(var(--toast-index)*0.1)))] [--shrink:calc(1-var(--scale))] [transition:transform_0.5s_cubic-bezier(0.22,1,0.36,1),opacity_0.5s,height_0.15s] after:absolute after:left-0 after:h-[calc(var(--gap)+1px)] after:w-full after:content-[''] data-ending-style:opacity-0 data-expanded:h-(--toast-height) data-limited:opacity-0 data-ending-style:data-[swipe-direction=down]:transform-[translateY(calc(var(--toast-swipe-movement-y)+150%))] data-expanded:data-ending-style:data-[swipe-direction=down]:transform-[translateY(calc(var(--toast-swipe-movement-y)+150%))] data-ending-style:data-[swipe-direction=left]:transform-[translateX(calc(var(--toast-swipe-movement-x)-150%))_translateY(var(--offset-y))] data-expanded:data-ending-style:data-[swipe-direction=left]:transform-[translateX(calc(var(--toast-swipe-movement-x)-150%))_translateY(var(--offset-y))] data-ending-style:data-[swipe-direction=right]:transform-[translateX(calc(var(--toast-swipe-movement-x)+150%))_translateY(var(--offset-y))] data-expanded:data-ending-style:data-[swipe-direction=right]:transform-[translateX(calc(var(--toast-swipe-movement-x)+150%))_translateY(var(--offset-y))] data-ending-style:data-[swipe-direction=up]:transform-[translateY(calc(var(--toast-swipe-movement-y)-150%))] data-expanded:data-ending-style:data-[swipe-direction=up]:transform-[translateY(calc(var(--toast-swipe-movement-y)-150%))]\",\n {\n variants: {\n vertical: {\n top: \"top-0 origin-top [transform:translateX(var(--toast-swipe-movement-x))_translateY(calc(var(--toast-swipe-movement-y)+(var(--toast-index)*var(--peek))+(var(--shrink)*var(--height))))_scale(var(--scale))] [--offset-y:calc(var(--toast-offset-y)+(var(--toast-index)*var(--gap))+var(--toast-swipe-movement-y))] after:bottom-full data-expanded:transform-[translateX(var(--toast-swipe-movement-x))_translateY(calc(var(--offset-y)))] data-starting-style:transform-[translateY(-150%)] [&[data-ending-style]:not([data-limited]):not([data-swipe-direction])]:transform-[translateY(-150%)]\",\n bottom:\n \"bottom-0 origin-bottom [transform:translateX(var(--toast-swipe-movement-x))_translateY(calc(var(--toast-swipe-movement-y)-(var(--toast-index)*var(--peek))-(var(--shrink)*var(--height))))_scale(var(--scale))] [--offset-y:calc(var(--toast-offset-y)*-1+calc(var(--toast-index)*var(--gap)*-1)+var(--toast-swipe-movement-y))] after:top-full data-expanded:transform-[translateX(var(--toast-swipe-movement-x))_translateY(calc(var(--offset-y)))] data-starting-style:transform-[translateY(150%)] [&[data-ending-style]:not([data-limited]):not([data-swipe-direction])]:transform-[translateY(150%)]\",\n },\n horizontal: {\n left: \"right-auto left-0\",\n center: \"right-0 left-0 mx-auto\",\n right: \"right-0 left-auto\",\n },\n },\n defaultVariants: {\n vertical: \"bottom\",\n horizontal: \"right\",\n },\n },\n);\n\nconst anchoredToastVariants = cva(\n \"pointer-events-auto w-80 rounded-lg border bg-popup bg-clip-padding p-4 data-ending-style:opacity-0 data-starting-style:opacity-0\",\n);\n\nconst toastContentVariants = cva(\n \"overflow-hidden transition-opacity duration-250 data-behind:pointer-events-none data-behind:opacity-0 data-expanded:pointer-events-auto data-expanded:opacity-100\",\n);\n\nconst toastBodyVariants = cva(\"flex items-center gap-3\");\n\ntype ToastPosition = NonNullable<VariantProps<typeof toastViewportVariants>[\"position\"]>;\ntype StackVertical = NonNullable<VariantProps<typeof stackedToastVariants>[\"vertical\"]>;\ntype StackHorizontal = NonNullable<VariantProps<typeof stackedToastVariants>[\"horizontal\"]>;\ntype ToastManager = ReturnType<typeof ToastPrimitive.createToastManager>;\n\ninterface ToastProviderProps {\n children: React.ReactNode;\n position?: ToastPosition;\n limit?: number;\n timeout?: number;\n toastManager?: ToastManager;\n}\n\nconst globalToastManager = ToastPrimitive.createToastManager();\nexport const globalToast = globalToastManager;\n\nexport function ToastProvider({\n children,\n position = \"bottom-right\",\n limit = 5,\n timeout = 5000,\n toastManager,\n}: ToastProviderProps) {\n const localToastManagerRef = React.useRef<ToastManager | null>(null);\n\n if (!localToastManagerRef.current) {\n localToastManagerRef.current = ToastPrimitive.createToastManager();\n }\n\n const manager = toastManager ?? localToastManagerRef.current;\n\n return (\n <ToastPrimitive.Provider toastManager={manager} limit={limit} timeout={timeout}>\n {children}\n <ToastPrimitive.Portal>\n <ToastPrimitive.Viewport className={cn(toastViewportVariants({ position }))}>\n <ToastStackConsumer position={position} />\n </ToastPrimitive.Viewport>\n <ToastPrimitive.Viewport className=\"pointer-events-none fixed inset-0 z-50 outline-none\">\n <ToastAnchorConsumer />\n </ToastPrimitive.Viewport>\n </ToastPrimitive.Portal>\n </ToastPrimitive.Provider>\n );\n}\n\nfunction ToastStackConsumer({ position }: { position: ToastPosition }) {\n const { toasts } = ToastPrimitive.useToastManager();\n const stackToasts = toasts.filter((currentToast) => !currentToast.positionerProps?.anchor);\n\n return (\n <>\n {stackToasts.map((currentToast) => (\n <Toast key={currentToast.id} toast={currentToast} position={position} />\n ))}\n </>\n );\n}\n\nfunction ToastAnchorConsumer() {\n const { toasts } = ToastPrimitive.useToastManager();\n const anchorToasts = toasts.filter((currentToast) =>\n Boolean(currentToast.positionerProps?.anchor),\n );\n\n return (\n <>\n {anchorToasts.map((currentToast) => {\n const { className, ...positionerProps } = currentToast.positionerProps ?? {};\n\n return (\n <ToastPrimitive.Positioner\n key={currentToast.id}\n toast={currentToast}\n className={cn(\"pointer-events-none z-[calc(1000-var(--toast-index))]\", className)}\n {...positionerProps}\n >\n <AnchoredToast toast={currentToast} />\n </ToastPrimitive.Positioner>\n );\n })}\n </>\n );\n}\n\nfunction Toast({\n className,\n toast,\n position,\n ...props\n}: ToastPrimitive.Root.Props & { position: ToastPosition }) {\n const { vertical, horizontal } = getStackPlacement(position);\n\n return (\n <ToastPrimitive.Root\n toast={toast}\n className={cn(stackedToastVariants({ vertical, horizontal, className }))}\n {...props}\n >\n <ToastPrimitive.Content className={cn(toastContentVariants())}>\n <ToastBody toast={toast} />\n </ToastPrimitive.Content>\n </ToastPrimitive.Root>\n );\n}\n\nfunction AnchoredToast({ className, toast, ...props }: ToastPrimitive.Root.Props) {\n return (\n <ToastPrimitive.Root\n toast={toast}\n className={cn(anchoredToastVariants({ className }))}\n {...props}\n >\n <ToastPrimitive.Content className={cn(toastContentVariants())}>\n <ToastBody toast={toast} />\n </ToastPrimitive.Content>\n </ToastPrimitive.Root>\n );\n}\n\nfunction ToastBody({ toast }: { toast: ToastPrimitive.Root.Props[\"toast\"] }) {\n let icon;\n\n switch (toast.type as ToastTypes) {\n case \"success\":\n icon = <CheckCircle2 className=\"h-4 w-4 text-success\" />;\n break;\n case \"error\":\n icon = <AlertCircle className=\"h-4 w-4 text-destructive\" />;\n break;\n default:\n icon = null;\n break;\n }\n\n return (\n <div className={cn(toastBodyVariants())}>\n {icon ? <div>{icon}</div> : null}\n <div className=\"flex flex-1 flex-col\">\n {toast.title ? <ToastPrimitive.Title className=\"text-sm font-medium\" /> : null}\n {toast.description ? (\n <ToastPrimitive.Description className=\"text-sm text-muted-foreground\" />\n ) : null}\n {toast.actionProps ? (\n <ToastPrimitive.Action className=\"mt-2 inline-flex h-7 items-center justify-center self-start rounded-md border px-2.5 text-xs font-medium hover:bg-muted\" />\n ) : null}\n </div>\n </div>\n );\n}\n\nfunction getStackPlacement(position: ToastPosition): {\n vertical: StackVertical;\n horizontal: StackHorizontal;\n} {\n const vertical: StackVertical = position.startsWith(\"top\") ? \"top\" : \"bottom\";\n\n let horizontal: StackHorizontal = \"center\";\n if (position.endsWith(\"left\")) {\n horizontal = \"left\";\n }\n if (position.endsWith(\"right\")) {\n horizontal = \"right\";\n }\n\n return {\n vertical,\n horizontal,\n };\n}\n\nfunction useToast<Data extends object = any>() {\n return ToastPrimitive.useToastManager<Data>();\n}\n\nexport { ToastProvider as Toast };\nexport { useToast };\nexport type { ToastPosition, ToastManager };\n",
13
14
  "type": "registry:ui"
14
15
  }
15
16
  ]
@@ -9,7 +9,7 @@
9
9
  "files": [
10
10
  {
11
11
  "path": "toggle.tsx",
12
- "content": "\"use client\";\n\nimport { Toggle as TogglePrimitive } from \"@base-ui/react/toggle\";\nimport { ToggleGroup as ToggleGroupPrimitive } from \"@base-ui/react/toggle-group\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst toggleVariants = cva(\n \"group/toggle inline-flex items-center justify-center gap-1 rounded text-sm font-medium whitespace-nowrap transition-all outline-none hover:bg-muted hover:text-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 aria-pressed:bg-muted data-pressed:bg-muted dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: \"bg-transparent hover:bg-muted\",\n outline: \"border border-input bg-transparent hover:bg-muted\",\n },\n size: {\n default: \"h-8 min-w-8 px-2\",\n sm: \"h-7 min-w-7 rounded-[min(var(--radius-md),12px)] px-1.5 text-[0.8rem]\",\n lg: \"h-9 min-w-9 px-2.5\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n },\n);\n\nfunction Toggle({\n className,\n variant = \"default\",\n size = \"default\",\n ...props\n}: TogglePrimitive.Props & VariantProps<typeof toggleVariants>) {\n return (\n <TogglePrimitive\n data-slot=\"toggle\"\n className={cn(toggleVariants({ variant, size, className }))}\n {...props}\n />\n );\n}\n\nfunction ToggleGroup({ className, ...props }: ToggleGroupPrimitive.Props) {\n return (\n <ToggleGroupPrimitive\n className={cn(\"flex items-center gap-0.5 rounded border p-0.5\", className)}\n {...props}\n />\n );\n}\n\nexport { Toggle, toggleVariants, ToggleGroup };\n",
12
+ "content": "\"use client\";\n\nimport { Toggle as TogglePrimitive } from \"@base-ui/react/toggle\";\nimport { ToggleGroup as ToggleGroupPrimitive } from \"@base-ui/react/toggle-group\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst toggleVariants = cva(\n \"group/toggle inline-flex items-center justify-center gap-1 rounded text-sm font-medium whitespace-nowrap transition-all outline-none hover:bg-muted hover:text-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 aria-pressed:bg-muted data-pressed:bg-muted dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_[data-slot=fill]_*]:fill-transparent data-[pressed]:[&_[data-slot=fill]_*]:fill-current\",\n {\n variants: {\n variant: {\n default: \"bg-transparent hover:bg-muted\",\n outline: \"border border-input bg-transparent hover:bg-muted\",\n },\n size: {\n default: \"h-8 min-w-8 px-2\",\n sm: \"h-7 min-w-7 rounded-[min(var(--radius-md),12px)] px-1.5 text-[0.8rem]\",\n lg: \"h-9 min-w-9 px-2.5\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n },\n);\n\nfunction Toggle({\n className,\n variant = \"default\",\n size = \"default\",\n ...props\n}: TogglePrimitive.Props & VariantProps<typeof toggleVariants>) {\n return (\n <TogglePrimitive\n data-slot=\"toggle\"\n className={cn(toggleVariants({ variant, size, className }))}\n {...props}\n />\n );\n}\n\nfunction ToggleGroup({ className, ...props }: ToggleGroupPrimitive.Props) {\n return (\n <ToggleGroupPrimitive\n className={cn(\"flex items-center gap-0.5 rounded border p-0.5\", className)}\n {...props}\n />\n );\n}\n\nexport { Toggle, toggleVariants, ToggleGroup };\n",
13
13
  "type": "registry:ui"
14
14
  }
15
15
  ]
@@ -8,7 +8,7 @@
8
8
  "files": [
9
9
  {
10
10
  "path": "toolbar.tsx",
11
- "content": "\"use client\";\n\nimport { Toolbar as ToolbarPrimitive } from \"@base-ui/react\";\n\nimport { cn } from \"@/lib/utils\";\n\nfunction Toolbar({ className, ...props }: ToolbarPrimitive.Root.Props) {\n return (\n <ToolbarPrimitive.Root\n className={cn(\"flex h-9 items-center justify-evenly gap-1 border bg-muted p-1\", className)}\n {...props}\n />\n );\n}\n\nfunction ToolbarButton({ className, ...props }: ToolbarPrimitive.Button.Props) {\n return <ToolbarPrimitive.Button className={cn(className)} {...props} />;\n}\n\nfunction ToolbarLink({ className, ...props }: ToolbarPrimitive.Link.Props) {\n return <ToolbarPrimitive.Link className={cn(className)} {...props} />;\n}\n\nfunction ToolbarInput({ className, ...props }: ToolbarPrimitive.Input.Props) {\n return <ToolbarPrimitive.Input className={cn(className)} {...props} />;\n}\n\nfunction ToolbarGroup({ className, ...props }: ToolbarPrimitive.Group.Props) {\n return <ToolbarPrimitive.Group className={cn(className)} {...props} />;\n}\n\nfunction ToolbarSeparator({ className, ...props }: ToolbarPrimitive.Separator.Props) {\n return (\n <ToolbarPrimitive.Separator\n className={cn(\n \"shrink-0 bg-primary/40 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:w-px data-[orientation=vertical]:self-stretch\",\n className,\n )}\n {...props}\n />\n );\n}\n\nexport { Toolbar, ToolbarButton, ToolbarLink, ToolbarInput, ToolbarGroup, ToolbarSeparator };\n",
11
+ "content": "\"use client\";\n\nimport { Toolbar as ToolbarPrimitive } from \"@base-ui/react\";\n\nimport { cn } from \"@/lib/utils\";\n\nfunction Toolbar({ className, ...props }: ToolbarPrimitive.Root.Props) {\n return (\n <ToolbarPrimitive.Root\n className={cn(\"flex h-9 items-center justify-evenly gap-1 rounded-xl border p-1\", className)}\n {...props}\n />\n );\n}\n\nfunction ToolbarButton({ className, ...props }: ToolbarPrimitive.Button.Props) {\n return <ToolbarPrimitive.Button className={cn(className)} {...props} />;\n}\n\nfunction ToolbarLink({ className, ...props }: ToolbarPrimitive.Link.Props) {\n return <ToolbarPrimitive.Link className={cn(className)} {...props} />;\n}\n\nfunction ToolbarInput({ className, ...props }: ToolbarPrimitive.Input.Props) {\n return <ToolbarPrimitive.Input className={cn(className)} {...props} />;\n}\n\nfunction ToolbarGroup({ className, ...props }: ToolbarPrimitive.Group.Props) {\n return (\n <ToolbarPrimitive.Group className={cn(\"flex items-center gap-0.5\", className)} {...props} />\n );\n}\n\nfunction ToolbarSeparator({ className, ...props }: ToolbarPrimitive.Separator.Props) {\n return (\n <ToolbarPrimitive.Separator\n className={cn(\n \"shrink-0 bg-primary/30 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:w-px data-[orientation=vertical]:self-stretch\",\n className,\n )}\n {...props}\n />\n );\n}\n\nexport { Toolbar, ToolbarButton, ToolbarLink, ToolbarInput, ToolbarGroup, ToolbarSeparator };\n",
12
12
  "type": "registry:ui"
13
13
  }
14
14
  ]
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "tooltip",
3
+ "type": "registry:ui",
4
+ "dependencies": [
5
+ "@base-ui/react"
6
+ ],
7
+ "registryDependencies": [],
8
+ "files": [
9
+ {
10
+ "path": "tooltip.tsx",
11
+ "content": "\"use client\";\n\nimport { Tooltip as TooltipPrimitive } from \"@base-ui/react/tooltip\";\n\nimport { cn } from \"@/lib/utils\";\n\nfunction TooltipProvider({ ...props }: TooltipPrimitive.Provider.Props) {\n return <TooltipPrimitive.Provider {...props} />;\n}\n\nfunction Tooltip({ ...props }: TooltipPrimitive.Root.Props) {\n return <TooltipPrimitive.Root {...props} />;\n}\n\nfunction TooltipTrigger({ ...props }: TooltipPrimitive.Trigger.Props) {\n return <TooltipPrimitive.Trigger {...props} />;\n}\n\nfunction TooltipContent({\n className,\n children,\n side = \"top\",\n sideOffset = 6,\n align = \"center\",\n alignOffset = 0,\n ...props\n}: TooltipPrimitive.Popup.Props &\n Pick<TooltipPrimitive.Positioner.Props, \"align\" | \"alignOffset\" | \"side\" | \"sideOffset\">) {\n return (\n <TooltipPrimitive.Portal>\n <TooltipPrimitive.Positioner\n side={side}\n sideOffset={sideOffset}\n align={align}\n alignOffset={alignOffset}\n className=\"z-50\"\n >\n <TooltipPrimitive.Popup\n className={cn(\n \"origin-(--transform-origin) rounded-md bg-popup px-2 py-1 text-xs text-popup-foreground shadow-md ring-1 ring-foreground/10 duration-100 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95\",\n className,\n )}\n {...props}\n >\n {children}\n <TooltipPrimitive.Arrow className=\"data-[side=bottom]:-top-0.5 data-[side=left]:-right-0.5 data-[side=right]:-left-0.5 data-[side=top]:-bottom-0.5\" />\n </TooltipPrimitive.Popup>\n </TooltipPrimitive.Positioner>\n </TooltipPrimitive.Portal>\n );\n}\n\nexport { Tooltip, TooltipProvider, TooltipTrigger, TooltipContent };",
12
+ "type": "registry:ui"
13
+ }
14
+ ]
15
+ }
@@ -1,6 +1,6 @@
1
1
  import { Link } from "@tanstack/react-router";
2
- import { MenuIcon, SunMoonIcon } from "lucide-react";
3
- import { useState } from "react";
2
+ import { SunMoonIcon } from "lucide-react";
3
+
4
4
 
5
5
  import { DocsButton } from "@/components/docs/docs-button";
6
6
  import { useTheme } from "@/components/docs/theme-provider";
@@ -9,7 +9,7 @@ import { MobileMenu } from "./mobile-menu";
9
9
 
10
10
  export function Header() {
11
11
  const { toggleTheme, theme } = useTheme();
12
- const [showMobileMenu, setShowMobileMenu] = useState(false);
12
+
13
13
 
14
14
  return (
15
15
  <header className=" sticky top-0 z-10 h-12 border-b bg-background">
@@ -31,19 +31,9 @@ export function Header() {
31
31
  <DocsButton onClick={toggleTheme} variant={"ghost"} className={"hidden lg:inline-flex"}>
32
32
  <SunMoonIcon className=" size-4" />
33
33
  </DocsButton>
34
-
35
- <DocsButton
36
- onClick={() => setShowMobileMenu(!showMobileMenu)}
37
- variant={"ghost"}
38
- size={"sm"}
39
- className={"lg:hidden"}
40
- >
41
- <MenuIcon data-icon="start" />
42
- Navigation
43
- </DocsButton>
34
+ <MobileMenu />
44
35
  </div>
45
36
 
46
- <MobileMenu open={showMobileMenu} onClose={() => setShowMobileMenu(false)} />
47
37
  </header>
48
38
  );
49
39
  }
@@ -1,86 +1,35 @@
1
1
  import { Link } from "@tanstack/react-router";
2
- import { clsx } from "clsx";
3
2
  import { allComponents } from "content-collections";
4
- import { Suspense, useEffect, useRef } from "react";
5
-
3
+ import { Suspense, useState } from "react";
6
4
  import { SuspenseFallback } from "./suspense-fallback";
5
+ import { Drawer, DrawerPopup, DrawerTrigger } from "@/components/ui/drawer";
6
+ import { Button } from "@/components/ui/button";
7
+ import { MenuIcon } from "lucide-react";
7
8
 
8
- export function MobileMenu({ open, onClose }: { open: boolean; onClose: () => void }) {
9
- const panelRef = useRef<HTMLDivElement | null>(null);
10
-
11
- useEffect(() => {
12
- function onKey(e: KeyboardEvent) {
13
- if (e.key === "Escape") onClose();
14
- }
15
-
16
- if (open) {
17
- document.addEventListener("keydown", onKey);
18
- document.body.style.overflow = "hidden";
19
- // Move focus into the panel for accessibility
20
- setTimeout(() => panelRef.current?.focus(), 0);
21
- } else {
22
- document.body.style.overflow = "";
23
- }
24
-
25
- return () => {
26
- document.removeEventListener("keydown", onKey);
27
- document.body.style.overflow = "";
28
- };
29
- }, [open, onClose]);
9
+ export function MobileMenu() {
30
10
 
31
- return (
32
- <div aria-hidden={!open} className={clsx("fixed inset-0 z-50", !open && "pointer-events-none")}>
33
- <div
34
- className={clsx(
35
- "fixed inset-0 bg-black/40 transition-opacity duration-200",
36
- open ? "pointer-events-auto opacity-100" : "pointer-events-none opacity-0",
37
- "motion-reduce:transition-none",
38
- )}
39
- onClick={onClose}
40
- aria-hidden
41
- />
11
+ const [open, setOpen] = useState(false);
42
12
 
43
- <div
44
- ref={panelRef}
45
- role="dialog"
46
- aria-modal
47
- tabIndex={-1}
48
- className={clsx(
49
- "fixed right-0 bottom-0 left-0 transform border-t bg-popup p-4 transition-transform duration-300 ease-[cubic-bezier(.22,1,.36,1)]",
50
- open ? "translate-y-0" : "translate-y-full",
51
- "motion-reduce:transform-none motion-reduce:transition-none",
52
- )}
53
- >
54
- <nav className="mt-4 flex flex-col gap-2">
55
- <Link to="/components" className="text-sm text-muted-foreground">
56
- Components
57
- </Link>
58
- <Link to="/" className="text-base">
59
- Home
60
- </Link>
61
- <div>
62
- <Link to="/components" className="text-base">
63
- Components
13
+ return <Drawer open={open} onOpenChange={setOpen} >
14
+ <DrawerTrigger className={'flex md:hidden'} render={<Button size={'xs'} variant={'secondary'} >
15
+ <MenuIcon />
16
+ Navigation
17
+ </Button>} />
18
+ <DrawerPopup position="bottom">
19
+ <nav className="mt-4 flex flex-col gap-2">
20
+ <span className="text-sm font-medium text-muted-foreground">Components</span>
21
+ <Suspense fallback={<SuspenseFallback />}>
22
+ {allComponents.map((component) => (
23
+ <Link key={component.slug} to={'/components/$slug'} params={{
24
+ slug: component.slug
25
+ }} onClick={() => setOpen(false)}>
26
+ <Button variant={'link'}>
27
+ {component.title}
28
+ </Button>
64
29
  </Link>
65
- <div className=" ml-4 flex flex-col">
66
- <Suspense fallback={<SuspenseFallback />}>
67
- {[...allComponents]
68
- .sort((a, b) => a.title.localeCompare(b.title))
69
- .map((component) => (
70
- <Link
71
- key={component.slug}
72
- to="/components/$slug"
73
- params={{ slug: component.slug }}
74
- className="text-base"
75
- >
76
- {component.title}
77
- </Link>
78
- ))}
79
- </Suspense>
80
- </div>
81
- </div>
82
- </nav>
83
- </div>
84
- </div>
85
- );
30
+ ))}
31
+ </Suspense>
32
+ </nav>
33
+ </DrawerPopup>
34
+ </Drawer>
86
35
  }
@@ -3,11 +3,12 @@ import { allComponents } from "content-collections";
3
3
  import { ComponentProps } from "react";
4
4
 
5
5
  import { DocsButton } from "@/components/docs/docs-button";
6
+ import { ScrollArea } from "@/components/ui/scroll-area";
6
7
  import { cn } from "@/lib/utils";
7
8
 
8
9
  function NavSection({ title, children }: { title: string; children: React.ReactNode }) {
9
10
  return (
10
- <div className="flex flex-col gap-2">
11
+ <div className="flex min-h-0 flex-1 flex-col gap-2">
11
12
  <h4 className=" pl-2 font-heading text-xs font-medium text-muted-foreground">{title}</h4>
12
13
  {children}
13
14
  </div>
@@ -16,27 +17,32 @@ function NavSection({ title, children }: { title: string; children: React.ReactN
16
17
 
17
18
  export function NavSidebar({ className, ...props }: ComponentProps<"nav">) {
18
19
  return (
19
- <nav className={cn("hidden h-full w-64 flex-col p-4 lg:flex", className)} {...props}>
20
+ <nav className={cn("hidden h-full min-h-0 w-64 flex-col p-4 lg:flex", className)} {...props}>
20
21
  <NavSection title="Components">
21
- <ul>
22
- {[...allComponents]
23
- .sort((a, b) => a.title.localeCompare(b.title))
24
- .map((component) => (
25
- <li key={component.slug}>
26
- <Link to="/components/$slug" params={{ slug: component.slug }}>
27
- {({ isActive }) => (
28
- <DocsButton
29
- variant={"ghost"}
30
- size={"sm"}
31
- className={cn("w-fit justify-start rounded-none", isActive ? "bg-muted" : "")}
32
- >
33
- {component.title}
34
- </DocsButton>
35
- )}
36
- </Link>
37
- </li>
38
- ))}
39
- </ul>
22
+ <ScrollArea className="h-full">
23
+ <ul>
24
+ {[...allComponents]
25
+ .sort((a, b) => a.title.localeCompare(b.title))
26
+ .map((component) => (
27
+ <li key={component.slug}>
28
+ <Link to="/components/$slug" params={{ slug: component.slug }}>
29
+ {({ isActive }) => (
30
+ <DocsButton
31
+ variant={"ghost"}
32
+ size={"sm"}
33
+ className={cn(
34
+ "w-fit justify-start rounded-none",
35
+ isActive ? "bg-muted" : "",
36
+ )}
37
+ >
38
+ {component.title}
39
+ </DocsButton>
40
+ )}
41
+ </Link>
42
+ </li>
43
+ ))}
44
+ </ul>
45
+ </ScrollArea>
40
46
  </NavSection>
41
47
  </nav>
42
48
  );
@@ -1,5 +1,6 @@
1
1
  import { ComponentProps } from "react";
2
2
 
3
+ import { ScrollArea } from "@/components/ui/scroll-area";
3
4
  import { cn } from "@/lib/utils";
4
5
 
5
6
  import { NavSidebar } from "./nav-list";
@@ -11,10 +12,12 @@ export function SplitLayout({
11
12
  ...props
12
13
  }: ComponentProps<"div">) {
13
14
  return (
14
- <div className={cn("flex h-full w-full", className)} {...props}>
15
+ <div className={cn("flex h-full min-h-0 w-full", className)} {...props}>
15
16
  <NavSidebar />
16
- <main className="min-w-0 flex-1 overflow-auto">
17
- <div className="min-h-full lg:border-l">{children}</div>
17
+ <main className="min-w-0 flex-1">
18
+ <ScrollArea className="h-full">
19
+ <div className="min-h-full lg:border-l">{children}</div>
20
+ </ScrollArea>
18
21
  </main>
19
22
  </div>
20
23
  );
@@ -2,7 +2,7 @@ import { cva, VariantProps } from "class-variance-authority";
2
2
  import { ComponentProps } from "react";
3
3
 
4
4
  const badgeVariants = cva(
5
- "group/badge inline-flex h-5 min-h-5 w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-lg border border-transparent px-2.5 py-0.5 text-xs font-medium whitespace-nowrap transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 has-data-[icon=end]:pr-1.5 has-data-[icon=start]:pl-1.5 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3!",
5
+ "group/badge inline-flex h-5 min-h-5 w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-full border border-transparent px-2.5 py-0.5 text-xs font-medium whitespace-nowrap transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 has-data-[icon=end]:pr-1.5 has-data-[icon=start]:pl-1.5 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3!",
6
6
  {
7
7
  variants: {
8
8
  variant: {
@@ -10,7 +10,7 @@ function Checkbox({ className, ...props }: CheckboxPrimitive.Root.Props) {
10
10
  <CheckboxPrimitive.Root
11
11
  data-slot="checkbox"
12
12
  className={cn(
13
- "peer inline-flex size-4 max-w-4 shrink-0 items-center justify-center rounded border border-input bg-background transition-colors group-data-invalid/field:border-destructive focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 focus-visible:outline-none group-data-invalid/field:focus-visible:border-destructive group-data-invalid/field:focus-visible:ring-destructive/20 disabled:cursor-not-allowed disabled:opacity-50 data-checked:border-primary data-checked:bg-primary data-checked:text-primary-foreground data-indeterminate:border-primary data-indeterminate:bg-primary data-indeterminate:text-primary-foreground dark:group-data-invalid/field:border-destructive/50 dark:group-data-invalid/field:focus-visible:ring-destructive/40",
13
+ "peer inline-flex size-4 max-w-4 min-w-4 shrink-0 items-center justify-center rounded border border-input bg-background transition-colors group-data-invalid/field:border-destructive focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 focus-visible:outline-none group-data-invalid/field:focus-visible:border-destructive group-data-invalid/field:focus-visible:ring-destructive/20 disabled:cursor-not-allowed disabled:opacity-50 data-checked:border-primary data-checked:bg-primary data-checked:text-primary-foreground data-indeterminate:border-primary data-indeterminate:bg-primary data-indeterminate:text-primary-foreground dark:group-data-invalid/field:border-destructive/50 dark:group-data-invalid/field:focus-visible:ring-destructive/40",
14
14
  className,
15
15
  )}
16
16
  {...props}
@@ -89,7 +89,7 @@ function DrawerPopup({
89
89
  data-slot="drawer-popup"
90
90
  data-position={position}
91
91
  className={cn(
92
- "pointer-events-auto grid w-full gap-4 overflow-y-auto overscroll-contain bg-background p-6 text-sm text-foreground shadow-lg ring-1 ring-foreground/10 duration-150 outline-none data-closed:animate-out data-closed:fade-out-0 data-open:animate-in data-open:fade-in-0 data-swiping:transition-none data-swiping:select-none data-[position=bottom]:max-h-dvh data-[position=bottom]:w-dvw data-[position=bottom]:translate-y-[calc(var(--drawer-snap-point-offset)+var(--drawer-swipe-movement-y))] data-[position=bottom]:slide-in-from-bottom-10 data-[position=left]:h-dvh data-[position=left]:w-[min(24rem,calc(100vw-1rem))] data-[position=left]:translate-x-(--drawer-swipe-movement-x) data-[position=left]:slide-in-from-left-10 data-[position=right]:h-dvh data-[position=right]:w-[min(24rem,calc(100vw-1rem))] data-[position=right]:translate-x-(--drawer-swipe-movement-x) data-[position=right]:slide-in-from-right-10 data-[position=top]:max-h-dvh data-[position=top]:w-dvw data-[position=top]:translate-y-[calc(var(--drawer-snap-point-offset)+var(--drawer-swipe-movement-y))] data-[position=top]:slide-in-from-top-10",
92
+ "pointer-events-auto grid w-full gap-4 overflow-y-auto overscroll-contain bg-background p-6 text-sm text-foreground shadow-lg ring-1 ring-foreground/10 duration-150 outline-none data-closed:animate-out data-closed:fade-out-0 data-open:animate-in data-open:fade-in-0 data-swiping:transition-none data-swiping:select-none data-[position=bottom]:max-h-dvh data-[position=bottom]:w-dvw data-[position=bottom]:translate-y-[calc(var(--drawer-snap-point-offset)+var(--drawer-swipe-movement-y))] data-[position=bottom]:slide-in-from-bottom-10 data-[position=bottom]:[data-ending-style]:slide--from-bottom-10 data-[position=left]:h-dvh data-[position=left]:w-[min(24rem,calc(100vw-1rem))] data-[position=left]:translate-x-(--drawer-swipe-movement-x) data-[position=left]:slide-in-from-left-10 data-[position=right]:h-dvh data-[position=right]:w-[min(24rem,calc(100vw-1rem))] data-[position=right]:translate-x-(--drawer-swipe-movement-x) data-[position=right]:slide-in-from-right-10 data-[position=top]:max-h-dvh data-[position=top]:w-dvw data-[position=top]:translate-y-[calc(var(--drawer-snap-point-offset)+var(--drawer-swipe-movement-y))] data-[position=top]:slide-in-from-top-10 ",
93
93
 
94
94
  className,
95
95
  )}
@@ -1,36 +1,18 @@
1
1
  "use client";
2
2
 
3
3
  import { Field as FieldPrimitive } from "@base-ui/react/field";
4
- import { cva, VariantProps } from "class-variance-authority";
5
4
  import { useMemo } from "react";
6
5
 
7
6
  import { cn } from "@/lib/utils";
8
7
 
9
- const fieldVariants = cva("group/field flex gap-2 data-[invalid=true]:text-destructive", {
10
- variants: {
11
- orientation: {
12
- vertical: "flex-col *:w-full [&>.sr-only]:w-auto",
13
- horizontal:
14
- "flex-row items-center has-[>[data-slot=field-content]]:items-start *:data-[slot=field-label]:flex-auto has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px",
15
- responsive:
16
- "flex-col *:w-full @md/field-group:flex-row @md/field-group:items-center @md/field-group:*:w-auto @md/field-group:has-[>[data-slot=field-content]]:items-start @md/field-group:*:data-[slot=field-label]:flex-auto [&>.sr-only]:w-auto @md/field-group:has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px",
17
- },
18
- },
19
- defaultVariants: {
20
- orientation: "vertical",
21
- },
22
- });
23
-
24
- function Field({
25
- className,
26
- orientation = "vertical",
27
- ...props
28
- }: FieldPrimitive.Root.Props & VariantProps<typeof fieldVariants>) {
8
+ function Field({ className, ...props }: FieldPrimitive.Root.Props) {
29
9
  return (
30
10
  <FieldPrimitive.Root
31
11
  data-slot="field-root"
32
- data-orientation={orientation}
33
- className={cn(fieldVariants({ orientation }), className)}
12
+ className={cn(
13
+ "group/field flex flex-col gap-2 *:w-full data-invalid:text-destructive [&>.sr-only]:w-auto",
14
+ className,
15
+ )}
34
16
  {...props}
35
17
  />
36
18
  );
@@ -41,8 +23,7 @@ function FieldLabel({ className, ...props }: FieldPrimitive.Label.Props) {
41
23
  <FieldPrimitive.Label
42
24
  data-slot="field-label"
43
25
  className={cn(
44
- "group/field-label peer/field-label flex w-fit gap-2 text-sm leading-snug group-data-[disabled=true]/field:opacity-50 has-data-checked:border-primary/30 has-data-checked:bg-primary/5 has-[>[data-slot=field]]:rounded-lg has-[>[data-slot=field]]:border *:data-[slot=field]:p-2.5 dark:has-data-checked:border-primary/20 dark:has-data-checked:bg-primary/10",
45
- "has-[>[data-slot=field]]:w-full has-[>[data-slot=field]]:flex-col",
26
+ "group/field-label peer/field-label flex w-fit gap-1 text-sm leading-snug group-data-disabled/field:opacity-50 has-data-checked:border-primary/30 has-data-checked:bg-primary/5 dark:has-data-checked:border-primary/20 dark:has-data-checked:bg-primary/10",
46
27
  className,
47
28
  )}
48
29
  {...props}
@@ -72,7 +53,7 @@ function FieldDescription({ className, ...props }: FieldPrimitive.Description.Pr
72
53
  <FieldPrimitive.Description
73
54
  data-slot="field-description"
74
55
  className={cn(
75
- "text-left text-sm leading-normal font-normal text-muted-foreground group-has-data-horizontal/field:text-balance [[data-variant=legend]+&]:-mt-1.5",
56
+ "text-left text-xs leading-normal font-normal text-muted-foreground [[data-variant=legend]+&]:-mt-1.5",
76
57
  "last:mt-0 nth-last-2:-mt-1",
77
58
  "[&>a]:underline [&>a]:underline-offset-4 [&>a:hover]:text-primary",
78
59
  className,
@@ -116,7 +97,7 @@ function FieldError({
116
97
  <FieldPrimitive.Error
117
98
  role="alert"
118
99
  data-slot="field-error"
119
- className={cn("text-sm font-normal text-destructive", className)}
100
+ className={cn("text-xs font-normal text-destructive", className)}
120
101
  {...props}
121
102
  >
122
103
  {content}
@@ -128,7 +109,7 @@ function FieldItem({ className, ...props }: FieldPrimitive.Item.Props) {
128
109
  return (
129
110
  <FieldPrimitive.Item
130
111
  data-slot="field-item"
131
- className={cn("flex items-center gap-2", className)}
112
+ className={cn("flex flex-col gap-1", className)}
132
113
  {...props}
133
114
  />
134
115
  );
@@ -5,7 +5,7 @@ import { Form as FormPrimitive } from "@base-ui/react/form";
5
5
  import { cn } from "@/lib/utils";
6
6
 
7
7
  function Form({ className, ...props }: FormPrimitive.Props) {
8
- return <FormPrimitive className={cn("", className)} {...props} />;
8
+ return <FormPrimitive data-slot="form-root" className={cn(className)} {...props} />;
9
9
  }
10
10
 
11
11
  export { Form };