@nqlib/nqui 0.4.3 → 0.4.4

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 (153) hide show
  1. package/INSTALLATION.md +215 -0
  2. package/README.md +104 -151
  3. package/dist/button-CJHdCq9I.js +155 -0
  4. package/dist/button-R304rhsj.cjs +1 -0
  5. package/dist/calendar.cjs.js +1 -1
  6. package/dist/calendar.es.js +1 -1
  7. package/dist/carousel-D1FMVglR.cjs +1 -0
  8. package/dist/carousel-U7RZhYZj.js +179 -0
  9. package/dist/carousel.cjs.js +1 -1
  10. package/dist/carousel.es.js +1 -1
  11. package/dist/command-palette-DCtLpM3Q.js +694 -0
  12. package/dist/command-palette-MHc03bBf.cjs +5 -0
  13. package/dist/command.cjs.js +1 -1
  14. package/dist/command.es.js +1 -1
  15. package/dist/components/custom/color-picker.d.ts +1 -1
  16. package/dist/components/custom/color-picker.d.ts.map +1 -1
  17. package/dist/components/custom/color-slider.d.ts +4 -10
  18. package/dist/components/custom/color-slider.d.ts.map +1 -1
  19. package/dist/components/custom/enhanced-radio-group.d.ts +13 -4
  20. package/dist/components/custom/enhanced-radio-group.d.ts.map +1 -1
  21. package/dist/components/custom/enhanced-tabs.d.ts.map +1 -1
  22. package/dist/components/debug/debug-features.d.ts +29 -0
  23. package/dist/components/debug/debug-features.d.ts.map +1 -0
  24. package/dist/components/debug/debug-panel.d.ts.map +1 -1
  25. package/dist/components/error-boundary.d.ts +20 -0
  26. package/dist/components/error-boundary.d.ts.map +1 -0
  27. package/dist/components/index.d.ts +103 -0
  28. package/dist/components/index.d.ts.map +1 -0
  29. package/dist/components/ui/badge.d.ts +16 -5
  30. package/dist/components/ui/badge.d.ts.map +1 -1
  31. package/dist/components/ui/button.d.ts +38 -4
  32. package/dist/components/ui/button.d.ts.map +1 -1
  33. package/dist/components/ui/checkbox.d.ts +16 -2
  34. package/dist/components/ui/checkbox.d.ts.map +1 -1
  35. package/dist/components/ui/combobox.d.ts +2 -1
  36. package/dist/components/ui/combobox.d.ts.map +1 -1
  37. package/dist/components/ui/input-group.d.ts +1 -1
  38. package/dist/components/ui/input-group.d.ts.map +1 -1
  39. package/dist/components/ui/pagination.d.ts +3 -2
  40. package/dist/components/ui/pagination.d.ts.map +1 -1
  41. package/dist/components/ui/radio-group.d.ts +3 -1
  42. package/dist/components/ui/radio-group.d.ts.map +1 -1
  43. package/dist/components/ui/select.d.ts +6 -1
  44. package/dist/components/ui/select.d.ts.map +1 -1
  45. package/dist/components/ui/sidebar.d.ts +1 -1
  46. package/dist/components/ui/sidebar.d.ts.map +1 -1
  47. package/dist/components/ui/slider.d.ts +10 -2
  48. package/dist/components/ui/slider.d.ts.map +1 -1
  49. package/dist/components/ui/sonner.d.ts +18 -2
  50. package/dist/components/ui/sonner.d.ts.map +1 -1
  51. package/dist/components/ui/spinner.d.ts +2 -1
  52. package/dist/components/ui/spinner.d.ts.map +1 -1
  53. package/dist/components/ui/switch.d.ts +15 -2
  54. package/dist/components/ui/switch.d.ts.map +1 -1
  55. package/dist/components/ui/tabs.d.ts +1 -1
  56. package/dist/components/ui/tabs.d.ts.map +1 -1
  57. package/dist/components/ui/toggle.d.ts +1 -1
  58. package/dist/components/ui/toggle.d.ts.map +1 -1
  59. package/dist/debug-panel-CG-vAN0L.js +9016 -0
  60. package/dist/debug-panel-DHBfAc1V.cjs +75 -0
  61. package/dist/debug.cjs.js +1 -0
  62. package/dist/debug.es.js +7 -0
  63. package/dist/{drawer-CU4lkcz7.js → drawer-DO26uhym.js} +31 -31
  64. package/dist/drawer-DVarEy65.cjs +1 -0
  65. package/dist/drawer.cjs.js +1 -1
  66. package/dist/drawer.es.js +1 -1
  67. package/dist/{enhanced-calendar-BENbxw7_.js → enhanced-calendar-BGlsSYJd.js} +1 -1
  68. package/dist/{enhanced-calendar-5PA8CeF7.cjs → enhanced-calendar-C7EQIr6i.cjs} +1 -1
  69. package/dist/entries/debug.d.ts +14 -0
  70. package/dist/entries/debug.d.ts.map +1 -0
  71. package/dist/entries/sonner.d.ts +1 -2
  72. package/dist/entries/sonner.d.ts.map +1 -1
  73. package/dist/hooks/use-mobile.d.ts.map +1 -1
  74. package/dist/hooks/use-scroll-spy.d.ts.map +1 -1
  75. package/dist/index-CI756mSv.cjs +41 -0
  76. package/dist/index-CgfzsUO6.js +1069 -0
  77. package/dist/index.d.ts +2 -98
  78. package/dist/index.d.ts.map +1 -1
  79. package/dist/lib/index.d.ts +9 -0
  80. package/dist/lib/index.d.ts.map +1 -0
  81. package/dist/lib/wrap-inline-label-text.d.ts +7 -0
  82. package/dist/lib/wrap-inline-label-text.d.ts.map +1 -0
  83. package/dist/nqui.cjs.js +49 -245
  84. package/dist/nqui.es.js +7399 -16735
  85. package/dist/sonner-CpmECDBk.js +179 -0
  86. package/dist/sonner-nE9hIalJ.cjs +48 -0
  87. package/dist/sonner.cjs.js +1 -1
  88. package/dist/sonner.es.js +3 -2
  89. package/dist/styles.css +186 -1
  90. package/docs/components/README.md +107 -8
  91. package/docs/components/nqui-badge.md +1 -0
  92. package/docs/components/nqui-button.md +3 -1
  93. package/docs/components/nqui-card.md +8 -0
  94. package/docs/components/nqui-carousel.md +6 -0
  95. package/docs/components/nqui-checkbox.md +38 -1
  96. package/docs/components/nqui-color-slider.md +5 -3
  97. package/docs/components/nqui-combobox.md +58 -37
  98. package/docs/components/nqui-drawer.md +1 -1
  99. package/docs/components/nqui-radio-group.md +45 -2
  100. package/docs/components/nqui-scroll-area.md +1 -1
  101. package/docs/components/nqui-select.md +2 -2
  102. package/docs/components/nqui-sheet.md +1 -1
  103. package/docs/components/nqui-slider.md +13 -0
  104. package/docs/components/nqui-spinner.md +6 -1
  105. package/docs/components/nqui-switch.md +23 -1
  106. package/docs/components/nqui-tabs.md +11 -1
  107. package/docs/components/nqui-toaster.md +5 -1
  108. package/docs/internal-notes/PUBLISHING.md +46 -4
  109. package/docs/nqui-skills/SKILL.md +102 -0
  110. package/docs/nqui-skills/design-system.md +143 -0
  111. package/docs/nqui-skills/rules/composition.md +183 -0
  112. package/docs/nqui-skills/rules/forms.md +190 -0
  113. package/docs/nqui-skills/rules/icons.md +158 -0
  114. package/docs/nqui-skills/rules/styling.md +192 -0
  115. package/package.json +23 -12
  116. package/scripts/build-styles.js +16 -0
  117. package/scripts/cli.js +1 -0
  118. package/scripts/download-skills.js +91 -0
  119. package/scripts/examples/nextjs-layout-sidebar.tsx +100 -0
  120. package/scripts/examples/nextjs-page-sidebar.tsx +81 -0
  121. package/scripts/examples/vite-app.tsx +135 -0
  122. package/scripts/examples/vite-main.tsx +17 -0
  123. package/scripts/examples.js +92 -6
  124. package/scripts/generate-docs.js +169 -0
  125. package/scripts/init-css.js +34 -14
  126. package/scripts/init-cursor.js +8 -0
  127. package/scripts/init-debug-css.js +4 -2
  128. package/scripts/post-install.js +41 -9
  129. package/scripts/publish-npmjs.js +17 -3
  130. package/scripts/resolve-target-dir.js +20 -1
  131. package/scripts/verify-build.js +1 -1
  132. package/scripts/wizard.js +12 -7
  133. package/dist/button-CYFTFDKe.cjs +0 -1
  134. package/dist/button-nJvDl3w8.js +0 -44
  135. package/dist/carousel-DEyyJi49.js +0 -179
  136. package/dist/carousel-Dhhz8m5V.cjs +0 -1
  137. package/dist/command-palette-UHk8zZOg.cjs +0 -45
  138. package/dist/command-palette-d-TrdBsM.js +0 -1778
  139. package/dist/components/custom/enhanced-badge.d.ts +0 -33
  140. package/dist/components/custom/enhanced-badge.d.ts.map +0 -1
  141. package/dist/components/custom/enhanced-button.d.ts +0 -34
  142. package/dist/components/custom/enhanced-button.d.ts.map +0 -1
  143. package/dist/components/custom/enhanced-checkbox.d.ts +0 -28
  144. package/dist/components/custom/enhanced-checkbox.d.ts.map +0 -1
  145. package/dist/components/custom/enhanced-combobox.d.ts +0 -35
  146. package/dist/components/custom/enhanced-combobox.d.ts.map +0 -1
  147. package/dist/components/custom/enhanced-select.d.ts +0 -30
  148. package/dist/components/custom/enhanced-select.d.ts.map +0 -1
  149. package/dist/components/custom/enhanced-sonner.d.ts +0 -16
  150. package/dist/components/custom/enhanced-sonner.d.ts.map +0 -1
  151. package/dist/drawer-BcIxWRN8.cjs +0 -1
  152. package/dist/sonner-Co6YpYVs.js +0 -546
  153. package/dist/sonner-DbQhVp8m.cjs +0 -330
@@ -11,9 +11,31 @@ import { Checkbox } from "@nqlib/nqui"
11
11
  ## Basic
12
12
 
13
13
  ```tsx
14
- <Checkbox checked={checked} onCheckedChange={setChecked} />
14
+ const [checked, setChecked] = useState(false)
15
+
16
+ <Checkbox checked={checked} onCheckedChange={setChecked}>Accept terms</Checkbox>
17
+ ```
18
+
19
+ ## With Label
20
+
21
+ Checkbox automatically wraps in a label when children are provided:
22
+
23
+ ```tsx
24
+ <Checkbox>Accept terms</Checkbox>
25
+ ```
26
+
27
+ ## Gap
28
+
29
+ Control the gap between checkbox and label:
30
+
31
+ ```tsx
32
+ <Checkbox gap={2}>Compact gap (8px)</Checkbox>
33
+ <Checkbox gap={3}>Default gap (12px)</Checkbox>
34
+ <Checkbox gap={4}>Loose gap (16px)</Checkbox>
15
35
  ```
16
36
 
37
+ Options: `0`, `1`, `2`, `3`, `4` (maps to Tailwind gap-0 through gap-4).
38
+
17
39
  ## Variants
18
40
 
19
41
  ```tsx
@@ -27,8 +49,23 @@ import { Checkbox } from "@nqlib/nqui"
27
49
  <Checkbox checked="indeterminate" onCheckedChange={...} />
28
50
  ```
29
51
 
52
+ ## Hit area (expanded pointer target)
53
+
54
+ nqui ships [Bazza **hit-area** utilities](https://bazza.dev/craft/2026/hit-area) in library CSS (`hit-area-*`, `hit-area-x-*`, `hit-area-debug`, etc.). They extend the clickable region with a `::before` layer without changing layout.
55
+
56
+ **Enhanced checkbox:** The checkmark is drawn with `::after` on the control root so `::before` stays free for `hit-area-*` on the **same** element. Add a class when you want a larger target (e.g. padded table cells):
57
+
58
+ ```tsx
59
+ <Checkbox className="hit-area-6" checked={rowSelected} onCheckedChange={...} aria-label="Select row" />
60
+ ```
61
+
62
+ **Label hover pill:** `.checkbox-animated-label::before` is on the **label** wrapper only; it does not conflict with `hit-area-*` on the checkbox button.
63
+
64
+ **Without hit-area:** You can still wrap the control in `<span className="relative hit-area-6">` if you prefer the expanded area on a wrapper.
65
+
30
66
  ## Notes
31
67
 
68
+ - Implementation: **`packages/nqui/src/components/ui/checkbox.tsx`** (enhanced + core in one module).
32
69
  - Injects `<style>` at mount. Use client-only guard for SSR.
33
70
  - Square and round share the same animation (pulse + checkmark scale); round has no SVG filters.
34
71
  - Use `CoreCheckbox` for plain Radix checkbox.
@@ -10,10 +10,12 @@ import { ColorSlider } from "@nqlib/nqui"
10
10
 
11
11
  ## Types
12
12
 
13
+ Built on **`Slider`** from `ui/slider` (white thumb + shadow). For **non-controlled** demos, prefer **`defaultValue`** so the thumb stays draggable.
14
+
13
15
  ```tsx
14
- <ColorSlider sliderType="hue" value={[240]} onValueChange={setVal} min={0} max={360} />
15
- <ColorSlider sliderType="saturation" value={[0.5]} onValueChange={setVal} min={0} max={1} step={0.01} />
16
- <ColorSlider sliderType="lightness" value={[0.6]} onValueChange={setVal} min={0} max={1} step={0.01} />
16
+ <ColorSlider sliderType="hue" defaultValue={[240]} onValueChange={setVal} min={0} max={360} />
17
+ <ColorSlider sliderType="saturation" defaultValue={[0.5]} onValueChange={setVal} min={0} max={1} step={0.01} />
18
+ <ColorSlider sliderType="lightness" defaultValue={[0.6]} onValueChange={setVal} min={0} max={1} step={0.01} />
17
19
  ```
18
20
 
19
21
  ## Custom
@@ -1,73 +1,94 @@
1
1
  # nqui Combobox
2
2
 
3
- > **Searchable** select. Single or multi-select. Use when user types to filter options.
3
+ > **Searchable** select (Base UI). User types to filter options. Single or multiple selection.
4
4
 
5
5
  ## When to Use
6
6
 
7
- - **Selection:** Single or multiple
8
- - **Key feature:** User searches/filters options by typing
9
- - **Options:** Many (dozens, hundreds)
7
+ - **Selection:** Single (default) or multiple (`multiple` on root)
8
+ - **Key feature:** Filter list by typing in the input
9
+ - **Options:** Many rows; use **`items`** on `Combobox` + render prop on `ComboboxList` for built-in filtering
10
10
 
11
- **Choose Combobox when:** Options are too many to scroll, or user knows the name. Type to filter. Use Select when options are few and no search needed.
11
+ **Choose Combobox when:** Users need search. Use **Select** when a plain dropdown is enough.
12
12
 
13
13
  ## Import
14
14
 
15
15
  ```tsx
16
16
  import {
17
- Combobox, ComboboxInput, ComboboxContent, ComboboxList,
18
- ComboboxItem, ComboboxEmpty, ComboboxChips, ComboboxChip,
19
- ComboboxTrigger, ComboboxValue, ComboboxCollection, ComboboxGroup,
20
- ComboboxLabel, ComboboxSeparator
17
+ Combobox,
18
+ ComboboxInput,
19
+ ComboboxContent,
20
+ ComboboxList,
21
+ ComboboxItem,
22
+ ComboboxEmpty,
23
+ ComboboxGroup,
24
+ ComboboxLabel,
25
+ ComboboxSeparator,
26
+ ComboboxCollection,
27
+ ComboboxChips,
28
+ ComboboxChip,
29
+ ComboboxChipsInput,
30
+ ComboboxTrigger,
31
+ ComboboxValue,
32
+ ComboboxClear,
33
+ useComboboxAnchor,
21
34
  } from "@nqlib/nqui"
22
35
  ```
23
36
 
24
- ## Basic
37
+ ## Single selection + type-to-filter (recommended)
38
+
39
+ Pass **`items`** to `Combobox` and use a **render function** as the only child of `ComboboxList`. Place **`ComboboxEmpty`** next to `ComboboxList` (both under `ComboboxContent`), not inside `ComboboxList` alongside the function.
25
40
 
26
41
  ```tsx
27
- <Combobox options={items} value={value} onChange={setValue}>
42
+ const fruits = ["Apple", "Banana", "Cherry", "Date", "Elderberry"]
43
+
44
+ <Combobox items={fruits}>
28
45
  <ComboboxInput placeholder="Search..." />
29
46
  <ComboboxContent>
47
+ <ComboboxEmpty>No results found.</ComboboxEmpty>
30
48
  <ComboboxList>
31
- {items.map((item) => (
32
- <ComboboxItem key={item.value} value={item.value}>{item.label}</ComboboxItem>
33
- ))}
49
+ {(item) => (
50
+ <ComboboxItem key={item} value={item}>
51
+ {item}
52
+ </ComboboxItem>
53
+ )}
34
54
  </ComboboxList>
35
- <ComboboxEmpty>No results</ComboboxEmpty>
36
55
  </ComboboxContent>
37
56
  </Combobox>
38
57
  ```
39
58
 
40
- ## showClear
59
+ ## Static list (no `items` filter)
41
60
 
42
- ```tsx
43
- <Combobox showClear ... />
44
- ```
45
-
46
- ## Multi-select chips
61
+ You can still render `ComboboxItem` children manually when you control filtering yourself.
47
62
 
48
63
  ```tsx
49
- <Combobox multiSelect value={selected} onChange={setSelected}>
50
- <ComboboxChips placeholder="Select...">
51
- {(vals) => vals.map((v) => <ComboboxChip key={v} value={v} onRemove={...} />)}
52
- </ComboboxChips>
53
- ...
64
+ <Combobox>
65
+ <ComboboxInput placeholder="Search..." />
66
+ <ComboboxContent>
67
+ <ComboboxList>
68
+ <ComboboxItem value="a">A</ComboboxItem>
69
+ <ComboboxItem value="b">B</ComboboxItem>
70
+ </ComboboxList>
71
+ </ComboboxContent>
54
72
  </Combobox>
55
73
  ```
56
74
 
57
- ## Groups
75
+ ## Clear button
58
76
 
59
77
  ```tsx
60
- <ComboboxCollection>
61
- <ComboboxGroup>
62
- <ComboboxLabel>Group A</ComboboxLabel>
63
- <ComboboxItem value="a">A</ComboboxItem>
64
- </ComboboxGroup>
65
- <ComboboxSeparator />
66
- ...
67
- </ComboboxCollection>
78
+ <ComboboxInput showClear placeholder="Search..." />
68
79
  ```
69
80
 
81
+ ## Multiple selection
82
+
83
+ Use **`multiple`** on `Combobox` (see [Base UI Combobox](https://base-ui.com/react/components/combobox)). Combine with **`ComboboxChips`**, **`ComboboxChip`**, **`ComboboxChipsInput`** as needed for chip UI.
84
+
85
+ ## Implementation
86
+
87
+ - **Source:** `packages/nqui/src/components/ui/combobox.tsx`
88
+ - **Public API:** exported from `@nqlib/nqui` (same as `CoreCombobox*` aliases in the barrel if you need the unprefixed base re-exports)
89
+ - **Styling:** Input group uses injected CSS once per page (`nqui-combobox-styles-v1`) for trigger depth/shadow; component is `"use client"`.
90
+
70
91
  ## Notes
71
92
 
72
- - Injects CSS at mount; client-only in SSR.
73
- - `useComboboxAnchor` for PopoverAnchor positioning.
93
+ - **`useComboboxAnchor`:** ref for anchoring `ComboboxContent` when using chips / custom layout.
94
+ - **Dropdown items:** spacing/hover treatment aligns with **Select** (`SelectItem`-style density).
@@ -1,6 +1,6 @@
1
1
  # nqui Drawer
2
2
 
3
- > Bottom drawer. DrawerTrigger, DrawerContent, DrawerHeader, DrawerTitle, DrawerDescription, DrawerFooter.
3
+ > **Vaul** drawer. **DrawerContent** keeps an **inset rounded card** (`before:bg-card`, `before:inset-2`, `before:rounded-xl`) so the panel does not read as a full-bleed slab—surface follows **`card`** tokens in both themes.
4
4
 
5
5
  ## Import
6
6
 
@@ -18,13 +18,56 @@ import { RadioGroup, RadioGroupItem } from "@nqlib/nqui"
18
18
 
19
19
  ## Basic
20
20
 
21
+ RadioGroupItem now automatically wraps the radio button with a label when children are provided:
22
+
21
23
  ```tsx
24
+ const [value, setValue] = useState("a")
25
+
22
26
  <RadioGroup value={value} onValueChange={setValue}>
23
- <RadioGroupItem value="a" /> A
24
- <RadioGroupItem value="b" /> B
27
+ <RadioGroupItem value="a">Option A</RadioGroupItem>
28
+ <RadioGroupItem value="b">Option B</RadioGroupItem>
25
29
  </RadioGroup>
26
30
  ```
27
31
 
32
+ ## With Complex Content
33
+
34
+ ```tsx
35
+ <RadioGroup value={value} onValueChange={setValue}>
36
+ <RadioGroupItem value="email">
37
+ <div>
38
+ <div className="font-medium">Email</div>
39
+ <div className="text-sm text-muted-foreground">Receive notifications via email</div>
40
+ </div>
41
+ </RadioGroupItem>
42
+ <RadioGroupItem value="sms">
43
+ <div>
44
+ <div className="font-medium">SMS</div>
45
+ <div className="text-sm text-muted-foreground">Receive notifications via SMS</div>
46
+ </div>
47
+ </RadioGroupItem>
48
+ </RadioGroup>
49
+ ```
50
+
51
+ ## Spacing
52
+
53
+ Control the gap between radio items with the `gap` prop on RadioGroup:
54
+
55
+ ```tsx
56
+ <RadioGroup gap={0}>No gap</RadioGroup>
57
+ <RadioGroup gap={1}>4px gap</RadioGroup>
58
+ <RadioGroup gap={2}>Compact (8px)</RadioGroup>
59
+ <RadioGroup gap={3}>Default (12px)</RadioGroup>
60
+ <RadioGroup gap={4}>Loose (16px)</RadioGroup>
61
+ ```
62
+
63
+ Control the gap between radio button and label with the `spacing` prop on RadioGroupItem:
64
+
65
+ ```tsx
66
+ <RadioGroupItem value="a" spacing="compact">Tight spacing (8px)</RadioGroupItem>
67
+ <RadioGroupItem value="b" spacing="default">Default spacing (12px)</RadioGroupItem>
68
+ <RadioGroupItem value="c" spacing="comfortable">Loose spacing (16px)</RadioGroupItem>
69
+ ```
70
+
28
71
  ## Variants
29
72
 
30
73
  ```tsx
@@ -1,6 +1,6 @@
1
1
  # nqui ScrollArea
2
2
 
3
- > Custom scrollbar. fadeMask (enhanced), horizontal scroll.
3
+ > Default export is **EnhancedScrollArea** (fade mask, orientation). Underlying primitive: **`CoreScrollArea`** / `ScrollBar` from **`ui/scroll-area`**. Core scrollbar uses a **thinner** track/thumb (drawer-like).
4
4
 
5
5
  ## Import
6
6
 
@@ -48,6 +48,6 @@ import { Select, SelectTrigger, SelectValue, SelectContent, SelectItem, SelectGr
48
48
 
49
49
  ## Notes
50
50
 
51
- - Injects CSS at mount; client-only in SSR.
51
+ - **Content:** FrostedGlass + popover surface; **items** use relaxed row spacing (hover `accent`, margins) for dropdown parity with **Combobox** list items.
52
52
  - Use `SelectScrollUpButton` / `SelectScrollDownButton` for long lists.
53
- - `CoreSelect*` for plain styling.
53
+ - **`CoreSelect*`** for the same primitives without the enhanced trigger chrome (re-exported from the same `ui/select` module).
@@ -1,6 +1,6 @@
1
1
  # nqui Sheet
2
2
 
3
- > Side panel. SheetTrigger, SheetContent, SheetHeader, SheetTitle, SheetDescription, SheetFooter. side: top|right|bottom|left.
3
+ > Side panel (Radix **Dialog** pattern). **SheetContent** uses an **inset card** panel: transparent outer shell + `before:bg-card` block inset with **rounded corners** (matches drawer-style “card floating in the viewport”). **No edge borders** on the sheet shell (divider lines removed in favor of the card shape).
4
4
 
5
5
  ## Import
6
6
 
@@ -14,3 +14,16 @@ import { Slider } from "@nqlib/nqui"
14
14
  <Slider value={[50]} onValueChange={([v]) => setVal(v)} />
15
15
  <Slider value={[20, 80]} onValueChange={setRange} />
16
16
  ```
17
+
18
+ ## Sizes
19
+
20
+ ```tsx
21
+ <Slider size="sm" defaultValue={[40]} />
22
+ <Slider size="default" defaultValue={[40]} />
23
+ <Slider size="lg" defaultValue={[40]} />
24
+ ```
25
+
26
+ ## Notes
27
+
28
+ - **Thumb:** white, rounded-full, subtle shadow (aligned with **Switch** thumb language).
29
+ - **`size`:** `sm` | `default` | `lg` (control scale heights).
@@ -1,6 +1,6 @@
1
1
  # nqui Spinner
2
2
 
3
- > Loading spinner.
3
+ > Dual-arc loader (primary **`linearGradient`** strokes, rotating shell). Keyframes live in **`packages/nqui/src/index.css`** (`.nqui-spinner-*`).
4
4
 
5
5
  ## Import
6
6
 
@@ -14,3 +14,8 @@ import { Spinner } from "@nqlib/nqui"
14
14
  <Spinner />
15
15
  <Spinner className="size-6" />
16
16
  ```
17
+
18
+ ## Notes
19
+
20
+ - Root is a `div` with `role="status"` and `aria-label="Loading"`.
21
+ - Strokes use `var(--primary)` and `color-mix(in oklch, var(--primary) …, white)` so light/dark themes stay on-brand.
@@ -1,6 +1,6 @@
1
1
  # nqui Switch
2
2
 
3
- > Toggle switch. Core Radix.
3
+ > Toggle switch. **Radix** primitive with **size** variants and **capsule thumb** (white, shadow). Sizes align with control scale: `sm` / `default` / `lg`.
4
4
 
5
5
  ## Import
6
6
 
@@ -13,3 +13,25 @@ import { Switch } from "@nqlib/nqui"
13
13
  ```tsx
14
14
  <Switch checked={checked} onCheckedChange={setChecked} />
15
15
  ```
16
+
17
+ ## Sizes
18
+
19
+ ```tsx
20
+ <Switch size="sm" />
21
+ <Switch size="default" />
22
+ <Switch size="lg" />
23
+ ```
24
+
25
+ ## Hit area
26
+
27
+ The switch root has no `::before` styling, so you can add [hit-area utilities](https://bazza.dev/craft/2026/hit-area) on the same element:
28
+
29
+ ```tsx
30
+ <Switch className="hit-area-4" id="notifications" />
31
+ ```
32
+
33
+ Use sparingly in dense toolbars so expanded targets do not overlap.
34
+
35
+ ## Notes
36
+
37
+ - Thumb travel and track sizes are fixed per `size`; overriding height on the root without matching thumb classes may look off.
@@ -31,5 +31,15 @@ import { Tabs, TabsList, TabsTrigger, TabsContent } from "@nqlib/nqui"
31
31
 
32
32
  ## Notes
33
33
 
34
- - Sliding indicator needs `position: relative` on TabsList container.
34
+ - **Sliding indicator:** Requires `position: relative` on TabsList container (handled automatically by the component).
35
+ - **Responsive behavior:** On small screens, TabsList can overflow horizontally. Use `overflow-x-auto` on parent if needed.
36
+ - **Container requirements:** For the sliding indicator to work correctly, the TabsList container needs:
37
+ ```css
38
+ .sliding-indicator-container {
39
+ position: relative;
40
+ overflow: hidden;
41
+ min-width: 0;
42
+ }
43
+ ```
44
+ - **Resize handling:** The indicator recalculates position on window resize (built-in).
35
45
  - Use `EnhancedTabsList` props for additional customization.
@@ -1,6 +1,6 @@
1
1
  # nqui Toaster
2
2
 
3
- > Toast notifications (sonner). Semantic types, promise pattern.
3
+ > Toast notifications via **Sonner**. Default toast is **pill-shaped**; default **normal** toast uses **inverted** surface (dark fill in light theme, light fill in dark theme) using `--foreground` / `--background`. Implemented in **`packages/nqui/src/components/ui/sonner.tsx`** (`Toaster`). Compatibility aliases: `EnhancedSonner`, `CoreToaster` → same component.
4
4
 
5
5
  ## Import
6
6
 
@@ -42,3 +42,7 @@ toast.promise(fetchData(), {
42
42
  toast.success("Msg", { duration: 5000 })
43
43
  // Toaster: position, richColors, etc.
44
44
  ```
45
+
46
+ ## Notes
47
+
48
+ - **Subpath import:** `@nqlib/nqui/sonner` re-exports the same `Toaster`.
@@ -230,15 +230,57 @@ If a version had bugs (e.g. init-cursor routed to wrong script, skills not worki
230
230
  npm deprecate @nqlib/nqui@0.4.1 "Use 0.4.2 instead. See changelog."
231
231
  ```
232
232
 
233
- 4. **Unpublish** (rare, npm restrictions apply):
234
- - Must be within 72 hours of publish
235
- - No other packages can depend on it
236
- - `npm unpublish @nqlib/nqui@0.4.1 --force`
233
+ 4. **Unpublish** (rare, npm restrictions apply): See [Unpublishing](#unpublishing) below.
237
234
 
238
235
  **Recommendation:** Usually deprecate + publish patch. Unpublish only for security issues.
239
236
 
240
237
  ---
241
238
 
239
+ ## Unpublishing
240
+
241
+ ### npmjs.com
242
+
243
+ **Rules:**
244
+ - **Within 72 hours of publish**: You can unpublish. The version is then available for re-publish.
245
+ - **After 72 hours**: Unpublish is disallowed. Versions are permanently locked. Use deprecation instead.
246
+
247
+ **Unpublish a specific version** (within 72 hours):
248
+ ```bash
249
+ cd packages/nqui
250
+ npm unpublish @nqlib/nqui@0.4.1 --force --registry=https://registry.npmjs.com
251
+ ```
252
+
253
+ **Unpublish entire package** (within 72 hours, removes all versions):
254
+ ```bash
255
+ npm unpublish @nqlib/nqui --force --registry=https://registry.npmjs.com
256
+ ```
257
+
258
+ **After 72 hours – deprecate instead:**
259
+ ```bash
260
+ npm deprecate @nqlib/nqui@0.4.1 "Superseded by 0.4.2. Use npm install @nqlib/nqui@0.4.2"
261
+ ```
262
+
263
+ ### GitHub Packages
264
+
265
+ **Rules:**
266
+ - You can delete any version at any time.
267
+ - Deleted versions can be re-published (unlike npm).
268
+
269
+ **Delete via GitHub UI:**
270
+ 1. Go to your repo → **Packages** (right sidebar) or `https://github.com/ORG/REPO/packages`
271
+ 2. Click the package `nqui`
272
+ 3. **Manage package** → **Delete package** (entire package) or **Manage versions** → delete specific versions
273
+
274
+ **Delete via GitHub API** (for automation):
275
+ ```bash
276
+ # Requires GITHUB_TOKEN with delete:packages
277
+ curl -X DELETE -H "Authorization: token $GITHUB_TOKEN" \
278
+ "https://api.github.com/orgs/nqlib/packages/npm/nqui/versions/VERSION_ID"
279
+ ```
280
+ (Get `VERSION_ID` from the package page or API.)
281
+
282
+ ---
283
+
242
284
  ## Version Management
243
285
 
244
286
  The `npm version` command automatically:
@@ -0,0 +1,102 @@
1
+ ---
2
+ name: nqui Components
3
+ description: Component implementation guide for nqui. Use when building UI, designing app layouts, or implementing components with @nqlib/nqui.
4
+ ---
5
+
6
+ # nqui Components Guide
7
+
8
+ Reference `packages/nqui/docs/components/README.md` for the full component index and implementation rules.
9
+
10
+ ## Quick Reference
11
+
12
+ 1. **Main index:** `packages/nqui/docs/components/README.md` - all components, use cases, prerequisites
13
+ 2. **Per-component:** `packages/nqui/docs/components/nqui-<name>.md` - import, examples, variants
14
+ 3. **Design system:** this folder - sizing, grouped controls
15
+
16
+ ## App Design Rule: Inline Selection → ToggleGroup
17
+
18
+ When designing app UI (toolbars, headers, inline controls):
19
+
20
+ | Context | Use | NOT |
21
+ |---------|-----|-----|
22
+ | View mode (List/Grid/Table), scale (Linear/Log), size (S/M/L) | **ToggleGroup** `type="single"` | RadioGroup |
23
+ | Format toolbar (Bold/Italic/Underline), multi-toggle | **ToggleGroup** `type="multiple"` | Multiple Checkboxes |
24
+ | Toolbar actions (Undo/Redo, align) | **ButtonGroup** | - |
25
+ | Single on/off (Bold, Mute) | **Toggle** | - |
26
+
27
+ **Rule:** Inline/toolbar selection = ToggleGroup. Use RadioGroup only for form context (settings page, modal form, stacked list).
28
+
29
+ ## App Design Rule: Context-First (Toolbar in Real Environment)
30
+
31
+ **Rule:** Never show Toggle/ToggleGroup/ButtonGroup in isolation. Always place them in realistic app context.
32
+
33
+ | Context | Layout | Reference |
34
+ |---------|--------|-----------|
35
+ | Document editor | Toolbar above content; `bg-muted/30` container; `Separator` between groups | ComponentShowcase → Toggle & ToggleGroup |
36
+ | Chart/settings | Label + inline controls; `rounded-lg border bg-muted/30 p-3` | ComponentShowcase → Chart settings |
37
+ | Standalone | Inline with related UI | ComponentShowcase → Standalone toggle |
38
+
39
+ **Canonical implementation:** `packages/nqui/src/pages/ComponentShowcase.tsx` — Toggle & ToggleGroup section.
40
+
41
+ ## Design System Conventions
42
+
43
+ See **`design-system.md`** in this folder for sizing, grouped controls (including pill **ButtonGroup** / **ToggleGroup** shells), and file paths under `packages/nqui/src/components/ui/`.
44
+
45
+ ### Control Sizing
46
+ - sm = h-6
47
+ - default = h-7
48
+ - lg = h-8
49
+
50
+ ### Z-Index
51
+ Always use CSS variables from elevation.css:
52
+ - `--z-content` (10) - standard content
53
+ - `--z-sticky-content` (15) - sticky within containers
54
+ - `--z-sticky-page` (20) - page-level sticky
55
+ - `--z-floating` (30) - floating panels
56
+ - `--z-modal-backdrop` (40)
57
+ - `--z-modal` (50)
58
+ - `--z-popover` (60)
59
+ - `--z-tooltip` (70)
60
+
61
+ ### Component Naming
62
+ - Default exports are the enhanced/polished variants; use **Core\*** for plain primitives
63
+ - Implementations are consolidated under **`ui/`** (not separate `custom/enhanced-*` per component for Button, Badge, Checkbox, Select, Combobox, Sonner)
64
+ - File names: kebab-case
65
+ - Component names: PascalCase
66
+
67
+ ### Hit area (optional)
68
+
69
+ Library CSS includes [Bazza hit-area](https://bazza.dev/craft/2026/hit-area) utilities. For **Checkbox** / **Switch** in padded tables or lists, pass **`className="hit-area-6"`** (or `hit-area-4`, axis variants) on the **component root**, not on a wrapper-only parent. Opt-in only; use **`hit-area-debug`** while tuning. Details: `packages/nqui/docs/components/nqui-checkbox.md`, `nqui-switch.md`; examples: `ComponentShowcase` Checkbox + Switch sections.
70
+
71
+ ## Key Dependencies
72
+
73
+ Required peer dependencies:
74
+ - `@hugeicons/react`
75
+ - `@hugeicons/core-free-icons`
76
+
77
+ Optional:
78
+ - `next-themes` - for theme toggle
79
+ - `tw-animate-css` - for animations
80
+
81
+ ## Installation & Setup
82
+
83
+ ```bash
84
+ # Quick setup
85
+ npx @nqlib/nqui init-css
86
+
87
+ # App setup with sidebar
88
+ npx @nqlib/nqui init-css --sidebar
89
+
90
+ # Install peer dependencies
91
+ npx @nqlib/nqui install-peers
92
+ ```
93
+
94
+ ## CSS Variables
95
+
96
+ All components use CSS variables. Key ones:
97
+ - `--background`, `--foreground`
98
+ - `--muted`, `--muted-foreground`
99
+ - `--accent`, `--accent-foreground`
100
+ - `--border`, `--ring`
101
+ - `--primary`, `--primary-foreground`
102
+ - `--destructive`, `--destructive-foreground`