@nextlyhq/ui 0.0.2-alpha.37 → 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 +860 -656
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -95
- package/dist/index.d.ts +1 -95
- package/dist/index.mjs +609 -385
- 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/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 +41 -10
|
@@ -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/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.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nextlyhq/ui",
|
|
3
|
-
"version": "0.0.2-alpha.
|
|
3
|
+
"version": "0.0.2-alpha.39",
|
|
4
4
|
"description": "Nextly UI — Reusable React component library for Nextly plugins and custom admin UIs",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"keywords": [
|
|
@@ -17,13 +17,42 @@
|
|
|
17
17
|
"types": "dist/index.d.ts",
|
|
18
18
|
"exports": {
|
|
19
19
|
".": {
|
|
20
|
-
"
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
"import": {
|
|
21
|
+
"types": "./dist/index.d.ts",
|
|
22
|
+
"default": "./dist/index.mjs"
|
|
23
|
+
},
|
|
24
|
+
"require": {
|
|
25
|
+
"types": "./dist/index.d.cts",
|
|
26
|
+
"default": "./dist/index.cjs"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"./tailwind-preset": {
|
|
30
|
+
"import": {
|
|
31
|
+
"types": "./dist/tailwind-preset.d.ts",
|
|
32
|
+
"default": "./dist/tailwind-preset.mjs"
|
|
33
|
+
},
|
|
34
|
+
"require": {
|
|
35
|
+
"types": "./dist/tailwind-preset.d.cts",
|
|
36
|
+
"default": "./dist/tailwind-preset.cjs"
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"./utils": {
|
|
40
|
+
"import": {
|
|
41
|
+
"types": "./dist/utils.d.ts",
|
|
42
|
+
"default": "./dist/utils.mjs"
|
|
43
|
+
},
|
|
44
|
+
"require": {
|
|
45
|
+
"types": "./dist/utils.d.cts",
|
|
46
|
+
"default": "./dist/utils.cjs"
|
|
47
|
+
}
|
|
23
48
|
},
|
|
24
49
|
"./theme.css": "./dist/theme.css",
|
|
25
|
-
"./styles.css": "./dist/styles.css"
|
|
50
|
+
"./styles.css": "./dist/styles.css",
|
|
51
|
+
"./styles.scoped.css": "./dist/styles.scoped.css"
|
|
26
52
|
},
|
|
53
|
+
"sideEffects": [
|
|
54
|
+
"**/*.css"
|
|
55
|
+
],
|
|
27
56
|
"files": [
|
|
28
57
|
"dist",
|
|
29
58
|
"docs"
|
|
@@ -51,13 +80,15 @@
|
|
|
51
80
|
"postcss": "^8.5.6",
|
|
52
81
|
"react": "19.2.0",
|
|
53
82
|
"react-dom": "19.2.0",
|
|
83
|
+
"rimraf": "^6.1.3",
|
|
54
84
|
"tailwindcss": "^4.3.2",
|
|
55
85
|
"tsup": "^8.5.0",
|
|
56
86
|
"typescript": "^5.9.3",
|
|
57
87
|
"vite-tsconfig-paths": "^5.1.4",
|
|
58
88
|
"vitest": "^4.1.0",
|
|
59
|
-
"@nextlyhq/
|
|
60
|
-
"@nextlyhq/tsconfig": "0.0.2-alpha.
|
|
89
|
+
"@nextlyhq/admin-css": "0.0.2-alpha.39",
|
|
90
|
+
"@nextlyhq/tsconfig": "0.0.2-alpha.39",
|
|
91
|
+
"@nextlyhq/eslint-config": "0.0.2-alpha.39"
|
|
61
92
|
},
|
|
62
93
|
"dependencies": {
|
|
63
94
|
"@radix-ui/react-accordion": "^1.2.12",
|
|
@@ -98,10 +129,10 @@
|
|
|
98
129
|
},
|
|
99
130
|
"author": "Nextly <contact@nextlyhq.com> (https://nextlyhq.com)",
|
|
100
131
|
"scripts": {
|
|
101
|
-
"build": "
|
|
102
|
-
"build:js": "tsup",
|
|
132
|
+
"build": "pnpm build:js && node scripts/build-css.mjs",
|
|
133
|
+
"build:js": "rimraf dist && tsup && tsup --config tsup.server-safe.config.ts && node scripts/check-client-directive.mjs",
|
|
103
134
|
"build:css": "node scripts/build-css.mjs",
|
|
104
|
-
"dev": "tsup --watch",
|
|
135
|
+
"dev": "tsup --watch & tsup --config tsup.server-safe.config.ts --watch & wait",
|
|
105
136
|
"check-types": "tsc --noEmit",
|
|
106
137
|
"lint": "eslint . --max-warnings 0",
|
|
107
138
|
"lint:fix": "eslint . --fix",
|