gladvn 0.2.35 → 0.2.37

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 (134) hide show
  1. package/README.md +1 -1
  2. package/package.json +2 -1
  3. package/scripts/strip-comments.ts +79 -0
  4. package/src/blocks/auth-form.tsx +34 -30
  5. package/src/blocks/auth-recovery.tsx +9 -13
  6. package/src/blocks/auth-split.tsx +46 -36
  7. package/src/blocks/settings.tsx +84 -117
  8. package/src/components/macro/alert-preset.tsx +3 -1
  9. package/src/components/macro/carousel-preset.tsx +0 -1
  10. package/src/components/macro/checkbox-preset.test.tsx +2 -2
  11. package/src/components/macro/checkbox-preset.tsx +1 -2
  12. package/src/components/macro/command-preset.tsx +1 -1
  13. package/src/components/macro/date-picker.tsx +5 -18
  14. package/src/components/macro/dialog-preset.tsx +5 -3
  15. package/src/components/macro/input-preset.tsx +0 -1
  16. package/src/components/macro/select-preset.tsx +1 -1
  17. package/src/components/macro/switch-preset.test.tsx +1 -1
  18. package/src/components/micro/accordion.test.tsx +6 -12
  19. package/src/components/micro/alert-dialog.tsx +0 -2
  20. package/src/components/micro/alert.test.tsx +5 -8
  21. package/src/components/micro/alert.tsx +0 -2
  22. package/src/components/micro/badge.test.tsx +5 -7
  23. package/src/components/micro/badge.tsx +1 -3
  24. package/src/components/micro/button.test.tsx +19 -26
  25. package/src/components/micro/button.tsx +3 -11
  26. package/src/components/micro/calendar.tsx +12 -13
  27. package/src/components/micro/card.test.tsx +3 -5
  28. package/src/components/micro/carousel.tsx +0 -1
  29. package/src/components/micro/chart.tsx +3 -2
  30. package/src/components/micro/checkbox.test.tsx +9 -18
  31. package/src/components/micro/combobox.tsx +1 -3
  32. package/src/components/micro/command.tsx +23 -11
  33. package/src/components/micro/context-menu.tsx +0 -2
  34. package/src/components/micro/dialog.test.tsx +6 -14
  35. package/src/components/micro/dialog.tsx +0 -2
  36. package/src/components/micro/drawer.tsx +0 -3
  37. package/src/components/micro/dropdown-menu.test.tsx +8 -14
  38. package/src/components/micro/dropdown-menu.tsx +0 -2
  39. package/src/components/micro/field.tsx +3 -3
  40. package/src/components/micro/hover-card.tsx +0 -2
  41. package/src/components/micro/input-group.tsx +9 -42
  42. package/src/components/micro/input.test.tsx +15 -24
  43. package/src/components/micro/navigation-menu.tsx +0 -2
  44. package/src/components/micro/popover.test.tsx +5 -9
  45. package/src/components/micro/progress.tsx +5 -1
  46. package/src/components/micro/select.test.tsx +5 -18
  47. package/src/components/micro/select.tsx +3 -5
  48. package/src/components/micro/separator.tsx +1 -1
  49. package/src/components/micro/sheet.test.tsx +6 -14
  50. package/src/components/micro/sheet.tsx +0 -2
  51. package/src/components/micro/sidebar.tsx +5 -6
  52. package/src/components/micro/sonner.tsx +0 -1
  53. package/src/components/micro/switch.test.tsx +9 -18
  54. package/src/components/micro/switch.tsx +1 -1
  55. package/src/components/micro/tabs.test.tsx +5 -11
  56. package/src/components/micro/theme-provider.tsx +0 -12
  57. package/src/components/micro/toggle-group.tsx +1 -12
  58. package/src/components/micro/tooltip.test.tsx +7 -12
  59. package/src/dev/App.tsx +6 -6
  60. package/src/dev/components/BlockViewer.tsx +15 -4
  61. package/src/dev/components/Container.tsx +20 -0
  62. package/src/dev/components/GladvnLogo.tsx +3 -9
  63. package/src/dev/components/code-highlighter.tsx +5 -3
  64. package/src/dev/components/showcase.tsx +116 -168
  65. package/src/dev/sections/buttons.tsx +4 -9
  66. package/src/dev/sections/display.tsx +68 -72
  67. package/src/dev/sections/feedback.tsx +304 -314
  68. package/src/dev/sections/forms.tsx +10 -14
  69. package/src/dev/sections/interactive.tsx +32 -32
  70. package/src/dev/sections/overview.tsx +2 -10
  71. package/src/dev/showcase/accordion.tsx +512 -554
  72. package/src/dev/showcase/alert-dialog.tsx +525 -565
  73. package/src/dev/showcase/alert.tsx +352 -402
  74. package/src/dev/showcase/aspect-ratio.tsx +167 -193
  75. package/src/dev/showcase/avatar.tsx +231 -269
  76. package/src/dev/showcase/badge.tsx +92 -140
  77. package/src/dev/showcase/breadcrumb.tsx +113 -135
  78. package/src/dev/showcase/button.tsx +140 -173
  79. package/src/dev/showcase/calendar.tsx +187 -237
  80. package/src/dev/showcase/card.tsx +229 -261
  81. package/src/dev/showcase/carousel.tsx +288 -315
  82. package/src/dev/showcase/chart.tsx +44 -50
  83. package/src/dev/showcase/checkbox.tsx +286 -330
  84. package/src/dev/showcase/collapsible.tsx +143 -160
  85. package/src/dev/showcase/combobox.tsx +327 -369
  86. package/src/dev/showcase/command.tsx +106 -120
  87. package/src/dev/showcase/context-menu.tsx +93 -107
  88. package/src/dev/showcase/dialog.tsx +585 -630
  89. package/src/dev/showcase/drawer.tsx +176 -196
  90. package/src/dev/showcase/dropdown-menu.tsx +183 -201
  91. package/src/dev/showcase/empty.tsx +232 -274
  92. package/src/dev/showcase/hover-card.tsx +153 -180
  93. package/src/dev/showcase/input-group.tsx +221 -253
  94. package/src/dev/showcase/input-otp.tsx +204 -250
  95. package/src/dev/showcase/input.tsx +246 -325
  96. package/src/dev/showcase/item.tsx +134 -152
  97. package/src/dev/showcase/kbd.tsx +149 -172
  98. package/src/dev/showcase/label.tsx +50 -68
  99. package/src/dev/showcase/menubar.tsx +194 -213
  100. package/src/dev/showcase/navigation-menu.tsx +119 -133
  101. package/src/dev/showcase/overview-components/ArchitectureSection.tsx +126 -0
  102. package/src/dev/showcase/overview-components/CodeBlock.tsx +50 -0
  103. package/src/dev/showcase/overview-components/ColorPaletteSection.tsx +44 -0
  104. package/src/dev/showcase/overview-components/DashboardPreview.tsx +159 -0
  105. package/src/dev/showcase/overview-components/FeatureGridSection.tsx +535 -0
  106. package/src/dev/showcase/overview-components/FooterCTA.tsx +137 -0
  107. package/src/dev/showcase/overview-components/HeroSection.tsx +65 -0
  108. package/src/dev/showcase/overview-components/PrinciplesSection.tsx +128 -0
  109. package/src/dev/showcase/overview.tsx +21 -1163
  110. package/src/dev/showcase/pagination.tsx +144 -190
  111. package/src/dev/showcase/popover.tsx +181 -196
  112. package/src/dev/showcase/progress.tsx +141 -189
  113. package/src/dev/showcase/radio-group.tsx +272 -332
  114. package/src/dev/showcase/resizable.tsx +119 -141
  115. package/src/dev/showcase/scroll-area.tsx +21 -36
  116. package/src/dev/showcase/select.tsx +262 -322
  117. package/src/dev/showcase/separator.tsx +75 -73
  118. package/src/dev/showcase/sheet.tsx +333 -361
  119. package/src/dev/showcase/sidebar.tsx +53 -59
  120. package/src/dev/showcase/skeleton.tsx +93 -112
  121. package/src/dev/showcase/slider.tsx +244 -296
  122. package/src/dev/showcase/sonner.tsx +251 -258
  123. package/src/dev/showcase/spinner.tsx +46 -67
  124. package/src/dev/showcase/switch.tsx +298 -362
  125. package/src/dev/showcase/table.tsx +76 -80
  126. package/src/dev/showcase/tabs.tsx +302 -355
  127. package/src/dev/showcase/textarea.tsx +240 -293
  128. package/src/dev/showcase/toast.tsx +48 -54
  129. package/src/dev/showcase/toggle-group.tsx +104 -129
  130. package/src/dev/showcase/toggle.tsx +82 -102
  131. package/src/dev/showcase/tooltip.tsx +173 -192
  132. package/src/dev/showcase/why.tsx +6 -12
  133. package/src/hooks/use-mobile.test.ts +3 -2
  134. package/src/lib/utils.test.ts +5 -4
@@ -35,7 +35,7 @@ const badgeVariants = cva(
35
35
  },
36
36
  },
37
37
  compoundVariants: [
38
- // Solid
38
+
39
39
  {
40
40
  variant: "solid",
41
41
  color: "primary",
@@ -82,7 +82,6 @@ const badgeVariants = cva(
82
82
  className: "bg-accent text-accent-foreground",
83
83
  },
84
84
 
85
- // Outline
86
85
  {
87
86
  variant: "outline",
88
87
  color: "primary",
@@ -125,7 +124,6 @@ const badgeVariants = cva(
125
124
  className: "border-accent text-accent-foreground",
126
125
  },
127
126
 
128
- // Soft
129
127
  {
130
128
  variant: "soft",
131
129
  color: "primary",
@@ -7,82 +7,77 @@ import { describe, expect, it, vi } from "vitest";
7
7
  import { Button } from "./button";
8
8
 
9
9
  describe("Button", () => {
10
- // 1. Rendering & Attributes (API Surface)
10
+
11
11
  it("[3C.1-01] [P1] renders correctly with default props", () => {
12
- // Given
12
+
13
13
  render(<Button>Click me</Button>);
14
14
  const button = screen.getByRole("button", { name: "Click me" });
15
- // Then
15
+
16
16
  expect(button).toBeInTheDocument();
17
17
  expect(button).toHaveAttribute("data-variant", "solid");
18
18
  expect(button).toHaveAttribute("data-color", "primary");
19
19
  });
20
20
 
21
21
  it("[3C.1-02] [P1] applies custom variants and colors", () => {
22
- // Given
22
+
23
23
  render(
24
24
  <Button variant="outline" color="destructive">
25
25
  Delete
26
26
  </Button>,
27
27
  );
28
28
  const button = screen.getByRole("button", { name: "Delete" });
29
- // Then
29
+
30
30
  expect(button).toHaveAttribute("data-variant", "outline");
31
31
  expect(button).toHaveAttribute("data-color", "destructive");
32
32
  });
33
33
 
34
34
  it("[3C.1-03] [P1] merges custom classNames properly", () => {
35
- // Given
35
+
36
36
  render(<Button className="custom-test-class">Classy Button</Button>);
37
37
  const button = screen.getByRole("button", { name: "Classy Button" });
38
- // Then
38
+
39
39
  expect(button).toHaveClass("custom-test-class");
40
40
  });
41
41
 
42
42
  it("[3C.1-04] [P1] supports iconOnly attribute to render as square", () => {
43
- // Given
43
+
44
44
  render(<Button iconOnly>Icon</Button>);
45
45
  const button = screen.getByRole("button", { name: "Icon" });
46
- // Then
46
+
47
47
  expect(button).toHaveAttribute("data-icon", "true");
48
48
  });
49
49
 
50
- // 2. Behaviors (Interaction & Events)
51
50
  it("[3C.1-05] [P1] fires onClick event when clicked", async () => {
52
- // Given
51
+
53
52
  const user = userEvent.setup();
54
53
  const handleClick = vi.fn();
55
54
  render(<Button onClick={handleClick}>Click</Button>);
56
55
 
57
56
  const button = screen.getByRole("button", { name: "Click" });
58
- // When
57
+
59
58
  await user.click(button);
60
59
 
61
- // Then
62
60
  expect(handleClick).toHaveBeenCalledTimes(1);
63
61
  });
64
62
 
65
63
  it("[3C.1-06] [P1] can be focused and activated via keyboard", async () => {
66
- // Given
64
+
67
65
  const user = userEvent.setup();
68
66
  const handleClick = vi.fn();
69
67
  render(<Button onClick={handleClick}>Submit</Button>);
70
68
 
71
69
  const button = screen.getByRole("button", { name: "Submit" });
72
70
 
73
- // Test focus
74
- // When
75
71
  await user.tab();
76
- // Then
72
+
77
73
  expect(button).toHaveFocus();
78
74
 
79
- // Test keyboard activation (Enter)
80
75
  await user.keyboard("{Enter}");
81
76
  expect(handleClick).toHaveBeenCalledTimes(1);
82
77
  });
83
78
 
84
79
  it("[3C.1-07] [P1] handles disabled state correctly and blocks clicks", async () => {
85
- // Given
80
+
86
81
  const user = userEvent.setup();
87
82
  const handleClick = vi.fn();
88
83
  render(
@@ -92,29 +87,27 @@ describe("Button", () => {
92
87
  );
93
88
 
94
89
  const button = screen.getByRole("button", { name: "Disabled Button" });
95
- // Then
90
+
96
91
  expect(button).toBeDisabled();
97
92
 
98
- // When
99
93
  await user.click(button);
100
94
  expect(handleClick).not.toHaveBeenCalled();
101
95
  });
102
96
 
103
- // 3. Architecture & Integration
104
97
  it("[3C.1-08] [P1] forwards the ref to the underlying DOM element", () => {
105
- // Given
98
+
106
99
  const ref = React.createRef<HTMLButtonElement>();
107
100
  render(<Button ref={ref}>Ref Button</Button>);
108
- // Then
101
+
109
102
  expect(ref.current).toBeInstanceOf(HTMLButtonElement);
110
103
  expect(ref.current?.textContent).toBe("Ref Button");
111
104
  });
112
105
 
113
106
  it("[3C.1-09] [P1] supports polymorphism via render prop (Base UI 'render' pattern)", () => {
114
- // Given
107
+
115
108
  render(<Button render={<a href="/home" />}>Link Button</Button>);
116
109
  const link = screen.getByText("Link Button");
117
- // Then
110
+
118
111
  expect(link).toBeInTheDocument();
119
112
  expect(link.tagName).toBe("A");
120
113
  expect(link).toHaveAttribute("href", "/home");
@@ -36,7 +36,7 @@ const buttonVariants = cva(
36
36
  "group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-border text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:ring-3 focus-visible:ring-offset-1 focus-visible:ring-offset-background active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:focus-visible:ring-3 aria-invalid:focus-visible:ring-destructive/50 dark:aria-invalid:border-destructive/50 dark:aria-invalid:focus-visible:ring-destructive/50 data-[icon=true]:aspect-square data-[icon=true]:px-0",
37
37
  {
38
38
  variants: {
39
- // ── Visual style ─────────────────────────────────────────────
39
+
40
40
  variant: {
41
41
  solid: "border-transparent",
42
42
  outline: "bg-transparent",
@@ -45,8 +45,6 @@ const buttonVariants = cva(
45
45
  link: "border-transparent bg-transparent underline-offset-4 hover:underline",
46
46
  },
47
47
 
48
- // ── Semantic color ───────────────────────────────────────────
49
- // Left empty — actual classes are injected via compoundVariants below
50
48
  color: {
51
49
  primary: "",
52
50
  secondary: "",
@@ -59,7 +57,6 @@ const buttonVariants = cva(
59
57
  accent: "",
60
58
  },
61
59
 
62
- // ── Size ─────────────────────────────────────────────────────
63
60
  size: {
64
61
  sm: "h-7 gap-1 px-3 text-xs",
65
62
  md: "h-8 gap-1.5 px-3.5",
@@ -67,9 +64,8 @@ const buttonVariants = cva(
67
64
  },
68
65
  },
69
66
 
70
- // ── variant × color combinations ─────────────────────────────
71
67
  compoundVariants: [
72
- // solid — filled background, foreground text
68
+
73
69
  {
74
70
  variant: "solid",
75
71
  color: "primary",
@@ -125,7 +121,6 @@ const buttonVariants = cva(
125
121
  "bg-accent text-accent-foreground hover:bg-accent/85",
126
122
  },
127
123
 
128
- // outline — border + semantic text, tinted hover
129
124
  {
130
125
  variant: "outline",
131
126
  color: "primary",
@@ -174,7 +169,6 @@ const buttonVariants = cva(
174
169
  "border-accent text-accent-foreground hover:bg-accent/10",
175
170
  },
176
171
 
177
- // soft — tinted background, semantic text
178
172
  {
179
173
  variant: "soft",
180
174
  color: "primary",
@@ -222,7 +216,6 @@ const buttonVariants = cva(
222
216
  "bg-accent/50 text-accent-foreground hover:bg-accent/80",
223
217
  },
224
218
 
225
- // ghost — transparent, semantic text, tinted hover
226
219
  {
227
220
  variant: "ghost",
228
221
  color: "primary",
@@ -269,7 +262,6 @@ const buttonVariants = cva(
269
262
  className: "text-accent-foreground hover:bg-accent/10",
270
263
  },
271
264
 
272
- // link — just semantic text + underline on hover
273
265
  { variant: "link", color: "primary", className: "text-primary" },
274
266
  { variant: "link", color: "secondary", className: "text-secondary" },
275
267
  { variant: "link", color: "destructive", className: "text-destructive" },
@@ -279,7 +271,7 @@ const buttonVariants = cva(
279
271
  { variant: "link", color: "tertiary", className: "text-tertiary" },
280
272
  { variant: "link", color: "muted", className: "text-muted-foreground" },
281
273
  { variant: "link", color: "accent", className: "text-accent-foreground" },
282
- // focus ring — semantic color at /15 opacity with offset
274
+
283
275
  { color: "primary", className: "focus-visible:ring-primary/50" },
284
276
  { color: "secondary", className: "focus-visible:ring-secondary/50" },
285
277
  { color: "destructive", className: "focus-visible:ring-destructive/50" },
@@ -345,31 +345,30 @@ function CalendarDayButton({
345
345
  data-range-end={modifiers.range_end}
346
346
  data-range-middle={modifiers.range_middle}
347
347
  className={cn(
348
- // Base layout — size driven by parent group
348
+
349
349
  "relative isolate z-10 flex aspect-square size-7 flex-col items-center justify-center gap-1 rounded-md font-normal leading-none transition-colors outline-none select-none",
350
350
  "group-[.calendar-sm]/calendar:size-6 group-[.calendar-lg]/calendar:size-8",
351
- // Text size — responsive via parent group
351
+
352
352
  "text-sm group-[.calendar-sm]/calendar:text-xs",
353
- // Hover
353
+
354
354
  "hover:bg-accent hover:text-accent-foreground",
355
- // Focus ring (standard)
355
+
356
356
  "focus-visible:ring-3 focus-visible:ring-ring/50 focus-visible:ring-offset-1 focus-visible:ring-offset-background",
357
- // Press feedback
357
+
358
358
  "active:translate-y-px",
359
- // Disabled
359
+
360
360
  "disabled:pointer-events-none disabled:opacity-50",
361
- // Keyboard focus from react-day-picker
361
+
362
362
  "group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:ring-3 group-data-[focused=true]/day:ring-ring/50",
363
- // Selected single
363
+
364
364
  "data-[selected-single=true]:bg-primary data-[selected-single=true]:text-primary-foreground data-[selected-single=true]:hover:bg-primary/90",
365
- // Range start
365
+
366
366
  "data-[range-start=true]:bg-primary data-[range-start=true]:text-primary-foreground",
367
- // Range end
367
+
368
368
  "data-[range-end=true]:bg-primary data-[range-end=true]:text-primary-foreground",
369
- // Range middle
369
+
370
370
  "data-[range-middle=true]:bg-muted data-[range-middle=true]:text-foreground",
371
- // Content spans (event dots etc.) — consumer should use data-slot on spans
372
- // Dark mode
371
+
373
372
  "dark:hover:text-foreground",
374
373
  className,
375
374
  )}
@@ -13,7 +13,7 @@ import {
13
13
 
14
14
  describe("Card", () => {
15
15
  it("[3C.11-01] [P1] renders all card parts correctly", () => {
16
- // Given
16
+
17
17
  render(
18
18
  <Card data-testid="card">
19
19
  <CardHeader>
@@ -25,7 +25,6 @@ describe("Card", () => {
25
25
  </Card>,
26
26
  );
27
27
 
28
- // Then
29
28
  expect(screen.getByTestId("card")).toBeInTheDocument();
30
29
  expect(screen.getByText("Card Title")).toBeInTheDocument();
31
30
  expect(screen.getByText("Card Description")).toBeInTheDocument();
@@ -34,16 +33,15 @@ describe("Card", () => {
34
33
  });
35
34
 
36
35
  it("[3C.11-02] [P1] applies the size variants correctly", () => {
37
- // Given
36
+
38
37
  const { rerender } = render(
39
38
  <Card size="sm" data-testid="card-sm">
40
39
  Content
41
40
  </Card>,
42
41
  );
43
- // Then
42
+
44
43
  expect(screen.getByTestId("card-sm")).toHaveAttribute("data-size", "sm");
45
44
 
46
- // When
47
45
  rerender(
48
46
  <Card size="lg" data-testid="card-lg">
49
47
  Content
@@ -172,7 +172,6 @@ const CarouselContent = React.forwardRef<
172
172
  >(({ className, ...props }, ref) => {
173
173
  const { carouselRef } = useCarousel();
174
174
 
175
- // Combine forwarded ref and internal embla ref
176
175
  const setRefs = React.useCallback(
177
176
  (node: HTMLDivElement) => {
178
177
  carouselRef(node);
@@ -14,7 +14,6 @@ import * as RechartsPrimitive from "recharts";
14
14
 
15
15
  import { cn } from "../../lib/utils";
16
16
 
17
- // Format: { THEME_NAME: CSS_SELECTOR }
18
17
  const THEMES = { light: "", dark: ".dark" } as const;
19
18
 
20
19
  const INITIAL_DIMENSION = { width: 320, height: 200 } as const;
@@ -229,7 +228,9 @@ function ChartTooltipContent({
229
228
  key={index}
230
229
  className={cn(
231
230
  "flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground",
232
- indicator === "dot" && "items-center",
231
+ {
232
+ "items-center": indicator === "dot"
233
+ }
233
234
  )}
234
235
  >
235
236
  {formatter && item?.value !== undefined && item.name ? (
@@ -8,16 +8,16 @@ import { Checkbox } from "./checkbox";
8
8
 
9
9
  describe("Checkbox", () => {
10
10
  it("[3C.6-01] [P1] renders correctly", () => {
11
- // Given
11
+
12
12
  render(<Checkbox aria-label="Accept terms" />);
13
13
  const checkbox = screen.getByRole("checkbox", { name: "Accept terms" });
14
- // Then
14
+
15
15
  expect(checkbox).toBeInTheDocument();
16
16
  expect(checkbox).toHaveAttribute("data-slot", "checkbox");
17
17
  });
18
18
 
19
19
  it("[3C.6-02] [P1] handles user click to toggle state", async () => {
20
- // Given
20
+
21
21
  const user = userEvent.setup();
22
22
  const handleCheckedChange = vi.fn();
23
23
  render(
@@ -26,42 +26,34 @@ describe("Checkbox", () => {
26
26
 
27
27
  const checkbox = screen.getByRole("checkbox", { name: "Toggle" });
28
28
 
29
- // Initially unchecked
30
- // Then
31
29
  expect(checkbox).not.toBeChecked();
32
30
 
33
- // Click to check
34
- // When
35
31
  await user.click(checkbox);
36
32
  expect(checkbox).toBeChecked();
37
33
  expect(handleCheckedChange).toHaveBeenCalledWith(true, expect.anything());
38
34
 
39
- // Click to uncheck
40
35
  await user.click(checkbox);
41
36
  expect(checkbox).not.toBeChecked();
42
37
  expect(handleCheckedChange).toHaveBeenCalledWith(false, expect.anything());
43
38
  });
44
39
 
45
40
  it("[3C.6-03] [P1] can be focused and toggled via keyboard (Space)", async () => {
46
- // Given
41
+
47
42
  const user = userEvent.setup();
48
43
  render(<Checkbox aria-label="Keyboard toggle" />);
49
44
 
50
45
  const checkbox = screen.getByRole("checkbox", { name: "Keyboard toggle" });
51
46
 
52
- // Test focus
53
- // When
54
47
  await user.tab();
55
- // Then
48
+
56
49
  expect(checkbox).toHaveFocus();
57
50
 
58
- // Test keyboard activation (Space for checkbox)
59
51
  await user.keyboard("[Space]");
60
52
  expect(checkbox).toBeChecked();
61
53
  });
62
54
 
63
55
  it("[3C.6-04] [P1] handles disabled state correctly and blocks clicks", async () => {
64
- // Given
56
+
65
57
  const user = userEvent.setup();
66
58
  const handleCheckedChange = vi.fn();
67
59
  render(
@@ -73,20 +65,19 @@ describe("Checkbox", () => {
73
65
  );
74
66
 
75
67
  const checkbox = screen.getByRole("checkbox", { name: "Disabled" });
76
- // Then
68
+
77
69
  expect(checkbox).toHaveAttribute("aria-disabled", "true");
78
70
 
79
- // When
80
71
  await user.click(checkbox);
81
72
  expect(handleCheckedChange).not.toHaveBeenCalled();
82
73
  expect(checkbox).not.toBeChecked();
83
74
  });
84
75
 
85
76
  it("[3C.6-05] [P1] forwards the ref to the underlying DOM element", () => {
86
- // Given
77
+
87
78
  const ref = React.createRef<HTMLSpanElement>();
88
79
  render(<Checkbox ref={ref} aria-label="Ref checkbox" />);
89
- // Then
80
+
90
81
  expect(ref.current).toBeInstanceOf(HTMLSpanElement);
91
82
  });
92
83
  });
@@ -80,7 +80,7 @@ function ComboboxInput({ className, ...props }: ComboboxPrimitive.Input.Props) {
80
80
  data-slot="combobox-input"
81
81
  className={cn(
82
82
  "flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
83
- // Clear standalone styles when inside InputGroup
83
+
84
84
  "group-data-[slot=input-group]/input-group:border-0",
85
85
  "group-data-[slot=input-group]/input-group:shadow-none",
86
86
  "group-data-[slot=input-group]/input-group:h-auto",
@@ -239,8 +239,6 @@ function ComboboxSeparator({
239
239
  );
240
240
  }
241
241
 
242
-
243
-
244
242
  const comboboxChipsVariants = cva(
245
243
  "group/combobox-chips flex flex-wrap items-center gap-1 rounded-lg border border-input bg-transparent bg-clip-padding transition-colors focus-within:border-ring focus-within:ring-3 focus-within:ring-ring/50 has-aria-invalid:border-destructive has-aria-invalid:focus-within:ring-3 has-aria-invalid:focus-within:ring-destructive/20 has-[[data-slot=combobox-chip]]:px-1 dark:bg-input/30 dark:has-aria-invalid:border-destructive/50 dark:has-aria-invalid:focus-within:ring-destructive/40 has-disabled:opacity-50 has-disabled:cursor-not-allowed has-disabled:pointer-events-none",
246
244
  {
@@ -68,17 +68,21 @@ const CommandInput = React.forwardRef<
68
68
  data-slot="command-input-wrapper"
69
69
  className={cn(
70
70
  "pb-0",
71
- size === "sm" && "p-1",
72
- size === "md" && "p-2",
73
- size === "lg" && "p-3",
71
+ {
72
+ "p-1": size === "sm",
73
+ "p-2": size === "md",
74
+ "p-3": size === "lg",
75
+ }
74
76
  )}
75
77
  >
76
78
  <InputGroup
77
79
  className={cn(
78
80
  "rounded-lg border-input/30 bg-input/30 shadow-none",
79
- size === "sm" && "h-8",
80
- size === "md" && "h-10",
81
- size === "lg" && "h-11",
81
+ {
82
+ "h-8": size === "sm",
83
+ "h-10": size === "md",
84
+ "h-11": size === "lg",
85
+ }
82
86
  )}
83
87
  >
84
88
  <CommandPrimitive.Input
@@ -88,10 +92,16 @@ const CommandInput = React.forwardRef<
88
92
  {...props}
89
93
  />
90
94
  <InputGroupAddon
91
- className={cn("shrink-0", size === "lg" ? "pl-3" : "pl-2")}
95
+ className={cn("shrink-0", {
96
+ "pl-3": size === "lg",
97
+ "pl-2": size !== "lg",
98
+ })}
92
99
  >
93
100
  <SearchIcon
94
- className={cn("opacity-50", size === "lg" ? "size-5" : "size-4")}
101
+ className={cn("opacity-50", {
102
+ "size-5": size === "lg",
103
+ "size-4": size !== "lg",
104
+ })}
95
105
  />
96
106
  </InputGroupAddon>
97
107
  </InputGroup>
@@ -127,9 +137,11 @@ const CommandEmpty = React.forwardRef<
127
137
  data-slot="command-empty"
128
138
  className={cn(
129
139
  "text-center",
130
- size === "sm" && "py-4 text-xs",
131
- size === "md" && "py-6 text-sm",
132
- size === "lg" && "py-8 text-base",
140
+ {
141
+ "py-4 text-xs": size === "sm",
142
+ "py-6 text-sm": size === "md",
143
+ "py-8 text-base": size === "lg",
144
+ },
133
145
  className,
134
146
  )}
135
147
  {...props}
@@ -33,8 +33,6 @@ function ContextMenu({ ...props }: ContextMenuPrimitive.Root.Props) {
33
33
  }
34
34
  ContextMenu.displayName = "ContextMenu";
35
35
 
36
-
37
-
38
36
  const ContextMenuTrigger = React.forwardRef<
39
37
  React.ElementRef<typeof ContextMenuPrimitive.Trigger>,
40
38
  React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Trigger>
@@ -16,7 +16,7 @@ import {
16
16
 
17
17
  describe("Dialog", () => {
18
18
  it("[3C.4-01] [P1] renders trigger correctly and content is hidden initially", () => {
19
- // Given
19
+
20
20
  render(
21
21
  <Dialog>
22
22
  <DialogTrigger>Open Dialog</DialogTrigger>
@@ -30,15 +30,14 @@ describe("Dialog", () => {
30
30
  );
31
31
 
32
32
  const trigger = screen.getByRole("button", { name: "Open Dialog" });
33
- // Then
33
+
34
34
  expect(trigger).toBeInTheDocument();
35
35
 
36
- // Content should not be in the document
37
36
  expect(screen.queryByRole("dialog")).not.toBeInTheDocument();
38
37
  });
39
38
 
40
39
  it("[3C.4-02] [P1] opens the dialog when trigger is clicked", async () => {
41
- // Given
40
+
42
41
  const user = userEvent.setup();
43
42
  render(
44
43
  <Dialog>
@@ -56,10 +55,9 @@ describe("Dialog", () => {
56
55
  );
57
56
 
58
57
  const trigger = screen.getByRole("button", { name: "Open Dialog" });
59
- // When
58
+
60
59
  await user.click(trigger);
61
60
 
62
- // Then
63
61
  await waitFor(() => {
64
62
  const dialog = screen.getByRole("dialog");
65
63
  expect(dialog).toBeInTheDocument();
@@ -69,7 +67,7 @@ describe("Dialog", () => {
69
67
  });
70
68
 
71
69
  it("[3C.4-03] [P1] closes the dialog when Close button is clicked", async () => {
72
- // Given
70
+
73
71
  const user = userEvent.setup();
74
72
  render(
75
73
  <Dialog>
@@ -81,16 +79,12 @@ describe("Dialog", () => {
81
79
  </Dialog>,
82
80
  );
83
81
 
84
- // Open
85
- // When
86
82
  await user.click(screen.getByRole("button", { name: "Open Dialog" }));
87
83
 
88
- // Then
89
84
  await waitFor(() => {
90
85
  expect(screen.getByRole("dialog")).toBeInTheDocument();
91
86
  });
92
87
 
93
- // Close
94
88
  await user.click(screen.getByRole("button", { name: "Close Me" }));
95
89
 
96
90
  await waitFor(() => {
@@ -99,7 +93,7 @@ describe("Dialog", () => {
99
93
  });
100
94
 
101
95
  it("[3C.4-04] [P1] closes the dialog when Escape is pressed", async () => {
102
- // Given
96
+
103
97
  const user = userEvent.setup();
104
98
  render(
105
99
  <Dialog>
@@ -110,10 +104,8 @@ describe("Dialog", () => {
110
104
  </Dialog>,
111
105
  );
112
106
 
113
- // When
114
107
  await user.click(screen.getByRole("button", { name: "Open Dialog" }));
115
108
 
116
- // Then
117
109
  await waitFor(() => {
118
110
  expect(screen.getByRole("dialog")).toBeInTheDocument();
119
111
  });
@@ -26,8 +26,6 @@ const DialogTrigger = React.forwardRef<
26
26
  ));
27
27
  DialogTrigger.displayName = "DialogTrigger";
28
28
 
29
-
30
-
31
29
  const DialogClose = React.forwardRef<
32
30
  HTMLButtonElement,
33
31
  React.ComponentPropsWithoutRef<typeof DialogPrimitive.Close>
@@ -9,7 +9,6 @@
9
9
 
10
10
  import * as React from "react";
11
11
 
12
- // Fix TS2883: The inferred type cannot be named without a reference to @radix-ui/react-dialog
13
12
  import type { } from "@radix-ui/react-dialog";
14
13
  import { Drawer as DrawerPrimitive } from "vaul";
15
14
 
@@ -31,8 +30,6 @@ const DrawerTrigger = React.forwardRef<
31
30
  ));
32
31
  DrawerTrigger.displayName = "DrawerTrigger";
33
32
 
34
-
35
-
36
33
  const DrawerClose = React.forwardRef<
37
34
  React.ElementRef<typeof DrawerPrimitive.Close>,
38
35
  React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Close>