@nqlib/nqui 0.5.6 → 0.6.1

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 (76) hide show
  1. package/dist/{command-palette-DhoWGyk_.js → command-palette-CHUiGh5m.js} +2 -2
  2. package/dist/{command-palette-D24rOeE6.cjs → command-palette-DsvP2QNP.cjs} +2 -2
  3. package/dist/command.cjs.js +1 -1
  4. package/dist/command.es.js +1 -1
  5. package/dist/components/custom/table-of-contents.d.ts +2 -2
  6. package/dist/components/custom/table-of-contents.d.ts.map +1 -1
  7. package/dist/components/index.d.ts +3 -0
  8. package/dist/components/index.d.ts.map +1 -1
  9. package/dist/components/theme-appearance-menu.d.ts +9 -0
  10. package/dist/components/theme-appearance-menu.d.ts.map +1 -0
  11. package/dist/components/theme-toggle.d.ts +2 -0
  12. package/dist/components/theme-toggle.d.ts.map +1 -0
  13. package/dist/components/ui/checkbox.d.ts.map +1 -1
  14. package/dist/components/ui/combobox.d.ts +5 -3
  15. package/dist/components/ui/combobox.d.ts.map +1 -1
  16. package/dist/components/ui/toggle-group.d.ts.map +1 -1
  17. package/dist/{debug-panel-BjfW-YVo.js → debug-panel-BcYzsTp2.js} +1 -1
  18. package/dist/{debug-panel-CpqsKuxd.cjs → debug-panel-mwtujy5J.cjs} +1 -1
  19. package/dist/debug.cjs.js +1 -1
  20. package/dist/debug.es.js +1 -1
  21. package/dist/elevation-debate.html +286 -0
  22. package/dist/{input-shared-CDgy_NdJ.cjs → input-shared-C9Try5fg.cjs} +1 -1
  23. package/dist/{input-shared-NnOiyHpu.js → input-shared-DXf3Edqt.js} +1 -1
  24. package/dist/lib/floating-surface.d.ts +6 -2
  25. package/dist/lib/floating-surface.d.ts.map +1 -1
  26. package/dist/nqui.cjs.js +15 -13
  27. package/dist/nqui.es.js +2752 -2646
  28. package/dist/styles.css +151 -255
  29. package/docs/components/README.md +4 -1
  30. package/docs/components/nqui-combobox.md +15 -2
  31. package/docs/components/nqui-command-palette.md +7 -0
  32. package/docs/components/nqui-command.md +41 -0
  33. package/docs/components/nqui-scroll-area.md +69 -0
  34. package/docs/nqui-skills/AGENT_PROMPT.md +190 -0
  35. package/docs/nqui-skills/COMPONENTS_INDEX.md +51 -1
  36. package/docs/nqui-skills/COMPOSITION.md +321 -0
  37. package/docs/nqui-skills/ELEVATION.md +181 -0
  38. package/docs/nqui-skills/EVAL.md +148 -0
  39. package/docs/nqui-skills/HUMAN_GUIDE.md +18 -0
  40. package/docs/nqui-skills/MIGRATION.md +133 -0
  41. package/docs/nqui-skills/MOTION.md +189 -0
  42. package/docs/nqui-skills/README.md +2 -0
  43. package/docs/nqui-skills/READ_BUDGET.md +60 -0
  44. package/docs/nqui-skills/RECIPES.md +820 -0
  45. package/docs/nqui-skills/SKILL.md +58 -1
  46. package/docs/nqui-skills/STATES.md +154 -0
  47. package/docs/nqui-skills/THEMING.md +203 -0
  48. package/docs/nqui-skills/WRITING.md +205 -0
  49. package/docs/nqui-skills/_claude-commands/README.md +50 -0
  50. package/docs/nqui-skills/_claude-commands/design/SKILL.md +111 -0
  51. package/docs/nqui-skills/_claude-commands/edit/SKILL.md +97 -0
  52. package/docs/nqui-skills/adapt/SKILL.md +5 -2
  53. package/docs/nqui-skills/animate/SKILL.md +5 -2
  54. package/docs/nqui-skills/audit/SKILL.md +5 -2
  55. package/docs/nqui-skills/bolder/SKILL.md +5 -2
  56. package/docs/nqui-skills/clarify/SKILL.md +5 -2
  57. package/docs/nqui-skills/colorize/SKILL.md +5 -2
  58. package/docs/nqui-skills/delight/SKILL.md +5 -4
  59. package/docs/nqui-skills/distill/SKILL.md +5 -2
  60. package/docs/nqui-skills/impeccable/SKILL.md +0 -16
  61. package/docs/nqui-skills/impeccable/reference/INDEX.md +26 -0
  62. package/docs/nqui-skills/layout/SKILL.md +5 -2
  63. package/docs/nqui-skills/nqui-components/SKILL.md +33 -9
  64. package/docs/nqui-skills/nqui-composition/SKILL.md +148 -0
  65. package/docs/nqui-skills/nqui-data-tables/SKILL.md +127 -0
  66. package/docs/nqui-skills/nqui-design-system/SKILL.md +22 -1
  67. package/docs/nqui-skills/nqui-install/SKILL.md +1 -0
  68. package/docs/nqui-skills/overdrive/SKILL.md +5 -2
  69. package/docs/nqui-skills/polish/SKILL.md +5 -4
  70. package/docs/nqui-skills/quieter/SKILL.md +5 -2
  71. package/docs/nqui-skills/shape/SKILL.md +5 -2
  72. package/docs/nqui-skills/typeset/SKILL.md +5 -2
  73. package/package.json +2 -1
  74. package/scripts/build-styles.js +4 -3
  75. package/scripts/cli.js +2 -0
  76. package/scripts/install-claude-skills.js +148 -0
@@ -0,0 +1,148 @@
1
+ ---
2
+ name: nqui-composition
3
+ description: Compose nqui components into calm, product-quality screens. Use when building pages, layouts, or flows — not when looking up a single component's props. Apple-inspired craft (clarity, deference, depth). Pair with COMPOSITION.md patterns and RECIPES.md combos. Invoke before nqui-components for new views.
4
+ ---
5
+
6
+ # nqui Composition — Apple-inspired Craft
7
+
8
+ This skill is for **putting components together**, not for picking variants of one component (that's `nqui-components`). Read this *before* writing JSX for a new view. The goal is to make screens that feel deliberate, calm, and trustworthy — not busy, generic, or AI-flavored.
9
+
10
+ ## Three Apple principles, translated to nqui
11
+
12
+ These come from Apple's Human Interface Guidelines but applied concretely to React + Tailwind component work.
13
+
14
+ ### 1. Clarity — content leads, chrome defers
15
+
16
+ Everything on screen exists to serve the content. If chrome (borders, shadows, decorative panels, hover effects) competes with the content, the chrome loses.
17
+
18
+ **Apply it:**
19
+ - One typeface for UI text. Use weight and size for hierarchy, not extra families.
20
+ - Borders are 1px and use `border-border` (subtle), never a 2-3px decorative accent.
21
+ - The most prominent thing on screen should be the user's content, not the navigation.
22
+ - Color is scarce. One accent (`primary`), one each for success/warning/error semantic tokens. That's it.
23
+ - Icons are 16-20px in product UI. Bigger only when they ARE the content (empty states, hero illustrations).
24
+
25
+ **Don't:**
26
+ - Wrap every region in a Card "to give it structure" — structure comes from spacing and type, not from boxes.
27
+ - Use multiple competing accent colors. A second "look at me" color cannibalizes the first.
28
+ - Set body text below 14px or above 16px in product UI.
29
+
30
+ ### 2. Deference — UI yields to data
31
+
32
+ The interface should disappear once the user understands it. After the first second, the user should be looking at *their stuff*, not at *your buttons*.
33
+
34
+ **Apply it:**
35
+ - Toolbars sit in `bg-muted/30` containers, not floating on `bg-background` (a floating toolbar is louder than the content below it).
36
+ - Secondary actions are `variant="ghost"` or `variant="outline"`. Never two primaries.
37
+ - Filter chips and segmented controls use the subtlest treatment that still reads — `bg-muted` for off-state, `bg-accent` for on-state, no shadows.
38
+ - Empty states are quiet. A small icon, one sentence, one action. Not a marketing illustration.
39
+ - Loading states (`Skeleton`) match the shape of the content they replace — not a generic spinner that demands attention.
40
+
41
+ **Don't:**
42
+ - Animate everything. Motion that doesn't serve comprehension is noise.
43
+ - Apply `shadow-lg` to flat surfaces. Shadows imply elevation; on a flat element they read as decoration, not affordance.
44
+ - Use `font-bold` on labels, metadata, or supporting text. Bold is for the thing the user came to read.
45
+
46
+ ### 3. Depth — layers must mean something
47
+
48
+ Apple uses depth (translucency, layering, motion) to signal hierarchy: which surface is closer, which is further, what's modal vs ambient. nqui uses the same logic with `z-index` tokens and surface backgrounds.
49
+
50
+ **Apply it:**
51
+ - Z-index comes from `elevation.css` semantic tokens (`--z-sticky-page`, `--z-modal`, `--z-popover`). Never raw numbers.
52
+ - Three-layer surface logic in master-detail or split views: outer wrapper (`bg-muted/20`), panels (`bg-background`), inside cards or selected items (`bg-accent/70`). The contrast IS the separation.
53
+ - Modals, sheets, and popovers cast subtle shadows because they're physically "above" the page. Inline cards don't, because they're flat.
54
+ - Motion conveys depth: a Sheet slides in from the edge (it came from outside), a Dialog fades + scales (it appeared in place).
55
+
56
+ **Don't:**
57
+ - Use `backdrop-blur` on inline content (it's a depth signal — reserve for overlays and sticky headers over scroll).
58
+ - Nest cards inside cards. If you need a sub-region, use spacing and a `Separator`, not another bordered box.
59
+ - Apply z-index tokens for ordering elements that aren't elevated — they cause stacking-context bugs.
60
+
61
+ ## The composition checklist (run before writing JSX)
62
+
63
+ 1. **What is the one outcome on this screen?** Write it down in five words.
64
+ 2. **What is the single primary action?** Everything else is secondary.
65
+ 3. **What can move off this view?** A sheet, a route, a hover card, an "advanced" section.
66
+ 4. **How many surfaces?** Cap at three (chrome + primary + optional secondary). If you have more, you have too many.
67
+ 5. **What is the canonical empty state?** What is the loading state? What is the error state? Skip this and the UI will leak placeholder lorem text.
68
+ 6. **What's the responsive breakdown?** Below what container width does this collapse to a single column / Sheet?
69
+
70
+ If you can't answer all six in under a minute, you don't understand the screen yet. Don't start coding.
71
+
72
+ ## Decision rules baked in
73
+
74
+ These are not stylistic suggestions — they are rules:
75
+
76
+ | Situation | Rule |
77
+ |-----------|------|
78
+ | Inline selection (mode, format, view-type) | `ToggleGroup`, never `RadioGroup` |
79
+ | Form with >5 fields | Use `Sheet` or a dedicated route, never a `Dialog` |
80
+ | Destructive confirm | `AlertDialog`, never `Dialog` |
81
+ | Master-detail under ~900px container width | Switch detail to `Sheet`, don't shrink both panels |
82
+ | Status indicator | `Badge` (or a 6-8px colored dot), never `border-left: 4px` stripe |
83
+ | Loading | `Skeleton` shaped like the content, not a `Spinner` |
84
+ | Empty | `Empty` component, not a stylized div |
85
+ | Toolbar | `bg-muted/30` container with internal `Separator` for groups |
86
+ | Page chrome height | `h-12` (48px) — for header bars and section headers |
87
+ | Default control size | `sm` for dense product UI, `default` for marketing/forms |
88
+
89
+ ## Hierarchy without dependence on color
90
+
91
+ Apple's interfaces look intentional largely because they get hierarchy from **type weight, size, spacing, and proximity** before reaching for color. nqui defaults support this:
92
+
93
+ - **Most important**: `text-base font-semibold text-foreground` (or `text-lg`/`text-xl` for page H1)
94
+ - **Standard reading**: `text-sm text-foreground`
95
+ - **Supporting / metadata**: `text-xs text-muted-foreground` or `text-sm text-muted-foreground`
96
+ - **Labels / categories**: `text-xs uppercase tracking-wider text-muted-foreground font-semibold`
97
+ - **Numeric data**: add `tabular-nums` so numbers align
98
+
99
+ Spacing rhythm: 8 → 12 → 16 → 24 → 32 → 48. Tight inside related groups (8-12), generous between sections (24-48). The variation IS the hierarchy.
100
+
101
+ ## Elevation — the 2+1 surface rule
102
+
103
+ **Cap inline nesting at 2 surfaces.** Past that, spacing + type weight + occasional Separator carry the hierarchy. One additional `surface-elevated` is reserved for overlays (modals, sheets, popovers). This is the entire elevation system — see `../ELEVATION.md` for the full rule + decision tree.
104
+
105
+ | Depth | Carrier |
106
+ |-------|---------|
107
+ | Page → card | Surface flip (A → B) |
108
+ | Card → sub-section | Spacing + uppercase label, NOT a new shade |
109
+ | Section → sub-detail | More spacing + type weight, NOT a new shade |
110
+ | Modal over content | `surface-elevated` (the only legitimate third) |
111
+
112
+ **When tempted to add a third inline surface:** more space, a stronger label, or move it to a sheet/route. Never a new shade.
113
+
114
+ ## Surface vocabulary (when to use which container)
115
+
116
+ | Surface | When | Avoid for |
117
+ |---------|------|-----------|
118
+ | `Card` | Bounded topic with its own title (Team members, Shipping address, Chart) | A single button, a filter chip, page-level layout |
119
+ | `Item` (ghost variant) | A row in a list — issue, file, message, contact | Standalone content blocks |
120
+ | `Item` (outline variant) | A row that needs to read as a tappable card | Lists where rows share a topic and proximity already groups them |
121
+ | `Sheet` | Side panel for filters, detail view, inline forms | Confirmations, single-input prompts |
122
+ | `Dialog` | Focused task requiring input (create record, edit small form) | Anything destructive |
123
+ | `AlertDialog` | Destructive or irreversible confirmation only | Informational alerts |
124
+ | `Popover` | Quick contextual content tied to a trigger element | Long content, anything with its own scroll |
125
+ | `Drawer` | Mobile-first bottom sheet (gesture-heavy) | Desktop primary patterns |
126
+ | `HoverCard` | Optional preview information on hover (link preview, user card) | Anything critical to the task |
127
+
128
+ ## What "Apple-quality" actually looks like in practice
129
+
130
+ The shorthand "make it look like Apple" usually means three things, in order:
131
+
132
+ 1. **More space than you think you need.** Padding is generosity. Cramped UIs read as cheap.
133
+ 2. **Fewer styles, applied more consistently.** Two button variants used everywhere beat six used inconsistently.
134
+ 3. **Honest materials.** Glass surfaces over scroll. Solid surfaces in flat regions. Shadows for things that are physically above. Don't mix metaphors.
135
+
136
+ If you reach for `shadow-2xl`, `bg-gradient-to-br`, `backdrop-blur`, or a fourth typeface — stop and revisit. None of those are necessary for a screen to look refined. Restraint is the technique.
137
+
138
+ ## Files to load next
139
+
140
+ | Need | Open |
141
+ |------|------|
142
+ | A blueprint for the screen type (settings, dashboard, master-detail, wizard, command, dialog) | `../COMPOSITION.md` |
143
+ | Combos: "I need to do X, what components together?" | `../RECIPES.md` |
144
+ | Specific component props/variants | `../components/nqui-<name>.md` |
145
+ | Sizing, spacing tokens, scroll patterns | `../nqui-design-system/SKILL.md` |
146
+ | Brand voice / typography / color depth | `../impeccable/SKILL.md` (one time per conversation) |
147
+
148
+ Do not bulk-read. See `../READ_BUDGET.md`.
@@ -0,0 +1,127 @@
1
+ ---
2
+ name: nqui-data-tables
3
+ description: One-shot TanStack or native HTML data tables with nqui ScrollArea — bounded card height, sticky header, horizontal+vertical scroll, flex height chain, viewport pinning, optional infinite scroll or paged Back/Next. Use for dashboards, dense grids, portfolio views.
4
+ ---
5
+
6
+ # nqui Data Tables (ScrollArea + flex)
7
+
8
+ Single playbook to ship a **card-wrapped** table that scrolls **inside** the card (sticky header, many columns) without overlapping a **footer** below the grid.
9
+
10
+ ## Load order (save tokens)
11
+
12
+ 1. **`docs/components/nqui-scroll-area.md`** — **§0** symptom routing (Card, Sheet, sidebar), flex height chain §1, pitfalls §2–§5, **`§6` Data tables / wide grids** (`orientation="both"`, `h-0 flex-1`, `viewportStyle` pin), `viewportRef`.
13
+ 2. **`nqui-design-system/SKILL.md`** — **Card + ScrollArea** contract, `min-h-0`, spacing, control sizes.
14
+ 3. **`nqui-components`** — imports for `ScrollArea`, `Table*`, `Button`, `cn`.
15
+
16
+ ## One-shot structure
17
+
18
+ ```
19
+ <div className={tableShellClass}> // capped column flex + clip
20
+ <ScrollArea …> // flex child: scroll slot
21
+ <div className={tablePaddingClass}> // px inside scrollport
22
+ <table>… sticky thead … tbody …</table>
23
+ {/* optional infinite-scroll sentinel */}
24
+ </div>
25
+ </ScrollArea>
26
+ <div className={tableFooterClass}>…</div> // shrink-0, outside ScrollArea
27
+ </div>
28
+ ```
29
+
30
+ ### 1) Shell (`tableShellClass`)
31
+
32
+ Use **one** outer wrapper for `ScrollArea` + footer:
33
+
34
+ - **`flex flex-col overflow-hidden`** — column stack; clip bleed.
35
+ - **`min-h-[18rem]`** (tune) — floor so `flex-1` children get real height when data is short.
36
+ - **`max-h-[min(84dvh,calc(100dvh-8rem))]`** (tune) — ceiling so tall data **must** scroll inside.
37
+ - **`rounded-2xl border border-border bg-card`** — nqui card surface.
38
+
39
+ **Per-table height:** merge extra utilities with `cn(tableShellClass, extra)` (e.g. taller Operations desk) instead of changing the default for every table.
40
+
41
+ ### 2) ScrollArea root classes
42
+
43
+ ```txt
44
+ h-0 max-h-full min-h-0 min-w-0 flex-1 overflow-hidden w-full
45
+ ```
46
+
47
+ - **`h-0` + `flex-1`** — flex-column pattern so this child receives a **definite** main-axis size (avoids `min-height: auto` content blow-through).
48
+ - **`overflow-hidden`** — keeps Radix layout clipped to the slot.
49
+
50
+ ### 3) ScrollArea props (data grids)
51
+
52
+ ```tsx
53
+ <ScrollArea
54
+ orientation="both" // default "vertical" uses overflow-x-hidden — breaks wide <table>
55
+ fadeMask={false} // dense grids: skip edge fade masks over cells
56
+ className={tableScrollAreaRootClass}
57
+ viewportRef={viewportRef} // optional: IO root, scrollTop
58
+ viewportStyle={tableScrollViewportStyle}
59
+ >
60
+ ```
61
+
62
+ ### 4) `viewportStyle` — pin Radix viewport (critical)
63
+
64
+ **Do not rely on `height: 100%` / `maxHeight: 100%` alone** on the viewport in flex-heavy trees: the viewport can still **grow to content height**, cover the footer, and show **no** vertical scroll (`clientHeight === scrollHeight`).
65
+
66
+ Export a shared object (TypeScript `CSSProperties`):
67
+
68
+ ```ts
69
+ export const tableScrollViewportStyle: CSSProperties = {
70
+ position: "absolute",
71
+ inset: 0,
72
+ minHeight: 0,
73
+ minWidth: 0,
74
+ overscrollBehavior: "contain",
75
+ };
76
+ ```
77
+
78
+ Enhanced `ScrollArea` root is **`relative`** — absolute viewport fills that box.
79
+
80
+ ### 5) Padding inside the scrollport
81
+
82
+ Wrap the `<table>` in **`px-4 pt-0`** (or project rhythm) so horizontal scroll and sticky headers align with card padding.
83
+
84
+ ### 6) Sticky `<thead>`
85
+
86
+ - Header cells: **`sticky top-0 z-20 bg-card`** + border token bottom edge.
87
+ - Sticky **lead columns** (optional): **`sticky left-*`** with header `z` above body `z`; use **opaque** `bg-card` / `bg-muted` so cells don’t show through.
88
+
89
+ ### 7) Footer
90
+
91
+ - **`shrink-0`** (included in typical `tableFooterClass` patterns).
92
+ - Keep counts, pagination, CSV actions **here** — not inside `ScrollArea`.
93
+
94
+ ## Flex ancestors
95
+
96
+ Put **`min-h-0`** / **`min-w-0`** on **every** flex ancestor between the page root and the table card when the page itself is also flex + scroll. See **§1 Flex / resizable panels** in `nqui-scroll-area.md`.
97
+
98
+ ## Infinite scroll (optional)
99
+
100
+ 1. Pass Radix **viewport** node as `IntersectionObserver` **`root`** (`viewportRef` callback or ref merge).
101
+ 2. Place a **sentinel** `<div className="h-1 shrink-0" />` after `<table>` inside the padded wrapper.
102
+ 3. Reset visible row window when **data / sort / filters** change.
103
+
104
+ ## Paged Back / Next (optional)
105
+
106
+ - No sentinel. **`useState(page)`** + **`rows.slice(page * PAGE_SIZE, …)`**.
107
+ - Reset **`page`** to `0` on data/sort change; clamp when `rows.length` shrinks.
108
+
109
+ ## Anti-patterns
110
+
111
+ | Don’t | Why |
112
+ |-------|-----|
113
+ | `orientation="vertical"` only + `min-w-[1200px]` table | Horizontal scroll is suppressed in nqui’s vertical mode. |
114
+ | `flex-1` ScrollArea without `h-0` / `min-h-0` chain | Viewport grows with rows; footer overlap or no scroll. |
115
+ | Nested `ScrollArea` in expanded rows | Prefer `overflow-auto` on inner panels. |
116
+ | Two accidental scroll roots (card + inner) without `max-h` | Double scrollbars / layout fights. |
117
+
118
+ ## Definition of done (quick verify)
119
+
120
+ - With many rows: **`viewport.scrollHeight > viewport.clientHeight`** and wheel scroll moves **`scrollTop`**.
121
+ - Footer stays **below** the scroll clip; no overlap at rest.
122
+ - Wide table: horizontal scrollbar appears when **`table` min-width** exceeds viewport.
123
+
124
+ ## SSOT paths
125
+
126
+ - Package skills: `packages/nqui/docs/nqui-skills/nqui-data-tables/SKILL.md` (this file).
127
+ - After `npx @nqlib/nqui init-skills`: `.cursor/nqui-skills/nqui-data-tables/SKILL.md` in consumer repos.
@@ -1,12 +1,24 @@
1
1
  ---
2
2
  name: nqui-design-system
3
- description: Design system conventions for nqui component library. Use when creating or modifying nqui UI components (sizing, spacing, Card + ScrollArea flex scroll / min-h-0, grouped controls, density).
3
+ description: Design system conventions for nqui component library. Use when creating or modifying nqui UI components (sizing, spacing, Card + ScrollArea flex scroll / min-h-0, grouped controls, density). Pair with nqui-data-tables for dashboard table shells.
4
4
  ---
5
5
 
6
6
  # nqui Design System
7
7
 
8
8
  Guidelines for AI agents and developers implementing or modifying nqui components. Follow these rules to maintain visual consistency.
9
9
 
10
+ ## Elevation — 2 inline surfaces + 1 elevated (mandatory)
11
+
12
+ nqui uses a **hybrid elevation model**: 2 alternating inline surface tokens + 1 elevated surface for overlays. Spacing and type weight carry hierarchy beyond 2 surfaces. Full philosophy + decision tree in `../ELEVATION.md`.
13
+
14
+ | Token | Tailwind | When |
15
+ |-------|----------|------|
16
+ | `surface-a` | `bg-background` | Page, alternates with B |
17
+ | `surface-b` | `bg-muted/40` | Card/panel/distinct topic region |
18
+ | `surface-elevated` | `bg-popover` + `shadow-lg` | Modals, sheets, popovers (the only legitimate third surface) |
19
+
20
+ **Hard cap: 2 nested inline surfaces.** If you reach for a third shade, use spacing (`gap-6` between sections) + an uppercase label (`text-xs uppercase tracking-wider`) instead. A third nested surface is almost always a symptom of weak composition.
21
+
10
22
  ## Control Size Scale
11
23
 
12
24
  All interactive controls (buttons, toggles, inputs, selects) use a unified scale:
@@ -132,6 +144,14 @@ Never use flat `bg-muted` only for selected state; always add gradient + shadow
132
144
  3. **Scrollable body:** Prefer **`CardContent`** (or a wrapper) with **`min-h-0 flex-1 overflow-hidden`**, then **ScrollArea** with **`className="min-h-0 h-full"`** or **`min-h-0 flex-1`** inside a **`flex flex-col min-h-0`** card.
133
145
  4. **Parent must constrain height:** e.g. `h-full`, `min-h-0`, or explicit `max-h-*` / `h-[...]`; otherwise “100%” has no reference.
134
146
 
147
+ **Applies beyond Card:** **Sheet** / **Drawer** body, **sidebar** columns, **dashboard** panes, and **resizable** splits use the **same** contract — one **`flex flex-col min-h-0 overflow-hidden`** shell that owns the clip, **chrome** (`header`, tabs, toolbars) as **`shrink-0`**, scroll body in **`flex-1 min-h-0`**. Symptom → fix routing: **`docs/components/nqui-scroll-area.md` §0**.
148
+
149
+ **Data tables / wide grids (same failure modes, stricter recipe):**
150
+
151
+ - **`orientation="both"`** — default **`vertical`** uses **`overflow-x-hidden`** on the viewport; a **`min-w-*`** `<table>` then **cannot** scroll horizontally. See **`docs/components/nqui-scroll-area.md` §6**.
152
+ - **ScrollArea root in a capped flex column:** **`h-0 max-h-full min-h-0 min-w-0 flex-1 overflow-hidden w-full`** so flex assigns a **finite** slot (not content-height blow-through).
153
+ - **`viewportStyle`:** **`position: "absolute"`, `inset: 0`, `minHeight: 0`, `minWidth: 0`** — **`height: 100%`** on the Radix viewport often **does not bind** in deep flex layouts; the viewport then grows with content and overlaps a footer below. See **`docs/components/nqui-scroll-area.md` §6** and **`docs/nqui-skills/nqui-data-tables/SKILL.md`**.
154
+
135
155
  **Reference implementations:** `Card` + **`stickyHeader`** in `src/components/ui/card.tsx`; `src/pages/ComponentShowcase.tsx` where ScrollArea sits in a bounded layout.
136
156
 
137
157
  **Checklist before merging a scrollable card:**
@@ -140,6 +160,7 @@ Never use flat `bg-muted` only for selected state; always add gradient + shadow
140
160
  - [ ] Card column is **`flex flex-col min-h-0`** (and **`h-full`** if filling a panel).
141
161
  - [ ] Scroll wrapper: **`flex-1 min-h-0 overflow-hidden`**.
142
162
  - [ ] **ScrollArea** has **`min-h-0`** and fills the wrapper (**`h-full`** / **`flex-1`**).
163
+ - [ ] **Wide table in ScrollArea:** **`orientation="both"`** + **`viewportStyle`** absolute fill if `%` height failed (see component doc §6).
143
164
 
144
165
  ## Density & visual hierarchy (product feel)
145
166
 
@@ -51,6 +51,7 @@ Copies `docs/nqui-skills` to `.cursor/nqui-skills/`, copies **`docs/components`*
51
51
 
52
52
  ```bash
53
53
  npx @nqlib/nqui init-skills
54
+ npx @nqlib/nqui init-claude-skills
54
55
  ```
55
56
 
56
57
  Use **`HUMAN_GUIDE.md`** for task-based wayfinding; **`COMPONENTS_INDEX.md`** to pick **one** `nqui-*.md` at a time (saves tokens).
@@ -15,9 +15,12 @@ Start your response with:
15
15
 
16
16
  Push an interface past conventional limits. This isn't just about visual effects — it's about using the full power of the browser to make any part of an interface feel extraordinary: a table that handles a million rows, a dialog that morphs from its trigger, a form that validates in real-time with streaming feedback, a page transition that feels cinematic.
17
17
 
18
- ## MANDATORY PREPARATION
18
+ ## Context check (lightweight)
19
19
 
20
- Invoke /impeccable — it contains design principles, anti-patterns, and the **Context Gathering Protocol**. Follow the protocol before proceeding — if no design context exists yet, you MUST run /impeccable teach first.
20
+ Before proceeding, ensure design context is loaded:
21
+ - If `.impeccable.md` exists in project root, the project context is set — DO NOT re-invoke /impeccable.
22
+ - If `.impeccable.md` is missing, run `/impeccable teach` ONCE to create it.
23
+ - For depth on one topic only, see `impeccable/reference/INDEX.md` and load ONE file.
21
24
 
22
25
  **EXTRA IMPORTANT FOR THIS SKILL**: Context determines what "extraordinary" means. A particle system on a creative portfolio is impressive. The same particle system on a settings page is embarrassing. But a settings page with instant optimistic saves and animated state transitions? That's extraordinary too. Understand the project's personality and goals before deciding what's appropriate.
23
26
 
@@ -6,11 +6,12 @@ user-invocable: true
6
6
  argument-hint: "[target]"
7
7
  ---
8
8
 
9
- ## MANDATORY PREPARATION
9
+ ## Context check (lightweight)
10
10
 
11
- Invoke /impeccable — it contains design principles, anti-patterns, and the **Context Gathering Protocol**. Follow the protocol before proceeding — if no design context exists yet, you MUST run /impeccable teach first. Additionally gather: quality bar (MVP vs flagship).
12
-
13
- ---
11
+ Before proceeding, ensure design context is loaded:
12
+ - If `.impeccable.md` exists in project root, the project context is set — DO NOT re-invoke /impeccable.
13
+ - If `.impeccable.md` is missing, run `/impeccable teach` ONCE to create it.
14
+ - For depth on a specific topic, see `impeccable/reference/INDEX.md` and load ONE file.
14
15
 
15
16
  Perform a meticulous final pass to catch all the small details that separate good work from great work. The difference between shipped and polished.
16
17
 
@@ -8,9 +8,12 @@ argument-hint: "[target]"
8
8
 
9
9
  Reduce visual intensity in designs that are too bold, aggressive, or overstimulating, creating a more refined and approachable aesthetic without losing effectiveness.
10
10
 
11
- ## MANDATORY PREPARATION
11
+ ## Context check (lightweight)
12
12
 
13
- Invoke /impeccable — it contains design principles, anti-patterns, and the **Context Gathering Protocol**. Follow the protocol before proceeding — if no design context exists yet, you MUST run /impeccable teach first.
13
+ Before proceeding, ensure design context is loaded:
14
+ - If `.impeccable.md` exists in project root, the project context is set — DO NOT re-invoke /impeccable.
15
+ - If `.impeccable.md` is missing, run `/impeccable teach` ONCE to create it.
16
+ - For depth on one topic only, see `impeccable/reference/INDEX.md` and load ONE file.
14
17
 
15
18
  ---
16
19
 
@@ -6,9 +6,12 @@ user-invocable: true
6
6
  argument-hint: "[feature to shape]"
7
7
  ---
8
8
 
9
- ## MANDATORY PREPARATION
9
+ ## Context check (lightweight)
10
10
 
11
- Invoke /impeccable, which contains design principles, anti-patterns, and the **Context Gathering Protocol**. Follow the protocol before proceeding. If no design context exists yet, you MUST run /impeccable teach first.
11
+ Before proceeding, ensure design context is loaded:
12
+ - If `.impeccable.md` exists in project root, the project context is set — DO NOT re-invoke /impeccable.
13
+ - If `.impeccable.md` is missing, run `/impeccable teach` ONCE to create it.
14
+ - For depth on one topic only, see `impeccable/reference/INDEX.md` and load ONE file.
12
15
 
13
16
  ---
14
17
 
@@ -8,9 +8,12 @@ argument-hint: "[target]"
8
8
 
9
9
  Assess and improve typography that feels generic, inconsistent, or poorly structured — turning default-looking text into intentional, well-crafted type.
10
10
 
11
- ## MANDATORY PREPARATION
11
+ ## Context check (lightweight)
12
12
 
13
- Invoke /impeccable — it contains design principles, anti-patterns, and the **Context Gathering Protocol**. Follow the protocol before proceeding — if no design context exists yet, you MUST run /impeccable teach first.
13
+ Before proceeding, ensure design context is loaded:
14
+ - If `.impeccable.md` exists in project root, the project context is set — DO NOT re-invoke /impeccable.
15
+ - If `.impeccable.md` is missing, run `/impeccable teach` ONCE to create it.
16
+ - For depth on one topic only, see `impeccable/reference/INDEX.md` and load ONE file.
14
17
 
15
18
  ---
16
19
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nqlib/nqui",
3
- "version": "0.5.6",
3
+ "version": "0.6.1",
4
4
  "description": "A React component library with enhanced UI components and developer tools",
5
5
  "type": "module",
6
6
  "main": "./dist/nqui.cjs.js",
@@ -118,6 +118,7 @@
118
118
  "nqui-init-css": "scripts/init-css.js",
119
119
  "nqui-init-cursor": "scripts/init-cursor.js",
120
120
  "nqui-init-skills": "scripts/download-skills.js",
121
+ "nqui-init-claude-skills": "scripts/install-claude-skills.js",
121
122
  "nqui-install-peers": "scripts/install-peers.js",
122
123
  "nqui-init-debug": "scripts/init-debug-css.js",
123
124
  "nqui-setup": "scripts/post-install.js"
@@ -103,7 +103,8 @@ function extractStandaloneCSS() {
103
103
  // These need to be preserved in the final output for zero-config setup
104
104
  // Match pattern: /* comment */ @source inline( ... ); (multiline)
105
105
  // Tailwind v4 requires: @source inline("class1 class2 class3");
106
- const sourceInlineRegex = /\/\*[^*]*\*+(?:[^/*][^*]*\*+)*\/\s*@source\s+inline\([\s\S]*?\)\s*;/g;
106
+ // Match only real directives (not comments that mention "@source inline")
107
+ const sourceInlineRegex = /\/\*[^*]*\*+(?:[^/*][^*]*\*+)*\/\s*@source\s+inline\("[^"]*"\)\s*;/g;
107
108
  const sourceInlineMatches = indexCss.match(sourceInlineRegex) || [];
108
109
 
109
110
  // Convert multiline format to single-line format required by Tailwind v4
@@ -145,10 +146,10 @@ function extractStandaloneCSS() {
145
146
  .replace(/\/\*\s*Import elevation system\s*\*\//g, '')
146
147
  .replace(/\/\*\s*Hit-area utilities \(expanded pointer targets\)\s*\*\/\s*\n/g, '')
147
148
  // Remove @source inline() directives (already extracted above) - must match multiline
148
- .replace(/\/\*[^*]*\*+(?:[^/*][^*]*\*+)*\/\s*@source\s+inline\([\s\S]*?\)\s*;/g, '')
149
+ .replace(/\/\*[^*]*\*+(?:[^/*][^*]*\*+)*\/\s*@source\s+inline\("[^"]*"\)\s*;/g, '')
149
150
  // Remove other @source directives (non-inline ones)
150
151
  .replace(/@source\s+(?!inline\()[^;]+;?\s*\n/g, '')
151
- .replace(/@custom-variant\s+[^;]+;?\s*\n/g, '');
152
+ .replace(/@custom-variant\s+[^\n]+;\s*\n/g, '');
152
153
 
153
154
  if (hitAreaCss) {
154
155
  indexCss = indexCss.replace(
package/scripts/cli.js CHANGED
@@ -6,6 +6,7 @@
6
6
  * Usage:
7
7
  * npx @nqlib/nqui init-css [output.css]
8
8
  * npx @nqlib/nqui init-cursor
9
+ * npx @nqlib/nqui init-claude-skills
9
10
  * npx @nqlib/nqui install-peers
10
11
  * npx @nqlib/nqui init-debug
11
12
  * npx @nqlib/nqui setup
@@ -21,6 +22,7 @@ const subcommand = process.argv[2];
21
22
  const routes = {
22
23
  'init-cursor': './init-cursor.js',
23
24
  'init-skills': './download-skills.js',
25
+ 'init-claude-skills': './install-claude-skills.js',
24
26
  'install-peers': './install-peers.js',
25
27
  'init-debug': './init-debug-css.js',
26
28
  'init-debug-css': './init-debug-css.js',
@@ -0,0 +1,148 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Install nqui skills for Claude Code / Claude Desktop.
4
+ *
5
+ * Usage: npx @nqlib/nqui init-claude-skills [--force]
6
+ *
7
+ * Copies packages/nqui/docs/nqui-skills/* → ~/.claude/skills/<skill-name>/
8
+ * Hub markdown → ~/.claude/skills/nqui/
9
+ * Component docs → ~/.claude/skills/nqui-components/components/
10
+ */
11
+
12
+ import { cpSync, existsSync, mkdirSync, readdirSync, readFileSync, statSync, writeFileSync } from 'fs';
13
+ import { homedir } from 'os';
14
+ import { join } from 'path';
15
+ import { getPackageRoot } from './getPackageRoot.js';
16
+
17
+ const root = getPackageRoot();
18
+ const SKILLS_SOURCE = join(root, 'docs', 'nqui-skills');
19
+ const COMPONENTS_SOURCE = join(root, 'docs', 'components');
20
+ const CLAUDE_SKILLS = join(homedir(), '.claude', 'skills');
21
+
22
+ // Root docs that live in the nqui hub directory (~/.claude/skills/nqui/)
23
+ const HUB_FILES = [
24
+ 'SKILL.md',
25
+ 'README.md',
26
+ 'HUMAN_GUIDE.md',
27
+ 'COMPOSITION.md',
28
+ 'COMPONENTS_INDEX.md',
29
+ 'READ_BUDGET.md',
30
+ // Apple-craft + production AI skills (v0.6+)
31
+ 'RECIPES.md',
32
+ 'STATES.md',
33
+ 'WRITING.md',
34
+ 'MOTION.md',
35
+ 'ELEVATION.md',
36
+ 'AGENT_PROMPT.md',
37
+ 'EVAL.md',
38
+ 'THEMING.md',
39
+ 'MIGRATION.md',
40
+ ];
41
+
42
+ // Slash-command entry points (/design, /edit) — bundled in docs/_claude-commands/
43
+ const SLASH_COMMANDS = ['design', 'edit'];
44
+
45
+ function ensureDir(dir) {
46
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
47
+ }
48
+
49
+ function isSkillDir(name) {
50
+ const path = join(SKILLS_SOURCE, name);
51
+ return statSync(path).isDirectory() && existsSync(join(path, 'SKILL.md'));
52
+ }
53
+
54
+ function patchHubSkill(destSkillPath) {
55
+ let content = readFileSync(destSkillPath, 'utf8');
56
+ content = content.replace(
57
+ /Installed into `\.cursor\/nqui-skills\/` via `npx @nqlib\/nqui init-skills`\./,
58
+ 'Installed into `~/.claude/skills/` via `npx @nqlib/nqui init-claude-skills`.',
59
+ );
60
+ content = content.replace(
61
+ /- `\.cursor\/nqui-skills\/components\/nqui-<name>\.md` \(after init-skills\)/,
62
+ '- `~/.claude/skills/nqui-components/components/nqui-<name>.md`',
63
+ );
64
+ content = content.replace(
65
+ /SSOT: `packages\/nqui\/docs\/nqui-skills\/`/,
66
+ 'SSOT: `packages/nqui/docs/nqui-skills/` (repo) · installed: `~/.claude/skills/`',
67
+ );
68
+ writeFileSync(destSkillPath, content);
69
+ }
70
+
71
+ export async function installClaudeSkills({ force = true } = {}) {
72
+ if (!existsSync(SKILLS_SOURCE)) {
73
+ console.error('Source skills not found:', SKILLS_SOURCE);
74
+ process.exit(1);
75
+ }
76
+
77
+ ensureDir(CLAUDE_SKILLS);
78
+
79
+ const hubDest = join(CLAUDE_SKILLS, 'nqui');
80
+ if (existsSync(hubDest) && !force) {
81
+ console.log('⏭️ ~/.claude/skills/nqui exists. Use --force to overwrite.');
82
+ } else {
83
+ ensureDir(hubDest);
84
+ for (const file of HUB_FILES) {
85
+ const src = join(SKILLS_SOURCE, file);
86
+ if (existsSync(src)) cpSync(src, join(hubDest, file), { force: true });
87
+ }
88
+ patchHubSkill(join(hubDest, 'SKILL.md'));
89
+ console.log('✅ Hub →', hubDest);
90
+ }
91
+
92
+ for (const name of readdirSync(SKILLS_SOURCE)) {
93
+ if (!isSkillDir(name)) continue;
94
+ const dest = join(CLAUDE_SKILLS, name);
95
+ if (existsSync(dest) && !force) {
96
+ console.log(`⏭️ ${name} — use --force to overwrite`);
97
+ continue;
98
+ }
99
+ cpSync(join(SKILLS_SOURCE, name), dest, { recursive: true, force: true });
100
+ console.log('✅', name, '→', dest);
101
+ }
102
+
103
+ // Per-component docs go in the hub at nqui/components/ (where AGENT_PROMPT.md
104
+ // and READ_BUDGET.md route to). Also keep a copy at nqui-components/components/
105
+ // for backward compatibility with the previous routing.
106
+ if (existsSync(COMPONENTS_SOURCE)) {
107
+ const hubComponentsDest = join(CLAUDE_SKILLS, 'nqui', 'components');
108
+ const legacyComponentsDest = join(CLAUDE_SKILLS, 'nqui-components', 'components');
109
+ if (existsSync(hubComponentsDest) && !force) {
110
+ console.log('⏭️ nqui/components — use --force to overwrite');
111
+ } else {
112
+ ensureDir(join(CLAUDE_SKILLS, 'nqui'));
113
+ cpSync(COMPONENTS_SOURCE, hubComponentsDest, { recursive: true, force: true });
114
+ console.log('✅ Component docs →', hubComponentsDest);
115
+ }
116
+ if (existsSync(join(CLAUDE_SKILLS, 'nqui-components'))) {
117
+ cpSync(COMPONENTS_SOURCE, legacyComponentsDest, { recursive: true, force: true });
118
+ }
119
+ }
120
+
121
+ // Slash command entry points — /design and /edit become Claude Code tools
122
+ const slashSrc = join(SKILLS_SOURCE, '_claude-commands');
123
+ if (existsSync(slashSrc)) {
124
+ for (const cmd of SLASH_COMMANDS) {
125
+ const cmdSrc = join(slashSrc, cmd);
126
+ const cmdDest = join(CLAUDE_SKILLS, cmd);
127
+ if (!existsSync(cmdSrc)) continue;
128
+ if (existsSync(cmdDest) && !force) {
129
+ console.log(`⏭️ /${cmd} — use --force to overwrite`);
130
+ continue;
131
+ }
132
+ cpSync(cmdSrc, cmdDest, { recursive: true, force: true });
133
+ console.log(`✅ /${cmd} →`, cmdDest);
134
+ }
135
+ }
136
+
137
+ console.log('\n📚 Claude skills installed under ~/.claude/skills/');
138
+ console.log(' Restart Claude Code or Claude Desktop to pick them up.');
139
+ console.log(' Try: /design [a login form] — build a new screen');
140
+ console.log(' /edit [the sprint page] — refine existing UI');
141
+ console.log(' Hub: /nqui · Components: /nqui-components · Tokens: /nqui-design-system');
142
+ }
143
+
144
+ const force = process.argv.includes('--force') || !process.argv.includes('--no-force');
145
+ installClaudeSkills({ force }).catch((err) => {
146
+ console.error(err);
147
+ process.exit(1);
148
+ });