@nikala-ui/core 0.11.0 → 0.12.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 (107) hide show
  1. package/package.json +43 -2
  2. package/registry/api-table.json +21 -0
  3. package/registry/banner.json +1 -1
  4. package/registry/button.json +1 -1
  5. package/registry/callout.json +19 -0
  6. package/registry/checkbox.json +4 -1
  7. package/registry/code-block.json +26 -0
  8. package/registry/code-group.json +20 -0
  9. package/registry/combobox.json +1 -1
  10. package/registry/command.json +3 -2
  11. package/registry/component-viewer.json +25 -0
  12. package/registry/container.json +18 -0
  13. package/registry/context-menu.json +1 -1
  14. package/registry/create-app-updater.json +13 -0
  15. package/registry/create-document-tabs.json +13 -0
  16. package/registry/create-global-shortcut.json +13 -0
  17. package/registry/create-tauri-window.json +13 -0
  18. package/registry/create-tiptap-editor.json +34 -0
  19. package/registry/dialog.json +1 -1
  20. package/registry/dropdown-menu.json +3 -2
  21. package/registry/field.json +1 -1
  22. package/registry/file-tree.json +21 -0
  23. package/registry/footer.json +1 -1
  24. package/registry/form-message.json +3 -2
  25. package/registry/icon-button.json +1 -1
  26. package/registry/index.json +336 -5
  27. package/registry/navbar.json +1 -1
  28. package/registry/navigation-menu.json +1 -1
  29. package/registry/number-input.json +1 -1
  30. package/registry/package-manager-tabs.json +24 -0
  31. package/registry/pager.json +21 -0
  32. package/registry/popover.json +4 -1
  33. package/registry/resizable.json +1 -1
  34. package/registry/rich-text-editor.json +95 -0
  35. package/registry/scroll-area.json +1 -1
  36. package/registry/section-heading.json +21 -0
  37. package/registry/select.json +3 -2
  38. package/registry/sheet.json +1 -1
  39. package/registry/sidebar.json +1 -1
  40. package/registry/status.json +1 -1
  41. package/registry/steps.json +20 -0
  42. package/registry/switch.json +4 -1
  43. package/registry/table-of-contents.json +23 -0
  44. package/registry/tabs.json +4 -1
  45. package/registry/theme-manager.json +6 -5
  46. package/registry/titlebar-tabs.json +24 -0
  47. package/registry/titlebar.json +26 -0
  48. package/registry/toggle-group.json +1 -1
  49. package/registry/updater-modal.json +26 -0
  50. package/src/index.ts +48 -0
  51. package/src/registry/components/ui/api-table.tsx +117 -0
  52. package/src/registry/components/ui/banner.tsx +0 -2
  53. package/src/registry/components/ui/button.tsx +1 -1
  54. package/src/registry/components/ui/callout.tsx +137 -0
  55. package/src/registry/components/ui/checkbox.tsx +1 -1
  56. package/src/registry/components/ui/code-block.tsx +326 -0
  57. package/src/registry/components/ui/code-group.tsx +105 -0
  58. package/src/registry/components/ui/combobox.tsx +83 -18
  59. package/src/registry/components/ui/command.tsx +110 -106
  60. package/src/registry/components/ui/component-viewer.tsx +363 -0
  61. package/src/registry/components/ui/container.tsx +45 -0
  62. package/src/registry/components/ui/context-menu.tsx +67 -22
  63. package/src/registry/components/ui/dialog.tsx +42 -32
  64. package/src/registry/components/ui/dropdown-menu.tsx +69 -31
  65. package/src/registry/components/ui/field.tsx +7 -3
  66. package/src/registry/components/ui/file-tree.tsx +181 -0
  67. package/src/registry/components/ui/footer.tsx +1 -1
  68. package/src/registry/components/ui/form-message.tsx +2 -2
  69. package/src/registry/components/ui/icon-button.tsx +1 -1
  70. package/src/registry/components/ui/navbar.tsx +18 -11
  71. package/src/registry/components/ui/navigation-menu.tsx +2 -2
  72. package/src/registry/components/ui/number-input.tsx +3 -3
  73. package/src/registry/components/ui/package-manager-tabs.tsx +226 -0
  74. package/src/registry/components/ui/pager.tsx +102 -0
  75. package/src/registry/components/ui/popover.tsx +1 -1
  76. package/src/registry/components/ui/resizable.tsx +3 -1
  77. package/src/registry/components/ui/rich-text-editor/bubble-menu.tsx +236 -0
  78. package/src/registry/components/ui/rich-text-editor/editor.tsx +308 -0
  79. package/src/registry/components/ui/rich-text-editor/extensions.ts +116 -0
  80. package/src/registry/components/ui/rich-text-editor/footer.tsx +36 -0
  81. package/src/registry/components/ui/rich-text-editor/image-dialog.tsx +75 -0
  82. package/src/registry/components/ui/rich-text-editor/index.ts +11 -0
  83. package/src/registry/components/ui/rich-text-editor/link-dialog.tsx +48 -0
  84. package/src/registry/components/ui/rich-text-editor/markdown.ts +170 -0
  85. package/src/registry/components/ui/rich-text-editor/slash-command.tsx +301 -0
  86. package/src/registry/components/ui/rich-text-editor/table-controls.tsx +68 -0
  87. package/src/registry/components/ui/rich-text-editor/toolbar.tsx +465 -0
  88. package/src/registry/components/ui/rich-text-editor/use-editor.ts +231 -0
  89. package/src/registry/components/ui/scroll-area.tsx +12 -2
  90. package/src/registry/components/ui/section-heading.tsx +108 -0
  91. package/src/registry/components/ui/select.tsx +16 -19
  92. package/src/registry/components/ui/sheet.tsx +58 -53
  93. package/src/registry/components/ui/sidebar.tsx +4 -4
  94. package/src/registry/components/ui/status.tsx +7 -5
  95. package/src/registry/components/ui/steps.tsx +198 -0
  96. package/src/registry/components/ui/switch.tsx +1 -1
  97. package/src/registry/components/ui/table-of-contents.tsx +131 -0
  98. package/src/registry/components/ui/tabs.tsx +1 -1
  99. package/src/registry/components/ui/theme-toggle.tsx +175 -139
  100. package/src/registry/components/ui/titlebar-tabs.tsx +773 -0
  101. package/src/registry/components/ui/titlebar.tsx +468 -0
  102. package/src/registry/components/ui/toggle-group.tsx +1 -1
  103. package/src/registry/components/ui/updater-modal.tsx +254 -0
  104. package/src/registry/metadata.ts +167 -6
  105. package/src/registry/providers/theme-provider.tsx +16 -8
  106. package/src/registry/providers/theme-script.tsx +29 -9
  107. package/src/registry/providers/theme-transitions.ts +81 -50
@@ -7,7 +7,8 @@ import {
7
7
  type JSX,
8
8
  type Accessor,
9
9
  } from "solid-js";
10
- import { createScrollPosition, createElementSize } from "@nikala-ui/hooks";
10
+ import { createScrollPosition } from "@/hooks/create-scroll-position";
11
+ import { createElementSize } from "@/hooks/create-resize-observer";
11
12
  import { cn } from "@/lib/cn";
12
13
 
13
14
  export interface ScrollAreaProps extends JSX.HTMLAttributes<HTMLDivElement> {
@@ -50,9 +51,11 @@ export const ScrollArea: Component<ScrollAreaProps> = (props) => {
50
51
  const scrollWidth = viewportRef.scrollWidth;
51
52
  const clientWidth = viewportRef.clientWidth;
52
53
 
54
+ // Track available lengths (considering 4px track padding)
53
55
  const trackHeight = verticalTrackRef ? verticalTrackRef.clientHeight - 4 : clientHeight - 4;
54
56
  const trackWidth = horizontalTrackRef ? horizontalTrackRef.clientWidth - 4 : clientWidth - 4;
55
57
 
58
+ // Vertical thumb metrics
56
59
  if (scrollHeight > clientHeight && clientHeight > 0) {
57
60
  const vRatio = clientHeight / scrollHeight;
58
61
  const calculatedHeight = Math.max(vRatio * trackHeight, 20);
@@ -64,6 +67,7 @@ export const ScrollArea: Component<ScrollAreaProps> = (props) => {
64
67
  setThumbHeight(0);
65
68
  }
66
69
 
70
+ // Horizontal thumb metrics
67
71
  if (scrollWidth > clientWidth && clientWidth > 0) {
68
72
  const hRatio = clientWidth / scrollWidth;
69
73
  const calculatedWidth = Math.max(hRatio * trackWidth, 20);
@@ -84,6 +88,7 @@ export const ScrollArea: Component<ScrollAreaProps> = (props) => {
84
88
  updateThumbMetrics();
85
89
  });
86
90
 
91
+ // Enable mouse drag on Vertical Thumb
87
92
  const handleVerticalThumbPointerDown = (e: PointerEvent) => {
88
93
  if (!viewportRef || !verticalTrackRef) return;
89
94
  e.preventDefault();
@@ -115,6 +120,7 @@ export const ScrollArea: Component<ScrollAreaProps> = (props) => {
115
120
  window.addEventListener("pointerup", onPointerUp);
116
121
  };
117
122
 
123
+ // Enable mouse drag on Horizontal Thumb
118
124
  const handleHorizontalThumbPointerDown = (e: PointerEvent) => {
119
125
  if (!viewportRef || !horizontalTrackRef) return;
120
126
  e.preventDefault();
@@ -146,6 +152,7 @@ export const ScrollArea: Component<ScrollAreaProps> = (props) => {
146
152
  window.addEventListener("pointerup", onPointerUp);
147
153
  };
148
154
 
155
+ // Convert vertical mouse wheel into horizontal scroll proportionally
149
156
  const handleWheel = (e: WheelEvent) => {
150
157
  if (orientation() === "horizontal" && viewportRef) {
151
158
  if (Math.abs(e.deltaY) > Math.abs(e.deltaX)) {
@@ -161,9 +168,10 @@ export const ScrollArea: Component<ScrollAreaProps> = (props) => {
161
168
  onWheel={handleWheel}
162
169
  {...rest}
163
170
  >
171
+ {/* Scroll Viewport Container */}
164
172
  <div
165
173
  ref={viewportRef}
166
- class="h-full w-full overflow-auto scrollbar-none rounded-[inherit]"
174
+ class="h-full w-full max-h-[inherit] overflow-auto scrollbar-none rounded-[inherit]"
167
175
  style={{
168
176
  "scrollbar-width": "none",
169
177
  "-ms-overflow-style": "none",
@@ -172,6 +180,7 @@ export const ScrollArea: Component<ScrollAreaProps> = (props) => {
172
180
  {local.children}
173
181
  </div>
174
182
 
183
+ {/* Vertical Scrollbar Track & Thumb */}
175
184
  {(orientation() === "vertical" || orientation() === "both") && thumbHeight() > 0 && (
176
185
  <div
177
186
  ref={verticalTrackRef}
@@ -193,6 +202,7 @@ export const ScrollArea: Component<ScrollAreaProps> = (props) => {
193
202
  </div>
194
203
  )}
195
204
 
205
+ {/* Horizontal Scrollbar Track & Thumb */}
196
206
  {(orientation() === "horizontal" || orientation() === "both") && thumbWidth() > 0 && (
197
207
  <div
198
208
  ref={horizontalTrackRef}
@@ -0,0 +1,108 @@
1
+ import {
2
+ splitProps,
3
+ Show,
4
+ type JSX,
5
+ type Component,
6
+ } from "solid-js";
7
+ import { cva, type VariantProps } from "class-variance-authority";
8
+ import { Badge } from "@/components/ui/badge";
9
+ import { cn } from "@/lib/cn";
10
+
11
+ const headingVariants = cva("tracking-tight", {
12
+ variants: {
13
+ variant: {
14
+ page: "text-3xl sm:text-4xl font-bold",
15
+ section: "text-2xl font-semibold border-b border-border/50 pb-2",
16
+ compact: "text-base font-semibold",
17
+ },
18
+ },
19
+ defaultVariants: {
20
+ variant: "section",
21
+ },
22
+ });
23
+
24
+ const descriptionVariants = cva("text-muted-foreground leading-relaxed", {
25
+ variants: {
26
+ variant: {
27
+ page: "text-lg",
28
+ section: "text-sm",
29
+ compact: "text-xs",
30
+ },
31
+ },
32
+ defaultVariants: {
33
+ variant: "section",
34
+ },
35
+ });
36
+
37
+ export interface SectionHeadingProps
38
+ extends Omit<JSX.HTMLAttributes<HTMLDivElement>, "title">,
39
+ VariantProps<typeof headingVariants> {
40
+ /** Heading text content */
41
+ title: string;
42
+ /** Optional badge label displayed next to the title */
43
+ badge?: string;
44
+ /** Badge style variant */
45
+ badgeVariant?: "default" | "secondary" | "outline" | "destructive";
46
+ /** Optional subtitle or explanatory note below the title */
47
+ description?: string;
48
+ class?: string;
49
+ }
50
+
51
+ /**
52
+ * Reusable heading block with title, optional badge, and description.
53
+ * Supports "page" (h1), "section" (h2 with divider), and "compact" (h3) variants.
54
+ */
55
+ export const SectionHeading: Component<SectionHeadingProps> = (props) => {
56
+ const [local, rest] = splitProps(props, [
57
+ "title",
58
+ "badge",
59
+ "badgeVariant",
60
+ "description",
61
+ "variant",
62
+ "class",
63
+ ]);
64
+
65
+ const v = () => local.variant || "section";
66
+
67
+ return (
68
+ <div class={cn("space-y-2", local.class)} {...rest}>
69
+ <div class={cn("flex items-center gap-2", v() === "section" && "w-full")}>
70
+ <Show when={v() === "page"}>
71
+ <h1 class={headingVariants({ variant: v() })}>
72
+ {local.title}
73
+ </h1>
74
+ </Show>
75
+
76
+ <Show when={v() === "section"}>
77
+ <h2 class={cn("w-full", headingVariants({ variant: v() }))}>
78
+ {local.title}
79
+ </h2>
80
+ </Show>
81
+
82
+ <Show when={v() === "compact"}>
83
+ <h3 class={headingVariants({ variant: v() })}>
84
+ {local.title}
85
+ </h3>
86
+ </Show>
87
+
88
+ <Show when={local.badge}>
89
+ <Badge
90
+ variant={local.badgeVariant || "outline"}
91
+ class={cn(
92
+ "select-none",
93
+ v() === "page" ? "text-xs" : "font-mono text-[10px] py-0 px-1.5 font-medium"
94
+ )}
95
+ >
96
+ {local.badge}
97
+ </Badge>
98
+ </Show>
99
+ </div>
100
+
101
+ <Show when={local.description}>
102
+ <p class={descriptionVariants({ variant: v() })}>
103
+ {local.description}
104
+ </p>
105
+ </Show>
106
+ </div>
107
+ );
108
+ };
@@ -1,20 +1,24 @@
1
- import { splitProps, type Component, type JSX, type ValidComponent } from "solid-js";
1
+ import { splitProps, type JSX, type ValidComponent } from "solid-js";
2
2
  import * as SelectPrimitive from "@kobalte/core/select";
3
3
  import type { PolymorphicProps } from "@kobalte/core/polymorphic";
4
- import { createClickOutside } from "@nikala-ui/hooks";
5
- import { ScrollArea } from "./scroll-area";
4
+ import { createClickOutside } from "@/hooks/create-click-outside";
5
+ import { ScrollArea } from "@/components/ui/scroll-area";
6
6
  import { cn } from "@/lib/cn";
7
7
 
8
8
  export type SelectRootProps<Option = any, OptGroup = any, T extends ValidComponent = "div"> =
9
- SelectPrimitive.SelectRootProps<Option, OptGroup, T>;
9
+ SelectPrimitive.SelectRootProps<Option, OptGroup, T> & {
10
+ class?: string;
11
+ };
10
12
 
11
13
  /**
12
- * Root Select component wrapper built on Kobalte primitives.
14
+ * Root Select component built on top of Kobalte headless primitives.
13
15
  */
14
16
  export const Select = <Option = any, OptGroup = any, T extends ValidComponent = "div">(
15
- props: SelectRootProps<Option, OptGroup, T>
17
+ props: PolymorphicProps<T, SelectRootProps<Option, OptGroup, T>>
16
18
  ) => {
17
- return <SelectPrimitive.Root {...props} />;
19
+ const [local, rest] = splitProps(props as SelectRootProps, ["class"]);
20
+
21
+ return <SelectPrimitive.Root class={cn("relative w-full", local.class)} {...(rest as any)} />;
18
22
  };
19
23
 
20
24
  export type SelectTriggerProps<T extends ValidComponent = "button"> =
@@ -136,23 +140,16 @@ export const SelectItem = <T extends ValidComponent = "li">(
136
140
  return (
137
141
  <SelectPrimitive.Item
138
142
  class={cn(
139
- "relative flex w-full cursor-pointer select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none data-[disabled]:pointer-events-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:opacity-50 text-foreground",
143
+ "relative flex w-full cursor-pointer select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none data-disabled:pointer-events-none data-highlighted:bg-accent data-highlighted:text-accent-foreground",
140
144
  local.class
141
145
  )}
142
146
  {...rest}
143
147
  >
144
- <span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
145
- <SelectPrimitive.ItemIndicator
146
- as="svg"
147
- class="h-4 w-4"
148
- viewBox="0 0 24 24"
149
- fill="none"
150
- stroke="currentColor"
151
- stroke-width="2"
152
- >
148
+ <SelectPrimitive.ItemIndicator class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
149
+ <svg class="h-4 w-4 fill-none stroke-current stroke-2" viewBox="0 0 24 24">
153
150
  <path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7" />
154
- </SelectPrimitive.ItemIndicator>
155
- </span>
151
+ </svg>
152
+ </SelectPrimitive.ItemIndicator>
156
153
  <SelectPrimitive.ItemLabel>{local.children}</SelectPrimitive.ItemLabel>
157
154
  </SelectPrimitive.Item>
158
155
  );
@@ -3,7 +3,7 @@ import * as DialogPrimitive from "@kobalte/core/dialog";
3
3
  import type { PolymorphicProps } from "@kobalte/core/polymorphic";
4
4
  import { cva, type VariantProps } from "class-variance-authority";
5
5
  import { X } from "lucide-solid";
6
- import { ScrollArea } from "./scroll-area";
6
+ import { ScrollArea } from "@/components/ui/scroll-area";
7
7
  import { cn } from "@/lib/cn";
8
8
 
9
9
  // Global CSS Keyframe Animations specifically designed for Kobalte animationend DOM events
@@ -15,7 +15,7 @@ const sheetStyles = `
15
15
  @keyframes sheet-slide-in-top { from { transform: translateY(-100%); } to { transform: translateY(0); } }
16
16
  @keyframes sheet-slide-out-top { from { transform: translateY(0); } to { transform: translateY(-100%); } }
17
17
  @keyframes sheet-slide-in-bottom { from { transform: translateY(100%); } to { transform: translateY(0); } }
18
- @keyframes sheet-slide-out-bottom { from { transform: translateY(0); } to { transform: translateY(-100%); } }
18
+ @keyframes sheet-slide-out-bottom { from { transform: translateY(0); } to { transform: translateY(100%); } }
19
19
  @keyframes sheet-fade-in { from { opacity: 0; } to { opacity: 1; } }
20
20
  @keyframes sheet-fade-out { from { opacity: 1; } to { opacity: 0; } }
21
21
  `;
@@ -28,12 +28,10 @@ export const sheetVariants = cva(
28
28
  {
29
29
  variants: {
30
30
  side: {
31
- top: "inset-x-0 top-0 border-b data-[expanded]:animate-[sheet-slide-in-top_300ms_ease-in-out] data-[closed]:animate-[sheet-slide-out-top_300ms_ease-in-out]",
32
- bottom:
33
- "inset-x-0 bottom-0 border-t data-[expanded]:animate-[sheet-slide-in-bottom_300ms_ease-in-out] data-[closed]:animate-[sheet-slide-out-bottom_300ms_ease-in-out]",
34
- left: "inset-y-0 left-0 h-full w-3/4 border-r sm:max-w-sm data-[expanded]:animate-[sheet-slide-in-left_300ms_ease-in-out] data-[closed]:animate-[sheet-slide-out-left_300ms_ease-in-out]",
35
- right:
36
- "inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm data-[expanded]:animate-[sheet-slide-in-right_300ms_ease-in-out] data-[closed]:animate-[sheet-slide-out-right_300ms_ease-in-out]",
31
+ left: "fixed top-0 bottom-0 left-0 w-3/4 border-r border-border sm:max-w-sm data-[expanded]:animate-[sheet-slide-in-left_300ms_ease-in-out] data-[closed]:animate-[sheet-slide-out-left_300ms_ease-in-out]",
32
+ right: "fixed top-0 bottom-0 right-0 w-3/4 border-l border-border sm:max-w-sm data-[expanded]:animate-[sheet-slide-in-right_300ms_ease-in-out] data-[closed]:animate-[sheet-slide-out-right_300ms_ease-in-out]",
33
+ top: "fixed top-0 left-0 right-0 border-b border-border data-[expanded]:animate-[sheet-slide-in-top_300ms_ease-in-out] data-[closed]:animate-[sheet-slide-out-top_300ms_ease-in-out]",
34
+ bottom: "fixed bottom-0 left-0 right-0 border-t border-border data-[expanded]:animate-[sheet-slide-in-bottom_300ms_ease-in-out] data-[closed]:animate-[sheet-slide-out-bottom_300ms_ease-in-out]",
37
35
  },
38
36
  },
39
37
  defaultVariants: {
@@ -42,20 +40,23 @@ export const sheetVariants = cva(
42
40
  }
43
41
  );
44
42
 
45
- export const Sheet = DialogPrimitive.Root;
43
+ export type SheetRootProps = DialogPrimitive.DialogRootProps;
44
+
45
+ export const Sheet: Component<SheetRootProps> = (props) => {
46
+ return <DialogPrimitive.Root {...props} />;
47
+ };
48
+
46
49
  export const SheetTrigger = DialogPrimitive.Trigger;
47
50
  export const SheetClose = DialogPrimitive.CloseButton;
48
- export const SheetPortal = DialogPrimitive.Portal;
49
51
 
50
- export type SheetOverlayProps<T extends ValidComponent = "div"> =
51
- DialogPrimitive.DialogOverlayProps<T> & {
52
- /** Whether to apply backdrop blur (default: true) */
53
- blur?: boolean;
54
- class?: string;
55
- };
52
+ export interface SheetOverlayProps<T extends ValidComponent = "div"> {
53
+ /** Whether to apply background blur effect or keep transparent (default: true) */
54
+ blur?: boolean;
55
+ class?: string;
56
+ }
56
57
 
57
58
  /**
58
- * Fullscreen dark backdrop with fade keyframe animation.
59
+ * Backdrop overlay wrapper with fade-in and fade-out animations.
59
60
  */
60
61
  export const SheetOverlay = <T extends ValidComponent = "div">(
61
62
  props: PolymorphicProps<T, SheetOverlayProps<T>>
@@ -65,8 +66,8 @@ export const SheetOverlay = <T extends ValidComponent = "div">(
65
66
  return (
66
67
  <DialogPrimitive.Overlay
67
68
  class={cn(
68
- "fixed inset-0 z-50 transition-all duration-200 data-[expanded]:animate-[sheet-fade-in_300ms_ease-in-out] data-[closed]:animate-[sheet-fade-out_300ms_ease-in-out]",
69
- local.blur !== false ? "bg-black/80 backdrop-blur-sm" : "bg-black/80",
69
+ "fixed inset-0 z-50 data-[expanded]:animate-[sheet-fade-in_300ms_ease-in-out] data-[closed]:animate-[sheet-fade-out_300ms_ease-in-out]",
70
+ local.blur !== false ? "bg-black/80 backdrop-blur-sm" : "bg-transparent",
70
71
  local.class
71
72
  )}
72
73
  {...(rest as any)}
@@ -76,28 +77,32 @@ export const SheetOverlay = <T extends ValidComponent = "div">(
76
77
 
77
78
  export type SheetContentProps<T extends ValidComponent = "div"> =
78
79
  DialogPrimitive.DialogContentProps<T> &
79
- VariantProps<typeof sheetVariants> & {
80
- side?: "top" | "bottom" | "left" | "right";
81
- showCloseButton?: boolean;
82
- closeOnOutsideClick?: boolean;
83
- blur?: boolean;
84
- class?: string;
85
- children?: JSX.Element;
86
- };
80
+ VariantProps<typeof sheetVariants> & {
81
+ /** Direction from which the sheet slides out: top, bottom, left, right */
82
+ side?: "top" | "bottom" | "left" | "right";
83
+ /** Whether to display the top-right close (X) button (default: true) */
84
+ showCloseButton?: boolean;
85
+ /** Whether clicking outside closes the sheet (default: true) */
86
+ closeOnOutsideClick?: boolean;
87
+ /** Whether to apply background backdrop blur (default: true) */
88
+ blur?: boolean;
89
+ class?: string;
90
+ children?: JSX.Element;
91
+ };
87
92
 
88
93
  /**
89
- * Slide-out panel container with ScrollArea and animation support.
94
+ * Main sheet container with smooth CSS keyframe slide animations.
90
95
  */
91
96
  export const SheetContent = <T extends ValidComponent = "div">(
92
97
  props: PolymorphicProps<T, SheetContentProps<T>>
93
98
  ) => {
94
99
  const [local, rest] = splitProps(props as SheetContentProps, [
95
- "class",
96
- "children",
97
100
  "side",
98
101
  "showCloseButton",
99
102
  "closeOnOutsideClick",
100
103
  "blur",
104
+ "class",
105
+ "children",
101
106
  "onPointerDownOutside",
102
107
  "onInteractOutside",
103
108
  ]);
@@ -123,7 +128,7 @@ export const SheetContent = <T extends ValidComponent = "div">(
123
128
  };
124
129
 
125
130
  return (
126
- <SheetPortal>
131
+ <DialogPrimitive.Portal>
127
132
  <style>{sheetStyles}</style>
128
133
  <SheetOverlay blur={local.blur} />
129
134
  <DialogPrimitive.Content
@@ -144,7 +149,7 @@ export const SheetContent = <T extends ValidComponent = "div">(
144
149
  </DialogPrimitive.CloseButton>
145
150
  </Show>
146
151
  </DialogPrimitive.Content>
147
- </SheetPortal>
152
+ </DialogPrimitive.Portal>
148
153
  );
149
154
  };
150
155
 
@@ -172,44 +177,44 @@ export const SheetFooter: Component<SheetFooterProps> = (props) => {
172
177
 
173
178
  return (
174
179
  <div
175
- class={cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2 pt-4", local.class)}
180
+ class={cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", local.class)}
176
181
  {...rest}
177
182
  />
178
183
  );
179
184
  };
180
185
 
181
- export interface SheetTitleProps {
182
- class?: string;
183
- children?: JSX.Element;
184
- }
186
+ export type SheetTitleProps<T extends ValidComponent = "h2"> =
187
+ DialogPrimitive.DialogTitleProps<T> & {
188
+ class?: string;
189
+ };
185
190
 
186
- export const SheetTitle: Component<SheetTitleProps> = (props) => {
187
- const [local, rest] = splitProps(props, ["class", "children"]);
191
+ export const SheetTitle = <T extends ValidComponent = "h2">(
192
+ props: PolymorphicProps<T, SheetTitleProps<T>>
193
+ ) => {
194
+ const [local, rest] = splitProps(props as SheetTitleProps, ["class"]);
188
195
 
189
196
  return (
190
197
  <DialogPrimitive.Title
191
198
  class={cn("text-lg font-semibold text-foreground", local.class)}
192
- {...rest}
193
- >
194
- {local.children}
195
- </DialogPrimitive.Title>
199
+ {...(rest as any)}
200
+ />
196
201
  );
197
202
  };
198
203
 
199
- export interface SheetDescriptionProps {
200
- class?: string;
201
- children?: JSX.Element;
202
- }
204
+ export type SheetDescriptionProps<T extends ValidComponent = "p"> =
205
+ DialogPrimitive.DialogDescriptionProps<T> & {
206
+ class?: string;
207
+ };
203
208
 
204
- export const SheetDescription: Component<SheetDescriptionProps> = (props) => {
205
- const [local, rest] = splitProps(props, ["class", "children"]);
209
+ export const SheetDescription = <T extends ValidComponent = "p">(
210
+ props: PolymorphicProps<T, SheetDescriptionProps<T>>
211
+ ) => {
212
+ const [local, rest] = splitProps(props as SheetDescriptionProps, ["class"]);
206
213
 
207
214
  return (
208
215
  <DialogPrimitive.Description
209
216
  class={cn("text-sm text-muted-foreground", local.class)}
210
- {...rest}
211
- >
212
- {local.children}
213
- </DialogPrimitive.Description>
217
+ {...(rest as any)}
218
+ />
214
219
  );
215
220
  };
@@ -15,9 +15,9 @@ import {
15
15
  } from "solid-js";
16
16
  import { cva, type VariantProps } from "class-variance-authority";
17
17
  import { PanelLeft, PanelRight } from "lucide-solid";
18
- import { Tooltip, TooltipTrigger, TooltipContent } from "./tooltip";
19
- import { Skeleton } from "./skeleton";
20
- import { Separator } from "./separator";
18
+ import { Tooltip, TooltipTrigger, TooltipContent } from "@/components/ui/tooltip";
19
+ import { Skeleton } from "@/components/ui/skeleton";
20
+ import { Separator } from "@/components/ui/separator";
21
21
  import { cn } from "@/lib/cn";
22
22
 
23
23
  /* --- Constants --- */
@@ -211,7 +211,7 @@ export const Sidebar: ParentComponent<SidebarProps> = (props) => {
211
211
  data-variant={variant()}
212
212
  data-side={side()}
213
213
  class={cn(
214
- "group relative flex flex-col bg-card text-card-foreground transition-all duration-200 ease-in-out shrink-0",
214
+ "group relative flex flex-col bg-card text-card-foreground transition-[width,opacity] duration-200 ease-in-out shrink-0",
215
215
  !isCollapsed()
216
216
  ? "w-[var(--sidebar-width,17rem)]"
217
217
  : collapsible() === "icon"
@@ -106,11 +106,13 @@ export const Status: Component<StatusProps> = (props) => {
106
106
  />
107
107
  </Show>
108
108
  <span
109
- class={statusDotVariants({
110
- variant: local.variant,
111
- size: local.size,
112
- animation: local.animation === "ping" ? "none" : local.animation,
113
- })}
109
+ class={cn(
110
+ statusDotVariants({
111
+ variant: local.variant,
112
+ size: local.size,
113
+ animation: local.animation === "ping" ? "none" : local.animation,
114
+ })
115
+ )}
114
116
  />
115
117
  </span>
116
118
  {local.children}