@nextlyhq/ui 0.0.2-alpha.35 → 0.0.2-alpha.39
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/README.md +77 -11
- package/dist/index.cjs +936 -655
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +29 -109
- package/dist/index.d.ts +29 -109
- package/dist/index.mjs +685 -387
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/styles.scoped.css +2 -0
- package/dist/tailwind-preset.cjs +98 -0
- package/dist/tailwind-preset.cjs.map +1 -0
- package/dist/tailwind-preset.d.cts +80 -0
- package/dist/tailwind-preset.d.ts +80 -0
- package/dist/tailwind-preset.mjs +93 -0
- package/dist/tailwind-preset.mjs.map +1 -0
- package/dist/theme.css +63 -29
- package/dist/utils.cjs +13 -0
- package/dist/utils.cjs.map +1 -0
- package/dist/utils.d.cts +17 -0
- package/dist/utils.d.ts +17 -0
- package/dist/utils.mjs +11 -0
- package/dist/utils.mjs.map +1 -0
- package/docs/plugin-ui-authoring.md +26 -26
- package/package.json +47 -13
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
declare const uiPreset: {
|
|
2
|
+
theme: {
|
|
3
|
+
extend: {
|
|
4
|
+
colors: {
|
|
5
|
+
border: string;
|
|
6
|
+
input: string;
|
|
7
|
+
ring: string;
|
|
8
|
+
background: string;
|
|
9
|
+
foreground: string;
|
|
10
|
+
primary: {
|
|
11
|
+
DEFAULT: string;
|
|
12
|
+
foreground: string;
|
|
13
|
+
};
|
|
14
|
+
secondary: {
|
|
15
|
+
DEFAULT: string;
|
|
16
|
+
foreground: string;
|
|
17
|
+
};
|
|
18
|
+
destructive: {
|
|
19
|
+
DEFAULT: string;
|
|
20
|
+
solid: string;
|
|
21
|
+
foreground: string;
|
|
22
|
+
};
|
|
23
|
+
success: {
|
|
24
|
+
DEFAULT: string;
|
|
25
|
+
solid: string;
|
|
26
|
+
foreground: string;
|
|
27
|
+
};
|
|
28
|
+
warning: {
|
|
29
|
+
DEFAULT: string;
|
|
30
|
+
foreground: string;
|
|
31
|
+
};
|
|
32
|
+
muted: {
|
|
33
|
+
DEFAULT: string;
|
|
34
|
+
foreground: string;
|
|
35
|
+
};
|
|
36
|
+
accent: {
|
|
37
|
+
DEFAULT: string;
|
|
38
|
+
foreground: string;
|
|
39
|
+
};
|
|
40
|
+
popover: {
|
|
41
|
+
DEFAULT: string;
|
|
42
|
+
foreground: string;
|
|
43
|
+
};
|
|
44
|
+
card: {
|
|
45
|
+
DEFAULT: string;
|
|
46
|
+
foreground: string;
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
borderRadius: {
|
|
50
|
+
lg: string;
|
|
51
|
+
md: string;
|
|
52
|
+
sm: string;
|
|
53
|
+
};
|
|
54
|
+
keyframes: {
|
|
55
|
+
"accordion-down": {
|
|
56
|
+
from: {
|
|
57
|
+
height: string;
|
|
58
|
+
};
|
|
59
|
+
to: {
|
|
60
|
+
height: string;
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
"accordion-up": {
|
|
64
|
+
from: {
|
|
65
|
+
height: string;
|
|
66
|
+
};
|
|
67
|
+
to: {
|
|
68
|
+
height: string;
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
animation: {
|
|
73
|
+
"accordion-down": string;
|
|
74
|
+
"accordion-up": string;
|
|
75
|
+
};
|
|
76
|
+
};
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
export { uiPreset as default, uiPreset };
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
declare const uiPreset: {
|
|
2
|
+
theme: {
|
|
3
|
+
extend: {
|
|
4
|
+
colors: {
|
|
5
|
+
border: string;
|
|
6
|
+
input: string;
|
|
7
|
+
ring: string;
|
|
8
|
+
background: string;
|
|
9
|
+
foreground: string;
|
|
10
|
+
primary: {
|
|
11
|
+
DEFAULT: string;
|
|
12
|
+
foreground: string;
|
|
13
|
+
};
|
|
14
|
+
secondary: {
|
|
15
|
+
DEFAULT: string;
|
|
16
|
+
foreground: string;
|
|
17
|
+
};
|
|
18
|
+
destructive: {
|
|
19
|
+
DEFAULT: string;
|
|
20
|
+
solid: string;
|
|
21
|
+
foreground: string;
|
|
22
|
+
};
|
|
23
|
+
success: {
|
|
24
|
+
DEFAULT: string;
|
|
25
|
+
solid: string;
|
|
26
|
+
foreground: string;
|
|
27
|
+
};
|
|
28
|
+
warning: {
|
|
29
|
+
DEFAULT: string;
|
|
30
|
+
foreground: string;
|
|
31
|
+
};
|
|
32
|
+
muted: {
|
|
33
|
+
DEFAULT: string;
|
|
34
|
+
foreground: string;
|
|
35
|
+
};
|
|
36
|
+
accent: {
|
|
37
|
+
DEFAULT: string;
|
|
38
|
+
foreground: string;
|
|
39
|
+
};
|
|
40
|
+
popover: {
|
|
41
|
+
DEFAULT: string;
|
|
42
|
+
foreground: string;
|
|
43
|
+
};
|
|
44
|
+
card: {
|
|
45
|
+
DEFAULT: string;
|
|
46
|
+
foreground: string;
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
borderRadius: {
|
|
50
|
+
lg: string;
|
|
51
|
+
md: string;
|
|
52
|
+
sm: string;
|
|
53
|
+
};
|
|
54
|
+
keyframes: {
|
|
55
|
+
"accordion-down": {
|
|
56
|
+
from: {
|
|
57
|
+
height: string;
|
|
58
|
+
};
|
|
59
|
+
to: {
|
|
60
|
+
height: string;
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
"accordion-up": {
|
|
64
|
+
from: {
|
|
65
|
+
height: string;
|
|
66
|
+
};
|
|
67
|
+
to: {
|
|
68
|
+
height: string;
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
animation: {
|
|
73
|
+
"accordion-down": string;
|
|
74
|
+
"accordion-up": string;
|
|
75
|
+
};
|
|
76
|
+
};
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
export { uiPreset as default, uiPreset };
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// src/tailwind-preset.ts
|
|
2
|
+
var statusScale = (base) => ({
|
|
3
|
+
50: `color-mix(in srgb, var(${base}), white 95%)`,
|
|
4
|
+
100: `color-mix(in srgb, var(${base}), white 90%)`,
|
|
5
|
+
200: `color-mix(in srgb, var(${base}), white 70%)`,
|
|
6
|
+
300: `color-mix(in srgb, var(${base}), white 50%)`,
|
|
7
|
+
400: `color-mix(in srgb, var(${base}), white 30%)`,
|
|
8
|
+
500: `var(${base})`,
|
|
9
|
+
600: `color-mix(in srgb, var(${base}), black 10%)`,
|
|
10
|
+
700: `color-mix(in srgb, var(${base}), black 30%)`,
|
|
11
|
+
800: `color-mix(in srgb, var(${base}), black 50%)`,
|
|
12
|
+
900: `color-mix(in srgb, var(${base}), black 70%)`,
|
|
13
|
+
950: `color-mix(in srgb, var(${base}), black 85%)`
|
|
14
|
+
});
|
|
15
|
+
var uiPreset = {
|
|
16
|
+
theme: {
|
|
17
|
+
extend: {
|
|
18
|
+
colors: {
|
|
19
|
+
border: "var(--nx-border)",
|
|
20
|
+
input: "var(--nx-input)",
|
|
21
|
+
ring: "var(--nx-ring)",
|
|
22
|
+
background: "var(--nx-background)",
|
|
23
|
+
foreground: "var(--nx-foreground)",
|
|
24
|
+
primary: {
|
|
25
|
+
DEFAULT: "var(--nx-primary)",
|
|
26
|
+
foreground: "var(--nx-primary-foreground)"
|
|
27
|
+
},
|
|
28
|
+
secondary: {
|
|
29
|
+
DEFAULT: "var(--nx-secondary)",
|
|
30
|
+
foreground: "var(--nx-secondary-foreground)"
|
|
31
|
+
},
|
|
32
|
+
destructive: {
|
|
33
|
+
DEFAULT: "var(--nx-destructive)",
|
|
34
|
+
// Saturated fill for solid buttons, distinct from the text-tuned base.
|
|
35
|
+
solid: "var(--nx-destructive-solid)",
|
|
36
|
+
foreground: "var(--nx-destructive-foreground)",
|
|
37
|
+
...statusScale("--nx-destructive")
|
|
38
|
+
},
|
|
39
|
+
success: {
|
|
40
|
+
DEFAULT: "var(--nx-success)",
|
|
41
|
+
solid: "var(--nx-success-solid)",
|
|
42
|
+
foreground: "var(--nx-success-foreground)",
|
|
43
|
+
...statusScale("--nx-success")
|
|
44
|
+
},
|
|
45
|
+
warning: {
|
|
46
|
+
DEFAULT: "var(--nx-warning)",
|
|
47
|
+
foreground: "var(--nx-warning-foreground)",
|
|
48
|
+
...statusScale("--nx-warning")
|
|
49
|
+
},
|
|
50
|
+
muted: {
|
|
51
|
+
DEFAULT: "var(--nx-muted)",
|
|
52
|
+
foreground: "var(--nx-muted-foreground)"
|
|
53
|
+
},
|
|
54
|
+
accent: {
|
|
55
|
+
DEFAULT: "var(--nx-accent)",
|
|
56
|
+
foreground: "var(--nx-accent-foreground)"
|
|
57
|
+
},
|
|
58
|
+
popover: {
|
|
59
|
+
DEFAULT: "var(--nx-popover)",
|
|
60
|
+
foreground: "var(--nx-popover-foreground)"
|
|
61
|
+
},
|
|
62
|
+
card: {
|
|
63
|
+
DEFAULT: "var(--nx-card)",
|
|
64
|
+
foreground: "var(--nx-card-foreground)"
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
borderRadius: {
|
|
68
|
+
lg: "var(--radius)",
|
|
69
|
+
md: "calc(var(--radius) - 2px)",
|
|
70
|
+
sm: "calc(var(--radius) - 4px)"
|
|
71
|
+
},
|
|
72
|
+
keyframes: {
|
|
73
|
+
"accordion-down": {
|
|
74
|
+
from: { height: "0" },
|
|
75
|
+
to: { height: "var(--radix-accordion-content-height)" }
|
|
76
|
+
},
|
|
77
|
+
"accordion-up": {
|
|
78
|
+
from: { height: "var(--radix-accordion-content-height)" },
|
|
79
|
+
to: { height: "0" }
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
animation: {
|
|
83
|
+
"accordion-down": "accordion-down 0.3s cubic-bezier(0.87, 0, 0.13, 1)",
|
|
84
|
+
"accordion-up": "accordion-up 0.3s cubic-bezier(0.87, 0, 0.13, 1)"
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
var tailwind_preset_default = uiPreset;
|
|
90
|
+
|
|
91
|
+
export { tailwind_preset_default as default, uiPreset };
|
|
92
|
+
//# sourceMappingURL=tailwind-preset.mjs.map
|
|
93
|
+
//# sourceMappingURL=tailwind-preset.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/tailwind-preset.ts"],"names":[],"mappings":"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","file":"tailwind-preset.mjs","sourcesContent":["/**\n * Tailwind CSS preset for @nextlyhq/ui components.\n *\n * Defines the CSS custom property contract that all UI components expect.\n * Consumers must provide the actual CSS variable values in their stylesheets.\n *\n * Usage (Tailwind v3, ESM):\n * // tailwind.config.ts\n * import uiPreset from \"@nextlyhq/ui/tailwind-preset\";\n * export default { presets: [uiPreset], ... };\n *\n * Usage (Tailwind v3, CommonJS):\n * // tailwind.config.js\n * const { uiPreset } = require(\"@nextlyhq/ui/tailwind-preset\");\n * module.exports = { presets: [uiPreset], ... };\n *\n * Usage (Tailwind v4 with @config):\n * Consumers define the equivalent @theme tokens in their CSS.\n * This file serves as the reference contract.\n */\n/**\n * The numbered shade scale for a status color, mixed from its base the same way\n * the v4 `@theme` block does, so v3 preset consumers get the same utilities the\n * components emit (`bg-destructive-700`, `bg-success-100 text-success-700`, ...).\n */\nconst statusScale = (base: string): Record<number, string> => ({\n 50: `color-mix(in srgb, var(${base}), white 95%)`,\n 100: `color-mix(in srgb, var(${base}), white 90%)`,\n 200: `color-mix(in srgb, var(${base}), white 70%)`,\n 300: `color-mix(in srgb, var(${base}), white 50%)`,\n 400: `color-mix(in srgb, var(${base}), white 30%)`,\n 500: `var(${base})`,\n 600: `color-mix(in srgb, var(${base}), black 10%)`,\n 700: `color-mix(in srgb, var(${base}), black 30%)`,\n 800: `color-mix(in srgb, var(${base}), black 50%)`,\n 900: `color-mix(in srgb, var(${base}), black 70%)`,\n 950: `color-mix(in srgb, var(${base}), black 85%)`,\n});\n\nconst uiPreset = {\n theme: {\n extend: {\n colors: {\n border: \"var(--nx-border)\",\n input: \"var(--nx-input)\",\n ring: \"var(--nx-ring)\",\n background: \"var(--nx-background)\",\n foreground: \"var(--nx-foreground)\",\n primary: {\n DEFAULT: \"var(--nx-primary)\",\n foreground: \"var(--nx-primary-foreground)\",\n },\n secondary: {\n DEFAULT: \"var(--nx-secondary)\",\n foreground: \"var(--nx-secondary-foreground)\",\n },\n destructive: {\n DEFAULT: \"var(--nx-destructive)\",\n // Saturated fill for solid buttons, distinct from the text-tuned base.\n solid: \"var(--nx-destructive-solid)\",\n foreground: \"var(--nx-destructive-foreground)\",\n ...statusScale(\"--nx-destructive\"),\n },\n success: {\n DEFAULT: \"var(--nx-success)\",\n solid: \"var(--nx-success-solid)\",\n foreground: \"var(--nx-success-foreground)\",\n ...statusScale(\"--nx-success\"),\n },\n warning: {\n DEFAULT: \"var(--nx-warning)\",\n foreground: \"var(--nx-warning-foreground)\",\n ...statusScale(\"--nx-warning\"),\n },\n muted: {\n DEFAULT: \"var(--nx-muted)\",\n foreground: \"var(--nx-muted-foreground)\",\n },\n accent: {\n DEFAULT: \"var(--nx-accent)\",\n foreground: \"var(--nx-accent-foreground)\",\n },\n popover: {\n DEFAULT: \"var(--nx-popover)\",\n foreground: \"var(--nx-popover-foreground)\",\n },\n card: {\n DEFAULT: \"var(--nx-card)\",\n foreground: \"var(--nx-card-foreground)\",\n },\n },\n borderRadius: {\n lg: \"var(--radius)\",\n md: \"calc(var(--radius) - 2px)\",\n sm: \"calc(var(--radius) - 4px)\",\n },\n keyframes: {\n \"accordion-down\": {\n from: { height: \"0\" },\n to: { height: \"var(--radix-accordion-content-height)\" },\n },\n \"accordion-up\": {\n from: { height: \"var(--radix-accordion-content-height)\" },\n to: { height: \"0\" },\n },\n },\n animation: {\n \"accordion-down\": \"accordion-down 0.3s cubic-bezier(0.87, 0, 0.13, 1)\",\n \"accordion-up\": \"accordion-up 0.3s cubic-bezier(0.87, 0, 0.13, 1)\",\n },\n },\n },\n};\n\n// Exported both ways on purpose. CommonJS cannot represent a default-only\n// module without `module.exports =`, which makes the emitted declarations\n// disagree with the runtime shape (attw's FalseExportDefault); a named export\n// alongside it keeps `require()` and `import` consistent and typed.\nexport { uiPreset };\nexport default uiPreset;\n"]}
|
package/dist/theme.css
CHANGED
|
@@ -177,6 +177,9 @@
|
|
|
177
177
|
--color-destructive-800: color-mix(in srgb, var(--nx-destructive), black 50%);
|
|
178
178
|
--color-destructive-900: color-mix(in srgb, var(--nx-destructive), black 70%);
|
|
179
179
|
--color-destructive-950: color-mix(in srgb, var(--nx-destructive), black 85%);
|
|
180
|
+
/* Saturated fill for solid buttons; distinct from the text-tuned base so
|
|
181
|
+
* white on-color text stays AA in both modes. */
|
|
182
|
+
--color-destructive-solid: var(--nx-destructive-solid);
|
|
180
183
|
--color-destructive-foreground: var(--nx-destructive-foreground);
|
|
181
184
|
|
|
182
185
|
--color-success: var(--nx-success);
|
|
@@ -191,6 +194,8 @@
|
|
|
191
194
|
--color-success-800: color-mix(in srgb, var(--nx-success), black 50%);
|
|
192
195
|
--color-success-900: color-mix(in srgb, var(--nx-success), black 70%);
|
|
193
196
|
--color-success-950: color-mix(in srgb, var(--nx-success), black 85%);
|
|
197
|
+
/* Saturated fill for solid usage; distinct from the text-tuned base. */
|
|
198
|
+
--color-success-solid: var(--nx-success-solid);
|
|
194
199
|
--color-success-foreground: var(--nx-success-foreground);
|
|
195
200
|
|
|
196
201
|
--color-warning: var(--nx-warning);
|
|
@@ -620,24 +625,34 @@
|
|
|
620
625
|
|
|
621
626
|
/* Utility colors */
|
|
622
627
|
--nx-muted: oklch(0.9696 0 0);
|
|
623
|
-
|
|
628
|
+
/* Darkened so muted text clears WCAG 4.5:1 on the muted surface (was 4.35:1). */
|
|
629
|
+
--nx-muted-foreground: oklch(0.54 0.0407 257.44);
|
|
624
630
|
/* slate-500 */
|
|
625
631
|
--nx-accent: oklch(0.5547 0.0407 257.44);
|
|
626
632
|
/* Slate-500 per user request #64748b */
|
|
627
633
|
--nx-accent-foreground: oklch(1 0 0);
|
|
628
634
|
/* white */
|
|
629
635
|
|
|
630
|
-
/* State colors - WCAG 2.2 AA Compliant
|
|
631
|
-
|
|
632
|
-
|
|
636
|
+
/* State colors - WCAG 2.2 AA Compliant.
|
|
637
|
+
* Each status has two roles kept as separate tokens, the industry-standard
|
|
638
|
+
* split (Radix/Primer): the base token is the readable TEXT color used by
|
|
639
|
+
* `text-destructive` and derived shades, and `-solid` is the saturated FILL
|
|
640
|
+
* used by buttons under white on-color text. One value cannot serve both in
|
|
641
|
+
* dark mode (a fill dark enough for white text is too dark to read as text
|
|
642
|
+
* on the page), so they diverge there. */
|
|
643
|
+
/* Darkened from red-500; renders as #d92c32, ~4.8:1 as text on white. */
|
|
644
|
+
--nx-destructive: oklch(0.5778 0.2078 25.33);
|
|
645
|
+
--nx-destructive-solid: oklch(0.5778 0.2078 25.33);
|
|
633
646
|
--nx-destructive-foreground: oklch(1 0 0);
|
|
634
647
|
/* white */
|
|
635
|
-
|
|
636
|
-
|
|
648
|
+
/* Darkened from green-600; renders as #00852c, ~4.8:1 as text on white. */
|
|
649
|
+
--nx-success: oklch(0.53 0.17 149.2);
|
|
650
|
+
--nx-success-solid: oklch(0.53 0.17 149.2);
|
|
637
651
|
--nx-success-foreground: oklch(1 0 0);
|
|
638
652
|
/* white */
|
|
639
|
-
|
|
640
|
-
|
|
653
|
+
/* Darkened from amber-500 so it reads as text on white at WCAG 4.5:1 (was
|
|
654
|
+
* 2.15:1); its light shades still tint badge/alert surfaces. */
|
|
655
|
+
--nx-warning: oklch(0.565 0.1646 70.11);
|
|
641
656
|
--nx-warning-foreground: oklch(0.2079 0.0399 265.73);
|
|
642
657
|
/* slate-900 - REQUIRED for AA contrast (warning-500 on white = 3.4:1, fails AA) */
|
|
643
658
|
|
|
@@ -656,13 +671,15 @@
|
|
|
656
671
|
* held above 4.5:1 on --nx-code-bg since code is small text. */
|
|
657
672
|
--nx-code-bg: oklch(0.9761 0.0035 247.86);
|
|
658
673
|
--nx-code-fg: oklch(0.2079 0.0399 265.73);
|
|
659
|
-
|
|
674
|
+
/* Darkened slightly to clear WCAG 4.5:1 on the code surface (was 4.44:1). */
|
|
675
|
+
--nx-code-comment: oklch(0.541 0.0407 257.44);
|
|
660
676
|
--nx-code-keyword: oklch(0.4882 0.2172 303.9);
|
|
661
677
|
--nx-code-string: oklch(0.4478 0.1189 152.1);
|
|
662
678
|
--nx-code-number: oklch(0.5106 0.1518 44.2);
|
|
663
679
|
--nx-code-function: oklch(0.4757 0.1444 254.6);
|
|
664
680
|
--nx-code-operator: oklch(0.4936 0.1418 8.4);
|
|
665
|
-
|
|
681
|
+
/* Darkened slightly to clear WCAG 4.5:1 on the code surface (was 4.44:1). */
|
|
682
|
+
--nx-code-punctuation: oklch(0.541 0.0407 257.44);
|
|
666
683
|
--nx-code-variable: oklch(0.4694 0.1173 62.3);
|
|
667
684
|
--nx-code-tag: oklch(0.5054 0.1905 27.5);
|
|
668
685
|
--nx-code-deleted: oklch(0.5054 0.1905 27.5);
|
|
@@ -673,11 +690,12 @@
|
|
|
673
690
|
* subtle = decorative dividers/cards; default = tables/groups;
|
|
674
691
|
* strong = interactive control edges (inputs/checkbox) for prominence. */
|
|
675
692
|
--nx-border-subtle: oklch(0 0 0 / 0.08);
|
|
676
|
-
|
|
677
|
-
--nx-border
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
693
|
+
/* Alpha raised so the composited border clears WCAG 3:1 on the page (was 1.35:1). */
|
|
694
|
+
--nx-border: oklch(0 0 0 / 0.445);
|
|
695
|
+
/* Alpha raised so the composited strong border clears WCAG 3:1 / ~4:1 (was 2.11:1). */
|
|
696
|
+
--nx-border-strong: oklch(0 0 0 / 0.502);
|
|
697
|
+
/* Darkened so the field border clears WCAG 3:1 on the page (was 2.32:1). */
|
|
698
|
+
--nx-input: oklch(0.6454 0.0116 286.11);
|
|
681
699
|
--nx-ring: var(--nx-primary);
|
|
682
700
|
|
|
683
701
|
/* Chart colors for data visualization */
|
|
@@ -720,7 +738,8 @@
|
|
|
720
738
|
/* slate-100 */
|
|
721
739
|
--nx-sidebar-accent-foreground: oklch(0.2079 0.0399 265.73);
|
|
722
740
|
/* slate-900 */
|
|
723
|
-
|
|
741
|
+
/* Darkened so the sidebar border clears WCAG 3:1 on its surface (was 1.23:1). */
|
|
742
|
+
--nx-sidebar-border: oklch(0.6446 0.0126 255.53);
|
|
724
743
|
/* slate-200 */
|
|
725
744
|
--nx-sidebar-ring: var(--nx-primary);
|
|
726
745
|
|
|
@@ -746,7 +765,10 @@
|
|
|
746
765
|
* read as distinct surfaces in dark mode instead of merging into the page */
|
|
747
766
|
--nx-card-foreground: oklch(0.9838 0.0035 247.86);
|
|
748
767
|
/* slate-50 */
|
|
749
|
-
|
|
768
|
+
/* Darkened toward the card elevation so borders, inputs, and muted text
|
|
769
|
+
* placed on a popover clear their WCAG minimums (border was 2.85:1, input
|
|
770
|
+
* 1.73:1); the surface was too light for its own contents. */
|
|
771
|
+
--nx-popover: oklch(0.24 0.0249 257.44);
|
|
750
772
|
/* slate-800 */
|
|
751
773
|
--nx-popover-foreground: oklch(0.9838 0.0035 247.86);
|
|
752
774
|
/* slate-50 */
|
|
@@ -773,13 +795,23 @@
|
|
|
773
795
|
--nx-accent-foreground: oklch(1 0 0);
|
|
774
796
|
/* white */
|
|
775
797
|
|
|
776
|
-
/* State colors - WCAG 2.2 AA Compliant (Dark Mode)
|
|
777
|
-
|
|
778
|
-
|
|
798
|
+
/* State colors - WCAG 2.2 AA Compliant (Dark Mode).
|
|
799
|
+
* The base token is lightened from the fill color so it reads as text on the
|
|
800
|
+
* dark page at 4.5:1; `-solid` keeps the darker fill so white on-color text
|
|
801
|
+
* on buttons still clears 4.5:1. Warning is already light enough to read on
|
|
802
|
+
* dark, so its base is unchanged here. */
|
|
803
|
+
/* Lightened red so it reads as text at WCAG 4.5:1 on the dark page and on the
|
|
804
|
+
* lighter popover surface (was 4.17:1 on the page, 4.25:1 on a popover). */
|
|
805
|
+
--nx-destructive: oklch(0.65 0.2078 25.33);
|
|
806
|
+
/* Darker red fill so white on-color button text clears 4.5:1. */
|
|
807
|
+
--nx-destructive-solid: oklch(0.5778 0.2078 25.33);
|
|
779
808
|
--nx-destructive-foreground: oklch(1 0 0);
|
|
780
809
|
/* white */
|
|
781
|
-
|
|
782
|
-
|
|
810
|
+
/* Lightened green so it reads as text at WCAG 4.5:1 on the dark page and on
|
|
811
|
+
* the lighter popover surface (was 4.17:1 on the page, 4.29:1 on a popover). */
|
|
812
|
+
--nx-success: oklch(0.6 0.1921 149.58);
|
|
813
|
+
/* Darker green fill so white on-color button text clears 4.5:1. */
|
|
814
|
+
--nx-success-solid: oklch(0.5225 0.1921 149.58);
|
|
783
815
|
--nx-success-foreground: oklch(1 0 0);
|
|
784
816
|
/* white */
|
|
785
817
|
--nx-warning: oklch(0.7686 0.1646 70.11);
|
|
@@ -815,11 +847,13 @@
|
|
|
815
847
|
* Recomputed as white-over-dark alpha (not a flipped hex) so dividers read
|
|
816
848
|
* on the deep background without glowing. Was ~1.2:1 (too faint). */
|
|
817
849
|
--nx-border-subtle: oklch(1 0 0 / 0.08);
|
|
818
|
-
|
|
819
|
-
--nx-border
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
850
|
+
/* Alpha raised so the composited border clears WCAG 3:1 on the page (was 1.36:1). */
|
|
851
|
+
--nx-border: oklch(1 0 0 / 0.366);
|
|
852
|
+
/* Alpha raised so the composited strong border clears WCAG 3:1 / ~4:1 (was 3.00:1). */
|
|
853
|
+
--nx-border-strong: oklch(1 0 0 / 0.418);
|
|
854
|
+
/* Brightened so the field border clears WCAG 3:1 on the lighter popover
|
|
855
|
+
* surface as well as the page and card (was 1.73:1 on a popover). */
|
|
856
|
+
--nx-input: oklch(0.54 0.0128 285.92);
|
|
823
857
|
--nx-ring: var(--nx-primary);
|
|
824
858
|
|
|
825
859
|
/* Chart colors for data visualization (same as light mode) */
|
|
@@ -846,8 +880,8 @@
|
|
|
846
880
|
/* slate-800 */
|
|
847
881
|
--nx-sidebar-accent-foreground: oklch(0.9838 0.0035 247.86);
|
|
848
882
|
/* slate-50 */
|
|
849
|
-
|
|
850
|
-
|
|
883
|
+
/* Lightened so the sidebar border clears WCAG 3:1 on its surface (was 1.19:1). */
|
|
884
|
+
--nx-sidebar-border: oklch(0.4975 0.0129 257.43);
|
|
851
885
|
--nx-sidebar-ring: var(--nx-primary);
|
|
852
886
|
|
|
853
887
|
/* Data table specific colors - dark mode */
|
package/dist/utils.cjs
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var clsx = require('clsx');
|
|
4
|
+
var tailwindMerge = require('tailwind-merge');
|
|
5
|
+
|
|
6
|
+
// src/lib/utils.ts
|
|
7
|
+
function cn(...inputs) {
|
|
8
|
+
return tailwindMerge.twMerge(clsx.clsx(inputs));
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
exports.cn = cn;
|
|
12
|
+
//# sourceMappingURL=utils.cjs.map
|
|
13
|
+
//# sourceMappingURL=utils.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/utils.ts"],"names":["twMerge","clsx"],"mappings":";;;;;;AAeO,SAAS,MAAM,MAAA,EAAsB;AAC1C,EAAA,OAAOA,qBAAA,CAAQC,SAAA,CAAK,MAAM,CAAC,CAAA;AAC7B","file":"utils.cjs","sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Utility function to merge class names with Tailwind CSS support.\n *\n * Combines clsx for conditional class names with tailwind-merge\n * to properly handle Tailwind CSS class conflicts.\n *\n * @example\n * ```typescript\n * cn('px-2 py-1', 'px-4') // => 'py-1 px-4'\n * cn('text-muted-foreground', condition && 'text-foreground')\n * ```\n */\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n"]}
|
package/dist/utils.d.cts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ClassValue } from 'clsx';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Utility function to merge class names with Tailwind CSS support.
|
|
5
|
+
*
|
|
6
|
+
* Combines clsx for conditional class names with tailwind-merge
|
|
7
|
+
* to properly handle Tailwind CSS class conflicts.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* cn('px-2 py-1', 'px-4') // => 'py-1 px-4'
|
|
12
|
+
* cn('text-muted-foreground', condition && 'text-foreground')
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
declare function cn(...inputs: ClassValue[]): string;
|
|
16
|
+
|
|
17
|
+
export { cn };
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ClassValue } from 'clsx';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Utility function to merge class names with Tailwind CSS support.
|
|
5
|
+
*
|
|
6
|
+
* Combines clsx for conditional class names with tailwind-merge
|
|
7
|
+
* to properly handle Tailwind CSS class conflicts.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* cn('px-2 py-1', 'px-4') // => 'py-1 px-4'
|
|
12
|
+
* cn('text-muted-foreground', condition && 'text-foreground')
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
declare function cn(...inputs: ClassValue[]): string;
|
|
16
|
+
|
|
17
|
+
export { cn };
|
package/dist/utils.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/utils.ts"],"names":[],"mappings":";;;;AAeO,SAAS,MAAM,MAAA,EAAsB;AAC1C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC7B","file":"utils.mjs","sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Utility function to merge class names with Tailwind CSS support.\n *\n * Combines clsx for conditional class names with tailwind-merge\n * to properly handle Tailwind CSS class conflicts.\n *\n * @example\n * ```typescript\n * cn('px-2 py-1', 'px-4') // => 'py-1 px-4'\n * cn('text-muted-foreground', condition && 'text-foreground')\n * ```\n */\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n"]}
|
|
@@ -20,8 +20,8 @@ points:
|
|
|
20
20
|
| `@nextlyhq/ui/styles.css` | Pre-compiled bundle (Tailwind + tokens + reset). Zero config. | Standalone UI, or a quick embed with no build wiring. |
|
|
21
21
|
|
|
22
22
|
**Inside a Nextly admin plugin you usually need neither.** The admin already loads
|
|
23
|
-
`@nextlyhq/admin/style.css`, which defines every token scoped to `.
|
|
24
|
-
`.
|
|
23
|
+
`@nextlyhq/admin/style.css`, which defines every token scoped to `.nextly-admin` (and
|
|
24
|
+
`.nextly-admin.dark` for dark mode). Plugin admin views render inside that scope, so the tokens
|
|
25
25
|
are already on the page. Your plugin CSS should **consume** those tokens, never redefine
|
|
26
26
|
them.
|
|
27
27
|
|
|
@@ -36,52 +36,52 @@ Tokens are **complete color values** (OKLCH). Reference them directly:
|
|
|
36
36
|
|
|
37
37
|
```css
|
|
38
38
|
.my-panel {
|
|
39
|
-
background: var(--card);
|
|
40
|
-
color: var(--foreground);
|
|
41
|
-
border: 1px solid var(--border);
|
|
39
|
+
background: var(--nx-card);
|
|
40
|
+
color: var(--nx-foreground);
|
|
41
|
+
border: 1px solid var(--nx-border);
|
|
42
42
|
border-radius: var(--radius);
|
|
43
43
|
}
|
|
44
44
|
```
|
|
45
45
|
|
|
46
46
|
### Never wrap a token in `hsl()` / `rgb()`
|
|
47
47
|
|
|
48
|
-
Older Nextly builds stored tokens as bare HSL channels (`--primary: 221 83% 53%`) and code
|
|
49
|
-
wrapped them: `hsl(var(--primary))`. **That convention is gone.** Tokens are now full colors
|
|
50
|
-
(`--primary: oklch(0 0 0)`), so `hsl(var(--primary))` becomes `hsl(oklch(0 0 0))`, which is
|
|
48
|
+
Older Nextly builds stored tokens as bare HSL channels (`--nx-primary: 221 83% 53%`) and code
|
|
49
|
+
wrapped them: `hsl(var(--nx-primary))`. **That convention is gone.** Tokens are now full colors
|
|
50
|
+
(`--nx-primary: oklch(0 0 0)`), so `hsl(var(--nx-primary))` becomes `hsl(oklch(0 0 0))`, which is
|
|
51
51
|
invalid CSS — the browser drops the declaration and your element loses its color. Always:
|
|
52
52
|
|
|
53
53
|
```css
|
|
54
54
|
/* ✗ wrong — produces hsl(oklch(...)), silently dropped */
|
|
55
|
-
color: hsl(var(--foreground));
|
|
55
|
+
color: hsl(var(--nx-foreground));
|
|
56
56
|
|
|
57
57
|
/* ✓ right */
|
|
58
|
-
color: var(--foreground);
|
|
58
|
+
color: var(--nx-foreground);
|
|
59
59
|
```
|
|
60
60
|
|
|
61
61
|
### Alpha / transparency
|
|
62
62
|
|
|
63
|
-
You can no longer do `hsl(var(--primary) / 0.1)`. Use `color-mix`:
|
|
63
|
+
You can no longer do `hsl(var(--nx-primary) / 0.1)`. Use `color-mix`:
|
|
64
64
|
|
|
65
65
|
```css
|
|
66
66
|
/* 10% primary over transparent */
|
|
67
|
-
background: color-mix(in srgb, var(--primary) 10%, transparent);
|
|
67
|
+
background: color-mix(in srgb, var(--nx-primary) 10%, transparent);
|
|
68
68
|
|
|
69
69
|
/* a subtle hover tint from the foreground */
|
|
70
|
-
background: color-mix(in srgb, var(--foreground) 6%, transparent);
|
|
70
|
+
background: color-mix(in srgb, var(--nx-foreground) 6%, transparent);
|
|
71
71
|
```
|
|
72
72
|
|
|
73
73
|
### The tokens you may use
|
|
74
74
|
|
|
75
|
-
Colors: `--background` / `--foreground`, `--card` / `--card-foreground`,
|
|
76
|
-
`--popover` / `--popover-foreground`, `--primary` / `--primary-foreground`,
|
|
77
|
-
`--secondary` / `--secondary-foreground`, `--muted` / `--muted-foreground`,
|
|
78
|
-
`--accent` / `--accent-foreground`, `--destructive`, `--success`, `--warning`,
|
|
79
|
-
`--border`, `--border-strong`, `--input`, `--ring`,
|
|
80
|
-
`--sidebar-background` and the `--sidebar-*` family.
|
|
75
|
+
Colors: `--nx-background` / `--nx-foreground`, `--nx-card` / `--nx-card-foreground`,
|
|
76
|
+
`--nx-popover` / `--nx-popover-foreground`, `--nx-primary` / `--nx-primary-foreground`,
|
|
77
|
+
`--nx-secondary` / `--nx-secondary-foreground`, `--nx-muted` / `--nx-muted-foreground`,
|
|
78
|
+
`--nx-accent` / `--nx-accent-foreground`, `--nx-destructive`, `--nx-success`, `--nx-warning`,
|
|
79
|
+
`--nx-border`, `--nx-border-strong`, `--nx-input`, `--nx-ring`,
|
|
80
|
+
`--nx-sidebar-background` and the `--nx-sidebar-*` family.
|
|
81
81
|
|
|
82
82
|
Sizing: `--radius` (the system is square — this is `0`; always route corner radius through
|
|
83
|
-
it so a future rounding is one edit), and the control-height scale `--control-height`,
|
|
84
|
-
`--control-height-sm`, `--control-height-md`, `--control-height-lg` for anything that should
|
|
83
|
+
it so a future rounding is one edit), and the control-height scale `--nx-control-height`,
|
|
84
|
+
`--nx-control-height-sm`, `--nx-control-height-md`, `--nx-control-height-lg` for anything that should
|
|
85
85
|
line up with admin inputs and buttons.
|
|
86
86
|
|
|
87
87
|
Do not hardcode hex, `rgb()`, `rgba()`, or named colors. The only literals allowed are
|
|
@@ -96,7 +96,7 @@ a stylesheet. They are already token-driven, accessible, and dark-mode-correct.
|
|
|
96
96
|
|
|
97
97
|
```tsx
|
|
98
98
|
import { Button, Input, Select, Switch, Badge } from "@nextlyhq/ui";
|
|
99
|
-
import { cn } from "@nextlyhq/ui";
|
|
99
|
+
import { cn } from "@nextlyhq/ui/utils";
|
|
100
100
|
|
|
101
101
|
<Button variant="outline" size="sm">Add field</Button>
|
|
102
102
|
<Input placeholder="Form name" />
|
|
@@ -114,13 +114,13 @@ control). When you write it, it must obey the token contract in section 2 and be
|
|
|
114
114
|
|
|
115
115
|
## 4. Dark mode is automatic — don't fight it
|
|
116
116
|
|
|
117
|
-
The admin flips every token under `.
|
|
117
|
+
The admin flips every token under `.nextly-admin.dark`. If you only ever reference tokens, your
|
|
118
118
|
UI switches with it and you never write a dark rule.
|
|
119
119
|
|
|
120
120
|
- **Never** hardcode a light or dark color.
|
|
121
121
|
- **Never** gate admin theming on `@media (prefers-color-scheme: dark)` — admin dark mode is
|
|
122
|
-
class-based (`.dark` / `.
|
|
123
|
-
UI ignore the admin's own theme toggle. Use Tailwind's `dark:` variant or `.
|
|
122
|
+
class-based (`.dark` / `.nextly-admin.dark`), independent of the OS. A media query makes your
|
|
123
|
+
UI ignore the admin's own theme toggle. Use Tailwind's `dark:` variant or `.nextly-admin.dark`
|
|
124
124
|
descendant selectors if you truly need a mode-specific tweak.
|
|
125
125
|
|
|
126
126
|
---
|
|
@@ -169,7 +169,7 @@ allowlist in the script with a one-line reason — don't silence the whole check
|
|
|
169
169
|
|
|
170
170
|
- [ ] Colors come from `var(--token)` — no `hsl()`/`rgb()` wrappers, no hardcoded values.
|
|
171
171
|
- [ ] Alpha uses `color-mix(in srgb, var(--token) N%, transparent)`.
|
|
172
|
-
- [ ] Corner radius routes through `var(--radius)`; control heights use `--control-height*`.
|
|
172
|
+
- [ ] Corner radius routes through `var(--radius)`; control heights use `--nx-control-height*`.
|
|
173
173
|
- [ ] New UI uses `@nextlyhq/ui` components + Tailwind utilities where practical.
|
|
174
174
|
- [ ] No `@media (prefers-color-scheme)`; dark mode inherited from the admin.
|
|
175
175
|
- [ ] Class names are prefixed/scoped; no bare element selectors.
|