@ponchia/ui 0.3.6 → 0.4.0
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/CHANGELOG.md +945 -0
- package/README.md +16 -6
- package/classes/index.d.ts +1 -0
- package/classes/index.js +1 -0
- package/classes/vscode.css-custom-data.json +4 -12
- package/css/dataviz.css +96 -0
- package/css/dots.css +30 -2
- package/css/skins.css +54 -0
- package/css/tokens.css +4 -10
- package/dist/bronto.css +1 -1
- package/dist/css/dataviz.css +1 -0
- package/dist/css/dots.css +1 -1
- package/dist/css/skins.css +1 -0
- package/dist/css/tokens.css +1 -1
- package/docs/adr/0001-color-system.md +272 -0
- package/docs/contrast.md +170 -51
- package/docs/reference.md +11 -9
- package/docs/theming.md +66 -1
- package/docs/usage.md +46 -5
- package/glyphs/glyphs.d.ts +14 -1
- package/glyphs/glyphs.js +143 -2
- package/llms.txt +43 -4
- package/package.json +54 -5
- package/react/index.d.ts +36 -0
- package/react/index.js +67 -0
- package/solid/index.d.ts +36 -0
- package/solid/index.js +67 -0
- package/tokens/charts.d.ts +37 -0
- package/tokens/charts.js +96 -0
- package/tokens/charts.json +61 -0
- package/tokens/index.d.ts +3 -3
- package/tokens/index.js +4 -8
- package/tokens/index.json +8 -16
- package/tokens/resolved.json +9 -13
- package/tokens/skins.d.ts +27 -0
- package/tokens/skins.js +62 -0
- package/tokens/tokens.dtcg.json +4 -24
package/solid/index.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @ponchia/ui/solid — thin Solid bindings over @ponchia/ui/behaviors.
|
|
3
|
+
*
|
|
4
|
+
* The CSS is the framework; these are *optional* primitives that wrap the
|
|
5
|
+
* SSR-safe vanilla `init*` behaviors in Solid's lifecycle (run on mount, clean
|
|
6
|
+
* up on dispose). Thin adapters, not a component library (architecture ADR).
|
|
7
|
+
* `solid-js` is an optional peer dependency.
|
|
8
|
+
*
|
|
9
|
+
* Behaviors delegate from a root (default `document`); call a primitive once in
|
|
10
|
+
* a component that owns the relevant subtree, `{ root: el }` to scope it.
|
|
11
|
+
*
|
|
12
|
+
* import { useDialog, useToast } from '@ponchia/ui/solid';
|
|
13
|
+
* function App() {
|
|
14
|
+
* useDialog(); // wires every .ui-modal under document
|
|
15
|
+
* const toast = useToast();
|
|
16
|
+
* return <button onClick={() => toast('Saved', { tone: 'success' })}>Save</button>;
|
|
17
|
+
* }
|
|
18
|
+
*/
|
|
19
|
+
import { onMount, onCleanup } from 'solid-js';
|
|
20
|
+
import {
|
|
21
|
+
applyStoredTheme,
|
|
22
|
+
initThemeToggle,
|
|
23
|
+
dismissible,
|
|
24
|
+
initDisclosure,
|
|
25
|
+
initMenu,
|
|
26
|
+
initFormValidation,
|
|
27
|
+
initCombobox,
|
|
28
|
+
initPopover,
|
|
29
|
+
initTableSort,
|
|
30
|
+
initTabs,
|
|
31
|
+
initDialog,
|
|
32
|
+
initCarousel,
|
|
33
|
+
initDotGlyph,
|
|
34
|
+
toast,
|
|
35
|
+
} from '../behaviors/index.js';
|
|
36
|
+
|
|
37
|
+
/** Run a delegated behavior for the component's lifetime (init on mount, its
|
|
38
|
+
* returned cleanup on dispose). */
|
|
39
|
+
export function useBrontoBehavior(init, opts) {
|
|
40
|
+
onMount(() => {
|
|
41
|
+
const cleanup = init(opts);
|
|
42
|
+
if (typeof cleanup === 'function') onCleanup(cleanup);
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export const useThemeToggle = (opts) => useBrontoBehavior(initThemeToggle, opts);
|
|
47
|
+
export const useDismissible = (opts) => useBrontoBehavior(dismissible, opts);
|
|
48
|
+
export const useDisclosure = (opts) => useBrontoBehavior(initDisclosure, opts);
|
|
49
|
+
export const useMenu = (opts) => useBrontoBehavior(initMenu, opts);
|
|
50
|
+
export const useFormValidation = (opts) => useBrontoBehavior(initFormValidation, opts);
|
|
51
|
+
export const useCombobox = (opts) => useBrontoBehavior(initCombobox, opts);
|
|
52
|
+
export const usePopover = (opts) => useBrontoBehavior(initPopover, opts);
|
|
53
|
+
export const useTableSort = (opts) => useBrontoBehavior(initTableSort, opts);
|
|
54
|
+
export const useTabs = (opts) => useBrontoBehavior(initTabs, opts);
|
|
55
|
+
export const useDialog = (opts) => useBrontoBehavior(initDialog, opts);
|
|
56
|
+
export const useCarousel = (opts) => useBrontoBehavior(initCarousel, opts);
|
|
57
|
+
export const useDotGlyph = (opts) => useBrontoBehavior(initDotGlyph, opts);
|
|
58
|
+
|
|
59
|
+
/** The `toast()` imperative (no lifecycle of its own). */
|
|
60
|
+
export const useToast = () => toast;
|
|
61
|
+
|
|
62
|
+
// No-flash theme application must run before paint — do it in an inline head
|
|
63
|
+
// script, not on mount. Re-exported for manual/SSR-bootstrap use.
|
|
64
|
+
export { applyStoredTheme };
|
|
65
|
+
|
|
66
|
+
// Convenience: the framework-agnostic class contract, re-exported.
|
|
67
|
+
export { cls, ui, cx } from '../classes/index.js';
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/** @ponchia/ui — GENERATED from tokens/charts.js by scripts/gen-charts.mjs.
|
|
2
|
+
* Do not edit by hand; run `npm run charts:build`. Drift-checked in CI. */
|
|
3
|
+
|
|
4
|
+
/** A theme's data-viz palette. Values are CSS colour strings (OKLCH for the
|
|
5
|
+
* authored series; `var(--accent)` for series 1). For resolved sRGB **hex**
|
|
6
|
+
* (canvas/SVG/charting libs), import `@ponchia/ui/charts.json` instead. */
|
|
7
|
+
export interface ChartTheme {
|
|
8
|
+
/** 8 distinct series colours (index 0 = `var(--accent)`, the brand). */
|
|
9
|
+
categorical: string[];
|
|
10
|
+
/** Single-hue sequential ramp (light→dark), for heatmaps/intensity. */
|
|
11
|
+
sequential: string[];
|
|
12
|
+
/** Diverging ramp (− … neutral … +), for gains/losses. */
|
|
13
|
+
diverging: string[];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** The categorical CSS custom-property names (1-based; `--chart-1` = the accent). */
|
|
17
|
+
export type ChartTokenName =
|
|
18
|
+
| '--chart-1'
|
|
19
|
+
| '--chart-2'
|
|
20
|
+
| '--chart-3'
|
|
21
|
+
| '--chart-4'
|
|
22
|
+
| '--chart-5'
|
|
23
|
+
| '--chart-6'
|
|
24
|
+
| '--chart-7'
|
|
25
|
+
| '--chart-8';
|
|
26
|
+
|
|
27
|
+
/** The opt-in data-viz palette source, per theme (CSS colour strings). */
|
|
28
|
+
export declare const charts: { light: ChartTheme; dark: ChartTheme };
|
|
29
|
+
|
|
30
|
+
/** Series 1 sentinel — the live brand accent. */
|
|
31
|
+
export declare const ACCENT: 'var(--accent)';
|
|
32
|
+
|
|
33
|
+
export declare const CHART_CATEGORICAL: 8;
|
|
34
|
+
export declare const CHART_PATTERN_COUNT: 8;
|
|
35
|
+
|
|
36
|
+
declare const _default: { light: ChartTheme; dark: ChartTheme };
|
|
37
|
+
export default _default;
|
package/tokens/charts.js
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @ponchia/ui — Tier-4 data-viz colour module (ADR-0001 step 7).
|
|
3
|
+
*
|
|
4
|
+
* The single source for the opt-in chart palette (`@ponchia/ui/css/dataviz.css`
|
|
5
|
+
* + `tokens/charts.json`). **Charts only, never UI chrome** — `check-color-policy`
|
|
6
|
+
* forbids `var(--chart-*)` in core component CSS. Opt-in: a separate entrypoint,
|
|
7
|
+
* never in the default bundle.
|
|
8
|
+
*
|
|
9
|
+
* Hybrid accent-led: **series 1 is the live `var(--accent)`** (the brand stays
|
|
10
|
+
* series 1, so it re-themes/-skins for free); series 2–8 are an Okabe-Ito-derived
|
|
11
|
+
* colourblind-safe set, authored in OKLCH per-theme (darker in light, brighter
|
|
12
|
+
* in dark) and **gated for pairwise distinguishability under normal + simulated
|
|
13
|
+
* protan/deutan/tritan vision** (scripts/check-charts.mjs). Series 8 is a neutral
|
|
14
|
+
* grey (on-brand, and a useful "other"/baseline series).
|
|
15
|
+
*
|
|
16
|
+
* Colour is never the sole signal: `--chart-pattern-1..8` ship a matching
|
|
17
|
+
* dot-matrix pattern per series (WCAG 1.4.1). Use colour N WITH pattern N.
|
|
18
|
+
*
|
|
19
|
+
* Generated → drift-checked: css/dataviz.css, tokens/charts.json (resolved hex
|
|
20
|
+
* for JS/canvas/SVG/charting libs), tokens/charts.d.ts.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
/** Series 1 is the live accent (a CSS var, not a fixed hue). Resolved to the
|
|
24
|
+
* theme accent for the JSON/gate. */
|
|
25
|
+
export const ACCENT = 'var(--accent)';
|
|
26
|
+
|
|
27
|
+
/** Series 2–8 — the Okabe-Ito colourblind-safe set, used **verbatim** (the same
|
|
28
|
+
* hues both themes). Authored as sRGB hex on purpose: Okabe-Ito is a published,
|
|
29
|
+
* CVD-proven *set*, and round-tripping through OKLCH (or re-spacing per theme)
|
|
30
|
+
* breaks the careful lightness relationships that make it colourblind-safe —
|
|
31
|
+
* which the CVD gate caught. Series 1 (the accent, per-theme) replaces
|
|
32
|
+
* Okabe-Ito's vermillion; a dark slate-grey is the 8th (a CVD-distinct "other"
|
|
33
|
+
* / baseline, far enough in lightness from the reddish-purple to clear deutan).
|
|
34
|
+
* The sequential/diverging ramps below ARE authored in OKLCH (new work). */
|
|
35
|
+
const FILLS = [
|
|
36
|
+
'#e69f00', // 2 orange
|
|
37
|
+
'#56b4e9', // 3 sky blue
|
|
38
|
+
'#009e73', // 4 bluish green
|
|
39
|
+
'#f0e442', // 5 yellow
|
|
40
|
+
'#0072b2', // 6 blue
|
|
41
|
+
'#cc79a7', // 7 reddish purple
|
|
42
|
+
'#4d5358', // 8 dark slate (CVD-distinct neutral)
|
|
43
|
+
];
|
|
44
|
+
|
|
45
|
+
export const charts = {
|
|
46
|
+
light: {
|
|
47
|
+
categorical: [ACCENT, ...FILLS],
|
|
48
|
+
sequential: [
|
|
49
|
+
'oklch(94% 0.03 25deg)',
|
|
50
|
+
'oklch(85% 0.07 25deg)',
|
|
51
|
+
'oklch(74% 0.12 25deg)',
|
|
52
|
+
'oklch(62% 0.16 25deg)',
|
|
53
|
+
'oklch(50% 0.16 25deg)',
|
|
54
|
+
'oklch(38% 0.13 25deg)',
|
|
55
|
+
],
|
|
56
|
+
diverging: [
|
|
57
|
+
'oklch(45% 0.14 255deg)', // − strong blue
|
|
58
|
+
'oklch(62% 0.1 250deg)',
|
|
59
|
+
'oklch(82% 0.05 245deg)',
|
|
60
|
+
'oklch(90% 0.01 250deg)', // mid neutral
|
|
61
|
+
'oklch(80% 0.07 60deg)',
|
|
62
|
+
'oklch(66% 0.13 55deg)',
|
|
63
|
+
'oklch(56% 0.15 45deg)', // + strong orange
|
|
64
|
+
],
|
|
65
|
+
},
|
|
66
|
+
dark: {
|
|
67
|
+
categorical: [ACCENT, ...FILLS],
|
|
68
|
+
sequential: [
|
|
69
|
+
'oklch(30% 0.1 25deg)',
|
|
70
|
+
'oklch(42% 0.15 25deg)',
|
|
71
|
+
'oklch(55% 0.17 25deg)',
|
|
72
|
+
'oklch(68% 0.15 25deg)',
|
|
73
|
+
'oklch(80% 0.1 25deg)',
|
|
74
|
+
'oklch(90% 0.05 25deg)',
|
|
75
|
+
],
|
|
76
|
+
diverging: [
|
|
77
|
+
'oklch(70% 0.13 250deg)', // − blue
|
|
78
|
+
'oklch(60% 0.12 252deg)',
|
|
79
|
+
'oklch(48% 0.08 255deg)',
|
|
80
|
+
'oklch(40% 0.01 250deg)', // mid neutral
|
|
81
|
+
'oklch(58% 0.1 60deg)',
|
|
82
|
+
'oklch(72% 0.13 58deg)',
|
|
83
|
+
'oklch(80% 0.12 55deg)', // + orange
|
|
84
|
+
],
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
/** Pattern fills — dot-matrix CSS background-images, the second (non-colour)
|
|
89
|
+
* channel per series. Each uses `--chart-pattern-ink` (set it to the series
|
|
90
|
+
* colour). Index matches the categorical series. */
|
|
91
|
+
export const CHART_PATTERN_COUNT = 8;
|
|
92
|
+
|
|
93
|
+
/** Number of categorical series. */
|
|
94
|
+
export const CHART_CATEGORICAL = 8;
|
|
95
|
+
|
|
96
|
+
export default charts;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$comment": "@ponchia/ui data-viz palette resolved to static hex per theme, for non-CSS render targets (canvas/SVG/charting libs). Series 1 = the resolved brand accent. Generated from tokens/charts.js — do not edit by hand; run `npm run charts:build`. Drift-checked in CI.",
|
|
3
|
+
"light": {
|
|
4
|
+
"categorical": [
|
|
5
|
+
"#d71921",
|
|
6
|
+
"#e69f00",
|
|
7
|
+
"#56b4e9",
|
|
8
|
+
"#009e73",
|
|
9
|
+
"#f0e442",
|
|
10
|
+
"#0072b2",
|
|
11
|
+
"#cc79a7",
|
|
12
|
+
"#4d5358"
|
|
13
|
+
],
|
|
14
|
+
"sequential": [
|
|
15
|
+
"#ffe4e1",
|
|
16
|
+
"#f9bdb7",
|
|
17
|
+
"#ed8c84",
|
|
18
|
+
"#d55753",
|
|
19
|
+
"#ac3031",
|
|
20
|
+
"#79191b"
|
|
21
|
+
],
|
|
22
|
+
"diverging": [
|
|
23
|
+
"#0c54a0",
|
|
24
|
+
"#558ac0",
|
|
25
|
+
"#aac8e3",
|
|
26
|
+
"#d9dfe5",
|
|
27
|
+
"#e0b491",
|
|
28
|
+
"#ce7a3b",
|
|
29
|
+
"#b95115"
|
|
30
|
+
]
|
|
31
|
+
},
|
|
32
|
+
"dark": {
|
|
33
|
+
"categorical": [
|
|
34
|
+
"#ff3b41",
|
|
35
|
+
"#e69f00",
|
|
36
|
+
"#56b4e9",
|
|
37
|
+
"#009e73",
|
|
38
|
+
"#f0e442",
|
|
39
|
+
"#0072b2",
|
|
40
|
+
"#cc79a7",
|
|
41
|
+
"#4d5358"
|
|
42
|
+
],
|
|
43
|
+
"sequential": [
|
|
44
|
+
"#551112",
|
|
45
|
+
"#8d1a1e",
|
|
46
|
+
"#c13c3b",
|
|
47
|
+
"#e66e68",
|
|
48
|
+
"#f8a49d",
|
|
49
|
+
"#fed2cd"
|
|
50
|
+
],
|
|
51
|
+
"diverging": [
|
|
52
|
+
"#5aa3ec",
|
|
53
|
+
"#4683c5",
|
|
54
|
+
"#3e5f8a",
|
|
55
|
+
"#44484d",
|
|
56
|
+
"#a56b38",
|
|
57
|
+
"#e18e4b",
|
|
58
|
+
"#f9a870"
|
|
59
|
+
]
|
|
60
|
+
}
|
|
61
|
+
}
|
package/tokens/index.d.ts
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
export type ThemeName = 'light' | 'dark';
|
|
5
5
|
|
|
6
6
|
export type GlobalTokenName = '--radius-xl' | '--radius-lg' | '--radius-md' | '--radius-sm' | '--radius-pill' | '--space-2xs' | '--space-xs' | '--space-sm' | '--space-md' | '--space-lg' | '--space-xl' | '--space-2xl' | '--mono' | '--sans' | '--dot-font' | '--display' | '--text-2xs' | '--text-xs' | '--text-sm' | '--text-base' | '--text-lg' | '--text-xl' | '--tracking-wide' | '--tracking-wider' | '--ease-standard' | '--ease-spring' | '--ease-out' | '--duration-fast' | '--duration-base' | '--duration-slow' | '--dot-size' | '--dot-gap' | '--z-base' | '--z-raised' | '--z-sticky' | '--z-overlay' | '--z-popover' | '--z-toast' | '--accent-1' | '--accent-2' | '--accent-3' | '--accent-4' | '--accent-5' | '--accent-6' | '--surface-1' | '--surface-2' | '--surface-3' | '--surface-4' | '--surface-5' | '--surface-6' | '--bronto-color-bg' | '--bronto-color-surface' | '--bronto-color-surface-raised' | '--bronto-color-border' | '--bronto-color-border-strong' | '--bronto-color-text' | '--bronto-color-text-muted' | '--bronto-color-action' | '--bronto-color-on-action' | '--bronto-color-focus' | '--bronto-color-success' | '--bronto-color-warning' | '--bronto-color-danger' | '--bronto-color-info' | '--surface' | '--surface-raised' | '--surface-muted' | '--border' | '--border-strong';
|
|
7
|
-
export type LightTokenName = '--bg' | '--bg-elevated' | '--bg-accent' | '--panel' | '--panel-strong' | '--panel-soft' | '--line' | '--line-strong' | '--text' | '--text-soft' | '--text-dim' | '--accent' | '--accent-strong' | '--accent-text' | '--accent-soft' | '--success' | '--success-soft' | '--warning' | '--warning-soft' | '--
|
|
8
|
-
export type DarkTokenName = '--bg' | '--bg-elevated' | '--bg-accent' | '--panel' | '--panel-strong' | '--panel-soft' | '--line' | '--line-strong' | '--text' | '--text-soft' | '--text-dim' | '--accent' | '--accent-strong' | '--accent-text' | '--accent-soft' | '--success' | '--success-soft' | '--warning' | '--warning-soft' | '--
|
|
7
|
+
export type LightTokenName = '--bg' | '--bg-elevated' | '--bg-accent' | '--panel' | '--panel-strong' | '--panel-soft' | '--line' | '--line-strong' | '--text' | '--text-soft' | '--text-dim' | '--accent' | '--accent-strong' | '--accent-text' | '--accent-soft' | '--success' | '--success-soft' | '--warning' | '--warning-soft' | '--danger' | '--danger-soft' | '--info' | '--info-soft' | '--code-bg' | '--button-text' | '--field-dot' | '--field-dot-hot' | '--field-dot-accent' | '--focus-ring' | '--shadow' | '--shadow-raised';
|
|
8
|
+
export type DarkTokenName = '--bg' | '--bg-elevated' | '--bg-accent' | '--panel' | '--panel-strong' | '--panel-soft' | '--line' | '--line-strong' | '--text' | '--text-soft' | '--text-dim' | '--accent' | '--accent-strong' | '--accent-text' | '--accent-soft' | '--success' | '--success-soft' | '--warning' | '--warning-soft' | '--danger' | '--danger-soft' | '--info' | '--info-soft' | '--code-bg' | '--button-text' | '--field-dot' | '--field-dot-hot' | '--field-dot-accent' | '--focus-ring' | '--shadow' | '--shadow-raised';
|
|
9
9
|
|
|
10
10
|
/** Exact mirror of the :root blocks in css/tokens.css (literal keys). */
|
|
11
11
|
export declare const cssVars: {
|
|
@@ -15,7 +15,7 @@ export declare const cssVars: {
|
|
|
15
15
|
};
|
|
16
16
|
|
|
17
17
|
export type ScaleKey = 'radius-xl' | 'radius-lg' | 'radius-md' | 'radius-sm' | 'radius-pill' | 'space-2xs' | 'space-xs' | 'space-sm' | 'space-md' | 'space-lg' | 'space-xl' | 'space-2xl' | 'mono' | 'sans' | 'dot-font' | 'display' | 'text-2xs' | 'text-xs' | 'text-sm' | 'text-base' | 'text-lg' | 'text-xl' | 'tracking-wide' | 'tracking-wider' | 'ease-standard' | 'ease-spring' | 'ease-out' | 'duration-fast' | 'duration-base' | 'duration-slow' | 'dot-size' | 'dot-gap' | 'z-base' | 'z-raised' | 'z-sticky' | 'z-overlay' | 'z-popover' | 'z-toast' | 'accent-1' | 'accent-2' | 'accent-3' | 'accent-4' | 'accent-5' | 'accent-6' | 'surface-1' | 'surface-2' | 'surface-3' | 'surface-4' | 'surface-5' | 'surface-6' | 'bronto-color-bg' | 'bronto-color-surface' | 'bronto-color-surface-raised' | 'bronto-color-border' | 'bronto-color-border-strong' | 'bronto-color-text' | 'bronto-color-text-muted' | 'bronto-color-action' | 'bronto-color-on-action' | 'bronto-color-focus' | 'bronto-color-success' | 'bronto-color-warning' | 'bronto-color-danger' | 'bronto-color-info' | 'surface' | 'surface-raised' | 'surface-muted' | 'border' | 'border-strong';
|
|
18
|
-
export type ColorKey = 'bg' | 'bg-elevated' | 'bg-accent' | 'panel' | 'panel-strong' | 'panel-soft' | 'line' | 'line-strong' | 'text' | 'text-soft' | 'text-dim' | 'accent' | 'accent-strong' | 'accent-text' | 'accent-soft' | 'success' | 'success-soft' | 'warning' | 'warning-soft' | '
|
|
18
|
+
export type ColorKey = 'bg' | 'bg-elevated' | 'bg-accent' | 'panel' | 'panel-strong' | 'panel-soft' | 'line' | 'line-strong' | 'text' | 'text-soft' | 'text-dim' | 'accent' | 'accent-strong' | 'accent-text' | 'accent-soft' | 'success' | 'success-soft' | 'warning' | 'warning-soft' | 'danger' | 'danger-soft' | 'info' | 'info-soft' | 'code-bg' | 'button-text' | 'field-dot' | 'field-dot-hot' | 'field-dot-accent' | 'focus-ring' | 'shadow' | 'shadow-raised';
|
|
19
19
|
|
|
20
20
|
/** Ergonomic view derived from {@link cssVars} (`--` prefix stripped). */
|
|
21
21
|
export declare const tokens: {
|
package/tokens/index.js
CHANGED
|
@@ -56,10 +56,10 @@ export const cssVars = {
|
|
|
56
56
|
'--z-overlay': '30',
|
|
57
57
|
'--z-popover': '50',
|
|
58
58
|
'--z-toast': '60',
|
|
59
|
-
'--accent-1': 'color-mix(in
|
|
60
|
-
'--accent-2': 'color-mix(in
|
|
61
|
-
'--accent-3': 'color-mix(in
|
|
62
|
-
'--accent-4': 'color-mix(in
|
|
59
|
+
'--accent-1': 'color-mix(in oklch, var(--accent) 8%, var(--bg))',
|
|
60
|
+
'--accent-2': 'color-mix(in oklch, var(--accent) 16%, var(--bg))',
|
|
61
|
+
'--accent-3': 'color-mix(in oklch, var(--accent) 32%, var(--bg))',
|
|
62
|
+
'--accent-4': 'color-mix(in oklch, var(--accent) 60%, var(--bg))',
|
|
63
63
|
'--accent-5': 'var(--accent)',
|
|
64
64
|
'--accent-6': 'var(--accent-strong)',
|
|
65
65
|
'--surface-1': 'var(--bg)',
|
|
@@ -109,8 +109,6 @@ export const cssVars = {
|
|
|
109
109
|
'--success-soft': 'rgb(47, 125, 79, 0.12)',
|
|
110
110
|
'--warning': '#806414',
|
|
111
111
|
'--warning-soft': 'rgb(128, 100, 20, 0.13)',
|
|
112
|
-
'--orange': '#a85f32',
|
|
113
|
-
'--orange-soft': 'rgb(168, 95, 50, 0.13)',
|
|
114
112
|
'--danger': '#c01622',
|
|
115
113
|
'--danger-soft': 'rgb(192, 22, 34, 0.1)',
|
|
116
114
|
'--info': '#1f63c4',
|
|
@@ -145,8 +143,6 @@ export const cssVars = {
|
|
|
145
143
|
'--success-soft': 'rgb(78, 194, 126, 0.14)',
|
|
146
144
|
'--warning': '#d8bd72',
|
|
147
145
|
'--warning-soft': 'rgb(216, 189, 114, 0.14)',
|
|
148
|
-
'--orange': '#d08c5b',
|
|
149
|
-
'--orange-soft': 'rgb(208, 140, 91, 0.15)',
|
|
150
146
|
'--danger': '#ff4d54',
|
|
151
147
|
'--danger-soft': 'rgb(255, 77, 84, 0.15)',
|
|
152
148
|
'--info': '#6fb0e6',
|
package/tokens/index.json
CHANGED
|
@@ -39,10 +39,10 @@
|
|
|
39
39
|
"--z-overlay": "30",
|
|
40
40
|
"--z-popover": "50",
|
|
41
41
|
"--z-toast": "60",
|
|
42
|
-
"--accent-1": "color-mix(in
|
|
43
|
-
"--accent-2": "color-mix(in
|
|
44
|
-
"--accent-3": "color-mix(in
|
|
45
|
-
"--accent-4": "color-mix(in
|
|
42
|
+
"--accent-1": "color-mix(in oklch, var(--accent) 8%, var(--bg))",
|
|
43
|
+
"--accent-2": "color-mix(in oklch, var(--accent) 16%, var(--bg))",
|
|
44
|
+
"--accent-3": "color-mix(in oklch, var(--accent) 32%, var(--bg))",
|
|
45
|
+
"--accent-4": "color-mix(in oklch, var(--accent) 60%, var(--bg))",
|
|
46
46
|
"--accent-5": "var(--accent)",
|
|
47
47
|
"--accent-6": "var(--accent-strong)",
|
|
48
48
|
"--surface-1": "var(--bg)",
|
|
@@ -91,8 +91,6 @@
|
|
|
91
91
|
"--success-soft": "rgb(47, 125, 79, 0.12)",
|
|
92
92
|
"--warning": "#806414",
|
|
93
93
|
"--warning-soft": "rgb(128, 100, 20, 0.13)",
|
|
94
|
-
"--orange": "#a85f32",
|
|
95
|
-
"--orange-soft": "rgb(168, 95, 50, 0.13)",
|
|
96
94
|
"--danger": "#c01622",
|
|
97
95
|
"--danger-soft": "rgb(192, 22, 34, 0.1)",
|
|
98
96
|
"--info": "#1f63c4",
|
|
@@ -126,8 +124,6 @@
|
|
|
126
124
|
"--success-soft": "rgb(78, 194, 126, 0.14)",
|
|
127
125
|
"--warning": "#d8bd72",
|
|
128
126
|
"--warning-soft": "rgb(216, 189, 114, 0.14)",
|
|
129
|
-
"--orange": "#d08c5b",
|
|
130
|
-
"--orange-soft": "rgb(208, 140, 91, 0.15)",
|
|
131
127
|
"--danger": "#ff4d54",
|
|
132
128
|
"--danger-soft": "rgb(255, 77, 84, 0.15)",
|
|
133
129
|
"--info": "#6fb0e6",
|
|
@@ -182,10 +178,10 @@
|
|
|
182
178
|
"z-overlay": "30",
|
|
183
179
|
"z-popover": "50",
|
|
184
180
|
"z-toast": "60",
|
|
185
|
-
"accent-1": "color-mix(in
|
|
186
|
-
"accent-2": "color-mix(in
|
|
187
|
-
"accent-3": "color-mix(in
|
|
188
|
-
"accent-4": "color-mix(in
|
|
181
|
+
"accent-1": "color-mix(in oklch, var(--accent) 8%, var(--bg))",
|
|
182
|
+
"accent-2": "color-mix(in oklch, var(--accent) 16%, var(--bg))",
|
|
183
|
+
"accent-3": "color-mix(in oklch, var(--accent) 32%, var(--bg))",
|
|
184
|
+
"accent-4": "color-mix(in oklch, var(--accent) 60%, var(--bg))",
|
|
189
185
|
"accent-5": "var(--accent)",
|
|
190
186
|
"accent-6": "var(--accent-strong)",
|
|
191
187
|
"surface-1": "var(--bg)",
|
|
@@ -235,8 +231,6 @@
|
|
|
235
231
|
"success-soft": "rgb(47, 125, 79, 0.12)",
|
|
236
232
|
"warning": "#806414",
|
|
237
233
|
"warning-soft": "rgb(128, 100, 20, 0.13)",
|
|
238
|
-
"orange": "#a85f32",
|
|
239
|
-
"orange-soft": "rgb(168, 95, 50, 0.13)",
|
|
240
234
|
"danger": "#c01622",
|
|
241
235
|
"danger-soft": "rgb(192, 22, 34, 0.1)",
|
|
242
236
|
"info": "#1f63c4",
|
|
@@ -270,8 +264,6 @@
|
|
|
270
264
|
"success-soft": "rgb(78, 194, 126, 0.14)",
|
|
271
265
|
"warning": "#d8bd72",
|
|
272
266
|
"warning-soft": "rgb(216, 189, 114, 0.14)",
|
|
273
|
-
"orange": "#d08c5b",
|
|
274
|
-
"orange-soft": "rgb(208, 140, 91, 0.15)",
|
|
275
267
|
"danger": "#ff4d54",
|
|
276
268
|
"danger-soft": "rgb(255, 77, 84, 0.15)",
|
|
277
269
|
"info": "#6fb0e6",
|
package/tokens/resolved.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$comment": "@ponchia/ui colour tokens resolved to static values per theme (var() + sRGB color-mix() evaluated at build). For non-CSS render targets: MapLibre/canvas/WebGL/SVG. Generated from tokens/index.js — do not edit by hand; run `npm run resolved:build`. Drift-checked in CI.",
|
|
2
|
+
"$comment": "@ponchia/ui colour tokens resolved to static values per theme (var() + sRGB/OKLCH color-mix() evaluated at build). For non-CSS render targets: MapLibre/canvas/WebGL/SVG. Generated from tokens/index.js — do not edit by hand; run `npm run resolved:build`. Drift-checked in CI.",
|
|
3
3
|
"light": {
|
|
4
|
-
"--accent-1": "#
|
|
5
|
-
"--accent-2": "#
|
|
6
|
-
"--accent-3": "#
|
|
7
|
-
"--accent-4": "#
|
|
4
|
+
"--accent-1": "#f6e5e2",
|
|
5
|
+
"--accent-2": "#f6d6d2",
|
|
6
|
+
"--accent-3": "#f5b8b1",
|
|
7
|
+
"--accent-4": "#ed8378",
|
|
8
8
|
"--accent-5": "#d71921",
|
|
9
9
|
"--accent-6": "#b2151b",
|
|
10
10
|
"--surface-1": "#f4f4f2",
|
|
@@ -51,8 +51,6 @@
|
|
|
51
51
|
"--success-soft": "rgba(47, 125, 79, 0.12)",
|
|
52
52
|
"--warning": "#806414",
|
|
53
53
|
"--warning-soft": "rgba(128, 100, 20, 0.13)",
|
|
54
|
-
"--orange": "#a85f32",
|
|
55
|
-
"--orange-soft": "rgba(168, 95, 50, 0.13)",
|
|
56
54
|
"--danger": "#c01622",
|
|
57
55
|
"--danger-soft": "rgba(192, 22, 34, 0.1)",
|
|
58
56
|
"--info": "#1f63c4",
|
|
@@ -65,10 +63,10 @@
|
|
|
65
63
|
"--focus-ring": "#d71921"
|
|
66
64
|
},
|
|
67
65
|
"dark": {
|
|
68
|
-
"--accent-1": "#
|
|
69
|
-
"--accent-2": "#
|
|
70
|
-
"--accent-3": "#
|
|
71
|
-
"--accent-4": "#
|
|
66
|
+
"--accent-1": "#020000",
|
|
67
|
+
"--accent-2": "#0d0101",
|
|
68
|
+
"--accent-3": "#330506",
|
|
69
|
+
"--accent-4": "#80191c",
|
|
72
70
|
"--accent-5": "#ff3b41",
|
|
73
71
|
"--accent-6": "#ff5a5f",
|
|
74
72
|
"--surface-1": "#000000",
|
|
@@ -115,8 +113,6 @@
|
|
|
115
113
|
"--success-soft": "rgba(78, 194, 126, 0.14)",
|
|
116
114
|
"--warning": "#d8bd72",
|
|
117
115
|
"--warning-soft": "rgba(216, 189, 114, 0.14)",
|
|
118
|
-
"--orange": "#d08c5b",
|
|
119
|
-
"--orange-soft": "rgba(208, 140, 91, 0.15)",
|
|
120
116
|
"--danger": "#ff4d54",
|
|
121
117
|
"--danger-soft": "rgba(255, 77, 84, 0.15)",
|
|
122
118
|
"--info": "#6fb0e6",
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/** @ponchia/ui — GENERATED from tokens/skins.js by scripts/gen-skins.mjs.
|
|
2
|
+
* Do not edit by hand; run `npm run skins:build`. Drift-checked in CI. */
|
|
3
|
+
|
|
4
|
+
/** Every display-colorway name @ponchia/ui ships (literal union). Use as a
|
|
5
|
+
* type for a `data-bronto-skin` value (`const s: SkinName = 'amber-crt'`). */
|
|
6
|
+
export type SkinName =
|
|
7
|
+
| 'amber-crt'
|
|
8
|
+
| 'e-ink'
|
|
9
|
+
| 'phosphor-green';
|
|
10
|
+
|
|
11
|
+
/** A colorway: a display label + per-theme custom-property overrides (CSS
|
|
12
|
+
* value strings). `light`/`dark` always set `--accent`; `dark` may add a
|
|
13
|
+
* display knob such as `--dotmatrix-glow`. */
|
|
14
|
+
export interface Skin {
|
|
15
|
+
label: string;
|
|
16
|
+
light: Record<string, string>;
|
|
17
|
+
dark: Record<string, string>;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** The frozen name→colorway registry. */
|
|
21
|
+
export declare const skins: Record<SkinName, Skin>;
|
|
22
|
+
|
|
23
|
+
/** Every colorway name, frozen and sorted. */
|
|
24
|
+
export declare const SKIN_NAMES: readonly SkinName[];
|
|
25
|
+
|
|
26
|
+
declare const _default: Record<SkinName, Skin>;
|
|
27
|
+
export default _default;
|
package/tokens/skins.js
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @ponchia/ui — optional display colorways ("skins").
|
|
3
|
+
*
|
|
4
|
+
* The single source for the opt-in `data-bronto-skin` looks (ADR-0001 step 4).
|
|
5
|
+
* A skin is NOT a second brand colour — it *re-points the one accent* (and the
|
|
6
|
+
* Tier-3 dot-matrix display knobs) to a different single hue, so the
|
|
7
|
+
* one-accent-per-scope discipline holds while the palette gains creative range
|
|
8
|
+
* *across* skins. The neutral canvas, status palette, and every component stay
|
|
9
|
+
* exactly as they are.
|
|
10
|
+
*
|
|
11
|
+
* Accents are authored in **OKLCH** (ADR-0001 step 5 — "OKLCH for new work
|
|
12
|
+
* first"): perceptually-uniform lightness makes the light/dark pair easy to
|
|
13
|
+
* reason about, and it is within the package browser floor (Chrome 111+,
|
|
14
|
+
* Safari 16.4+, Firefox 121+ all support `oklch()` and `color-mix()`).
|
|
15
|
+
*
|
|
16
|
+
* Each skin gives a per-theme accent because — exactly like the core red
|
|
17
|
+
* (#d71921 light / #ff3b41 dark) — one hue cannot stay AA against both a white
|
|
18
|
+
* and a black button label; the light accent is darker, the dark one brighter.
|
|
19
|
+
* The derived family (`--accent-strong`/`-text`/`-soft`, `--focus-ring`,
|
|
20
|
+
* `--bg-accent`, `--field-dot-accent`) recomputes in the browser from the live
|
|
21
|
+
* `var(--accent)`, so a skin only sets `--accent` plus any display knobs.
|
|
22
|
+
*
|
|
23
|
+
* This module is the source for BOTH:
|
|
24
|
+
* - css/skins.css (generated by scripts/gen-skins.mjs, drift-checked)
|
|
25
|
+
* - the skin contrast audit (scripts/gen-contrast.mjs gates every skin accent)
|
|
26
|
+
*
|
|
27
|
+
* Skins are shipped OPT-IN: a separate `./css/skins.css` entrypoint, never part
|
|
28
|
+
* of the default `dist/bronto.css` bundle.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* name → { label, light, dark }. `light`/`dark` are CSS custom-property maps
|
|
33
|
+
* applied under the same conditions as the core light/dark palettes. Keep the
|
|
34
|
+
* key set of light and dark identical (a drift check enforces it).
|
|
35
|
+
*/
|
|
36
|
+
export const skins = {
|
|
37
|
+
'amber-crt': {
|
|
38
|
+
label: 'Amber CRT',
|
|
39
|
+
// Phosphor amber. Dark+saturated in light theme (AA under a white label),
|
|
40
|
+
// bright with a warm bloom in dark theme (the classic CRT glow).
|
|
41
|
+
light: { '--accent': 'oklch(52% 0.11 67deg)' },
|
|
42
|
+
dark: { '--accent': 'oklch(82% 0.15 82deg)', '--dotmatrix-glow': '0.4em' },
|
|
43
|
+
},
|
|
44
|
+
'phosphor-green': {
|
|
45
|
+
label: 'Phosphor Green',
|
|
46
|
+
// P1-phosphor green. Same light=dark-ink / dark=bright-glow split.
|
|
47
|
+
light: { '--accent': 'oklch(52% 0.13 150deg)' },
|
|
48
|
+
dark: { '--accent': 'oklch(84% 0.19 150deg)', '--dotmatrix-glow': '0.4em' },
|
|
49
|
+
},
|
|
50
|
+
'e-ink': {
|
|
51
|
+
label: 'E-ink',
|
|
52
|
+
// The opposite move: drop the hue almost entirely → a near-monochrome
|
|
53
|
+
// ink/paper accent, no glow. The most restrained look in the set.
|
|
54
|
+
light: { '--accent': 'oklch(34% 0.012 250deg)' },
|
|
55
|
+
dark: { '--accent': 'oklch(84% 0.008 250deg)' },
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
/** Skin names, frozen + sorted. */
|
|
60
|
+
export const SKIN_NAMES = Object.freeze(Object.keys(skins).sort());
|
|
61
|
+
|
|
62
|
+
export default skins;
|
package/tokens/tokens.dtcg.json
CHANGED
|
@@ -225,28 +225,28 @@
|
|
|
225
225
|
"$type": "color",
|
|
226
226
|
"$value": null,
|
|
227
227
|
"$extensions": {
|
|
228
|
-
"com.ponchia.css": "color-mix(in
|
|
228
|
+
"com.ponchia.css": "color-mix(in oklch, var(--accent) 8%, var(--bg))"
|
|
229
229
|
}
|
|
230
230
|
},
|
|
231
231
|
"2": {
|
|
232
232
|
"$type": "color",
|
|
233
233
|
"$value": null,
|
|
234
234
|
"$extensions": {
|
|
235
|
-
"com.ponchia.css": "color-mix(in
|
|
235
|
+
"com.ponchia.css": "color-mix(in oklch, var(--accent) 16%, var(--bg))"
|
|
236
236
|
}
|
|
237
237
|
},
|
|
238
238
|
"3": {
|
|
239
239
|
"$type": "color",
|
|
240
240
|
"$value": null,
|
|
241
241
|
"$extensions": {
|
|
242
|
-
"com.ponchia.css": "color-mix(in
|
|
242
|
+
"com.ponchia.css": "color-mix(in oklch, var(--accent) 32%, var(--bg))"
|
|
243
243
|
}
|
|
244
244
|
},
|
|
245
245
|
"4": {
|
|
246
246
|
"$type": "color",
|
|
247
247
|
"$value": null,
|
|
248
248
|
"$extensions": {
|
|
249
|
-
"com.ponchia.css": "color-mix(in
|
|
249
|
+
"com.ponchia.css": "color-mix(in oklch, var(--accent) 60%, var(--bg))"
|
|
250
250
|
}
|
|
251
251
|
},
|
|
252
252
|
"5": {
|
|
@@ -550,16 +550,6 @@
|
|
|
550
550
|
"$value": "rgb(128, 100, 20, 0.13)"
|
|
551
551
|
}
|
|
552
552
|
},
|
|
553
|
-
"orange": {
|
|
554
|
-
"DEFAULT": {
|
|
555
|
-
"$type": "color",
|
|
556
|
-
"$value": "#a85f32"
|
|
557
|
-
},
|
|
558
|
-
"soft": {
|
|
559
|
-
"$type": "color",
|
|
560
|
-
"$value": "rgb(168, 95, 50, 0.13)"
|
|
561
|
-
}
|
|
562
|
-
},
|
|
563
553
|
"danger": {
|
|
564
554
|
"DEFAULT": {
|
|
565
555
|
"$type": "color",
|
|
@@ -735,16 +725,6 @@
|
|
|
735
725
|
"$value": "rgb(216, 189, 114, 0.14)"
|
|
736
726
|
}
|
|
737
727
|
},
|
|
738
|
-
"orange": {
|
|
739
|
-
"DEFAULT": {
|
|
740
|
-
"$type": "color",
|
|
741
|
-
"$value": "#d08c5b"
|
|
742
|
-
},
|
|
743
|
-
"soft": {
|
|
744
|
-
"$type": "color",
|
|
745
|
-
"$value": "rgb(208, 140, 91, 0.15)"
|
|
746
|
-
}
|
|
747
|
-
},
|
|
748
728
|
"danger": {
|
|
749
729
|
"DEFAULT": {
|
|
750
730
|
"$type": "color",
|