@keenmate/base-css-variables 1.0.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 ADDED
@@ -0,0 +1,31 @@
1
+ # Changelog
2
+
3
+ All notable changes to `@keenmate/base-css-variables` are documented here. Format based on
4
+ [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
5
+
6
+ ## [1.0.0] — 2026-09-10
7
+
8
+ The **canonical `--base-*` contract** release. `base-variables.css` is LAYER 0 — the single
9
+ source of truth every KeenMate consumer derives from. `@keenmate/pure-css` mirrors this exact
10
+ token list into SCSS (`$base-*`), and the web components read `--base-*` directly, so overriding
11
+ one `--base-*` re-themes pure-admin **and** the web components together.
12
+
13
+ ### Added
14
+
15
+ - **Complete `--base-*` contract superset.** `base-variables.css` now carries the full token
16
+ vocabulary every consumer reads — accent/primary + secondary roles, the surface elevation
17
+ ladder (`page` < `subtle` < `main` < `elevated`, plus `hover`/`active`/`disabled` states),
18
+ the text hierarchy (`--base-text-color-1..4`, `--base-text-on-*`, `--base-text-inverted`),
19
+ borders, input fields, dropdown/popover, tooltip, the four status roles
20
+ (success/danger/warning/info) in the `-color`/`-bg`/`-text`/`text-on-*` model, typography,
21
+ sizing and spacing multipliers, the shadow/motion/z-index scales, mask-friendly Lucide icons,
22
+ and the 1–9 brand palette slots.
23
+ - **Light/dark via CSS `light-dark()`.** Mode-variant colors resolve against `color-scheme`;
24
+ `:root` opts into `color-scheme: light dark` (OS-driven), and `[data-theme="light"|"dark"]`
25
+ forces a mode on a subtree. Mode-invariant tokens (icons, scales, multipliers, palette) stay
26
+ single values.
27
+
28
+ ### Changed
29
+
30
+ - **Default theme rebased onto pure-admin "Corporate"** (sky-blue `#0ea5e9` accent, slate
31
+ surfaces, cyan info), with light and dark values paired through `light-dark()`.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 KeenMate
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,271 @@
1
+ # @keenmate/base-css-variables
2
+
3
+ The shared **base layer** of CSS custom properties (`--base-*`) used by all
4
+ KeenMate web components — [web-multiselect](https://www.npmjs.com/package/@keenmate/web-multiselect),
5
+ [web-daterangepicker](https://www.npmjs.com/package/@keenmate/web-daterangepicker),
6
+ [web-grid](https://www.npmjs.com/package/@keenmate/web-grid), web-treeview, and more.
7
+
8
+ Each component ships its own prefixed variables (`--ms-*`, `--drp-*`, `--wg-*`, …)
9
+ that **cascade from these `--base-*` values**. Define the base layer once and every
10
+ component picks up a consistent, coordinated theme. Override a single `--base-*`
11
+ variable and the change propagates everywhere.
12
+
13
+ ## What's New in 1.0.0
14
+
15
+ - **Contract — `base-variables.css` is the complete `--base-*` superset** — this file is now the single canonical source of truth (LAYER 0) that carries every token any KeenMate consumer reads: accent/primary + secondary roles, the surface elevation ladder (`--base-page-bg` < `--base-subtle-bg` < `--base-main-bg` < `--base-elevated-bg` plus the hover/active/disabled state axis), the `--base-text-color-1..4` hierarchy with `--base-text-on-*` / `--base-text-inverted`, inputs, dropdown/popover, tooltip, the four status roles in the `-color`/`-bg`/`-text`/`text-on-*` model, typography + sizing/spacing multipliers, the shadow/motion/z-index scales, mask-friendly Lucide icons, and the 1–9 brand palette slots. `@keenmate/pure-css` mirrors this exact list into SCSS (`$base-*`), so the two must stay in sync.
16
+ - **Theme — default rebased onto pure-admin "Corporate"** — the out-of-the-box palette is now Corporate (sky-blue `#0ea5e9` accent, slate text/surfaces, cyan info), with light and dark values paired through CSS `light-dark()`. `:root` sets `color-scheme: light dark` so it follows the OS by default, and `[data-theme="light"|"dark"]` forces a mode on any subtree. Mode-invariant tokens (icons, the spacing/shadow/motion/z-index scales, sizing/typography multipliers, palette slots) stay single values.
17
+
18
+ ## Install
19
+
20
+ ```bash
21
+ npm install @keenmate/base-css-variables
22
+ ```
23
+
24
+ ## Usage
25
+
26
+ Import the stylesheet once, as early as possible (before the component styles):
27
+
28
+ ```js
29
+ import '@keenmate/base-css-variables/base-variables.css';
30
+ ```
31
+
32
+ or in CSS / HTML:
33
+
34
+ ```css
35
+ @import '@keenmate/base-css-variables/base-variables.css';
36
+ ```
37
+
38
+ ```html
39
+ <link rel="stylesheet" href="node_modules/@keenmate/base-css-variables/base-variables.css">
40
+ ```
41
+
42
+ ## How it works
43
+
44
+ The base layer is a set of **semantic design tokens**, not raw colors. Several
45
+ tokens may resolve to the *same default value* yet exist as separate variables so
46
+ each **role** can be themed independently.
47
+
48
+ ### Semantic roles that overlap by default
49
+
50
+ `--base-main-bg` and `--base-input-bg` both default to white (light) / near-black
51
+ (dark), but they mean different things:
52
+
53
+ | Token | Meaning | Example component consumers |
54
+ |-------|---------|-----------------------------|
55
+ | `--base-main-bg` | The **global / primary surface** — the canvas an app shell, grid, dropzone or panel paints itself on | `--wg-surface-1` (grid surface), `--drp-primary-bg` (calendar panel), `--ms-hint-bg`, `--ms-actions-bg` |
56
+ | `--base-input-bg` | The background of **form fields** specifically | `--ms-input-bg`, `--drp-input-bg`, `--wg-input-bg` |
57
+
58
+ Because they are separate variables, you can, for example, keep a grid or dropzone
59
+ on a plain page background while giving input fields a subtly tinted fill:
60
+
61
+ ```css
62
+ :root {
63
+ --base-main-bg: #ffffff; /* page / grid / dropzone canvas */
64
+ --base-input-bg: #f7f9fc; /* inputs stand out slightly */
65
+ }
66
+ ```
67
+
68
+ If you only set `--base-main-bg`, inputs keep their own default — they don't
69
+ inherit from it. Set both when you want them to match.
70
+
71
+ ### Surface hierarchy
72
+
73
+ Background surfaces layer outward from the canvas; each step is a little more
74
+ prominent:
75
+
76
+ ```
77
+ --base-main-bg → --base-elevated-bg → --base-hover-bg → --base-active-bg
78
+ ```
79
+
80
+ - **main** — base canvas (page, grid, panel, dropzone)
81
+ - **elevated** — raised areas: headers, toolbars, dropdowns, popovers
82
+ - **hover** — pointer hover on a surface (rows, options)
83
+ - **active** — pressed / selected
84
+ - **inverse** — high-contrast surface, used for tooltips
85
+
86
+ Role-specific surfaces (`--base-input-bg`, `--base-dropdown-bg`, `--base-tooltip-bg`)
87
+ default to values in this scale but can be retargeted on their own — that's the
88
+ whole point of keeping them as distinct tokens.
89
+
90
+ ## The layer pipeline (pure-css → pure-admin)
91
+
92
+ `--base-*` is the **single knob**. This package is the canonical contract; its
93
+ consumers never define a parallel source of truth, they derive from it:
94
+
95
+ - **[`@keenmate/pure-css`](https://www.npmjs.com/package/@keenmate/pure-css)** mirrors
96
+ this token list into SCSS (`$base-*`), adds theme derivation + its own `--pc-*`
97
+ foundation tokens, and ships the grid / utilities / app-shell.
98
+ - **`@keenmate/pure-admin-core`** builds its component tokens (`--pc-*`) on top.
99
+ - **KeenMate web components** read `--base-*` directly (with inline fallbacks).
100
+
101
+ Every `--pc-*` is wired as `var(--base-*, <fallback>)`, so overriding **one**
102
+ `--base-*` re-themes pure-admin components *and* the web components together.
103
+ Traced end-to-end for the accent:
104
+
105
+ ```
106
+ LAYER 0 contract (THIS file, CSS) :root { --base-accent-color: #0ea5e9 }
107
+ │ pure-css mirrors the list into SCSS
108
+ LAYER 1 pure-css source (SCSS) $base-accent-color: #0ea5e9 !default; ◀─ a THEME overrides here
109
+ │ derive
110
+ LAYER 2 pure-css framework var (SCSS) $accent-color: $base-accent-color; (serves only as the build fallback)
111
+ │ emit (two mixins)
112
+ LAYER 3 pure-css emit ──▶ CSS --base-accent-color: #0ea5e9; ◀─ RAIL A · the knob
113
+ --pc-accent: var(--base-accent-color, #0ea5e9) ◀─ RAIL B · pure-admin's token
114
+
115
+ LAYER 4 pure-admin-core (CSS) --pc-accent-light, --pc-accent-hover,
116
+ --pc-link-color: var(--pc-accent), …
117
+
118
+ LAYER 5 consumers
119
+ pure-admin components background: var(--pc-accent-light);
120
+ web components --ms-accent-color: var(--base-accent-color, #3b82f6);
121
+ ```
122
+
123
+ - **RAIL A** (`--base-accent-color`) is the knob; **RAIL B** (`--pc-accent`) is
124
+ `var(--base-accent-color, …)`, so at runtime it simply *is* the base value — the
125
+ `<fallback>` only fires if RAIL A is ever missing (it isn't, once this file or a
126
+ theme is loaded).
127
+ - There is **no `$pc-*` SCSS variable**. The `pc` layer is born at emission as a CSS
128
+ property pointing back at `--base-*`; nothing to author in SCSS.
129
+
130
+ | Override… | Where | Effect |
131
+ |---|---|---|
132
+ | `--base-accent-color` | any `:root` / `.pc-mode-*` / `[data-*]` scope (runtime) | **everything** downstream, live — pure-admin **and** web components |
133
+ | `$base-accent-color` | pure-css SCSS (build) | the default baked into `base.css` + every `--pc-*` fallback |
134
+ | `--pc-accent` | a single `--pc-*` (runtime) | pure-admin only — use for a deliberate pure-admin-only divergence |
135
+
136
+ That middle-less "one knob" row is the whole design: a theme (or a time-of-day
137
+ `[data-daypart]` scope) re-sets `--base-*` and the entire `--pc-*` layer re-resolves.
138
+
139
+ ## Theming
140
+
141
+ Override any `--base-*` variable in your own `:root` (or any scope) — the value
142
+ flows into every component:
143
+
144
+ ```css
145
+ :root {
146
+ --base-accent-color: #e11d48; /* rebrand every component's accent */
147
+ --base-main-bg: #fafafa;
148
+ --base-border-radius-md: 1; /* rounder corners everywhere */
149
+ }
150
+ ```
151
+
152
+ ### Light / dark mode
153
+
154
+ Colors are defined with CSS [`light-dark()`](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/light-dark),
155
+ so they follow the active `color-scheme`.
156
+
157
+ - **Automatic** — the file sets `color-scheme: light dark` on `:root`, so it
158
+ follows the operating-system preference out of the box.
159
+ - **Manual** — force a theme on any subtree:
160
+
161
+ ```html
162
+ <html data-theme="dark"> <!-- or data-theme="light" -->
163
+ ```
164
+
165
+ or set `color-scheme: light | dark` on any element.
166
+
167
+ ## Variable reference
168
+
169
+ Naming is intentionally **not 1:1** between the base layer and component variables.
170
+ For example `--ms-primary-bg` reads `--base-hover-bg`, and `--drp-primary-bg` reads
171
+ `--base-main-bg`. Always theme via the `--base-*` variables listed here.
172
+
173
+ ### Accent colors
174
+ | Variable | Purpose |
175
+ |----------|---------|
176
+ | `--base-accent-color` | Primary brand / action color |
177
+ | `--base-accent-color-hover` | Accent hover state |
178
+ | `--base-accent-color-active` | Accent active / pressed state |
179
+ | `--base-accent-color-light` | Subtle accent tint for backgrounds |
180
+ | `--base-accent-color-light-hover` | Subtle accent tint, hover |
181
+
182
+ ### Background / surface
183
+ | Variable | Purpose |
184
+ |----------|---------|
185
+ | `--base-main-bg` | Main surface (inputs, dropdowns) |
186
+ | `--base-elevated-bg` | Elevated surfaces: headers, toolbars, popovers |
187
+ | `--base-hover-bg` | Hover state for any surface (option/row hover) |
188
+ | `--base-active-bg` | Active / pressed surface |
189
+ | `--base-inverse-bg` | Inverse surface (fallback for tooltip background) |
190
+
191
+ ### Text
192
+ | Variable | Purpose |
193
+ |----------|---------|
194
+ | `--base-text-color-1` | Headers, titles, high-emphasis |
195
+ | `--base-text-color-2` | Body text, labels |
196
+ | `--base-text-color-3` | Secondary content, subtitles |
197
+ | `--base-text-color-4` | Hints, placeholders, captions |
198
+ | `--base-text-color-on-accent` | Text on accent backgrounds |
199
+ | `--base-text-inverted` | Inverse of main text (on inverse / accent surfaces) |
200
+
201
+ ### Borders
202
+ | Variable | Purpose |
203
+ |----------|---------|
204
+ | `--base-border-color` | Standard border color |
205
+ | `--base-border` | Full border shorthand (`1px solid …`) |
206
+
207
+ ### Input fields
208
+ | Variable | Purpose |
209
+ |----------|---------|
210
+ | `--base-input-bg` | Input background |
211
+ | `--base-input-color` | Input text color |
212
+ | `--base-input-border` | Input border (normal) |
213
+ | `--base-input-border-hover` | Input border on hover |
214
+ | `--base-input-border-focus` | Input border on focus |
215
+ | `--base-input-placeholder-color` | Placeholder text |
216
+ | `--base-input-bg-disabled` | Disabled input background |
217
+ | `--base-disabled-bg` | Disabled / readonly surface |
218
+
219
+ ### Dropdown / popover
220
+ | Variable | Purpose |
221
+ |----------|---------|
222
+ | `--base-dropdown-bg` | Dropdown / popover background |
223
+ | `--base-dropdown-border` | Dropdown border |
224
+ | `--base-dropdown-box-shadow` | Dropdown shadow |
225
+
226
+ ### Tooltip
227
+ | Variable | Purpose |
228
+ |----------|---------|
229
+ | `--base-tooltip-bg` | Tooltip background |
230
+ | `--base-tooltip-text-color` | Tooltip text |
231
+ | `--base-tooltip-color` | Tooltip text alias (web-grid) |
232
+
233
+ ### Status colors
234
+ | Variable | Purpose |
235
+ |----------|---------|
236
+ | `--base-<role>-color` | Role **fill identity** (vivid), role ∈ success/danger/warning/info |
237
+ | `--base-<role>-bg` | Solid role fill (= `-color`) |
238
+ | `--base-<role>-color-hover` | Role fill, hover |
239
+ | `--base-<role>-bg-light` / `-bg-subtle` | Subtle role tints |
240
+ | `--base-<role>-border` | Role border tint |
241
+ | `--base-<role>-text` | Role as **foreground on a light surface** (text/links) |
242
+ | `--base-text-on-<role>` | Readable text **on** the role fill |
243
+ | `--base-checkbox-border-color` | Checkbox border |
244
+
245
+ ### Typography
246
+ | Variable | Purpose |
247
+ |----------|---------|
248
+ | `--base-font-family` | Font stack |
249
+ | `--base-font-size-2xs … 2xl` | Font sizes (unitless multipliers) |
250
+ | `--base-font-weight-normal / medium / semibold` | Font weights |
251
+ | `--base-line-height-tight / normal / relaxed` | Line heights |
252
+
253
+ ### Sizing
254
+ | Variable | Purpose |
255
+ |----------|---------|
256
+ | `--base-border-radius-sm / md / lg` | Corner radii (unitless multipliers) |
257
+ | `--base-input-size-xs…xl-height` | Standard input heights (unitless multipliers) |
258
+
259
+ > **Unitless multipliers:** font sizes, radii and input heights are stored as
260
+ > plain numbers and combined by components with their rem scale — e.g.
261
+ > `calc(var(--base-font-size-base) * 0.1rem)`. This keeps sizing consistent
262
+ > across all KeenMate components while remaining scalable.
263
+
264
+ ## Related
265
+
266
+ - [`@keenmate/theme-designer`](https://github.com/keenmate/theme-designer) — visual
267
+ theme designer & generator that produces `--base-*` values from 3 input colors.
268
+
269
+ ## License
270
+
271
+ MIT © KeenMate
@@ -0,0 +1,306 @@
1
+ /**
2
+ * KeenMate Base CSS Variables
3
+ * ---------------------------------------------------------------------------
4
+ * The shared "base layer" (`--base-*`) consumed by all KeenMate web components
5
+ * (web-multiselect, web-daterangepicker, web-grid, web-treeview, ...).
6
+ *
7
+ * Each component exposes its own prefixed variables (--ms-*, --drp-*, --wg-*, …)
8
+ * that cascade from these `--base-*` values. Override any `--base-*` variable to
9
+ * re-theme every component at once.
10
+ *
11
+ * THIS FILE IS THE CANONICAL `--base-*` CONTRACT (the parent). `@keenmate/pure-css`
12
+ * mirrors this token list into SCSS (`$base-*`) — adding theme derivation and the
13
+ * `.pc-mode-*` class model — but must not add tokens this file lacks. Keep in sync.
14
+ *
15
+ * DEFAULT THEME = pure-admin "Corporate" (professional blue/slate): accent sky-blue
16
+ * #0ea5e9, slate text/surfaces, cyan info. Light values = Corporate light mode,
17
+ * dark values = Corporate dark mode, paired via CSS `light-dark()`. Activation:
18
+ * - Automatic: follows the OS setting via `color-scheme: light dark` below.
19
+ * - Manual: set `color-scheme: light` / `dark` on an ancestor, or the
20
+ * `[data-theme]` rules at the bottom.
21
+ *
22
+ * Mode-invariant tokens (icons, the spacing/shadow/motion/z-index scales, sizes,
23
+ * typography multipliers, the brand palette slots) are single values.
24
+ */
25
+
26
+ :root {
27
+ color-scheme: light dark;
28
+
29
+ /* ======================================================================
30
+ * ACCENT / PRIMARY COLORS — Corporate brand blue (kept across modes).
31
+ * `primary` is the canonical role name; `accent` the legacy alias.
32
+ * ==================================================================== */
33
+ --base-accent-color: #0ea5e9;
34
+ --base-accent-color-hover: #0284c7;
35
+ --base-accent-color-active: #0369a1;
36
+ --base-accent-color-light: rgba(14, 165, 233, 0.05);
37
+ --base-accent-color-light-hover: rgba(14, 165, 233, 0.08);
38
+
39
+ --base-primary-color: var(--base-accent-color);
40
+ --base-primary-color-hover: var(--base-accent-color-hover);
41
+ --base-primary-color-active: var(--base-accent-color-active);
42
+ --base-primary-color-light: var(--base-accent-color-light);
43
+ --base-primary-color-light-hover: var(--base-accent-color-light-hover);
44
+
45
+ /* ======================================================================
46
+ * SECONDARY ROLE (neutral grey)
47
+ * ==================================================================== */
48
+ --base-secondary-color: #6c757d;
49
+ --base-secondary-color-hover: #545b62;
50
+
51
+ /* ======================================================================
52
+ * BACKGROUND / SURFACE COLORS
53
+ * Elevation ladder: page (canvas) < subtle (recessed) < main (content) <
54
+ * elevated (raised). hover/active/disabled are the interaction-state axis.
55
+ * ==================================================================== */
56
+ --base-page-bg: light-dark(#f8f9fa, #0f172a); /* Canvas/backdrop below the content */
57
+ --base-main-bg: light-dark(#ffffff, #1e293b); /* Content surface — cards, panels, grid */
58
+ --base-subtle-bg: light-dark(#e9ecef, #0f172a); /* Recessed/inset surface (code, wells) */
59
+ --base-elevated-bg: light-dark(#f1f5f9, #334155); /* Raised surface — headers, toolbars, popovers */
60
+ --base-inverse-bg: light-dark(#2c3e50, #f1f5f9); /* Inverse surface */
61
+ --base-overlay-bg: rgba(30, 41, 59, 0.5); /* Modal/overlay scrim */
62
+ --base-shadow-color: rgba(0, 0, 0, 0.15); /* Shadow tint for elevation */
63
+
64
+ --base-hover-bg: light-dark(#e9ecef, #334155); /* Hover state for any surface */
65
+ --base-active-bg: light-dark(#dadfe4, #475569); /* Active/pressed surface */
66
+ --base-disabled-bg: light-dark(#f1f3f5, #334155); /* Disabled surface (inert tone) */
67
+
68
+ /* ======================================================================
69
+ * TEXT COLORS (hierarchy)
70
+ * ==================================================================== */
71
+ --base-text-color-1: light-dark(#334155, #f1f5f9); /* Headers, titles, high-emphasis */
72
+ --base-text-color-2: light-dark(#64748b, #94a3b8); /* Body text, labels */
73
+ --base-text-color-3: light-dark(#94a3b8, #64748b); /* Secondary content, subtitles */
74
+ --base-text-color-4: light-dark(#cbd5e1, #475569); /* Hints, placeholders, captions */
75
+ --base-text-color-on-accent: #ffffff; /* Text on accent backgrounds */
76
+ --base-text-inverted: light-dark(#ffffff, #1a1a1a); /* Inverse of main text */
77
+
78
+ /* "Foreground on a role" convention = --base-text-on-<role> */
79
+ --base-text-on-primary: var(--base-text-color-on-accent);
80
+ --base-text-on-secondary: #ffffff;
81
+
82
+ /* ======================================================================
83
+ * BORDERS
84
+ * ==================================================================== */
85
+ --base-border-width: 1px; /* Shared stroke width the shorthands compose from */
86
+ --base-border-color: light-dark(#e2e8f0, #475569);
87
+ --base-border: var(--base-border-width) solid light-dark(#e2e8f0, #475569);
88
+ --base-checkbox-border-color: light-dark(#e2e8f0, #475569);
89
+
90
+ /* ======================================================================
91
+ * INPUT FIELDS
92
+ * ==================================================================== */
93
+ --base-input-bg: light-dark(#ffffff, #334155);
94
+ --base-input-color: light-dark(#334155, #f1f5f9);
95
+ --base-input-border-color: light-dark(#e2e8f0, #475569);
96
+ --base-input-border: var(--base-border-width) solid light-dark(#e2e8f0, #475569);
97
+ --base-input-border-hover: var(--base-border-width) solid #0ea5e9;
98
+ --base-input-border-focus: var(--base-border-width) solid #0ea5e9;
99
+ --base-input-placeholder-color: light-dark(#cbd5e1, #64748b);
100
+ --base-input-bg-disabled: light-dark(rgba(26, 26, 26, 0.03), rgba(229, 229, 229, 0.05));
101
+ --base-input-clear-color: light-dark(#94a3b8, #64748b);
102
+ --base-input-clear-bg-hover: var(--base-hover-bg);
103
+
104
+ /* ======================================================================
105
+ * DROPDOWN / POPOVER
106
+ * ==================================================================== */
107
+ --base-dropdown-bg: light-dark(#ffffff, #1e293b);
108
+ --base-dropdown-border: var(--base-border-width) solid light-dark(#e2e8f0, #475569);
109
+ --base-dropdown-box-shadow: light-dark(0 8px 16px rgba(0, 0, 0, 0.15), 0 8px 16px rgba(0, 0, 0, 0.4));
110
+
111
+ /* ======================================================================
112
+ * TOOLTIP
113
+ * ==================================================================== */
114
+ --base-tooltip-bg: light-dark(#2c3e50, #475569);
115
+ --base-tooltip-text-color: light-dark(#ffffff, #f1f5f9);
116
+ --base-tooltip-color: light-dark(#ffffff, #f1f5f9); /* Alias used by web-grid */
117
+
118
+ /* ======================================================================
119
+ * CONTEXTUAL / ROLE COLORS — success / danger / warning / info
120
+ * Model: `-color` = vivid FILL identity; `-bg` = solid fill (= color); `-text`
121
+ * = foreground on a light surface; `text-on-*` = text ON the fill. Corporate
122
+ * hues (emerald / red / amber / cyan).
123
+ * ==================================================================== */
124
+ /* success (#10b981) */
125
+ --base-success-color: #10b981;
126
+ --base-success-bg: #10b981;
127
+ --base-success-color-hover: #059669;
128
+ --base-success-bg-light: light-dark(rgba(16, 185, 129, 0.1), rgba(16, 185, 129, 0.2));
129
+ --base-success-bg-subtle: rgba(16, 185, 129, 0.08);
130
+ --base-success-border: rgba(16, 185, 129, 0.2);
131
+ --base-success-text: light-dark(#155724, #34d399);
132
+ --base-success-text-light: light-dark(#d4edda, #059669);
133
+ --base-text-on-success: #ffffff;
134
+
135
+ /* danger (#ef4444 fill / #dc2626 strong) */
136
+ --base-danger-color: #ef4444;
137
+ --base-danger-bg: #ef4444;
138
+ --base-danger-color-hover: #dc2626;
139
+ --base-danger-bg-light: light-dark(rgba(239, 68, 68, 0.1), rgba(239, 68, 68, 0.2));
140
+ --base-danger-bg-subtle: rgba(239, 68, 68, 0.08);
141
+ --base-danger-border: rgba(239, 68, 68, 0.2);
142
+ --base-danger-text: light-dark(#721c24, #f87171);
143
+ --base-danger-text-light: light-dark(#f8d7da, #dc2626);
144
+ --base-text-on-danger: #ffffff;
145
+
146
+ /* warning (#f59e0b) */
147
+ --base-warning-color: #f59e0b;
148
+ --base-warning-bg: #f59e0b;
149
+ --base-warning-color-hover: #d97706;
150
+ --base-warning-bg-light: light-dark(rgba(245, 158, 11, 0.1), rgba(245, 158, 11, 0.2));
151
+ --base-warning-bg-subtle: rgba(245, 158, 11, 0.08);
152
+ --base-warning-border: rgba(245, 158, 11, 0.2);
153
+ --base-warning-text: light-dark(#856404, #fbbf24);
154
+ --base-warning-text-light: light-dark(#fff3cd, #d97706);
155
+ --base-text-on-warning: #ffffff;
156
+
157
+ /* info (#06b6d4 — Corporate cyan) */
158
+ --base-info-color: #06b6d4;
159
+ --base-info-bg: #06b6d4;
160
+ --base-info-color-hover: #0891b2;
161
+ --base-info-bg-light: light-dark(rgba(6, 182, 212, 0.1), rgba(6, 182, 212, 0.2));
162
+ --base-info-bg-subtle: rgba(6, 182, 212, 0.08);
163
+ --base-info-border: rgba(6, 182, 212, 0.2);
164
+ --base-info-text: light-dark(#0c5460, #22d3ee);
165
+ --base-info-text-light: light-dark(#d1ecf1, #0891b2);
166
+ --base-text-on-info: #ffffff;
167
+
168
+ /* ======================================================================
169
+ * TYPOGRAPHY
170
+ * ==================================================================== */
171
+ --base-font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
172
+ --base-font-family-mono: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
173
+
174
+ /* Font sizes — unitless multipliers, used as calc(var(--base-font-size-*) * <rem-base>) */
175
+ --base-font-size-2xs: 1;
176
+ --base-font-size-xs: 1.2;
177
+ --base-font-size-sm: 1.4;
178
+ --base-font-size-base: 1.6;
179
+ --base-font-size-lg: 1.8;
180
+ --base-font-size-xl: 2;
181
+ --base-font-size-2xl: 2.4;
182
+
183
+ /* Font weights */
184
+ --base-font-weight-normal: 400;
185
+ --base-font-weight-medium: 500;
186
+ --base-font-weight-semibold: 600;
187
+ --base-font-weight-bold: 700;
188
+
189
+ /* Line heights */
190
+ --base-line-height-tight: 1.25;
191
+ --base-line-height-normal: 1.5;
192
+ --base-line-height-relaxed: 1.75;
193
+
194
+ /* ======================================================================
195
+ * SIZING — unitless multipliers (see font sizes note above)
196
+ * ==================================================================== */
197
+ --base-border-radius-sm: 0.4;
198
+ --base-border-radius-md: 0.6;
199
+ --base-border-radius-lg: 0.8;
200
+
201
+ /* Neutral heights. (Corporate bumps these +0.3 for its wider font — a theme
202
+ * ergonomic tweak, not base identity, so the canonical default stays neutral.) */
203
+ --base-input-size-xs-height: 3.1; /* 31px at 10px rem base */
204
+ --base-input-size-sm-height: 3.3; /* 33px */
205
+ --base-input-size-md-height: 3.5; /* 35px */
206
+ --base-input-size-lg-height: 3.8; /* 38px */
207
+ --base-input-size-xl-height: 4.1; /* 41px */
208
+
209
+ /* Rem base for the unitless multipliers above: calc(<multiplier> * var(--base-rem)) */
210
+ --base-rem: 1rem;
211
+
212
+ /* ======================================================================
213
+ * SPACING SCALE — unitless multipliers, calc(var(--base-space-*) * var(--base-rem))
214
+ * ==================================================================== */
215
+ --base-space-xs: 0.4;
216
+ --base-space-sm: 0.8;
217
+ --base-space-md: 1.2;
218
+ --base-space-base: 1.6;
219
+ --base-space-lg: 2.4;
220
+ --base-space-xl: 3.2;
221
+ --base-space-2xl: 4.8;
222
+
223
+ /* ======================================================================
224
+ * ELEVATION / SHADOW SCALE — colour from --base-shadow-color so it themes
225
+ * ==================================================================== */
226
+ --base-shadow-sm: 0 1px 3px var(--base-shadow-color);
227
+ --base-shadow-md: 0 2px 8px var(--base-shadow-color);
228
+ --base-shadow-lg: 0 4px 12px var(--base-shadow-color);
229
+
230
+ /* ======================================================================
231
+ * MOTION — durations + easings
232
+ * ==================================================================== */
233
+ --base-duration-fast: 0.1s;
234
+ --base-duration-normal: 0.15s;
235
+ --base-duration-medium: 0.25s;
236
+ --base-duration-slow: 0.3s;
237
+ --base-ease-standard: cubic-bezier(0.4, 0, 0.2, 1);
238
+ --base-ease-out: cubic-bezier(0, 0, 0.2, 1);
239
+ --base-ease-in: cubic-bezier(0.4, 0, 1, 1);
240
+
241
+ /* ======================================================================
242
+ * Z-INDEX SCALE — generic stacking tiers for overlay coordination
243
+ * ==================================================================== */
244
+ --base-z-dropdown: 7500;
245
+ --base-z-modal-backdrop: 6000;
246
+ --base-z-modal: 7000;
247
+ --base-z-popover: 7600;
248
+ --base-z-toast: 8000;
249
+ --base-z-tooltip: 9000;
250
+
251
+ /* ======================================================================
252
+ * ICONS — mask-friendly SVG glyphs (Lucide defaults), rendered via
253
+ * `mask: var(--base-icon-*); background: currentColor`. Mode-invariant.
254
+ * Two disclosure models: chevron ROTATES one glyph (points right, rotate 90°
255
+ * when open); expand/collapse SWAP two glyphs (+ collapsed, − open). carets
256
+ * are STATIC (swap up/down, never rotate). close/clear/remove share the ✕
257
+ * (clear & remove follow close); delete is a DESTRUCTIVE trash, not an ✕.
258
+ * ==================================================================== */
259
+ --base-icon-chevron: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 24 24%22 fill=%22none%22 stroke=%22%23000%22 stroke-width=%222%22 stroke-linecap=%22round%22 stroke-linejoin=%22round%22%3E%3Cpath d=%22m9 18 6-6-6-6%22/%3E%3C/svg%3E");
260
+ --base-icon-caret-down: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 24 24%22%3E%3Cpath fill=%22%23000%22 d=%22M12 15 6 9h12z%22/%3E%3C/svg%3E");
261
+ --base-icon-caret-up: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 24 24%22%3E%3Cpath fill=%22%23000%22 d=%22M12 9 6 15h12z%22/%3E%3C/svg%3E");
262
+ --base-icon-close: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 24 24%22 fill=%22none%22 stroke=%22%23000%22 stroke-width=%222%22 stroke-linecap=%22round%22 stroke-linejoin=%22round%22%3E%3Cpath d=%22M18 6 6 18%22/%3E%3Cpath d=%22m6 6 12 12%22/%3E%3C/svg%3E");
263
+ --base-icon-clear: var(--base-icon-close); /* field-clear — follows close */
264
+ --base-icon-remove: var(--base-icon-close); /* item take-out (non-destructive) — follows close */
265
+ --base-icon-expand: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 24 24%22 fill=%22none%22 stroke=%22%23000%22 stroke-width=%222%22 stroke-linecap=%22round%22 stroke-linejoin=%22round%22%3E%3Cpath d=%22M5 12h14%22/%3E%3Cpath d=%22M12 5v14%22/%3E%3C/svg%3E");
266
+ --base-icon-collapse: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 24 24%22 fill=%22none%22 stroke=%22%23000%22 stroke-width=%222%22 stroke-linecap=%22round%22 stroke-linejoin=%22round%22%3E%3Cpath d=%22M5 12h14%22/%3E%3C/svg%3E");
267
+ --base-icon-add: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 24 24%22 fill=%22none%22 stroke=%22%23000%22 stroke-width=%222%22 stroke-linecap=%22round%22 stroke-linejoin=%22round%22%3E%3Cpath d=%22M5 12h14%22/%3E%3Cpath d=%22M12 5v14%22/%3E%3C/svg%3E");
268
+ --base-icon-edit: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 24 24%22 fill=%22none%22 stroke=%22%23000%22 stroke-width=%222%22 stroke-linecap=%22round%22 stroke-linejoin=%22round%22%3E%3Cpath d=%22M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z%22/%3E%3C/svg%3E");
269
+ --base-icon-delete: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 24 24%22 fill=%22none%22 stroke=%22%23000%22 stroke-width=%222%22 stroke-linecap=%22round%22 stroke-linejoin=%22round%22%3E%3Cpath d=%22M3 6h18%22/%3E%3Cpath d=%22M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2%22/%3E%3Cpath d=%22M10 11v6%22/%3E%3Cpath d=%22M14 11v6%22/%3E%3C/svg%3E");
270
+ --base-icon-search: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 24 24%22 fill=%22none%22 stroke=%22%23000%22 stroke-width=%222%22 stroke-linecap=%22round%22 stroke-linejoin=%22round%22%3E%3Ccircle cx=%2211%22 cy=%2211%22 r=%228%22/%3E%3Cpath d=%22m21 21-4.3-4.3%22/%3E%3C/svg%3E");
271
+
272
+ /* ======================================================================
273
+ * THEME PALETTE SLOTS (1–9) + paired contrast text — Corporate palette
274
+ * ==================================================================== */
275
+ --base-color-1: #f59e0b; /* Amber */
276
+ --base-color-2: #ec4899; /* Pink */
277
+ --base-color-3: #10b981; /* Emerald */
278
+ --base-color-4: #0ea5e9; /* Sky blue */
279
+ --base-color-5: #8b5cf6; /* Violet */
280
+ --base-color-6: #6366f1; /* Indigo */
281
+ --base-color-7: #64748b; /* Slate */
282
+ --base-color-8: #0284c7; /* Corporate blue */
283
+ --base-color-9: #334155; /* Dark slate */
284
+ --base-color-1-text: #1a1a1a;
285
+ --base-color-2-text: #ffffff;
286
+ --base-color-3-text: #ffffff;
287
+ --base-color-4-text: #ffffff;
288
+ --base-color-5-text: #ffffff;
289
+ --base-color-6-text: #ffffff;
290
+ --base-color-7-text: #ffffff;
291
+ --base-color-8-text: #ffffff;
292
+ --base-color-9-text: #ffffff;
293
+ }
294
+
295
+ /* ---------------------------------------------------------------------------
296
+ * Manual theme control
297
+ * `light-dark()` follows `color-scheme`. These helpers let you force a theme
298
+ * on a subtree regardless of the OS setting.
299
+ * ------------------------------------------------------------------------- */
300
+ [data-theme="light"] {
301
+ color-scheme: light;
302
+ }
303
+
304
+ [data-theme="dark"] {
305
+ color-scheme: dark;
306
+ }
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "@keenmate/base-css-variables",
3
+ "version": "1.0.0",
4
+ "description": "Shared base layer of CSS custom properties (--base-*) for KeenMate web components",
5
+ "license": "MIT",
6
+ "author": "KeenMate",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/keenmate/base-css-variables.git"
10
+ },
11
+ "keywords": [
12
+ "css-variables",
13
+ "custom-properties",
14
+ "theme",
15
+ "design-tokens",
16
+ "keenmate"
17
+ ],
18
+ "type": "module",
19
+ "style": "./base-variables.css",
20
+ "exports": {
21
+ ".": "./base-variables.css",
22
+ "./base-variables.css": "./base-variables.css"
23
+ },
24
+ "files": [
25
+ "base-variables.css",
26
+ "README.md",
27
+ "CHANGELOG.md",
28
+ "LICENSE"
29
+ ],
30
+ "publishConfig": {
31
+ "access": "public"
32
+ }
33
+ }