@nqlib/nqui 0.4.8 → 0.5.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.
- package/dist/{button-CJHdCq9I.js → button-BrroJ39H.js} +35 -34
- package/dist/button-CrLihxcE.cjs +1 -0
- package/dist/calendar.cjs.js +1 -1
- package/dist/calendar.es.js +1 -1
- package/dist/{carousel-U7RZhYZj.js → carousel-C976t5jo.js} +1 -1
- package/dist/{carousel-D1FMVglR.cjs → carousel-VldrniuT.cjs} +1 -1
- package/dist/carousel.cjs.js +1 -1
- package/dist/carousel.es.js +1 -1
- package/dist/{command-palette-D_SFxXyQ.js → command-palette-2V1VSlOM.js} +1 -1
- package/dist/{command-palette-DSQYbRiH.cjs → command-palette-4Sv4QjZ2.cjs} +1 -1
- package/dist/command.cjs.js +1 -1
- package/dist/command.es.js +1 -1
- package/dist/components/custom/enhanced-tabs.d.ts +1 -0
- package/dist/components/custom/enhanced-tabs.d.ts.map +1 -1
- package/dist/components/ui/button.d.ts +4 -0
- package/dist/components/ui/button.d.ts.map +1 -1
- package/dist/components/ui/card.d.ts +1 -0
- package/dist/components/ui/card.d.ts.map +1 -1
- package/dist/components/ui/sonner.d.ts.map +1 -1
- package/dist/components/ui/tabs.d.ts +6 -4
- package/dist/components/ui/tabs.d.ts.map +1 -1
- package/dist/{debug-panel-CS_wuYVH.js → debug-panel-BnZDhlaR.js} +1621 -1749
- package/dist/{debug-panel-nDTrIh9s.cjs → debug-panel-R2ZLkucO.cjs} +10 -10
- package/dist/debug.cjs.js +1 -1
- package/dist/debug.es.js +1 -1
- package/dist/{enhanced-calendar-C7EQIr6i.cjs → enhanced-calendar-BEIfybRx.cjs} +1 -1
- package/dist/{enhanced-calendar-BGlsSYJd.js → enhanced-calendar-Cj-4xhqf.js} +1 -1
- package/dist/hooks/use-resolved-theme.d.ts +2 -4
- package/dist/hooks/use-resolved-theme.d.ts.map +1 -1
- package/dist/nqui.cjs.js +3 -23
- package/dist/nqui.es.js +605 -627
- package/dist/{sonner-CpmECDBk.js → sonner-C1ndgVQY.js} +24 -24
- package/dist/sonner-CP8np0BP.cjs +48 -0
- package/dist/sonner.cjs.js +1 -1
- package/dist/sonner.es.js +1 -1
- package/dist/styles.css +79 -84
- package/docs/components/README.md +11 -2
- package/docs/components/nqui-scroll-area.md +74 -0
- package/docs/components/nqui-tooltip.md +17 -2
- package/docs/nqui-skills/COMPONENTS_INDEX.md +48 -0
- package/docs/nqui-skills/HUMAN_GUIDE.md +21 -0
- package/docs/nqui-skills/README.md +20 -0
- package/docs/nqui-skills/SKILL.md +36 -89
- package/docs/nqui-skills/nqui-bundle-size-best-practices/SKILL.md +78 -0
- package/docs/nqui-skills/nqui-components/SKILL.md +101 -0
- package/docs/nqui-skills/{design-system.md → nqui-design-system/SKILL.md} +53 -25
- package/docs/nqui-skills/nqui-install/SKILL.md +65 -0
- package/docs/nqui-skills/nqui-local-published-toggle/SKILL.md +132 -0
- package/docs/nqui-skills/nqui-local-published-toggle/scripts/toggle-nqui.js +203 -0
- package/docs/nqui-skills/nqui-shadcn/SKILL.md +164 -0
- package/docs/nqui-skills/{rules → nqui-shadcn/rules}/forms.md +3 -3
- package/docs/nqui-skills/{rules → nqui-shadcn/rules}/styling.md +1 -1
- package/package.json +1 -1
- package/scripts/download-skills.js +28 -8
- package/scripts/examples/nextjs-layout-sidebar.tsx +3 -2
- package/scripts/examples/nextjs-layout.tsx +3 -2
- package/scripts/examples/vite-main.tsx +7 -1
- package/scripts/init-cursor.js +4 -3
- package/scripts/skill-templates.js +16 -6
- package/dist/button-R304rhsj.cjs +0 -1
- package/dist/sonner-nE9hIalJ.cjs +0 -48
- /package/docs/nqui-skills/{rules → nqui-shadcn/rules}/composition.md +0 -0
- /package/docs/nqui-skills/{rules → nqui-shadcn/rules}/icons.md +0 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# nqui skills (package copy)
|
|
2
|
+
|
|
3
|
+
These files mirror the **nqui** Cursor skills. They live in the `@nqlib/nqui` package so the library stays documented when split into its own repository.
|
|
4
|
+
|
|
5
|
+
| Skill | Path |
|
|
6
|
+
|-------|------|
|
|
7
|
+
| Hub (start here) | [SKILL.md](./SKILL.md) |
|
|
8
|
+
| **Task → components (designers)** | [HUMAN_GUIDE.md](./HUMAN_GUIDE.md) |
|
|
9
|
+
| **Component doc routing (agents; read first; saves tokens)** | [COMPONENTS_INDEX.md](./COMPONENTS_INDEX.md) |
|
|
10
|
+
| Per-component markdown (copied by `init-skills` to `.cursor/.../components/`) | `docs/components/` in repo; `components/` under this folder after init |
|
|
11
|
+
| Components & layouts | [nqui-components/SKILL.md](./nqui-components/SKILL.md) |
|
|
12
|
+
| Design system (sizing, Card + ScrollArea) | [nqui-design-system/SKILL.md](./nqui-design-system/SKILL.md) |
|
|
13
|
+
| shadcn-style usage rules | [nqui-shadcn/SKILL.md](./nqui-shadcn/SKILL.md) |
|
|
14
|
+
| Bundle size & peers | [nqui-bundle-size-best-practices/SKILL.md](./nqui-bundle-size-best-practices/SKILL.md) |
|
|
15
|
+
| Local vs published npm | [nqui-local-published-toggle/SKILL.md](./nqui-local-published-toggle/SKILL.md) |
|
|
16
|
+
| Install & setup commands | [nqui-install/SKILL.md](./nqui-install/SKILL.md) |
|
|
17
|
+
|
|
18
|
+
**Consumers:** run `npx @nqlib/nqui init-skills` (or `init-cursor`) to copy this folder to `.cursor/nqui-skills/` and to copy **`docs/components`** into **`.cursor/nqui-skills/components/`** (same content as in `node_modules/@nqlib/nqui/docs/components/`).
|
|
19
|
+
|
|
20
|
+
**Path note:** In this repo, paths are relative to the **nqui package root** (`docs/…`, `src/…`). In a monorepo, prefix with `packages/nqui/` where needed.
|
|
@@ -1,106 +1,53 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: nqui
|
|
3
|
-
description:
|
|
2
|
+
name: nqui
|
|
3
|
+
description: Hub for nqui skills — @nqlib/nqui components, design system, shadcn patterns, bundle size, local/published toggle, and install. Load sub-skills by task.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# nqui
|
|
6
|
+
# nqui skills (hub)
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
Use this file as the entry point when working inside **`docs/nqui-skills/`** (package) or **`.cursor/nqui-skills/`** (after `npx @nqlib/nqui init-skills`).
|
|
9
9
|
|
|
10
|
-
##
|
|
10
|
+
## Per-component docs (token-efficient)
|
|
11
11
|
|
|
12
|
-
1. **
|
|
13
|
-
2. **
|
|
14
|
-
3. **
|
|
12
|
+
1. Read **[COMPONENTS_INDEX.md](./COMPONENTS_INDEX.md)** first — which single `nqui-*.md` to open.
|
|
13
|
+
2. **Designers / task-based:** **[HUMAN_GUIDE.md](./HUMAN_GUIDE.md)** — forms, dashboards, navigation, empty/loading/error, without reading all of `README.md`.
|
|
14
|
+
3. **Source repo:** `docs/components/nqui-<name>.md`
|
|
15
|
+
4. **After `init-skills`:** `.cursor/nqui-skills/components/nqui-<name>.md` (same files as npm `docs/components/`)
|
|
15
16
|
|
|
16
|
-
|
|
17
|
+
Avoid loading every component doc or the full `README.md` unless you need broad “when to use” tables.
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
## Where to read docs (pick by context)
|
|
19
20
|
|
|
20
|
-
| Context |
|
|
21
|
-
|
|
22
|
-
|
|
|
23
|
-
|
|
|
24
|
-
|
|
|
25
|
-
| Single on/off (Bold, Mute) | **Toggle** | - |
|
|
21
|
+
| Context | Path |
|
|
22
|
+
|---------|------|
|
|
23
|
+
| **This package** (nqui repo or monorepo `packages/nqui`) | `docs/components/README.md`, `docs/components/nqui-<name>.md` |
|
|
24
|
+
| **Consumer after init-skills** | `.cursor/nqui-skills/components/README.md` and `nqui-<name>.md` |
|
|
25
|
+
| **npm only** | `node_modules/@nqlib/nqui/docs/components/` |
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
Per-component files: `nqui-<kebab-case>.md` (e.g. `nqui-combobox.md`).
|
|
28
28
|
|
|
29
|
-
##
|
|
29
|
+
## Skill index (load by task)
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
| Task | Open |
|
|
32
|
+
|------|------|
|
|
33
|
+
| UI, layouts, ToggleGroup vs Radio, Card + ScrollArea | [nqui-components/SKILL.md](./nqui-components/SKILL.md) |
|
|
34
|
+
| Sizing, spacing, density, grouped controls, flex scroll | [nqui-design-system/SKILL.md](./nqui-design-system/SKILL.md) |
|
|
35
|
+
| Imports, FieldGroup, forms, composition, icons, styling | [nqui-shadcn/SKILL.md](./nqui-shadcn/SKILL.md) |
|
|
36
|
+
| Peers, externals, subpath imports | [nqui-bundle-size-best-practices/SKILL.md](./nqui-bundle-size-best-practices/SKILL.md) |
|
|
37
|
+
| `npm link` local nqui vs registry | [nqui-local-published-toggle/SKILL.md](./nqui-local-published-toggle/SKILL.md) |
|
|
38
|
+
| `init-css`, `install-peers`, CLI | [nqui-install/SKILL.md](./nqui-install/SKILL.md) |
|
|
32
39
|
|
|
33
|
-
|
|
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 |
|
|
40
|
+
## UX principles (cross-cutting)
|
|
38
41
|
|
|
39
|
-
**
|
|
42
|
+
- **Accessibility:** Use semantic components; **don’t** hide required instructions in **Tooltip** only (see `docs/components/nqui-tooltip.md`). Forms: `data-invalid` / `aria-invalid` per `nqui-shadcn/rules/forms.md`. Dialogs need titles (`nqui-shadcn` composition rules).
|
|
43
|
+
- **Touch / pointer:** Hover-only content is **supplemental**; **Tooltip** / **HoverCard** are poor for primary info on touch. Use **default/lg** size and optional **hit-area** on small targets in padded rows (`nqui-components/SKILL.md`).
|
|
44
|
+
- **States:** **Loading** → Skeleton / Spinner; **empty** → Empty; **error** → Field + Alert + validation patterns.
|
|
45
|
+
- **Focus:** After closing overlays, preserve sensible focus (Radix defaults — don’t override with stray `tabIndex`).
|
|
40
46
|
|
|
41
|
-
##
|
|
47
|
+
## Quick rules
|
|
42
48
|
|
|
43
|
-
|
|
49
|
+
- **Inline/toolbar selection** → `ToggleGroup` (see **RadioGroup** when form semantics matter — `nqui-components/SKILL.md`).
|
|
50
|
+
- **Card + scroll** → thread `min-h-0` through flex to `ScrollArea`; see design-system skill.
|
|
51
|
+
- **Forms** → `FieldGroup` + `Field`; see `nqui-shadcn` rules.
|
|
44
52
|
|
|
45
|
-
|
|
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
|
-
### FrostedGlass (sticky glass headers)
|
|
62
|
-
|
|
63
|
-
`FrostedGlass` is only the blur layer. Implementations need a **second row** with `bg-background/40`, `relative z-[var(--z-content)]`, and content that **scrolls behind** the sticky header. Full checklist, props, and troubleshooting: **`packages/nqui/docs/components/nqui-frosted-glass.md`**. Canonical page header: `AppLayout`; card: **Card** `stickyHeader`.
|
|
64
|
-
|
|
65
|
-
### Component Naming
|
|
66
|
-
- Default exports are the enhanced/polished variants; use **Core\*** for plain primitives
|
|
67
|
-
- Implementations are consolidated under **`ui/`** (not separate `custom/enhanced-*` per component for Button, Badge, Checkbox, Select, Combobox, Sonner)
|
|
68
|
-
- File names: kebab-case
|
|
69
|
-
- Component names: PascalCase
|
|
70
|
-
|
|
71
|
-
### Hit area (optional)
|
|
72
|
-
|
|
73
|
-
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.
|
|
74
|
-
|
|
75
|
-
## Key Dependencies
|
|
76
|
-
|
|
77
|
-
Required peer dependencies:
|
|
78
|
-
- `@hugeicons/react`
|
|
79
|
-
- `@hugeicons/core-free-icons`
|
|
80
|
-
|
|
81
|
-
Optional:
|
|
82
|
-
- `next-themes` - for theme toggle
|
|
83
|
-
- `tw-animate-css` - for animations
|
|
84
|
-
|
|
85
|
-
## Installation & Setup
|
|
86
|
-
|
|
87
|
-
```bash
|
|
88
|
-
# Quick setup
|
|
89
|
-
npx @nqlib/nqui init-css
|
|
90
|
-
|
|
91
|
-
# App setup with sidebar
|
|
92
|
-
npx @nqlib/nqui init-css --sidebar
|
|
93
|
-
|
|
94
|
-
# Install peer dependencies
|
|
95
|
-
npx @nqlib/nqui install-peers
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
## CSS Variables
|
|
99
|
-
|
|
100
|
-
All components use CSS variables. Key ones:
|
|
101
|
-
- `--background`, `--foreground`
|
|
102
|
-
- `--muted`, `--muted-foreground`
|
|
103
|
-
- `--accent`, `--accent-foreground`
|
|
104
|
-
- `--border`, `--ring`
|
|
105
|
-
- `--primary`, `--primary-foreground`
|
|
106
|
-
- `--destructive`, `--destructive-foreground`
|
|
53
|
+
Full table: [README.md](./README.md).
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: nqui-bundle-size-best-practices
|
|
3
|
+
description: Bundle size best practices for @nqlib/nqui. Use when adding dependencies, creating packages that depend on nqui, or optimizing build output.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# nqui Bundle Size Best Practices
|
|
7
|
+
|
|
8
|
+
Guidelines for keeping **@nqlib/nqui** bundles small and maintainable.
|
|
9
|
+
|
|
10
|
+
## Principle
|
|
11
|
+
|
|
12
|
+
Keep the main bundle small. Externalize heavy optional dependencies so consumers install only what they use.
|
|
13
|
+
|
|
14
|
+
## When Adding a Dependency
|
|
15
|
+
|
|
16
|
+
Before adding a dependency, ask:
|
|
17
|
+
|
|
18
|
+
1. **Is it heavy (>50KB)?** Large libs (motion, @dnd-kit, embla-carousel, etc.) bloat the bundle.
|
|
19
|
+
2. **Is it optional?** Only some components use it (e.g. Sortable uses @dnd-kit). If yes, add as optional peer + external in Vite.
|
|
20
|
+
|
|
21
|
+
If both answers are yes, externalize it.
|
|
22
|
+
|
|
23
|
+
## Externalization Checklist
|
|
24
|
+
|
|
25
|
+
1. Add to `vite.config.ts` (package root) → `rollupOptions.external`:
|
|
26
|
+
```ts
|
|
27
|
+
"package-name",
|
|
28
|
+
```
|
|
29
|
+
2. Add to `package.json`:
|
|
30
|
+
- `peerDependencies`: `"package-name": "^x.y.0"`
|
|
31
|
+
- `peerDependenciesMeta`: `"package-name": { "optional": true }`
|
|
32
|
+
3. Keep in `dependencies` if the nqui dev app (showcase, Storybook) needs it.
|
|
33
|
+
4. Document in `internal-notes/PEER_DEPENDENCIES.md` which component(s) require it.
|
|
34
|
+
|
|
35
|
+
## Avoid Bundling
|
|
36
|
+
|
|
37
|
+
Do not add large dependencies as regular dependencies when they are feature-specific:
|
|
38
|
+
|
|
39
|
+
- **Animations**: motion, framer-motion
|
|
40
|
+
- **Drag and drop**: @dnd-kit/*
|
|
41
|
+
- **Carousels**: embla-carousel-react
|
|
42
|
+
- **Tables**: @tanstack/react-table
|
|
43
|
+
- **Resizable panels**: react-resizable-panels
|
|
44
|
+
- **Combobox**: `cmdk` (optional peer, shared with Command)
|
|
45
|
+
- **Syntax highlighting**: shiki, @shikijs/transformers
|
|
46
|
+
- **Sandboxes**: @codesandbox/sandpack-react
|
|
47
|
+
- **Command palettes**: cmdk
|
|
48
|
+
- **Date pickers**: react-day-picker, date-fns
|
|
49
|
+
- **Toasts**: sonner
|
|
50
|
+
- **Drawers**: vaul
|
|
51
|
+
- **Icons**: @hugeicons/react, @hugeicons/core-free-icons
|
|
52
|
+
|
|
53
|
+
## Subpath Exports
|
|
54
|
+
|
|
55
|
+
Consumers can import from subpaths for smaller bundles when using only specific component groups:
|
|
56
|
+
|
|
57
|
+
- `@nqlib/nqui/code` — CodeBlock
|
|
58
|
+
- `@nqlib/nqui/carousel` — Carousel
|
|
59
|
+
- `@nqlib/nqui/command` — Command, CommandPalette
|
|
60
|
+
- `@nqlib/nqui/sortable` — Sortable
|
|
61
|
+
- `@nqlib/nqui/calendar` — Calendar
|
|
62
|
+
- `@nqlib/nqui/sonner` — Toaster, Sonner
|
|
63
|
+
- `@nqlib/nqui/drawer` — Drawer
|
|
64
|
+
|
|
65
|
+
See `internal-notes/PEER_DEPENDENCIES.md` for peer requirements per subpath.
|
|
66
|
+
|
|
67
|
+
## Reference
|
|
68
|
+
|
|
69
|
+
- **Component-to-peer mapping:** `internal-notes/PEER_DEPENDENCIES.md`
|
|
70
|
+
- **Installation notes:** `internal-notes/INSTALLATION.md` (Optional components section)
|
|
71
|
+
|
|
72
|
+
## Other libraries in a monorepo
|
|
73
|
+
|
|
74
|
+
Packages that wrap or extend nqui should follow the same pattern:
|
|
75
|
+
|
|
76
|
+
- `peerDependencies`: `react`, `react-dom`, `@nqlib/nqui` (or workspace version)
|
|
77
|
+
- In Vite library build: externalize `react`, `react-dom`, `@nqlib/nqui`
|
|
78
|
+
- Keep heavy optional deps as peers when consumers may not need them
|
|
@@ -0,0 +1,101 @@
|
|
|
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. ToggleGroup for inline/toolbar selection; RadioGroup when form semantics matter. Card + ScrollArea + flex min-h-0 scroll patterns.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# nqui Components
|
|
7
|
+
|
|
8
|
+
## Where to read docs (pick by context)
|
|
9
|
+
|
|
10
|
+
| Context | Path |
|
|
11
|
+
|---------|------|
|
|
12
|
+
| **This package** (nqui as its own repo, or `packages/nqui` in a monorepo) | `docs/components/README.md` and `docs/components/nqui-<name>.md` |
|
|
13
|
+
| **Consumer app** (npm install; see `files` in `@nqlib/nqui` `package.json`) | `node_modules/@nqlib/nqui/docs/components/README.md` and `node_modules/@nqlib/nqui/docs/components/nqui-<name>.md` |
|
|
14
|
+
| **Task-based entry (designers)** | `docs/nqui-skills/HUMAN_GUIDE.md` |
|
|
15
|
+
|
|
16
|
+
Per-component files: `nqui-<kebab-case>.md` (e.g. `nqui-combobox.md`).
|
|
17
|
+
|
|
18
|
+
## When to Load
|
|
19
|
+
|
|
20
|
+
- Implementing UI with nqui components
|
|
21
|
+
- Adding or modifying a component in this package
|
|
22
|
+
- Choosing the right component for a use case
|
|
23
|
+
- Debugging component behavior
|
|
24
|
+
|
|
25
|
+
## App Design Rule: Inline Selection → ToggleGroup
|
|
26
|
+
|
|
27
|
+
When designing **toolbars, headers, and inline controls** (not traditional stacked forms):
|
|
28
|
+
|
|
29
|
+
| Context | Use | NOT |
|
|
30
|
+
|---------|-----|-----|
|
|
31
|
+
| View mode (List/Grid/Table), scale (Linear/Log), size (S/M/L) | **ToggleGroup** `type="single"` | RadioGroup |
|
|
32
|
+
| Format toolbar (Bold/Italic/Underline), multi-toggle | **ToggleGroup** `type="multiple"` | Multiple Checkboxes |
|
|
33
|
+
| Toolbar actions (Undo/Redo, align) | **ButtonGroup** | — |
|
|
34
|
+
| Single on/off (Bold, Mute) | **Toggle** | — |
|
|
35
|
+
|
|
36
|
+
**Default rule:** Inline/toolbar selection = **ToggleGroup**.
|
|
37
|
+
|
|
38
|
+
## ToggleGroup vs RadioGroup (semantics & a11y)
|
|
39
|
+
|
|
40
|
+
| Situation | Prefer |
|
|
41
|
+
|-----------|--------|
|
|
42
|
+
| Toolbar, chart controls, editor chrome, **spatially inline** options | **ToggleGroup** — correct visual language; Radix exposes `role="group"` / toggle semantics as implemented |
|
|
43
|
+
| **Stacked or labeled form** “choose one” (settings page, wizard, survey), users expect **radiogroup** behavior | **RadioGroup** — screen readers get **radiogroup / radio** semantics (“1 of N”) |
|
|
44
|
+
| Unsure | If it reads like a **form field**, use **RadioGroup**. If it reads like a **toolbar or segmented control**, use **ToggleGroup**. |
|
|
45
|
+
|
|
46
|
+
Do not use RadioGroup inside dense toolbars for purely visual reasons if ToggleGroup fits the interaction — but do not force ToggleGroup for **form questionnaires** where radio semantics matter.
|
|
47
|
+
|
|
48
|
+
## App Design Rule: Context-First (Toolbar in Real Environment)
|
|
49
|
+
|
|
50
|
+
**Rule:** Never show Toggle/ToggleGroup/ButtonGroup in isolation. Always place them in realistic app context.
|
|
51
|
+
|
|
52
|
+
| Context | Layout | Reference |
|
|
53
|
+
|---------|--------|-----------|
|
|
54
|
+
| Document editor | Toolbar above content; `bg-muted/30` container; `Separator` between groups | ComponentShowcase → Toggle & ToggleGroup |
|
|
55
|
+
| Chart/settings | Label + inline controls; `rounded-lg border bg-muted/30 p-3` | ComponentShowcase → Chart settings |
|
|
56
|
+
| Standalone | Inline with related UI | ComponentShowcase → Standalone toggle |
|
|
57
|
+
|
|
58
|
+
**Canonical implementation:** `src/pages/ComponentShowcase.tsx` — Toggle & ToggleGroup section.
|
|
59
|
+
|
|
60
|
+
## Quick Reference
|
|
61
|
+
|
|
62
|
+
1. **Human task → component:** `docs/nqui-skills/HUMAN_GUIDE.md`
|
|
63
|
+
2. **Main index:** `README.md` under `docs/components/` — full tables, prerequisites, layout patterns
|
|
64
|
+
3. **Per-component:** `nqui-<name>.md` — import, examples, variants
|
|
65
|
+
4. **Design system:** `docs/nqui-skills/nqui-design-system/SKILL.md` — sizing, **Card + ScrollArea flex scroll contract**
|
|
66
|
+
|
|
67
|
+
**Cursor:** `npx @nqlib/nqui init-cursor` syncs from `docs/nqui-skills/`.
|
|
68
|
+
|
|
69
|
+
## Accessibility & touch (summary)
|
|
70
|
+
|
|
71
|
+
- **Focus:** After closing **Dialog** / **Sheet**, return focus to the trigger; don’t leave focus in the void (Radix helps — don’t fight it with extra `tabIndex`).
|
|
72
|
+
- **Keyboard:** Interactive components must be focusable and activatable without a mouse; see per-component docs and `nqui-shadcn` rules.
|
|
73
|
+
- **Touch:** Default control heights (h-6 / h-7 / h-8) align with dense desktop UI; for **touch-primary** surfaces, prefer **default/lg** and optional **`hit-area-*`** on small controls in padded rows (`nqui-checkbox.md`, `nqui-switch.md`).
|
|
74
|
+
- **Hover-only:** **Tooltip** / **HoverCard** are poor places for **required** information — no hover on touch. See `docs/components/nqui-tooltip.md`.
|
|
75
|
+
|
|
76
|
+
## Card + ScrollArea (do not overflow the card)
|
|
77
|
+
|
|
78
|
+
When building **Card** + **ScrollArea** (or any **scroll inside flex**):
|
|
79
|
+
|
|
80
|
+
- Read **`docs/nqui-skills/nqui-design-system/SKILL.md`** → section **Card + ScrollArea (flex scroll contract)**.
|
|
81
|
+
- **Always** thread **`min-h-0`** on flex children from the height constraint down to **ScrollArea**.
|
|
82
|
+
- Do **not** rely on **`overflow-hidden`** on the outer **Card** alone without a proper **flex** + **`min-h-0`** chain (Card defaults **`overflow-visible`** for popovers).
|
|
83
|
+
|
|
84
|
+
## Key Conventions
|
|
85
|
+
|
|
86
|
+
- React 18+ and 19 supported
|
|
87
|
+
- Control sizes: sm=h-6, default=h-7, lg=h-8
|
|
88
|
+
- Enhanced vs Core: default is enhanced; use Core* for plain
|
|
89
|
+
- Z-index: CSS vars from `src/styles/elevation.css` only
|
|
90
|
+
|
|
91
|
+
## FrostedGlass sticky headers
|
|
92
|
+
|
|
93
|
+
`FrostedGlass` is only the blur layer. Pair it with a **second row** (`bg-background/40`, `relative z-[var(--z-content)]`) and ensure **content scrolls behind** the sticky header. Full detail: `docs/components/nqui-frosted-glass.md`. References: `AppLayout`, **Card** `stickyHeader`.
|
|
94
|
+
|
|
95
|
+
## Hit area (optional pointer targets)
|
|
96
|
+
|
|
97
|
+
nqui ships [Bazza hit-area](https://bazza.dev/craft/2026/hit-area) utilities (`hit-area-4`, `hit-area-6`, axis variants, `hit-area-debug`). Use when a **small control sits in a padded cell or row** and you want taps in the padding to hit the control.
|
|
98
|
+
|
|
99
|
+
- Put utilities on the **same element** as **Checkbox** or **Switch** — not on a wrapper-only parent.
|
|
100
|
+
- **Opt-in** — dense toolbars can get overlapping targets if every control uses a large hit area.
|
|
101
|
+
- **Docs:** `docs/components/nqui-checkbox.md`, `nqui-switch.md`; examples: `src/pages/ComponentShowcase.tsx`.
|
|
@@ -1,21 +1,21 @@
|
|
|
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
|
|
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).
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# nqui Design System
|
|
7
7
|
|
|
8
|
-
Guidelines for AI agents implementing or modifying nqui components. Follow these rules to maintain visual consistency.
|
|
8
|
+
Guidelines for AI agents and developers implementing or modifying nqui components. Follow these rules to maintain visual consistency.
|
|
9
9
|
|
|
10
10
|
## Control Size Scale
|
|
11
11
|
|
|
12
12
|
All interactive controls (buttons, toggles, inputs, selects) use a unified scale:
|
|
13
13
|
|
|
14
|
-
| Size
|
|
15
|
-
|
|
16
|
-
| `sm`
|
|
17
|
-
| `default
|
|
18
|
-
| `lg`
|
|
14
|
+
| Size | Height | Min Width | Use Case |
|
|
15
|
+
|------|--------|-----------|----------|
|
|
16
|
+
| `sm` | h-6 (24px) | min-w-6 | Compact UIs, dense tables, toolbars |
|
|
17
|
+
| `default` | h-7 (28px) | min-w-7 | Standard forms, primary actions |
|
|
18
|
+
| `lg` | h-8 (32px) | min-w-8 | Emphasis, secondary actions |
|
|
19
19
|
|
|
20
20
|
### Semantic Rule
|
|
21
21
|
|
|
@@ -85,7 +85,7 @@ Font: `--font-sans` (Inter Variable). Leading: `leading-normal` or `text-xs/rela
|
|
|
85
85
|
- **Child borders** – Items: `border-0` (container provides the border)
|
|
86
86
|
- **Dividers** – ToggleGroup: item borders (`border-foreground/20`) between items. Or `ToggleGroupSeparator` when `separator={false}`.
|
|
87
87
|
- **Corners** – First item: rounded-l (or rounded-t vertical), last: rounded-r (or rounded-b)
|
|
88
|
-
- **Several groups on one horizontal row** – `ButtonGroup`’s container is
|
|
88
|
+
- **Several groups on one horizontal row** – `ButtonGroup`’s container is `inline-flex`, so multiple sibling groups behave like inline boxes and align to **baseline**. Mixed content (labels vs icons vs `ButtonGroupText`) then looks vertically inconsistent. Prefer **`flex flex-wrap items-center gap-*`** or **grid** so you control cross-axis alignment (`items-center`, `items-end`) instead of baseline alignment.
|
|
89
89
|
|
|
90
90
|
## Toggle & ToggleGroup Visual Treatment (Visibility on Any Background)
|
|
91
91
|
|
|
@@ -94,7 +94,7 @@ Toggles and ToggleGroup items must remain visible on card, sidebar, and varied b
|
|
|
94
94
|
| State | Default/Outline | Segmented (single select) |
|
|
95
95
|
|-------|-----------------|---------------------------|
|
|
96
96
|
| **Off** | `border border-input/60` (or `border-input`), `shadow-sm`, `bg-background/50` (or transparent) | Transparent |
|
|
97
|
-
| **On** | `bg-secondary` + `nqui-button-gradient` + `nqui-button-shadow`
|
|
97
|
+
| **On** | `bg-secondary` + `nqui-button-gradient` + `nqui-button-shadow` | `bg-primary` + gradient + shadow |
|
|
98
98
|
| **Active (pressed)** | `active:shadow-[inset_0_3px_5px_rgba(0,0,0,0.125)]` | Same |
|
|
99
99
|
|
|
100
100
|
Never use flat `bg-muted` only for selected state; always add gradient + shadow for depth and visibility.
|
|
@@ -103,21 +103,49 @@ Never use flat `bg-muted` only for selected state; always add gradient + shadow
|
|
|
103
103
|
|
|
104
104
|
## Toolbar & In-Context Design
|
|
105
105
|
|
|
106
|
-
**Rule:** Show controls in realistic app context, not isolated. Reference: `
|
|
106
|
+
**Rule:** Show controls in realistic app context, not isolated. Reference: `src/pages/ComponentShowcase.tsx` (Toggle & ToggleGroup section).
|
|
107
107
|
|
|
108
108
|
| Context | Layout | Example |
|
|
109
109
|
|---------|--------|---------|
|
|
110
|
-
| Document editor | Toolbar above content
|
|
111
|
-
| Chart/settings panel | Label + inline controls, `rounded-lg border bg-muted/30 p-3` | Y-axis
|
|
112
|
-
| Standalone | Inline with related UI
|
|
110
|
+
| Document editor | Toolbar above content, `bg-muted/30`, `Separator` between groups | Bold / Italic / Underline; align left / center / right |
|
|
111
|
+
| Chart/settings panel | Label + inline controls, `rounded-lg border bg-muted/30 p-3` | Y-axis Linear/Log; size S/M/L |
|
|
112
|
+
| Standalone | Inline with related UI | Pin, Mute, single Toggle |
|
|
113
113
|
|
|
114
114
|
## Bounded content (default UX)
|
|
115
115
|
|
|
116
|
-
- **Rule:** Interactive surfaces should not **visually bleed** outside their box: prefer **ellipsis** (`truncate`), **line-clamp**, **controlled scroll**, or **wrapping**
|
|
117
|
-
- **Not universal:** Portals (dropdowns, popovers), **tooltips**, and **drag overlays** intentionally escape bounds. **Data tables** may use horizontal scroll.
|
|
118
|
-
- **Flex gotcha:** `inline-flex` + icon + `whitespace-nowrap` + raw
|
|
119
|
-
- **Built-in helpers in nqui:** Shared `wrapInlineLabelTextNodes` + `min-w-0 max-w-full` on **Button**, **Toggle**, **TabsTrigger**, **Badge**, **ComboboxChip**; **SelectTrigger** uses
|
|
120
|
-
- **Card:** **Card** uses **`min-w-0`** on shell + header/content/footer for flex/grid safety but keeps **`overflow-visible`** so overlays aren’t clipped; don’t rely on **`overflow-hidden`** on Card as a global
|
|
116
|
+
- **Rule:** Interactive surfaces should not **visually bleed** outside their box: prefer **ellipsis** (`truncate`), **line-clamp**, **controlled scroll**, or **wrapping** instead of letting text or icons paint past padding in narrow layouts.
|
|
117
|
+
- **Not universal:** Portals (dropdowns, popovers), **tooltips**, and **drag overlays** intentionally escape bounds. **Data tables** may use horizontal scroll.
|
|
118
|
+
- **Flex gotcha:** `inline-flex` + icon + `whitespace-nowrap` + raw string children keeps implicit **min-width: min-content**; parents need **`min-w-0`** (and often **`max-w-full`**) on the control and a truncating inner wrapper for long labels.
|
|
119
|
+
- **Built-in helpers in nqui:** Shared `wrapInlineLabelTextNodes` + `min-w-0 max-w-full` on **Button**, **Toggle**, **TabsTrigger**, **Badge**, **ComboboxChip**; **SelectTrigger** uses `min-w-0 max-w-full` and `min-w-0` on the value slot with `line-clamp-1`. **Carousel** prev/next sit **inside** the carousel box so they don’t spill out of **Card** (override via `className` if you want outside arrows).
|
|
120
|
+
- **Card:** **Card** uses **`min-w-0`** on shell + header/content/footer for flex/grid safety but keeps **`overflow-visible`** so overlays aren’t clipped; don’t rely on **`overflow-hidden`** on Card as a global catch-all unless you accept clipping dropdowns/focus.
|
|
121
|
+
|
|
122
|
+
## Card + ScrollArea (flex scroll contract)
|
|
123
|
+
|
|
124
|
+
**Symptom:** Content inside **Card** + **ScrollArea** overflows the card, ignores rounded corners, or **does not scroll** until someone adds `min-h-0` up the tree.
|
|
125
|
+
|
|
126
|
+
**Cause:** Flex items default to **`min-height: auto`**: they won’t shrink below content height, so the scroll region never gets a bounded height → **no scrollport**. Normal CSS, not a ScrollArea bug.
|
|
127
|
+
|
|
128
|
+
**Rules (every time you nest scrollable content in flex):**
|
|
129
|
+
|
|
130
|
+
1. **Height chain:** From the page shell down to **ScrollArea**, every flex child that must shrink needs **`min-h-0`** (often with **`flex-1`** or **`flex-shrink`**).
|
|
131
|
+
2. **Card root:** Keeps **`overflow-visible`** on purpose (dropdowns, popovers, focus rings). Do **not** use **`overflow-hidden`** on the outer **Card** alone as your only scroll fix — establish a **nested** scroll box.
|
|
132
|
+
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
|
+
4. **Parent must constrain height:** e.g. `h-full`, `min-h-0`, or explicit `max-h-*` / `h-[...]`; otherwise “100%” has no reference.
|
|
134
|
+
|
|
135
|
+
**Reference implementations:** `Card` + **`stickyHeader`** in `src/components/ui/card.tsx`; `src/pages/ComponentShowcase.tsx` where ScrollArea sits in a bounded layout.
|
|
136
|
+
|
|
137
|
+
**Checklist before merging a scrollable card:**
|
|
138
|
+
|
|
139
|
+
- [ ] Flex column from page → card includes **`min-h-0`** where the tree shrinks.
|
|
140
|
+
- [ ] Card column is **`flex flex-col min-h-0`** (and **`h-full`** if filling a panel).
|
|
141
|
+
- [ ] Scroll wrapper: **`flex-1 min-h-0 overflow-hidden`**.
|
|
142
|
+
- [ ] **ScrollArea** has **`min-h-0`** and fills the wrapper (**`h-full`** / **`flex-1`**).
|
|
143
|
+
|
|
144
|
+
## Density & visual hierarchy (product feel)
|
|
145
|
+
|
|
146
|
+
- **Density:** `size="sm"` and compact patterns (tables, sidebars) read as **dense**; default/lg and generous spacing read as **comfortable**. Don’t mix ad-hoc heights — use the **size scale** so density stays intentional.
|
|
147
|
+
- **Task priority:** One **primary** action per surface (full-color / high contrast). Secondary actions use **outline** / **secondary**; **tertiary** use **ghost** / muted text. Avoid multiple competing primaries.
|
|
148
|
+
- **Muted vs foreground:** Use **`text-muted-foreground`** for supporting labels, **`text-foreground`** for primary reading. Don’t gray out text that must be understood to complete a task.
|
|
121
149
|
|
|
122
150
|
## Customization
|
|
123
151
|
|
|
@@ -127,16 +155,16 @@ Never use flat `bg-muted` only for selected state; always add gradient + shadow
|
|
|
127
155
|
|
|
128
156
|
## Hit area utilities
|
|
129
157
|
|
|
130
|
-
**Hit area** expands the pointer target; it does **not** replace
|
|
158
|
+
**Hit area** expands the pointer target; it does **not** replace the **size** scale. Use **opt-in** on **Checkbox** / **Switch** in padded rows—not globally. See `docs/nqui-skills/nqui-components/SKILL.md` and `docs/components/nqui-checkbox.md` / `nqui-switch.md`.
|
|
131
159
|
|
|
132
160
|
## Files to Check for Consistency
|
|
133
161
|
|
|
134
|
-
- `
|
|
135
|
-
- `
|
|
136
|
-
- `
|
|
137
|
-
- `
|
|
138
|
-
- `
|
|
139
|
-
- `
|
|
162
|
+
- `src/components/ui/button.tsx`
|
|
163
|
+
- `src/components/ui/toggle.tsx`
|
|
164
|
+
- `src/components/ui/toggle-group.tsx`
|
|
165
|
+
- `src/components/ui/input.tsx`
|
|
166
|
+
- `src/components/ui/select.tsx`
|
|
167
|
+
- `src/components/ui/combobox.tsx`
|
|
140
168
|
|
|
141
169
|
## Anti-Patterns
|
|
142
170
|
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: nqui-install
|
|
3
|
+
description: Install and setup @nqlib/nqui. Use when the user wants to install nqui, set up a project, fix missing peers, or run setup commands. Execute these commands in the consumer project root.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# nqui Install & Setup
|
|
7
|
+
|
|
8
|
+
**When to load:** User asks to install nqui, set up a new project, fix "module not found" or missing peer deps, or run setup.
|
|
9
|
+
|
|
10
|
+
**Action:** Run the relevant command(s) below in the **consumer project root**, in order when doing full setup.
|
|
11
|
+
|
|
12
|
+
## 1. Install nqui + peers
|
|
13
|
+
|
|
14
|
+
**Minimal (icons only):**
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pnpm add @nqlib/nqui @hugeicons/react @hugeicons/core-free-icons
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
(npm: `npm install @nqlib/nqui @hugeicons/react @hugeicons/core-free-icons`)
|
|
21
|
+
|
|
22
|
+
**Full (all optional components):**
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npx @nqlib/nqui install-peers
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Or manually:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
pnpm add @nqlib/nqui @hugeicons/react @hugeicons/core-free-icons cmdk @dnd-kit/core @dnd-kit/modifiers @dnd-kit/sortable @dnd-kit/utilities embla-carousel-react @tanstack/react-table react-day-picker date-fns sonner vaul react-resizable-panels
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## 2. Setup CSS (required)
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npx @nqlib/nqui init-css
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Then add to main CSS (`app/globals.css` or `src/index.css`): `@import "@nqlib/nqui/styles";`
|
|
41
|
+
|
|
42
|
+
Or copy contents of `nqui/nqui-setup.css` to the top of main CSS.
|
|
43
|
+
|
|
44
|
+
## 3. Cursor skills (optional)
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
npx @nqlib/nqui init-cursor
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Copies `docs/nqui-skills` to `.cursor/nqui-skills/`, copies **`docs/components`** to **`.cursor/nqui-skills/components/`**, and may add rules. For skills only:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
npx @nqlib/nqui init-skills
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Use **`HUMAN_GUIDE.md`** for task-based wayfinding; **`COMPONENTS_INDEX.md`** to pick **one** `nqui-*.md` at a time (saves tokens).
|
|
57
|
+
|
|
58
|
+
## File locations (after install)
|
|
59
|
+
|
|
60
|
+
- Task → docs: `node_modules/@nqlib/nqui/docs/nqui-skills/HUMAN_GUIDE.md`
|
|
61
|
+
- Docs index: `node_modules/@nqlib/nqui/docs/components/README.md`
|
|
62
|
+
- Per component: `node_modules/@nqlib/nqui/docs/components/nqui-<name>.md`
|
|
63
|
+
- Skills (source in repo): `docs/nqui-skills/` inside the package
|
|
64
|
+
- Check setup: `npx nqui-setup` (or `npx @nqlib/nqui setup`)
|
|
65
|
+
|