@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
|
@@ -1,36 +1,36 @@
|
|
|
1
1
|
import { jsx as a } from "react/jsx-runtime";
|
|
2
|
-
import * as
|
|
2
|
+
import * as c from "react";
|
|
3
3
|
import { Toaster as T } from "sonner";
|
|
4
|
-
import { HugeiconsIcon as
|
|
4
|
+
import { HugeiconsIcon as i } from "@hugeicons/react";
|
|
5
5
|
import { Loading03Icon as S, MultiplicationSignCircleIcon as I, Alert02Icon as E, InformationCircleIcon as C, CheckmarkCircle02Icon as N } from "@hugeicons/core-free-icons";
|
|
6
|
-
var z = (t, n,
|
|
6
|
+
var z = (t, n, s, l, d, r, u, f) => {
|
|
7
7
|
let e = document.documentElement, g = ["light", "dark"];
|
|
8
|
-
function
|
|
9
|
-
(Array.isArray(t) ? t : [t]).forEach((
|
|
10
|
-
let v =
|
|
11
|
-
v ? (e.classList.remove(...
|
|
8
|
+
function m(o) {
|
|
9
|
+
(Array.isArray(t) ? t : [t]).forEach((p) => {
|
|
10
|
+
let v = p === "class", y = v && r ? d.map((x) => r[x] || x) : d;
|
|
11
|
+
v ? (e.classList.remove(...y), e.classList.add(r && r[o] ? r[o] : o)) : e.setAttribute(p, o);
|
|
12
12
|
}), w(o);
|
|
13
13
|
}
|
|
14
14
|
function w(o) {
|
|
15
15
|
f && g.includes(o) && (e.style.colorScheme = o);
|
|
16
16
|
}
|
|
17
|
-
function
|
|
17
|
+
function k() {
|
|
18
18
|
return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
|
19
19
|
}
|
|
20
|
-
if (
|
|
20
|
+
if (l) m(l);
|
|
21
21
|
else try {
|
|
22
|
-
let o = localStorage.getItem(n) ||
|
|
23
|
-
|
|
22
|
+
let o = localStorage.getItem(n) || s, p = u && o === "system" ? k() : o;
|
|
23
|
+
m(p);
|
|
24
24
|
} catch {
|
|
25
25
|
}
|
|
26
|
-
}, W =
|
|
26
|
+
}, W = c.createContext(void 0), A = { setTheme: (t) => {
|
|
27
27
|
}, themes: [] }, L = () => {
|
|
28
28
|
var t;
|
|
29
|
-
return (t =
|
|
29
|
+
return (t = c.useContext(W)) != null ? t : A;
|
|
30
30
|
};
|
|
31
|
-
|
|
32
|
-
let
|
|
33
|
-
return
|
|
31
|
+
c.memo(({ forcedTheme: t, storageKey: n, attribute: s, enableSystem: l, enableColorScheme: d, defaultTheme: r, value: u, themes: f, nonce: e, scriptProps: g }) => {
|
|
32
|
+
let m = JSON.stringify([s, n, r, t, f, u, l, d]).slice(1, -1);
|
|
33
|
+
return c.createElement("script", { ...g, suppressHydrationWarning: !0, nonce: typeof window > "u" ? e : "", dangerouslySetInnerHTML: { __html: `(${z.toString()})(${m})` } });
|
|
34
34
|
});
|
|
35
35
|
const b = "nqui-toast-styles-v2";
|
|
36
36
|
function M() {
|
|
@@ -86,17 +86,17 @@ function M() {
|
|
|
86
86
|
`, document.head.appendChild(t);
|
|
87
87
|
}
|
|
88
88
|
const h = ({ ...t }) => {
|
|
89
|
-
const { theme: n = "
|
|
90
|
-
return
|
|
89
|
+
const { theme: n = "light" } = L(), s = n === "dark" ? "dark" : "light";
|
|
90
|
+
return c.useEffect(() => {
|
|
91
91
|
M();
|
|
92
92
|
}, []), /* @__PURE__ */ a(
|
|
93
93
|
T,
|
|
94
94
|
{
|
|
95
|
-
theme:
|
|
95
|
+
theme: s,
|
|
96
96
|
className: "toaster group",
|
|
97
97
|
icons: {
|
|
98
98
|
success: /* @__PURE__ */ a(
|
|
99
|
-
|
|
99
|
+
i,
|
|
100
100
|
{
|
|
101
101
|
icon: N,
|
|
102
102
|
strokeWidth: 2,
|
|
@@ -104,7 +104,7 @@ const h = ({ ...t }) => {
|
|
|
104
104
|
}
|
|
105
105
|
),
|
|
106
106
|
info: /* @__PURE__ */ a(
|
|
107
|
-
|
|
107
|
+
i,
|
|
108
108
|
{
|
|
109
109
|
icon: C,
|
|
110
110
|
strokeWidth: 2,
|
|
@@ -112,7 +112,7 @@ const h = ({ ...t }) => {
|
|
|
112
112
|
}
|
|
113
113
|
),
|
|
114
114
|
warning: /* @__PURE__ */ a(
|
|
115
|
-
|
|
115
|
+
i,
|
|
116
116
|
{
|
|
117
117
|
icon: E,
|
|
118
118
|
strokeWidth: 2,
|
|
@@ -120,7 +120,7 @@ const h = ({ ...t }) => {
|
|
|
120
120
|
}
|
|
121
121
|
),
|
|
122
122
|
error: /* @__PURE__ */ a(
|
|
123
|
-
|
|
123
|
+
i,
|
|
124
124
|
{
|
|
125
125
|
icon: I,
|
|
126
126
|
strokeWidth: 2,
|
|
@@ -128,7 +128,7 @@ const h = ({ ...t }) => {
|
|
|
128
128
|
}
|
|
129
129
|
),
|
|
130
130
|
loading: /* @__PURE__ */ a(
|
|
131
|
-
|
|
131
|
+
i,
|
|
132
132
|
{
|
|
133
133
|
icon: S,
|
|
134
134
|
strokeWidth: 2,
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";const c=require("react/jsx-runtime"),T=require("react"),j=require("sonner"),i=require("@hugeicons/react"),l=require("@hugeicons/core-free-icons");function E(t){const r=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(t){for(const o in t)if(o!=="default"){const n=Object.getOwnPropertyDescriptor(t,o);Object.defineProperty(r,o,n.get?n:{enumerable:!0,get:()=>t[o]})}}return r.default=t,Object.freeze(r)}const d=E(T);var N=(t,r,o,n,u,a,f,h)=>{let s=document.documentElement,x=["light","dark"];function m(e){(Array.isArray(t)?t:[t]).forEach(g=>{let v=g==="class",S=v&&a?u.map(b=>a[b]||b):u;v?(s.classList.remove(...S),s.classList.add(a&&a[e]?a[e]:e)):s.setAttribute(g,e)}),y(e)}function y(e){h&&x.includes(e)&&(s.style.colorScheme=e)}function I(){return window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"}if(n)m(n);else try{let e=localStorage.getItem(r)||o,g=f&&e==="system"?I():e;m(g)}catch{}},C=d.createContext(void 0),O={setTheme:t=>{},themes:[]},k=()=>{var t;return(t=d.useContext(C))!=null?t:O};d.memo(({forcedTheme:t,storageKey:r,attribute:o,enableSystem:n,enableColorScheme:u,defaultTheme:a,value:f,themes:h,nonce:s,scriptProps:x})=>{let m=JSON.stringify([o,r,a,t,h,f,n,u]).slice(1,-1);return d.createElement("script",{...x,suppressHydrationWarning:!0,nonce:typeof window>"u"?s:"",dangerouslySetInnerHTML:{__html:`(${N.toString()})(${m})`}})});const w="nqui-toast-styles-v2";function z(){if(typeof document>"u"||document.getElementById(w))return;const t=document.createElement("style");t.id=w,t.textContent=`
|
|
2
|
+
/* Pill toast — inverted surface: dark-on-light app, light-on-dark app */
|
|
3
|
+
[data-sonner-toast] .cn-toast {
|
|
4
|
+
border: 1px solid color-mix(in oklch, var(--normal-text) 18%, transparent) !important;
|
|
5
|
+
border-radius: 9999px !important;
|
|
6
|
+
box-shadow:
|
|
7
|
+
0 1px 0 0 color-mix(in oklch, var(--normal-text) 12%, transparent),
|
|
8
|
+
0 1px 2px 0 oklch(0.15 0 0 / 0.08);
|
|
9
|
+
transition: all 200ms ease-in-out !important;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.dark [data-sonner-toast] .cn-toast {
|
|
13
|
+
box-shadow:
|
|
14
|
+
0 1px 0 0 color-mix(in oklch, var(--normal-text) 14%, transparent),
|
|
15
|
+
0 1px 2px 0 oklch(0.15 0 0 / 0.12);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
[data-sonner-toast] .cn-toast.toast-success {
|
|
19
|
+
border-left-width: 3px !important;
|
|
20
|
+
border-left-color: var(--success-500) !important;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
[data-sonner-toast] .cn-toast.toast-error {
|
|
24
|
+
border-left-width: 3px !important;
|
|
25
|
+
border-left-color: var(--danger-500) !important;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
[data-sonner-toast] .cn-toast.toast-warning {
|
|
29
|
+
border-left-width: 3px !important;
|
|
30
|
+
border-left-color: var(--warning-500) !important;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
[data-sonner-toast] .cn-toast.toast-info {
|
|
34
|
+
border-left-width: 3px !important;
|
|
35
|
+
border-left-color: var(--info-500) !important;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
[data-sonner-toast] .cn-toast.toast-loading {
|
|
39
|
+
border-left-width: 3px !important;
|
|
40
|
+
border-left-color: var(--primary-500) !important;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.cn-toast .toast-icon-success { color: var(--success); }
|
|
44
|
+
.cn-toast .toast-icon-error { color: var(--destructive); }
|
|
45
|
+
.cn-toast .toast-icon-warning { color: var(--warning); }
|
|
46
|
+
.cn-toast .toast-icon-info { color: var(--info); }
|
|
47
|
+
.cn-toast .toast-icon-loading { color: var(--primary); }
|
|
48
|
+
`,document.head.appendChild(t)}const p=({...t})=>{const{theme:r="light"}=k(),o=r==="dark"?"dark":"light";return d.useEffect(()=>{z()},[]),c.jsx(j.Toaster,{theme:o,className:"toaster group",icons:{success:c.jsx(i.HugeiconsIcon,{icon:l.CheckmarkCircle02Icon,strokeWidth:2,className:"size-4 text-success toast-icon-success"}),info:c.jsx(i.HugeiconsIcon,{icon:l.InformationCircleIcon,strokeWidth:2,className:"size-4 text-info toast-icon-info"}),warning:c.jsx(i.HugeiconsIcon,{icon:l.Alert02Icon,strokeWidth:2,className:"size-4 text-warning toast-icon-warning"}),error:c.jsx(i.HugeiconsIcon,{icon:l.MultiplicationSignCircleIcon,strokeWidth:2,className:"size-4 text-destructive toast-icon-error"}),loading:c.jsx(i.HugeiconsIcon,{icon:l.Loading03Icon,strokeWidth:2,className:"size-4 text-primary toast-icon-loading animate-spin"})},style:{"--normal-bg":"var(--foreground)","--normal-text":"var(--background)","--normal-border":"color-mix(in oklch, var(--background) 25%, transparent)","--border-radius":"9999px","--success-bg":"var(--success)","--success-text":"var(--success-foreground)","--success-border":"var(--success-400)","--error-bg":"var(--destructive)","--error-text":"var(--destructive-foreground)","--error-border":"var(--danger-400)","--warning-bg":"var(--warning)","--warning-text":"var(--warning-foreground)","--warning-border":"var(--warning-400)","--info-bg":"var(--info)","--info-text":"var(--info-foreground)","--info-border":"var(--info-400)"},toastOptions:{classNames:{toast:"cn-toast",success:"toast-success",error:"toast-error",warning:"toast-warning",info:"toast-info",loading:"toast-loading"}},...t})};p.displayName="Toaster";const H=p,_=p;exports.EnhancedSonner=_;exports.EnhancedToaster=H;exports.Toaster=p;exports.z=k;
|
package/dist/sonner.cjs.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./sonner-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./sonner-CP8np0BP.cjs");exports.CoreToaster=e.Toaster;exports.EnhancedSonner=e.EnhancedSonner;exports.EnhancedToaster=e.EnhancedToaster;exports.Toaster=e.Toaster;
|
package/dist/sonner.es.js
CHANGED
package/dist/styles.css
CHANGED
|
@@ -37,13 +37,13 @@
|
|
|
37
37
|
@source inline("border border-primary border-secondary border-destructive border-success border-warning border-info border-border border-input border-ring rounded-md rounded-lg rounded-full");
|
|
38
38
|
|
|
39
39
|
/* Background color utilities */
|
|
40
|
-
@source inline("bg-primary bg-secondary bg-destructive bg-success bg-warning bg-info bg-background bg-accent bg-transparent bg-none bg-muted bg-input bg-input/20 dark:bg-input/30
|
|
40
|
+
@source inline("bg-primary bg-secondary bg-destructive bg-success bg-warning bg-info bg-background bg-accent bg-transparent bg-none bg-muted bg-input bg-input/20 dark:bg-input/30 light:bg-input/30");
|
|
41
41
|
|
|
42
42
|
/* Text color utilities */
|
|
43
43
|
@source inline("text-primary-foreground text-secondary-foreground text-destructive-foreground text-success-foreground text-warning-foreground text-info-foreground text-accent-foreground text-muted-foreground text-foreground");
|
|
44
44
|
|
|
45
45
|
/* Hover state utilities */
|
|
46
|
-
@source inline("hover:opacity-100 hover:bg-primary/90 hover:bg-secondary/90 hover:bg-destructive/90 hover:bg-success/90 hover:bg-warning/90 hover:bg-info/90 hover:bg-accent hover:bg-muted hover:border-primary/90 hover:border-secondary/90 hover:border-destructive/90 hover:border-success/90 hover:border-warning/90 hover:border-info/90 hover:border-border hover:text-accent-foreground hover:text-muted-foreground hover:underline dark:hover:bg-muted/50
|
|
46
|
+
@source inline("hover:opacity-100 hover:bg-primary/90 hover:bg-secondary/90 hover:bg-destructive/90 hover:bg-success/90 hover:bg-warning/90 hover:bg-info/90 hover:bg-accent hover:bg-muted hover:border-primary/90 hover:border-secondary/90 hover:border-destructive/90 hover:border-success/90 hover:border-warning/90 hover:border-info/90 hover:border-border hover:text-accent-foreground hover:text-muted-foreground hover:underline dark:hover:bg-muted/50 light:hover:bg-muted/50");
|
|
47
47
|
|
|
48
48
|
/* Focus state utilities */
|
|
49
49
|
@source inline("focus:bg-primary/80 focus:bg-secondary/80 focus:bg-destructive/80 focus:bg-success/80 focus:bg-warning/80 focus:bg-info/80 focus:border-primary/80 focus:border-secondary/80 focus:border-destructive/80 focus:border-success/80 focus:border-warning/80 focus:border-info/80 focus:border-border focus:outline-0 focus-visible:outline-0 focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]");
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
@source inline("[&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 [&>svg]:size-2.5");
|
|
65
65
|
|
|
66
66
|
/* Group & State utilities */
|
|
67
|
-
@source inline("group/badge has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40
|
|
67
|
+
@source inline("group/badge has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 light:aria-invalid:ring-destructive/40 aria-invalid:border-destructive");
|
|
68
68
|
|
|
69
69
|
/* Z-index elevation utilities */
|
|
70
70
|
@source inline("z-[var(--z-debug)] z-[var(--z-sticky-page)] z-[var(--z-background)] z-[var(--z-content)] z-[var(--z-popover)] z-[var(--z-modal-backdrop)] z-[var(--z-modal)] z-[var(--z-tooltip)] z-[var(--z-sticky-content)] z-[var(--z-floating)]");
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
|
|
76
76
|
|
|
77
77
|
/* Custom dark mode variant - matches when .dark class is on element or ancestor */
|
|
78
|
-
/*
|
|
78
|
+
/* Non-dark themes — .light (warm paper) and .mid (dimmer neutral); both use light: utilities */
|
|
79
79
|
/* Hit-area — https://bazza.dev/craft/2026/hit-area */
|
|
80
80
|
/* Bazza hit-area utilities — https://bazza.dev/craft/2026/hit-area */
|
|
81
81
|
|
|
@@ -784,10 +784,14 @@
|
|
|
784
784
|
nqui Additional System Variables
|
|
785
785
|
============================================ */
|
|
786
786
|
|
|
787
|
-
/*
|
|
787
|
+
/*
|
|
788
|
+
* Non-dark surfaces: /* ============================================
|
|
788
789
|
nqui Color System & Design Tokens
|
|
789
790
|
============================================ */
|
|
790
791
|
|
|
792
|
+
:root + html.light = warm paper; html.mid = separate token block (showcase / comparison).
|
|
793
|
+
* Dark = .dark. Showcase app uses next-themes classes light | mid | dark.
|
|
794
|
+
*/
|
|
791
795
|
:root {
|
|
792
796
|
/* ============================================
|
|
793
797
|
Z-Index Elevation Scale
|
|
@@ -948,21 +952,16 @@
|
|
|
948
952
|
--z-debug: 9999;
|
|
949
953
|
|
|
950
954
|
/* Color system variables from colors.css */
|
|
951
|
-
/*
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
--primary-
|
|
958
|
-
--primary-200: oklch(0.90 0.10 240);
|
|
959
|
-
--primary-300: oklch(0.85 0.12 240);
|
|
960
|
-
--primary-400: oklch(0.80 0.14 240);
|
|
961
|
-
--primary-500: oklch(0.60 0.25 240); /* Main primary - darker for light mode */
|
|
962
|
-
--primary-600: oklch(0.50 0.28 240);
|
|
955
|
+
/* Primary scale — midpoint between classic light and dark (blue hue 240) */
|
|
956
|
+
--primary-100: oklch(0.675 0.115 240);
|
|
957
|
+
--primary-200: oklch(0.675 0.14 240);
|
|
958
|
+
--primary-300: oklch(0.675 0.16 240);
|
|
959
|
+
--primary-400: oklch(0.675 0.18 240);
|
|
960
|
+
--primary-500: oklch(0.625 0.225 240);
|
|
961
|
+
--primary-600: oklch(0.6 0.25 240);
|
|
963
962
|
|
|
964
963
|
/* ============================================
|
|
965
|
-
Semantic Color Scales
|
|
964
|
+
Semantic Color Scales — classic light (success / warning / danger / info)
|
|
966
965
|
============================================ */
|
|
967
966
|
|
|
968
967
|
/* Success Color Scale (Light Mode) - Green (Hue 142) */
|
|
@@ -998,16 +997,14 @@
|
|
|
998
997
|
--info-600: oklch(0.50 0.18 200);
|
|
999
998
|
|
|
1000
999
|
/* ============================================
|
|
1001
|
-
System Color Mappings
|
|
1000
|
+
System Color Mappings — system default uses primary scale + light semantic scales
|
|
1002
1001
|
============================================ */
|
|
1003
1002
|
|
|
1004
|
-
/* Primary Colors - Mapped to color scales */
|
|
1005
1003
|
--primary: var(--primary-500);
|
|
1006
|
-
--primary-foreground: oklch(0.98 0 0);
|
|
1004
|
+
--primary-foreground: oklch(0.98 0 0);
|
|
1007
1005
|
--primary-hover: var(--primary-400);
|
|
1008
|
-
--ring: var(--primary-500);
|
|
1006
|
+
--ring: var(--primary-500);
|
|
1009
1007
|
|
|
1010
|
-
/* Semantic Colors - Mapped to color scales */
|
|
1011
1008
|
--success: var(--success-500);
|
|
1012
1009
|
--success-foreground: oklch(0.98 0 0);
|
|
1013
1010
|
|
|
@@ -1021,21 +1018,21 @@
|
|
|
1021
1018
|
--info-foreground: oklch(0.98 0 0);
|
|
1022
1019
|
|
|
1023
1020
|
/* Additional variables from index.css */
|
|
1024
|
-
/*
|
|
1025
|
-
--background: oklch(
|
|
1026
|
-
--foreground: oklch(0.
|
|
1027
|
-
--card: oklch(0.
|
|
1028
|
-
--card-foreground: oklch(0.
|
|
1029
|
-
--popover: oklch(
|
|
1030
|
-
--popover-foreground: oklch(0.
|
|
1031
|
-
--secondary: oklch(0.
|
|
1032
|
-
--secondary-foreground: oklch(0.
|
|
1033
|
-
--muted: oklch(0.
|
|
1034
|
-
--muted-foreground: oklch(0.
|
|
1035
|
-
--accent: oklch(0.
|
|
1036
|
-
--accent-foreground: oklch(0.
|
|
1037
|
-
--border: oklch(0.
|
|
1038
|
-
--input: oklch(0.
|
|
1021
|
+
/* Light / system UI — warm paper */
|
|
1022
|
+
--background: oklch(0.985 0.002 78);
|
|
1023
|
+
--foreground: oklch(0.2416 0.0219 57);
|
|
1024
|
+
--card: oklch(0.9792 0.0042 78.3);
|
|
1025
|
+
--card-foreground: oklch(0.2416 0.0219 57);
|
|
1026
|
+
--popover: oklch(0.9792 0.0042 78.3);
|
|
1027
|
+
--popover-foreground: oklch(0.2416 0.0219 57);
|
|
1028
|
+
--secondary: oklch(0.927 0.009 73.15);
|
|
1029
|
+
--secondary-foreground: oklch(0.3067 0.0309 56.81);
|
|
1030
|
+
--muted: oklch(0.9111 0.0082 73.15);
|
|
1031
|
+
--muted-foreground: oklch(0.5576 0.0222 57.81);
|
|
1032
|
+
--accent: oklch(0.935 0.011 73.15);
|
|
1033
|
+
--accent-foreground: oklch(0.2416 0.0219 57);
|
|
1034
|
+
--border: oklch(0.89 0.0137 73.1);
|
|
1035
|
+
--input: oklch(0.89 0.0137 73.1);
|
|
1039
1036
|
|
|
1040
1037
|
/* Chart colors */
|
|
1041
1038
|
--chart-1: oklch(0.809 0.105 251.813);
|
|
@@ -1048,14 +1045,49 @@
|
|
|
1048
1045
|
--radius: 0.45rem;
|
|
1049
1046
|
|
|
1050
1047
|
/* Sidebar */
|
|
1051
|
-
--sidebar: oklch(0.
|
|
1052
|
-
--sidebar-foreground: oklch(0.
|
|
1048
|
+
--sidebar: oklch(0.9792 0.0042 78.3);
|
|
1049
|
+
--sidebar-foreground: oklch(0.2416 0.0219 57);
|
|
1053
1050
|
--sidebar-primary: var(--primary);
|
|
1054
1051
|
--sidebar-primary-foreground: var(--primary-foreground);
|
|
1055
|
-
--sidebar-accent: oklch(0.96 0
|
|
1056
|
-
--sidebar-accent-foreground: oklch(0.205 0
|
|
1057
|
-
--sidebar-border: oklch(0.
|
|
1058
|
-
--sidebar-ring:
|
|
1052
|
+
--sidebar-accent: oklch(0.96 0.004 75);
|
|
1053
|
+
--sidebar-accent-foreground: oklch(0.205 0.015 55);
|
|
1054
|
+
--sidebar-border: oklch(0.89 0.0137 73.1);
|
|
1055
|
+
--sidebar-ring: var(--ring);
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
/* Mid — between warm paper and dark (neutral, slightly dimmer than light) */
|
|
1059
|
+
.mid {
|
|
1060
|
+
--background: oklch(0.915 0.01 78);
|
|
1061
|
+
--foreground: oklch(0.28 0.022 57);
|
|
1062
|
+
--card: oklch(0.895 0.012 78);
|
|
1063
|
+
--card-foreground: oklch(0.28 0.022 57);
|
|
1064
|
+
--popover: oklch(0.895 0.012 78);
|
|
1065
|
+
--popover-foreground: oklch(0.28 0.022 57);
|
|
1066
|
+
--secondary: oklch(0.88 0.012 73);
|
|
1067
|
+
--secondary-foreground: oklch(0.32 0.028 57);
|
|
1068
|
+
--muted: oklch(0.855 0.012 73);
|
|
1069
|
+
--muted-foreground: oklch(0.48 0.024 58);
|
|
1070
|
+
--accent: oklch(0.87 0.014 73);
|
|
1071
|
+
--accent-foreground: oklch(0.28 0.022 57);
|
|
1072
|
+
--border: oklch(0.82 0.016 73);
|
|
1073
|
+
--input: oklch(0.82 0.016 73);
|
|
1074
|
+
|
|
1075
|
+
--chart-1: oklch(0.809 0.105 251.813);
|
|
1076
|
+
--chart-2: oklch(0.623 0.214 259.815);
|
|
1077
|
+
--chart-3: oklch(0.546 0.245 262.881);
|
|
1078
|
+
--chart-4: oklch(0.488 0.243 264.376);
|
|
1079
|
+
--chart-5: oklch(0.424 0.199 265.638);
|
|
1080
|
+
|
|
1081
|
+
--radius: 0.45rem;
|
|
1082
|
+
|
|
1083
|
+
--sidebar: oklch(0.9 0.01 78);
|
|
1084
|
+
--sidebar-foreground: oklch(0.28 0.022 57);
|
|
1085
|
+
--sidebar-primary: var(--primary);
|
|
1086
|
+
--sidebar-primary-foreground: var(--primary-foreground);
|
|
1087
|
+
--sidebar-accent: oklch(0.875 0.012 75);
|
|
1088
|
+
--sidebar-accent-foreground: oklch(0.26 0.018 55);
|
|
1089
|
+
--sidebar-border: oklch(0.82 0.016 73);
|
|
1090
|
+
--sidebar-ring: var(--ring);
|
|
1059
1091
|
}
|
|
1060
1092
|
|
|
1061
1093
|
.dark {
|
|
@@ -1168,43 +1200,6 @@
|
|
|
1168
1200
|
}
|
|
1169
1201
|
|
|
1170
1202
|
/*
|
|
1171
|
-
*
|
|
1172
|
-
*
|
|
1173
|
-
|
|
1174
|
-
* colors.css like default light.
|
|
1175
|
-
*/
|
|
1176
|
-
.mid {
|
|
1177
|
-
/* Surfaces: parallel to :root — slightly lower L and mild hue vs neutral light */
|
|
1178
|
-
--background: oklch(0.9574 0.0081 73.16);
|
|
1179
|
-
--foreground: oklch(0.2416 0.0219 57);
|
|
1180
|
-
--card: oklch(0.9792 0.0042 78.3);
|
|
1181
|
-
--card-foreground: oklch(0.2416 0.0219 57);
|
|
1182
|
-
--popover: oklch(0.9792 0.0042 78.3);
|
|
1183
|
-
--popover-foreground: oklch(0.2416 0.0219 57);
|
|
1184
|
-
--secondary: oklch(0.927 0.009 73.15);
|
|
1185
|
-
--secondary-foreground: oklch(0.3067 0.0309 56.81);
|
|
1186
|
-
--muted: oklch(0.9111 0.0082 73.15);
|
|
1187
|
-
--muted-foreground: oklch(0.5576 0.0222 57.81);
|
|
1188
|
-
/* Hover/focus wash (menus, ghost buttons) — high L like :root accent, not a filled control */
|
|
1189
|
-
--accent: oklch(0.935 0.011 73.15);
|
|
1190
|
-
--accent-foreground: oklch(0.2416 0.0219 57);
|
|
1191
|
-
--border: oklch(0.89 0.0137 73.1);
|
|
1192
|
-
--input: oklch(0.89 0.0137 73.1);
|
|
1193
|
-
|
|
1194
|
-
/* Charts: same as light (:root) */
|
|
1195
|
-
--chart-1: oklch(0.809 0.105 251.813);
|
|
1196
|
-
--chart-2: oklch(0.623 0.214 259.815);
|
|
1197
|
-
--chart-3: oklch(0.546 0.245 262.881);
|
|
1198
|
-
--chart-4: oklch(0.488 0.243 264.376);
|
|
1199
|
-
--chart-5: oklch(0.424 0.199 265.638);
|
|
1200
|
-
|
|
1201
|
-
/* Sidebar: same structure as :root (light) — primary via semantic tokens, ring follows focus */
|
|
1202
|
-
--sidebar: oklch(0.985 0.002 78);
|
|
1203
|
-
--sidebar-foreground: oklch(0.2416 0.0219 57);
|
|
1204
|
-
--sidebar-primary: var(--primary);
|
|
1205
|
-
--sidebar-primary-foreground: var(--primary-foreground);
|
|
1206
|
-
--sidebar-accent: oklch(0.96 0.004 75);
|
|
1207
|
-
--sidebar-accent-foreground: oklch(0.205 0.015 55);
|
|
1208
|
-
--sidebar-border: oklch(0.89 0.0137 73.1);
|
|
1209
|
-
--sidebar-ring: var(--ring);
|
|
1210
|
-
}
|
|
1203
|
+
* html.light — next-themes; surface tokens match :root (warm paper).
|
|
1204
|
+
* html.mid — next-themes; surfaces use .mid block above (distinct from light).
|
|
1205
|
+
*/
|
|
@@ -12,6 +12,15 @@ Implementation guides for each component. **AI Skill:** Optimized for AI/LLM con
|
|
|
12
12
|
|
|
13
13
|
---
|
|
14
14
|
|
|
15
|
+
## Start here (humans)
|
|
16
|
+
|
|
17
|
+
1. **Know your task?** Open **`docs/nqui-skills/HUMAN_GUIDE.md`** (in the package) or **`node_modules/@nqlib/nqui/docs/nqui-skills/HUMAN_GUIDE.md`** after install — maps *forms, toolbar, dashboard, empty/loading, …* → which doc to open first.
|
|
18
|
+
2. **Pick one component** → **`nqui-<kebab-case>.md`** in this folder (e.g. `nqui-combobox.md`). Don’t load every file.
|
|
19
|
+
3. **Need “which component?” tables** → scroll to **When to Use (Selection & Action Components)** and **Shared Conventions** below; skip **Prerequisites** until you wire build/CSS.
|
|
20
|
+
4. **Deep layout / scroll / sticky** → **Layout & Scroll Patterns** (implementation-heavy; skip if you’re only choosing a component).
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
15
24
|
## Prerequisites
|
|
16
25
|
|
|
17
26
|
| Dependency | Version | Notes |
|
|
@@ -28,7 +37,7 @@ Implementation guides for each component. **AI Skill:** Optimized for AI/LLM con
|
|
|
28
37
|
|
|
29
38
|
## Shared Conventions (AI Implementation Rules)
|
|
30
39
|
|
|
31
|
-
- **Control sizes:** `sm`=h-6, `default`=h-7, `lg`=h-8. Button, Toggle, ToggleGroup, Input, Select, Switch, Slider use this scale. See `
|
|
40
|
+
- **Control sizes:** `sm`=h-6, `default`=h-7, `lg`=h-8. Button, Toggle, ToggleGroup, Input, Select, Switch, Slider use this scale. See `docs/nqui-skills/nqui-design-system/SKILL.md` (package) or `.cursor/skills/nqui-design-system/SKILL.md` (monorepo copy).
|
|
32
41
|
- **CSS vars required:** nqui uses `--primary`, `--background`, `--foreground`, etc. Run `npx @nqlib/nqui init-css`.
|
|
33
42
|
- **Enhanced vs Core:** Default exports (`Button`, `Badge`, `Checkbox`, `Select`, etc.) are the polished/3D variants. Implementations live in **`packages/nqui/src/components/ui/*.tsx`** (single file per concern). Use `CoreButton`, `CoreBadge`, `CoreCheckbox`, etc. for base Radix/shadcn-style behavior. Separator: single component with `variant` prop (no CoreSeparator).
|
|
34
43
|
- **Grouped controls:** ButtonGroup, ToggleGroup share border; outer container uses **pill** radius (`rounded-full`). ToggleGroup uses item dividers (`border-foreground/20`) or `ToggleGroupSeparator`.
|
|
@@ -38,7 +47,7 @@ Implementation guides for each component. **AI Skill:** Optimized for AI/LLM con
|
|
|
38
47
|
- **SidebarProvider:** Must wrap entire layout (sidebar + content).
|
|
39
48
|
- **Z-index:** Use CSS vars from `styles/elevation.css` (e.g. `z-[var(--z-modal)]`). Never hardcode `z-10`, `z-50`, etc.
|
|
40
49
|
- **Keyboard:** Use `Keys`, `isMod`, `shouldIgnoreKeyboardShortcut` from `@/lib/keyboard` for custom shortcuts.
|
|
41
|
-
- **Bounded content:** Chips, pills, and inline controls should stay inside their box (ellipsis / line-clamp / scroll-by-design). See **Bounded content** in `
|
|
50
|
+
- **Bounded content:** Chips, pills, and inline controls should stay inside their box (ellipsis / line-clamp / scroll-by-design). See **Bounded content** in `docs/nqui-skills/nqui-design-system/SKILL.md`. Portals and tooltips are explicit exceptions.
|
|
42
51
|
|
|
43
52
|
---
|
|
44
53
|
|
|
@@ -30,3 +30,77 @@ import { ScrollArea, ScrollBar } from "@nqlib/nqui"
|
|
|
30
30
|
```tsx
|
|
31
31
|
<ScrollArea fadeMask>...</ScrollArea>
|
|
32
32
|
```
|
|
33
|
+
|
|
34
|
+
## `viewportRef`
|
|
35
|
+
|
|
36
|
+
Pass **`viewportRef`** when you need a ref to the scrollable viewport (programmatic `scrollTop`, `ResizeObserver`, etc.).
|
|
37
|
+
|
|
38
|
+
```tsx
|
|
39
|
+
const viewportRef = useRef<HTMLDivElement>(null);
|
|
40
|
+
|
|
41
|
+
<ScrollArea viewportRef={viewportRef} className="min-h-0 flex-1">
|
|
42
|
+
…
|
|
43
|
+
</ScrollArea>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Layout pitfalls (read before shipping)
|
|
49
|
+
|
|
50
|
+
Radix Scroll Area wraps content in a **viewport** plus an **inner wrapper** whose default layout can interact badly with **flex**, **wide content**, and **`pre` / monospace**. Follow the checks below to avoid: **no vertical scroll**, **content growing off-screen to the right**, or **nested scroll bugs**.
|
|
51
|
+
|
|
52
|
+
### 1. Flex / resizable panels — height chain
|
|
53
|
+
|
|
54
|
+
In a **flex column**, children default to `min-height: auto`, so a `flex-1` scroll region can **expand with content** and **never scroll**.
|
|
55
|
+
|
|
56
|
+
- Put **`min-h-0`** (and usually **`min-w-0`**) on **every** flex ancestor between the root and `ScrollArea`.
|
|
57
|
+
- On **`ScrollArea` root**, use something like **`min-h-0 flex-1`** (and **`h-full`** only when the parent’s height is well-defined).
|
|
58
|
+
|
|
59
|
+
```tsx
|
|
60
|
+
<div className="flex min-h-0 flex-1 flex-col overflow-hidden">
|
|
61
|
+
<ScrollArea className="min-h-0 flex-1" viewportRef={viewportRef}>
|
|
62
|
+
…
|
|
63
|
+
</ScrollArea>
|
|
64
|
+
</div>
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### 2. Prose, chat, markdown — width and wrapping
|
|
68
|
+
|
|
69
|
+
The viewport’s **inner wrapper** (Radix) often behaves like a **shrink-to-fit** width. Long **URLs**, **unbroken strings**, or **table layout** can make the inner column **wider than the panel**, so users lose content off the **right** even though vertical scroll “works”.
|
|
70
|
+
|
|
71
|
+
**Do:**
|
|
72
|
+
|
|
73
|
+
- On **`ScrollArea` root** (or the viewport via arbitrary selectors), ensure:
|
|
74
|
+
- **`overflow-x: hidden`** on the **viewport** so the column does not pan sideways at the transcript level.
|
|
75
|
+
- On the **inner content wrapper** (Radix’s direct child of the viewport): **`display: block`**, **`min-width: 0`**, **`max-width: 100%`**, **`width: 100%`**, and **`break-words`** / **`overflow-wrap: anywhere`** so body text **wraps downward** instead of widening the scroll area.
|
|
76
|
+
|
|
77
|
+
**Avoid:**
|
|
78
|
+
|
|
79
|
+
- Blindly forcing **`display: block`** on the inner wrapper **without** `min-w-0` / `max-w-full` / wrapping — that can **break vertical scroll measurement** in some trees. Prefer a **documented, tested** combination (height + width) for your shell (e.g. chat transcript vs. simple list).
|
|
80
|
+
|
|
81
|
+
**Consumer pattern (example):** apps may ship a shared class for “chat transcript” `ScrollArea` that sets viewport `overflow-x-hidden` and targets `[data-radix-scroll-area-viewport] > div` with block + `min-w-0` + `max-w-full` + `break-words`. Reuse one class per product so behavior stays consistent.
|
|
82
|
+
|
|
83
|
+
### 3. `<pre>`, fenced code, `white-space: pre`
|
|
84
|
+
|
|
85
|
+
**Do not** rely on `ScrollArea` as the only clip for **fenced code** or **`white-space: pre`** blocks. Radix’s structure often **fails to clip** tall/wide `pre` content predictably.
|
|
86
|
+
|
|
87
|
+
**Prefer:** a plain element with **`max-height`**, **`overflow-auto`**, and optional thin scrollbar styling (e.g. a utility class in app CSS). Keep **one** main column `ScrollArea` for the page/panel; use **native overflow** inside message bodies for code.
|
|
88
|
+
|
|
89
|
+
### 4. Nested `ScrollArea`
|
|
90
|
+
|
|
91
|
+
Avoid **nested** `ScrollArea` for small regions (reasoning previews, inline panels). Prefer **one** outer scroll for the column + **native `overflow-auto`** for inner blocks. Nested Radix scroll roots multiply width/height bugs.
|
|
92
|
+
|
|
93
|
+
### 5. Sidebar lists vs. chat transcript
|
|
94
|
+
|
|
95
|
+
A pattern that fixes **wide titles** in a list (e.g. forcing inner `display: block`) may **break** vertical scrolling in a **chat transcript**. Do not reuse one global class for both without verifying **both** behaviors; split constants (e.g. “sidebar list” vs. “chat transcript”) when needed.
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Checklist (copy for PRs)
|
|
100
|
+
|
|
101
|
+
- [ ] Flex ancestors use **`min-h-0`** where the scroll area must shrink.
|
|
102
|
+
- [ ] `ScrollArea` root uses **`min-h-0`** (+ **`flex-1`** / **`h-full`** as appropriate).
|
|
103
|
+
- [ ] Long **text** wraps: **`min-w-0`**, **`max-w-full`**, **`break-words`** / **`overflow-wrap: anywhere`**, viewport **`overflow-x-hidden`** if prose lives inside.
|
|
104
|
+
- [ ] **Code / `pre`**: **`max-height` + native `overflow-auto`**, not nested `ScrollArea`.
|
|
105
|
+
- [ ] **No unnecessary nested** `ScrollArea` for small inner regions.
|
|
106
|
+
- [ ] **`ScrollBar`** included where a visible scrollbar is desired (see Basic example).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# nqui Tooltip
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> Supplemental hint on **hover or focus** — not a substitute for visible labels or critical instructions.
|
|
4
4
|
|
|
5
5
|
## Import
|
|
6
6
|
|
|
@@ -21,4 +21,19 @@ import { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from "@nqlib
|
|
|
21
21
|
|
|
22
22
|
## Provider
|
|
23
23
|
|
|
24
|
-
Place once at app root (or layout).
|
|
24
|
+
Place **`TooltipProvider`** once at app root (or layout) so delays and portals work consistently.
|
|
25
|
+
|
|
26
|
+
## UX & accessibility
|
|
27
|
+
|
|
28
|
+
- **Do not** put **required** information only in a tooltip. Users who don’t hover (keyboard, touch, screen reader) may miss it. Repeat critical copy in the visible UI or **Dialog** / **Sheet** / inline help.
|
|
29
|
+
- **Keyboard:** Triggers should be focusable; tooltips typically show on **focus** as well as hover (Radix Tooltip behavior). Don’t rely on hover-only for anything mandatory.
|
|
30
|
+
- **Touch:** There is **no hover** on phones. Treat tooltip content as **nice-to-have**; use **Popover** or inline text for essential mobile copy.
|
|
31
|
+
- **Screen readers:** Tooltip content is exposed when the trigger is focused; keep text **short** and **non-semantic** for critical structure (don’t use tooltips as the only form label).
|
|
32
|
+
|
|
33
|
+
## When to use something else
|
|
34
|
+
|
|
35
|
+
| Need | Use instead |
|
|
36
|
+
|------|-------------|
|
|
37
|
+
| Rich content, tap to open | **Popover** (`nqui-popover.md`) |
|
|
38
|
+
| Long preview on hover | **HoverCard** (`nqui-hover-card.md`) |
|
|
39
|
+
| Blocking message | **Alert** or **Dialog** |
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: nqui-component-docs-index
|
|
3
|
+
description: Token-efficient map for nqui per-component docs. Use BEFORE opening README or multiple nqui-*.md files. Tells which single file to load for a component.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Component docs — load order (save tokens)
|
|
7
|
+
|
|
8
|
+
**Do not** bulk-read every file under `components/`. **Do not** load all of `README.md` unless you need full “when to use” tables.
|
|
9
|
+
|
|
10
|
+
1. **Pick one doc:** `nqui-<kebab-case>.md` for the component you are implementing (e.g. `nqui-toggle-group.md`). In this repo use **`docs/components/`**; after `init-skills` use **`.cursor/nqui-skills/components/`**.
|
|
11
|
+
2. **Unsure which component?** Skim **`README.md`** in that folder only for **“When to Use”** and the category table — or use **[HUMAN_GUIDE.md](./HUMAN_GUIDE.md)** (task → docs) or the **area → filenames** list below.
|
|
12
|
+
3. **Deep selection logic** (toolbar vs form, ToggleGroup vs RadioGroup): **`nqui-components/SKILL.md`** and **`nqui-design-system/SKILL.md`**.
|
|
13
|
+
|
|
14
|
+
## Paths
|
|
15
|
+
|
|
16
|
+
| Where | Per-component docs | Routing / human wayfinding |
|
|
17
|
+
|-------|--------------------|----------------------------|
|
|
18
|
+
| nqui repo / package source | `docs/components/nqui-<kebab>.md` | `docs/nqui-skills/COMPONENTS_INDEX.md` · `HUMAN_GUIDE.md` |
|
|
19
|
+
| Consumer after `init-skills` | `.cursor/nqui-skills/components/nqui-<kebab>.md` | `.cursor/nqui-skills/COMPONENTS_INDEX.md` · `HUMAN_GUIDE.md` |
|
|
20
|
+
| Installed only (no init-skills) | `node_modules/@nqlib/nqui/docs/components/nqui-<kebab>.md` | `node_modules/@nqlib/nqui/docs/nqui-skills/COMPONENTS_INDEX.md` · `HUMAN_GUIDE.md` |
|
|
21
|
+
|
|
22
|
+
Filenames always: `nqui-<kebab>.md`.
|
|
23
|
+
|
|
24
|
+
## Area → doc files (open **one**)
|
|
25
|
+
|
|
26
|
+
Suffix every name with `.md` in the components folder you are using (`docs/components/` or `.cursor/nqui-skills/components/`).
|
|
27
|
+
|
|
28
|
+
**Actions & selection:** `nqui-button` · `nqui-button-group` · `nqui-toggle` · `nqui-toggle-group`
|
|
29
|
+
|
|
30
|
+
**Forms & inputs:** `nqui-input` · `nqui-textarea` · `nqui-select` · `nqui-native-select` · `nqui-checkbox` · `nqui-radio-group` · `nqui-switch` · `nqui-slider` · `nqui-rating` · `nqui-input-otp` · `nqui-field` · `nqui-combobox` · `nqui-color-picker` · `nqui-color-slider` · `nqui-label` · `nqui-input-group`
|
|
31
|
+
|
|
32
|
+
**Display:** `nqui-badge` · `nqui-avatar` · `nqui-alert` · `nqui-empty` · `nqui-skeleton` · `nqui-spinner` · `nqui-progress` · `nqui-separator` · `nqui-card` · `nqui-item` · `nqui-kbd` · `nqui-tracker` · `nqui-frosted-glass` · `nqui-logo`
|
|
33
|
+
|
|
34
|
+
**Data:** `nqui-table` · `nqui-data-table`
|
|
35
|
+
|
|
36
|
+
**Code / embed:** `nqui-code-block` · `nqui-snippet` · `nqui-code-editor` · `nqui-sandbox`
|
|
37
|
+
|
|
38
|
+
**Navigation:** `nqui-breadcrumb` · `nqui-tabs` · `nqui-dropdown-menu` · `nqui-context-menu` · `nqui-menubar` · `nqui-navigation-menu` · `nqui-pagination` · `nqui-command` · `nqui-command-palette` · `nqui-table-of-contents`
|
|
39
|
+
|
|
40
|
+
**Overlays:** `nqui-dialog` · `nqui-alert-dialog` · `nqui-drawer` · `nqui-sheet` · `nqui-popover` · `nqui-hover-card` · `nqui-tooltip` · `nqui-toaster`
|
|
41
|
+
|
|
42
|
+
**Layout:** `nqui-accordion` · `nqui-collapsible` · `nqui-scroll-area` · `nqui-aspect-ratio` · `nqui-carousel` · `nqui-resizable` · `nqui-sidebar` · `nqui-sortable`
|
|
43
|
+
|
|
44
|
+
**Advanced:** `nqui-calendar`
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
Full index + long-form guidance: `README.md` next to those files (large — use sections, not whole-file dump).
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# nqui — task → docs (for designers & humans)
|
|
2
|
+
|
|
3
|
+
Use this file for **wayfinding** before diving into `README.md` (long) or dozens of `nqui-*.md` files. Paths below are from the **nqui package**; after `npx @nqlib/nqui init-skills`, the same files live under **`.cursor/nqui-skills/components/`**.
|
|
4
|
+
|
|
5
|
+
| I’m building… | Start here | Then open |
|
|
6
|
+
|---------------|------------|-----------|
|
|
7
|
+
| **Forms** (login, settings, checkout) | `docs/components/README.md` → Forms sections | One of `nqui-field.md`, `nqui-input.md`, `nqui-select.md`, `nqui-combobox.md`, … |
|
|
8
|
+
| **Toolbar / editor** (bold, view mode, align) | `nqui-skills/nqui-components/SKILL.md` (ToggleGroup rules) | `nqui-toggle-group.md`, `nqui-button-group.md` |
|
|
9
|
+
| **“Choose one” in a form** (stacked options, survey) | **RadioGroup** may be correct — see `nqui-components/SKILL.md` vs ToggleGroup | `nqui-radio-group.md` |
|
|
10
|
+
| **Dashboard / cards / lists** | `README.md` → Display | `nqui-card.md`, `nqui-item.md`, `nqui-table.md` or `nqui-data-table.md` |
|
|
11
|
+
| **Empty / loading / error** | Skeleton + Empty + Alert | `nqui-skeleton.md`, `nqui-empty.md`, `nqui-alert.md` |
|
|
12
|
+
| **Confirm destructive action** | Modal pattern | `nqui-alert-dialog.md` |
|
|
13
|
+
| **Navigation** | `README.md` → Navigation | `nqui-tabs.md`, `nqui-breadcrumb.md`, `nqui-sidebar.md`, … |
|
|
14
|
+
| **Touch-heavy or mobile** | Prefer **default/lg** controls; avoid **only** hover for critical info | `nqui-tooltip.md` (hover limits), `nqui-components/SKILL.md` (hit area) |
|
|
15
|
+
|
|
16
|
+
**Cross-cutting UX**
|
|
17
|
+
|
|
18
|
+
- **Accessibility:** Prefer components’ built-in Radix semantics; **don’t** put required instructions only in **Tooltip** (see `nqui-tooltip.md`). See `nqui-shadcn/SKILL.md` + rules for forms and dialogs.
|
|
19
|
+
- **States:** **Loading** → Skeleton / Spinner; **empty** → Empty; **error** → Field + Alert + validation patterns in `nqui-shadcn/rules/forms.md`.
|
|
20
|
+
|
|
21
|
+
**Agents:** For token-efficient routing, use **`COMPONENTS_INDEX.md`** first, then **one** `nqui-<name>.md`.
|