@iyulab/house-style 0.6.1 → 0.8.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 +68 -0
- package/README.md +31 -15
- package/package.json +7 -7
- package/styles/components.css +58 -25
- package/styles/patterns.css +17 -172
- package/styles/tailwind.css +12 -5
- package/styles/tokens.css +363 -158
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,73 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.8.0] - 2026-10-17
|
|
4
|
+
|
|
5
|
+
The palette moves to the application and the house gains presets; controls, rows and the type ladder grow a step.
|
|
6
|
+
The default look changes — see *Migrating*.
|
|
7
|
+
|
|
8
|
+
### Added
|
|
9
|
+
|
|
10
|
+
- **Seed colours.** An application sets `--hs-accent` (the main action, the current item, links, focus) and
|
|
11
|
+
`--hs-secondary` (a second emphasis) on `:root`. Every step the components need is derived from the seed, in light
|
|
12
|
+
and dark: `--hs-accent-fill` (the seed, darkened only as far as white text needs), `--hs-accent-contrast`,
|
|
13
|
+
`--hs-accent-soft`, `--hs-accent-ink`, and the same for `--hs-secondary`. Each derived step is its own token, so an
|
|
14
|
+
application overrides only the step its seed defeats. The derivations use relative colour syntax and `color-mix()`.
|
|
15
|
+
- **Presets** — `<html hs-palette="…">`, each with a light and a dark side:
|
|
16
|
+
- `cool` (no attribute, the new default): cool-grey neutrals, the accent as the filled main action, a light sidebar
|
|
17
|
+
whose current item is the accent tint, the current tab in the accent.
|
|
18
|
+
- `warm`: the look before this release — warm-grey neutrals, an ink main action, a neutral current item, an ink tab.
|
|
19
|
+
- `contrast`: the `cool` screen with a dark sidebar; the sidebar re-scopes the neutral roles, so its links, groups,
|
|
20
|
+
section titles and any menu it opens read as one dark surface.
|
|
21
|
+
- `--u-secondary-*` role tokens (for `color="secondary"` — requires an `@iyulab/components` release with the
|
|
22
|
+
`secondary` role) and chart series slot two following the secondary seed.
|
|
23
|
+
- Tailwind entry: `accent` · `accent-soft` · `accent-ink` · `on-accent` (and `secondary-*`) colours, `rounded-pill`.
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
|
|
27
|
+
- Controls are 32 / 36 / 40 (were 28 / 32 / 40) — buttons and fields alike, still a function of `--u-density`; buttons
|
|
28
|
+
are semibold, md at the density size. Labelled fields stay 40.
|
|
29
|
+
- Control, field and menu-item corners are 8px (were 6px); cards stay 10px. Tags are pills.
|
|
30
|
+
- Table rows are 44px, compact 36px (were 40 / 32). Cells are at the body size (14px) with a 13px semibold header;
|
|
31
|
+
`.hs-table` keeps a 20px edge on its first and last cells.
|
|
32
|
+
- Type: display 24px (was 22px) with a 32px line, overline tracking 0.04em; the hero figure stays 28px (display + 4).
|
|
33
|
+
- Tabs (`u-tab-nav`, `u-tab-panel`): the current tab takes the preset's tab colour, 14px, 10px × 12px.
|
|
34
|
+
- Shell: a 240px sidebar of 38px rows (8px × 10px, 18px icons, 10px gap, 8px corners); main padding 20px 32px 48px;
|
|
35
|
+
20px between page sections (`.hs-page`, `.hs-detail__cols`, `.hs-grid-cards`).
|
|
36
|
+
- Cool neutrals: canvas `#F5F6F8`, lines `#E0E0E0`, body text `#333232`, secondary text `#666666`; field edges stay
|
|
37
|
+
at 3:1 (`#858C96`).
|
|
38
|
+
|
|
39
|
+
### Removed
|
|
40
|
+
|
|
41
|
+
- `--hs-brand`, `--hs-brand-soft`, `--hs-brand-ink` and the Tailwind `brand*` colours — use the seeds.
|
|
42
|
+
|
|
43
|
+
### Migrating
|
|
44
|
+
|
|
45
|
+
- Brand tokens: `--hs-brand` → `--hs-accent` (one seed; drop `-soft`/`-ink` unless the derived step does not suit you,
|
|
46
|
+
then set `--hs-accent-soft` / `--hs-accent-ink`). Tailwind `bg-brand` → `bg-accent`, `bg-brand-soft` →
|
|
47
|
+
`bg-accent-soft`, `text-brand-ink` → `text-accent-ink`.
|
|
48
|
+
- To keep the previous colours: `<html hs-palette="warm">`. The size changes are not part of a preset; to keep the
|
|
49
|
+
previous sizes, set the tokens (`--u-radius-lg: 6px`, `--hs-row: 40px`, `--u-text-display-size: 22px`, …) and the
|
|
50
|
+
control padding on your own `:root` / `u-button`.
|
|
51
|
+
- Requires `@iyulab/components` 2.29.0 or later (peer range `^2.29.0`, was `^2.26.0`) — the house sets the
|
|
52
|
+
`secondary` role tokens, which components reads from 2.29.0.
|
|
53
|
+
|
|
54
|
+
## [0.7.0] - 2026-10-16
|
|
55
|
+
|
|
56
|
+
### Removed
|
|
57
|
+
|
|
58
|
+
- The patterns deprecated in 0.6.0, each replaced by a component:
|
|
59
|
+
- `.hs-filter-bar` (`__search` · `__end`) and `.hs-chips` → `u-list-page` `slot="filters"` / `slot="applied"` (`@iyulab/enterprise`).
|
|
60
|
+
- `.hs-table-card` and `.hs-pager` → `<u-list-page appearance="card">` with `u-pagination` in `slot="pager"`.
|
|
61
|
+
- `.hs-table-toolbar` (`--selected` · `__title` · `__actions`) → `<u-action-bar slot="toolbar">` with the title in `slot="summary"`.
|
|
62
|
+
- `.hs-card` (`__head` · `__title` · `__link`) → `<u-group-box title>` (`@iyulab/modern-app`) or `<u-card>` (`@iyulab/components`).
|
|
63
|
+
- `.hs-field` (`__label` · `__required` · `__help` · `__error`) → `<u-field label>` (`@iyulab/components`).
|
|
64
|
+
|
|
65
|
+
### Fixed
|
|
66
|
+
|
|
67
|
+
- `u-list-page` filters keep the page’s bottom alignment. The house rule set `align-items: center` on the filters row, so
|
|
68
|
+
a button next to a search field with a visible label stood level with the middle of «label + field» — about 10px above
|
|
69
|
+
the field.
|
|
70
|
+
|
|
3
71
|
## [0.6.1] - 2026-10-14
|
|
4
72
|
|
|
5
73
|
### Fixed
|
package/README.md
CHANGED
|
@@ -36,7 +36,7 @@ so its preflight would beat the theme; `tailwind.css` imports the theme into Tai
|
|
|
36
36
|
|---|---|
|
|
37
37
|
| `styles/index.css` (package root) | everything below plus Pretendard — for apps without Tailwind |
|
|
38
38
|
| `styles/theme.css` | the theme without fonts (bring your own face) |
|
|
39
|
-
| `styles/tokens.css` |
|
|
39
|
+
| `styles/tokens.css` | the presets (`cool` · `warm` · `contrast`, light and dark) for the `--u-*` token axes, the seeds `--hs-accent` · `--hs-secondary` and their derived steps, and the house scale |
|
|
40
40
|
| `styles/components.css` | the document flow (body text, `h1`–`h6`, block gaps, code spans, native control and scrollbar colours) and sizes and finish for `u-button`, `u-card`, `u-drawer`, `flex-table`, the app shell |
|
|
41
41
|
| `styles/patterns.css` | `hs-*` layout patterns — page head, saved views, filter bar, stat strip, table card, callout, form sections, side-sheet footer |
|
|
42
42
|
| `styles/tailwind.css` | the Tailwind v4 entry: fonts + theme (in Tailwind's `components` layer) + role utilities — `bg-canvas`, `text-ink-weak`, `border-line`, `bg-warning-soft`, `rounded-card` … |
|
|
@@ -56,30 +56,46 @@ Requires `@iyulab/components` 2.0 or later (the release that put its defaults in
|
|
|
56
56
|
Because the application is unlayered, a plain `:root { … }` rule overrides the theme — no
|
|
57
57
|
specificity tricks, no load-order rules. Scope a mode-specific value with `:root[theme="dark"]`.
|
|
58
58
|
|
|
59
|
-
###
|
|
59
|
+
### Palette — seeds from the app, balance from a preset
|
|
60
60
|
|
|
61
|
-
The
|
|
62
|
-
|
|
61
|
+
The application decides its colours; the house decides how the screen is balanced around them.
|
|
62
|
+
|
|
63
|
+
**Seeds.** Two colours on `:root`. Every step the components need is derived from them — a fill that white text
|
|
64
|
+
can sit on, a soft tint (the current navigation item, a selected row), a readable ink (links, the current tab),
|
|
65
|
+
and the dark-mode steps:
|
|
63
66
|
|
|
64
67
|
```css
|
|
65
68
|
:root {
|
|
66
|
-
--hs-
|
|
67
|
-
--hs-
|
|
68
|
-
--hs-brand-ink: #a3121a; /* its text */
|
|
69
|
-
}
|
|
70
|
-
:root[theme="dark"] {
|
|
71
|
-
--hs-brand-soft: #3a1a1c;
|
|
72
|
-
--hs-brand-ink: #ff9a9e;
|
|
69
|
+
--hs-accent: #c8161d; /* identity: the main action, the current item, links, focus */
|
|
70
|
+
--hs-secondary: #0f766e; /* a second emphasis: color="secondary", the second chart series */
|
|
73
71
|
}
|
|
74
72
|
```
|
|
75
73
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
74
|
+
A derivation cannot promise contrast for every seed (a pale yellow cannot carry white text). Each derived step is
|
|
75
|
+
its own token — `--hs-accent-fill` · `--hs-accent-contrast` · `--hs-accent-soft` · `--hs-accent-ink` (and the same
|
|
76
|
+
for `--hs-secondary`) — so an application overrides only the step its seed defeats. Set seeds on `:root`: a step
|
|
77
|
+
derived there does not follow a seed set further down the tree. Status colours (info · success · warning · danger)
|
|
78
|
+
never follow the seeds, so a red brand and «danger» stay two colours.
|
|
79
|
+
|
|
80
|
+
**Presets.** The balance of the whole screen — the temperature of the neutrals, the distance between canvas,
|
|
81
|
+
surface, lines and text, whether the main action is the accent or ink, and how dark the shell is. Each has a light
|
|
82
|
+
and a dark side (`theme="dark"`):
|
|
83
|
+
|
|
84
|
+
| `<html hs-palette="…">` | Neutrals | Main action | Sidebar | Current tab |
|
|
85
|
+
|---|---|---|---|---|
|
|
86
|
+
| *(none)* `cool` | cool grey | accent fill | light | accent |
|
|
87
|
+
| `warm` | warm grey | ink | light, neutral current item | ink |
|
|
88
|
+
| `contrast` | cool grey | accent fill | dark | accent |
|
|
89
|
+
|
|
90
|
+
One filled button per view under every preset — the rest are outlined, plain or in a menu.
|
|
91
|
+
|
|
92
|
+
**Fixed by the house** (token by token overridable): the 24/18/15/14/13/12/11 type ladder in Pretendard,
|
|
93
|
+
32/36/40 controls, 8px controls and menu items, 10px cards, pill status tags, 44px table rows (36px compact),
|
|
94
|
+
a 240px sidebar of 38px rows.
|
|
79
95
|
|
|
80
96
|
The type ladder is the `--u-text-*-size` steps plus two house steps derived from them —
|
|
81
97
|
`--hs-text-dense-size` (between body and label: table cells, definition lists, callouts) and
|
|
82
|
-
`--hs-text-hero-size` (display +
|
|
98
|
+
`--hs-text-hero-size` (display + 4px: a headline figure). Every pattern reads a step, so rescaling the
|
|
83
99
|
ladder (a larger mode, a product system) carries the patterns along.
|
|
84
100
|
|
|
85
101
|
### Text outside components
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iyulab/house-style",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "The iyulab house theme: a CSS-only theme for @iyulab components — tokens, component recipes, line-of-business layout patterns and a Tailwind CSS v4 preset — plus the guide site that documents it.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"pretendard": "^1.3.9"
|
|
59
59
|
},
|
|
60
60
|
"peerDependencies": {
|
|
61
|
-
"@iyulab/components": "^2.
|
|
61
|
+
"@iyulab/components": "^2.29.0",
|
|
62
62
|
"@iyulab/flex-table": ">=0.41.0",
|
|
63
63
|
"@iyulab/modern-app": ">=0.54.0"
|
|
64
64
|
},
|
|
@@ -71,13 +71,13 @@
|
|
|
71
71
|
}
|
|
72
72
|
},
|
|
73
73
|
"devDependencies": {
|
|
74
|
-
"@iyulab/components": "^2.
|
|
74
|
+
"@iyulab/components": "^2.29.0",
|
|
75
75
|
"@iyulab/data-components": "^0.51.0",
|
|
76
|
-
"@iyulab/enterprise": "^0.
|
|
77
|
-
"@iyulab/flex-table": "^0.
|
|
78
|
-
"@iyulab/modern-app": "^0.
|
|
76
|
+
"@iyulab/enterprise": "^0.35.0",
|
|
77
|
+
"@iyulab/flex-table": "^0.68.0",
|
|
78
|
+
"@iyulab/modern-app": "^0.55.0",
|
|
79
79
|
"@iyulab/router": "^0.24.0",
|
|
80
|
-
"@iyulab/u-widgets": "^0.
|
|
80
|
+
"@iyulab/u-widgets": "^0.35.0",
|
|
81
81
|
"@lit/react": "^1.0.8",
|
|
82
82
|
"@types/node": "^26.1.1",
|
|
83
83
|
"@types/react": "^19.3.0",
|
package/styles/components.css
CHANGED
|
@@ -93,25 +93,28 @@
|
|
|
93
93
|
color: var(--u-link-txt-color);
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
-
/* ── Button —
|
|
96
|
+
/* ── Button — 32 / 36 / 40, semibold ──────────────────────────────────── *
|
|
97
97
|
* Height follows the components' own formula (1.5em line + 2 × padding + 2px border), so
|
|
98
98
|
* these are padding values, not fixed heights: text and icon-only buttons stay equal.
|
|
99
|
-
* The font sizes are terms of that height formula (the control ladder
|
|
99
|
+
* The font sizes are terms of that height formula (the control ladder 32/36/40), not steps of
|
|
100
100
|
* the text ladder — tying them to `--u-text-*` would change control heights whenever the text
|
|
101
101
|
* ladder is rescaled. They are steps of the control density instead (`--u-density`, the
|
|
102
|
-
* components' size axis): at the default 14px they are 12 /
|
|
102
|
+
* components' size axis): at the default 14px they are 12 / 14 / 14 and the heights 32/36/40;
|
|
103
103
|
* a host that raises the density (a field or touch mode) grows all three together and in order.
|
|
104
|
-
* Padding is in em for the same reason — the n/
|
|
104
|
+
* Padding is in em for the same reason — the n/12 and n/14 factors give the px values at the
|
|
105
105
|
* default density exactly. (sm takes the components' own size: density × 6/7.) */
|
|
106
|
+
u-button {
|
|
107
|
+
font-weight: 600;
|
|
108
|
+
}
|
|
106
109
|
u-button:not([size]),
|
|
107
110
|
u-button[size='md'] {
|
|
108
|
-
font-size:
|
|
109
|
-
--btn-padding-block: calc(
|
|
110
|
-
--btn-padding-inline: calc(
|
|
111
|
+
font-size: var(--u-density, 14px);
|
|
112
|
+
--btn-padding-block: calc(6.5em / 14); /* 14px: 21 + 13 + 2 = 36 */
|
|
113
|
+
--btn-padding-inline: calc(14em / 14);
|
|
111
114
|
}
|
|
112
115
|
u-button[size='sm'] {
|
|
113
|
-
--btn-padding-block: calc(
|
|
114
|
-
--btn-padding-inline: calc(
|
|
116
|
+
--btn-padding-block: calc(6em / 12); /* 12px: 18 + 12 + 2 = 32 */
|
|
117
|
+
--btn-padding-inline: calc(10em / 12);
|
|
115
118
|
}
|
|
116
119
|
u-button[size='lg'] {
|
|
117
120
|
font-size: var(--u-density, 14px);
|
|
@@ -122,20 +125,21 @@ u-button[appearance='link'] {
|
|
|
122
125
|
--btn-padding-inline: 0;
|
|
123
126
|
}
|
|
124
127
|
|
|
125
|
-
/* ── Text fields — the same three heights as buttons:
|
|
128
|
+
/* ── Text fields — the same three heights as buttons: 32 / 36 / 40.
|
|
126
129
|
* (Components 2.0 renders fields at 14px by default, so a field no longer grows with the
|
|
127
130
|
* surrounding text; the house sets the box padding per size.) ── */
|
|
128
131
|
:is(u-input, u-select, u-textarea, u-date-picker, u-date-range-picker)[size='sm'] {
|
|
129
|
-
--u-field-padding-block: calc(
|
|
132
|
+
--u-field-padding-block: calc(6em / 12); /* 12px: 18 + 12 + 2 = 32 */
|
|
130
133
|
}
|
|
131
134
|
:is(u-input, u-select, u-textarea, u-date-picker, u-date-range-picker)[size='lg'] {
|
|
132
135
|
font-size: var(--u-density, 14px); /* with the density, like md — the step is the padding */
|
|
133
136
|
--u-field-padding-block: calc(8.5em / 14); /* 14px: 21 + 17 + 2 = 40 */
|
|
134
137
|
}
|
|
135
138
|
|
|
136
|
-
/* ── Tag — 22px
|
|
139
|
+
/* ── Tag — 22px pills (12px text · 1px block padding · hairline) to sit inside 44px rows.
|
|
137
140
|
* A status label is the default `soft` appearance (tint, no outline) with `dot`. ── */
|
|
138
141
|
u-tag {
|
|
142
|
+
border-radius: var(--u-radius-pill, 9999px);
|
|
139
143
|
--tag-padding-block: 1px;
|
|
140
144
|
--tag-padding-inline: 8px;
|
|
141
145
|
--tag-gap: 5px;
|
|
@@ -147,7 +151,7 @@ u-tag[size='sm'] {
|
|
|
147
151
|
--tag-gap: 4px;
|
|
148
152
|
}
|
|
149
153
|
|
|
150
|
-
/* ── Field — a labelled field is a form row: 40px controls (the side-sheet and edit-form size; toolbars keep
|
|
154
|
+
/* ── Field — a labelled field is a form row: 40px controls (the side-sheet and edit-form size; toolbars keep 36px
|
|
151
155
|
* with unlabelled controls), the label at the label step in the weak colour, the help line in the weaker colour.
|
|
152
156
|
* A control's own size wins (`size="sm"` / `"lg"` set the padding on the control itself). ── */
|
|
153
157
|
u-field {
|
|
@@ -172,11 +176,10 @@ u-field[invalid]::part(footer) {
|
|
|
172
176
|
color: var(--u-danger-color-strong);
|
|
173
177
|
}
|
|
174
178
|
|
|
175
|
-
/* ── List page (`@iyulab/enterprise`) — the list screen: filters on one
|
|
176
|
-
* that takes 240–360px, applied chips below, and with `appearance="card"` toolbar · table · pager on one flat
|
|
179
|
+
/* ── List page (`@iyulab/enterprise`) — the list screen: filters on one row with an 8px gap, bottom-aligned (the page’s
|
|
180
|
+
* own alignment — a labelled field’s input stays level with the buttons beside it), a search field that takes 240–360px, applied chips below, and with `appearance="card"` toolbar · table · pager on one flat
|
|
177
181
|
* surface (the toolbar row draws its own 48px band, a quiet pager line). ── */
|
|
178
182
|
u-list-page::part(filters) {
|
|
179
|
-
align-items: center;
|
|
180
183
|
gap: var(--u-space-sm, 8px);
|
|
181
184
|
}
|
|
182
185
|
u-list-page > u-input[slot='filters'][type='search'] {
|
|
@@ -225,13 +228,21 @@ u-rich-table::part(selection-info) {
|
|
|
225
228
|
color: var(--u-txt-color);
|
|
226
229
|
}
|
|
227
230
|
|
|
228
|
-
/* ──
|
|
229
|
-
*
|
|
231
|
+
/* ── Tabs — the current tab is the preset's tab colour (the accent ink; ink under `warm`) with a 2px bar, at the
|
|
232
|
+
* body step, 10px × 12px; the others stay in the weak ink. The same for a strip of links (saved views) and a tab
|
|
233
|
+
* panel. ── */
|
|
230
234
|
u-tab-nav {
|
|
231
|
-
--tab-nav-color: var(--
|
|
232
|
-
|
|
235
|
+
--tab-nav-color: var(--hs-tab-current-color);
|
|
236
|
+
}
|
|
237
|
+
u-tab-panel {
|
|
238
|
+
--tab-panel-color: var(--hs-tab-current-color);
|
|
233
239
|
}
|
|
234
|
-
u-tab-nav u-tab
|
|
240
|
+
:is(u-tab-nav, u-tab-panel) u-tab {
|
|
241
|
+
font-size: var(--u-text-body-size, 14px);
|
|
242
|
+
--tab-padding-block: 10px;
|
|
243
|
+
--tab-padding-inline: 12px;
|
|
244
|
+
}
|
|
245
|
+
:is(u-tab-nav, u-tab-panel) u-tab[active] {
|
|
235
246
|
font-weight: 600;
|
|
236
247
|
}
|
|
237
248
|
|
|
@@ -283,15 +294,15 @@ u-drawer::part(body) {
|
|
|
283
294
|
scrollbar-color: var(--u-border-color-strong) transparent;
|
|
284
295
|
}
|
|
285
296
|
|
|
286
|
-
/* ── Data table (`@iyulab/flex-table`) —
|
|
297
|
+
/* ── Data table (`@iyulab/flex-table`) — 44px rows, body-size cells, a quiet 13px semibold header,
|
|
287
298
|
* no zebra (hover and selection carry the row), tabular figures. ──────── */
|
|
288
299
|
flex-table {
|
|
289
300
|
--ft-font-family: var(--u-font-base);
|
|
290
|
-
--ft-font-size: var(--
|
|
301
|
+
--ft-font-size: var(--u-text-body-size, 14px);
|
|
291
302
|
--ft-row-height: var(--hs-row);
|
|
292
303
|
--ft-cell-padding-inline: 12px;
|
|
293
|
-
--ft-header-font-size: var(--
|
|
294
|
-
--ft-header-font-weight:
|
|
304
|
+
--ft-header-font-size: var(--hs-text-dense-size, 13px);
|
|
305
|
+
--ft-header-font-weight: 600;
|
|
295
306
|
--ft-header-text-color: var(--u-txt-color-weak);
|
|
296
307
|
--ft-header-bg: var(--u-bg-color-raised);
|
|
297
308
|
--ft-row-odd-bg: var(--u-bg-color);
|
|
@@ -319,6 +330,28 @@ u-page-header::part(subtitle) {
|
|
|
319
330
|
u-sidebar-layout::part(sidebar) {
|
|
320
331
|
border-inline-end: 1px solid var(--u-border-color);
|
|
321
332
|
}
|
|
333
|
+
/* The `contrast` preset's dark shell — the sidebar re-scopes the neutral roles to the shell values, so its links,
|
|
334
|
+
* groups, section titles and any menu it opens read as one dark surface (custom properties inherit through the
|
|
335
|
+
* shadow tree). The light presets leave the sidebar on the page's own roles. */
|
|
336
|
+
:root[hs-palette='contrast'] u-sidebar-layout::part(sidebar) {
|
|
337
|
+
--u-bg-color: var(--hs-shell-bg);
|
|
338
|
+
--u-panel-bg-color: var(--hs-shell-raised);
|
|
339
|
+
--u-input-bg-color: var(--hs-shell-raised);
|
|
340
|
+
--u-bg-color-raised: var(--hs-shell-raised);
|
|
341
|
+
--u-bg-color-hover: var(--hs-shell-hover);
|
|
342
|
+
--u-bg-color-active: var(--hs-shell-active);
|
|
343
|
+
--u-border-color: var(--hs-shell-line);
|
|
344
|
+
--u-border-color-weak: var(--hs-shell-line);
|
|
345
|
+
--u-txt-color: var(--hs-shell-ink);
|
|
346
|
+
--u-txt-color-hover: var(--hs-shell-ink);
|
|
347
|
+
--u-txt-color-active: var(--hs-shell-ink);
|
|
348
|
+
--u-txt-color-weak: var(--hs-shell-ink-weak);
|
|
349
|
+
--u-txt-color-weaker: var(--hs-shell-ink-weaker);
|
|
350
|
+
--u-icon-color: var(--hs-shell-ink-weak);
|
|
351
|
+
--u-icon-color-hover: var(--hs-shell-ink);
|
|
352
|
+
--u-icon-color-active: var(--hs-shell-ink);
|
|
353
|
+
border-inline-end-color: var(--hs-shell-line);
|
|
354
|
+
}
|
|
322
355
|
@media print {
|
|
323
356
|
u-sidebar-layout::part(main) {
|
|
324
357
|
background: none;
|
package/styles/patterns.css
CHANGED
|
@@ -10,12 +10,12 @@
|
|
|
10
10
|
* Prefix `hs-`. Everything sits in `@layer iyu.house`; an application rule always wins.
|
|
11
11
|
*
|
|
12
12
|
* Screen recipes (the guide shows each one):
|
|
13
|
-
* list = u-page-header →
|
|
13
|
+
* list = u-page-header → u-list-page (filters · applied · appearance="card": toolbar · table · pager)
|
|
14
14
|
* detail = side sheet: head (id · status · one primary action) → steps → u-info-section strip → tabs → cards
|
|
15
15
|
* edit = side sheet with .hs-fieldset sections and a pinned u-action-bar (summary slot)
|
|
16
16
|
*
|
|
17
17
|
* Rules the patterns encode:
|
|
18
|
-
* · one
|
|
18
|
+
* · one filled (main-action) button per view — the rest are outlined, plain or in a menu
|
|
19
19
|
* · conditions fold, results open — the table starts in the top third of the screen
|
|
20
20
|
* · numbers right-aligned in tabular figures; an empty value is an em dash
|
|
21
21
|
* · row actions appear on hover or selection, never as a red trash can on every row
|
|
@@ -30,103 +30,17 @@
|
|
|
30
30
|
.hs-page {
|
|
31
31
|
display: flex;
|
|
32
32
|
flex-direction: column;
|
|
33
|
-
gap: var(--
|
|
33
|
+
gap: var(--hs-section-gap, 20px);
|
|
34
34
|
min-width: 0;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
|
|
38
|
-
/* ──
|
|
39
|
-
*
|
|
40
|
-
* gives a search field 240–360px and centres the row — `components.css`), the applied chips (`u-chip removable`) in
|
|
41
|
-
* `slot="applied"`, which folds when empty. `__end` → `style="margin-inline-start: auto"` on the last filter.
|
|
42
|
-
* `.hs-chips` goes with it. remove: 0.7.0 */
|
|
43
|
-
.hs-filter-bar {
|
|
44
|
-
display: flex;
|
|
45
|
-
flex-wrap: wrap;
|
|
46
|
-
align-items: center;
|
|
47
|
-
gap: var(--u-space-sm, 8px);
|
|
48
|
-
}
|
|
49
|
-
.hs-filter-bar__search {
|
|
50
|
-
flex: 0 1 360px;
|
|
51
|
-
min-width: 240px;
|
|
52
|
-
}
|
|
53
|
-
.hs-filter-bar__end {
|
|
54
|
-
margin-inline-start: auto;
|
|
55
|
-
}
|
|
56
|
-
.hs-chips {
|
|
57
|
-
display: flex;
|
|
58
|
-
flex-wrap: wrap;
|
|
59
|
-
align-items: center;
|
|
60
|
-
gap: var(--u-space-xs, 6px);
|
|
61
|
-
}
|
|
62
|
-
.hs-chips:empty {
|
|
63
|
-
display: none;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
/* ── Table card — toolbar · table · pager on one surface ────────────────
|
|
68
|
-
* @deprecated `.hs-table-card` and `.hs-pager`: use `<u-list-page appearance="card">` (`@iyulab/enterprise` 0.33) —
|
|
69
|
-
* the toolbar, view and pager regions on one surface with lines between them, and `u-pagination` in `slot="pager"`.
|
|
70
|
-
* @deprecated `.hs-table-toolbar` (`--selected` · `__title` · `__actions`): on a card list page use
|
|
71
|
-
* `<u-action-bar slot="toolbar">` with the title in `slot="summary"` — the house recipe gives it the 48px band and the
|
|
72
|
-
* selected tint follows the page's `:state(selected)` (`@iyulab/enterprise` 0.34); `u-rich-table` styles its own toolbar
|
|
73
|
-
* (`@iyulab/data-components` 0.50). remove: 0.7.0 */
|
|
74
|
-
.hs-table-card {
|
|
75
|
-
background: var(--u-bg-color);
|
|
76
|
-
border: 1px solid var(--u-border-color);
|
|
77
|
-
border-radius: var(--u-radius-xl, 10px);
|
|
78
|
-
overflow: hidden;
|
|
79
|
-
min-width: 0;
|
|
80
|
-
}
|
|
81
|
-
.hs-table-card > flex-table {
|
|
82
|
-
border: 0;
|
|
83
|
-
}
|
|
84
|
-
.hs-table-toolbar {
|
|
85
|
-
display: flex;
|
|
86
|
-
align-items: center;
|
|
87
|
-
justify-content: space-between;
|
|
88
|
-
gap: var(--u-space-sm, 8px);
|
|
89
|
-
min-height: 48px;
|
|
90
|
-
padding: var(--u-space-sm, 8px) var(--u-space-md, 12px);
|
|
91
|
-
border-bottom: 1px solid var(--u-border-color);
|
|
92
|
-
flex-wrap: wrap;
|
|
93
|
-
}
|
|
94
|
-
/* With a selection the toolbar becomes the bulk-action bar. */
|
|
95
|
-
.hs-table-toolbar[data-selected],
|
|
96
|
-
.hs-table-toolbar--selected {
|
|
97
|
-
background: var(--u-primary-bg-color);
|
|
98
|
-
}
|
|
99
|
-
/* In a `u-list-page appearance="card"` toolbar the region draws the line below. */
|
|
100
|
-
u-list-page > .hs-table-toolbar {
|
|
101
|
-
border-bottom: 0;
|
|
102
|
-
}
|
|
103
|
-
.hs-table-toolbar__title {
|
|
104
|
-
font-size: var(--hs-text-dense-size, 13px);
|
|
105
|
-
font-weight: 600;
|
|
106
|
-
}
|
|
107
|
-
.hs-table-toolbar__actions {
|
|
108
|
-
display: flex;
|
|
109
|
-
align-items: center;
|
|
110
|
-
gap: var(--u-space-sm, 8px);
|
|
111
|
-
flex-wrap: wrap;
|
|
112
|
-
}
|
|
113
|
-
.hs-pager {
|
|
114
|
-
display: flex;
|
|
115
|
-
align-items: center;
|
|
116
|
-
justify-content: space-between;
|
|
117
|
-
gap: var(--u-space-sm, 8px);
|
|
118
|
-
padding: var(--u-space-sm, 8px) var(--u-space-md, 12px);
|
|
119
|
-
border-top: 1px solid var(--u-border-color);
|
|
120
|
-
font-size: var(--u-text-label-size, 12px);
|
|
121
|
-
color: var(--u-txt-color-weak);
|
|
122
|
-
font-variant-numeric: tabular-nums;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/* ── Plain table — for small server-rendered tables that do not need a grid ── */
|
|
38
|
+
/* ── Plain table — for small server-rendered tables that do not need a grid ──
|
|
39
|
+
* 44px body-size rows, a 13px semibold header; the first and last cells keep the card's 20px edge. */
|
|
126
40
|
.hs-table {
|
|
127
41
|
width: 100%;
|
|
128
42
|
border-collapse: collapse;
|
|
129
|
-
font-size: var(--
|
|
43
|
+
font-size: var(--u-text-body-size, 14px);
|
|
130
44
|
line-height: 20px;
|
|
131
45
|
color: var(--u-txt-color);
|
|
132
46
|
}
|
|
@@ -134,31 +48,33 @@ u-list-page > .hs-table-toolbar {
|
|
|
134
48
|
padding: var(--u-space-sm, 8px) var(--u-space-md, 12px);
|
|
135
49
|
text-align: start;
|
|
136
50
|
white-space: nowrap;
|
|
137
|
-
font-size: var(--
|
|
138
|
-
line-height:
|
|
139
|
-
font-weight:
|
|
51
|
+
font-size: var(--hs-text-dense-size, 13px);
|
|
52
|
+
line-height: 18px;
|
|
53
|
+
font-weight: 600;
|
|
140
54
|
color: var(--u-txt-color-weak);
|
|
141
55
|
background: var(--u-bg-color-raised);
|
|
142
56
|
border-bottom: 1px solid var(--u-border-color);
|
|
143
57
|
}
|
|
144
58
|
.hs-table td {
|
|
145
|
-
height: var(--hs-row,
|
|
59
|
+
height: var(--hs-row, 44px);
|
|
146
60
|
padding: 0 var(--u-space-md, 12px);
|
|
147
61
|
border-bottom: 1px solid var(--u-border-color);
|
|
148
62
|
vertical-align: middle;
|
|
149
63
|
}
|
|
64
|
+
.hs-table :is(th, td):first-child { padding-inline-start: var(--u-space-xl, 20px); }
|
|
65
|
+
.hs-table :is(th, td):last-child { padding-inline-end: var(--u-space-xl, 20px); }
|
|
150
66
|
.hs-table tbody tr:last-child td { border-bottom: 0; }
|
|
151
67
|
.hs-table tbody tr:hover td { background: var(--u-bg-color-hover); }
|
|
152
68
|
.hs-table tr[aria-selected='true'] td { background: var(--u-primary-bg-color); }
|
|
153
69
|
.hs-table tfoot td {
|
|
154
|
-
height: var(--hs-row,
|
|
70
|
+
height: var(--hs-row, 44px);
|
|
155
71
|
font-weight: 600;
|
|
156
72
|
}
|
|
157
73
|
/* One line separates the totals from the body — not one per totals row (subtotal · tax · total). */
|
|
158
74
|
.hs-table tfoot tr:first-child td { border-top: 1px solid var(--u-border-color); }
|
|
159
75
|
/* Totals rows follow the compact height too (`tfoot td` would otherwise win on specificity). */
|
|
160
76
|
.hs-table--compact td,
|
|
161
|
-
.hs-table--compact tfoot td { height: var(--hs-row-compact,
|
|
77
|
+
.hs-table--compact tfoot td { height: var(--hs-row-compact, 36px); }
|
|
162
78
|
.hs-table--top td { vertical-align: top; padding-block: var(--u-space-sm, 8px); height: auto; }
|
|
163
79
|
/* Cells (`th` too — header text aligns with its values) */
|
|
164
80
|
.hs-num,
|
|
@@ -184,7 +100,7 @@ a.hs-id:hover,
|
|
|
184
100
|
.hs-table .hs-continued td.hs-keep { color: var(--u-txt-color); }
|
|
185
101
|
/* A group header row with its subtotal. */
|
|
186
102
|
.hs-table .hs-group td {
|
|
187
|
-
height:
|
|
103
|
+
height: var(--hs-row-compact, 36px);
|
|
188
104
|
background: var(--u-bg-color-raised);
|
|
189
105
|
font-size: var(--u-text-label-size, 12px);
|
|
190
106
|
font-weight: 600;
|
|
@@ -208,38 +124,6 @@ tr[aria-selected='true'] .hs-row-actions {
|
|
|
208
124
|
.hs-row-actions { display: none; }
|
|
209
125
|
}
|
|
210
126
|
|
|
211
|
-
/* ── Card — a titled surface for detail panels and dashboards ───────────
|
|
212
|
-
* @deprecated `.hs-card` (`__head` · `__title` · `__link`): a titled card is `<u-group-box title>` (`@iyulab/modern-app`)
|
|
213
|
-
* with the link in `slot="actions"`; an untitled surface is `<u-card>` (`@iyulab/components`), or `<u-group-box flush>`
|
|
214
|
-
* when its content runs to the edge and holds a sticky footer (`u-card` clips its overflow). remove: 0.7.0 */
|
|
215
|
-
.hs-card {
|
|
216
|
-
background: var(--u-bg-color);
|
|
217
|
-
border: 1px solid var(--u-border-color);
|
|
218
|
-
border-radius: var(--u-radius-xl, 10px);
|
|
219
|
-
padding: var(--u-space-lg, 16px);
|
|
220
|
-
min-width: 0;
|
|
221
|
-
}
|
|
222
|
-
.hs-card__head {
|
|
223
|
-
display: flex;
|
|
224
|
-
align-items: center;
|
|
225
|
-
justify-content: space-between;
|
|
226
|
-
gap: var(--u-space-sm, 8px);
|
|
227
|
-
margin-bottom: var(--u-space-md, 12px);
|
|
228
|
-
}
|
|
229
|
-
.hs-card__title {
|
|
230
|
-
margin: 0;
|
|
231
|
-
font-size: var(--u-text-subtitle-size, 15px);
|
|
232
|
-
line-height: 22px;
|
|
233
|
-
font-weight: 600;
|
|
234
|
-
}
|
|
235
|
-
.hs-card__link {
|
|
236
|
-
font-size: var(--u-text-label-size, 12px);
|
|
237
|
-
font-weight: 500;
|
|
238
|
-
color: var(--u-link-txt-color);
|
|
239
|
-
text-decoration: none;
|
|
240
|
-
}
|
|
241
|
-
.hs-card__link:hover { text-decoration: underline; }
|
|
242
|
-
|
|
243
127
|
/* Description list — label / value pairs inside a card. */
|
|
244
128
|
.hs-dl {
|
|
245
129
|
display: grid;
|
|
@@ -258,7 +142,7 @@ tr[aria-selected='true'] .hs-row-actions {
|
|
|
258
142
|
.hs-detail__cols {
|
|
259
143
|
display: flex;
|
|
260
144
|
flex-wrap: wrap;
|
|
261
|
-
gap: var(--
|
|
145
|
+
gap: var(--hs-section-gap, 20px);
|
|
262
146
|
align-items: flex-start;
|
|
263
147
|
}
|
|
264
148
|
.hs-detail__cols > * {
|
|
@@ -272,7 +156,7 @@ tr[aria-selected='true'] .hs-row-actions {
|
|
|
272
156
|
.hs-grid-cards {
|
|
273
157
|
display: grid;
|
|
274
158
|
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
|
|
275
|
-
gap: var(--
|
|
159
|
+
gap: var(--hs-section-gap, 20px);
|
|
276
160
|
align-items: start;
|
|
277
161
|
}
|
|
278
162
|
|
|
@@ -305,45 +189,6 @@ tr[aria-selected='true'] .hs-row-actions {
|
|
|
305
189
|
clear: both;
|
|
306
190
|
margin-top: 0;
|
|
307
191
|
}
|
|
308
|
-
/* @deprecated Use `<u-field label>` (`@iyulab/components` 2.26) — `label`, `required`, `description` for the help line
|
|
309
|
-
and `invalid` + `validation-message` for the error; it names the control it wraps and fills the cell. The house
|
|
310
|
-
draws it this way (`components.css`: 40px controls, label and help steps). `.hs-field__label` · `__required` ·
|
|
311
|
-
`__help` · `__error` go with it. remove: 0.7.0 */
|
|
312
|
-
.hs-field {
|
|
313
|
-
display: grid;
|
|
314
|
-
gap: 6px;
|
|
315
|
-
align-content: start;
|
|
316
|
-
min-width: 0;
|
|
317
|
-
}
|
|
318
|
-
.hs-field__label {
|
|
319
|
-
font-size: var(--u-text-label-size, 12px);
|
|
320
|
-
line-height: 16px;
|
|
321
|
-
font-weight: 500;
|
|
322
|
-
color: var(--u-txt-color-weak);
|
|
323
|
-
}
|
|
324
|
-
.hs-field__required {
|
|
325
|
-
margin-inline-start: 2px;
|
|
326
|
-
color: var(--u-danger-color-strong);
|
|
327
|
-
}
|
|
328
|
-
.hs-field__help {
|
|
329
|
-
font-size: var(--u-text-caption-size, 12px);
|
|
330
|
-
line-height: 18px;
|
|
331
|
-
color: var(--u-txt-color-weaker);
|
|
332
|
-
}
|
|
333
|
-
.hs-field__error {
|
|
334
|
-
font-size: var(--u-text-caption-size, 12px);
|
|
335
|
-
line-height: 18px;
|
|
336
|
-
color: var(--u-danger-color-strong);
|
|
337
|
-
}
|
|
338
|
-
/* Form fields are 40px (the side-sheet and edit-form size); toolbars keep 32px. */
|
|
339
|
-
.hs-field {
|
|
340
|
-
--u-field-padding-block: calc(8.5em / 14); /* 14px: 21 + 17 + 2 = 40 — and with the density */
|
|
341
|
-
}
|
|
342
|
-
.hs-field :is(u-input, u-select, u-textarea, u-date-picker, u-date-range-picker) {
|
|
343
|
-
width: 100%;
|
|
344
|
-
--u-input-display: block;
|
|
345
|
-
--u-select-display: block;
|
|
346
|
-
}
|
|
347
192
|
/* Two or three columns — never four or more in a row. A column is at least half of a 480px row, so
|
|
348
193
|
* both grids drop to one column below 480px and .hs-grid-3 shows two between 480px and 728px. No size
|
|
349
194
|
* container: auto-fill against the grid's own width, capped at the column count. */
|
package/styles/tailwind.css
CHANGED
|
@@ -14,12 +14,13 @@
|
|
|
14
14
|
* utilities (a utility on an element still wins), and still below your unlayered CSS.
|
|
15
15
|
*
|
|
16
16
|
* Also maps the house roles onto utilities that read the live `--u-*` tokens (`@theme inline`),
|
|
17
|
-
* so dark mode and
|
|
17
|
+
* so dark mode, the preset (`hs-palette`) and the seed colours reach Tailwind classes with no rebuild:
|
|
18
18
|
*
|
|
19
19
|
* bg-canvas · bg-surface · bg-raised · bg-selected · border-line · border-line-strong
|
|
20
20
|
* text-ink · text-ink-weak · text-ink-weaker · text-link · ring-focus
|
|
21
21
|
* {text,bg,border}-{info,success,warning,danger} (text = readable step) · bg-{role}-soft
|
|
22
|
-
*
|
|
22
|
+
* {bg,text}-accent · bg-accent-soft · text-accent-ink · text-on-accent (and the same for secondary)
|
|
23
|
+
* rounded-control (8) · rounded-card (10) · rounded-pill · shadow-raise · shadow-overlay · font-sans
|
|
23
24
|
*
|
|
24
25
|
* Existing markup full of `text-gray-*` / `bg-slate-*`: add `tailwind-neutrals.css` too.
|
|
25
26
|
* ========================================================================== */
|
|
@@ -42,9 +43,14 @@
|
|
|
42
43
|
--color-focus: var(--u-focus-ring-color);
|
|
43
44
|
--color-action: var(--u-primary-color);
|
|
44
45
|
--color-on-action: var(--u-primary-txt-color);
|
|
45
|
-
--color-
|
|
46
|
-
--color-
|
|
47
|
-
--color-
|
|
46
|
+
--color-accent: var(--hs-accent-fill);
|
|
47
|
+
--color-accent-soft: var(--hs-accent-soft);
|
|
48
|
+
--color-accent-ink: var(--hs-accent-ink);
|
|
49
|
+
--color-on-accent: var(--hs-accent-contrast);
|
|
50
|
+
--color-secondary: var(--hs-secondary-fill);
|
|
51
|
+
--color-secondary-soft: var(--hs-secondary-soft);
|
|
52
|
+
--color-secondary-ink: var(--hs-secondary-ink);
|
|
53
|
+
--color-on-secondary: var(--hs-secondary-contrast);
|
|
48
54
|
|
|
49
55
|
--color-info: var(--u-info-color-strong);
|
|
50
56
|
--color-info-soft: var(--u-info-bg-color);
|
|
@@ -58,6 +64,7 @@
|
|
|
58
64
|
--radius-control: var(--u-radius-lg);
|
|
59
65
|
--radius-card: var(--u-radius-xl);
|
|
60
66
|
--radius-badge: var(--u-radius-md);
|
|
67
|
+
--radius-pill: var(--u-radius-pill, 9999px);
|
|
61
68
|
|
|
62
69
|
--shadow-raise: var(--u-shadow-sm);
|
|
63
70
|
--shadow-overlay: var(--u-shadow-lg);
|
package/styles/tokens.css
CHANGED
|
@@ -6,28 +6,303 @@
|
|
|
6
6
|
*
|
|
7
7
|
* built-in defaults (iyu.base) < this theme (iyu.house) < your application (unlayered)
|
|
8
8
|
*
|
|
9
|
-
*
|
|
10
|
-
* see "Brand" below. No specificity tricks are needed.
|
|
9
|
+
* Three layers of decision:
|
|
11
10
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
11
|
+
* the application two seed colours — `--hs-accent` (identity, the main action, the current item, links,
|
|
12
|
+
* focus) and `--hs-secondary` (a second emphasis: the second chart series, a
|
|
13
|
+
* `color="secondary"` tag or button). Every step the components need (a fill, a soft tint,
|
|
14
|
+
* a readable ink, the dark-mode steps) is derived from the seed here.
|
|
15
|
+
* a preset the balance of the whole screen — the temperature of the neutrals, how far apart canvas,
|
|
16
|
+
* surface, lines and text sit, whether the main action is the accent or ink, and how dark
|
|
17
|
+
* the shell is. `<html hs-palette="…">`: `cool` (no attribute — the default) · `warm` ·
|
|
18
|
+
* `contrast`. Each preset has a light and a dark side (`theme="dark"`).
|
|
19
|
+
* the house shape, size and type (the scale block at the end) — the same under every preset.
|
|
18
20
|
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
21
|
+
* Status colours (info · success · warning · danger) belong to the preset, never to the seeds: a red brand
|
|
22
|
+
* must not make «danger» and «brand» one colour.
|
|
23
|
+
*
|
|
24
|
+
* The derivations use CSS relative colour syntax and `color-mix()` (Chromium 119 · Safari 16.4 · Firefox 128).
|
|
25
|
+
* They cannot promise contrast for every seed (a pale yellow cannot carry white text), so each derived step is
|
|
26
|
+
* its own token an application can set: `--hs-accent-fill` · `-contrast` · `-soft` · `-ink`. Set seeds on
|
|
27
|
+
* `:root` — a token derived on `:root` does not follow a seed set further down the tree.
|
|
28
|
+
*
|
|
29
|
+
* Contrast and perception floors for every preset × mode are re-measured by `tests/tokens.test.mjs`.
|
|
22
30
|
* ========================================================================== */
|
|
23
31
|
|
|
24
32
|
@layer iyu.base, iyu.house;
|
|
25
33
|
|
|
26
34
|
@layer iyu.house {
|
|
27
35
|
|
|
28
|
-
/* ── light (
|
|
36
|
+
/* ── cool · light — the default (no `hs-palette`) ───────────────────────── */
|
|
29
37
|
:root {
|
|
30
|
-
/*
|
|
38
|
+
/* Seeds — an application sets these (and, only if a seed defeats a derivation, the derived steps). */
|
|
39
|
+
--hs-accent: #1F5FBF;
|
|
40
|
+
--hs-secondary: #B55F40;
|
|
41
|
+
|
|
42
|
+
/* Derived steps, light */
|
|
43
|
+
--hs-accent-fill: oklch(from var(--hs-accent) min(l, 0.55) c h); /* the seed, darkened only as far as white text needs */
|
|
44
|
+
--hs-accent-contrast: #FFFFFF;
|
|
45
|
+
--hs-accent-soft: color-mix(in oklab, var(--hs-accent) 11%, var(--u-bg-color));
|
|
46
|
+
--hs-accent-ink: oklch(from var(--hs-accent) min(l, 0.5) c h);
|
|
47
|
+
--hs-secondary-fill: oklch(from var(--hs-secondary) min(l, 0.55) c h);
|
|
48
|
+
--hs-secondary-contrast: #FFFFFF;
|
|
49
|
+
--hs-secondary-soft: color-mix(in oklab, var(--hs-secondary) 12%, var(--u-bg-color));
|
|
50
|
+
--hs-secondary-ink: oklch(from var(--hs-secondary) min(l, 0.48) c h);
|
|
51
|
+
|
|
52
|
+
/* Neutral ramp — cool grey. Most role tokens derive from it. */
|
|
53
|
+
--u-neutral-0: #FFFFFF;
|
|
54
|
+
--u-neutral-50: #F5F6F8;
|
|
55
|
+
--u-neutral-100: #EEF0F3;
|
|
56
|
+
--u-neutral-200: #E6E8EC;
|
|
57
|
+
--u-neutral-300: #E0E0E0;
|
|
58
|
+
--u-neutral-400: #C9CDD3;
|
|
59
|
+
--u-neutral-500: #858C96;
|
|
60
|
+
--u-neutral-600: #6B6F75;
|
|
61
|
+
--u-neutral-700: #666666;
|
|
62
|
+
--u-neutral-800: #333232;
|
|
63
|
+
--u-neutral-900: #1F2023;
|
|
64
|
+
--u-neutral-1000: #111214;
|
|
65
|
+
|
|
66
|
+
/* Depth — canvas (page) < surface (cards, tables, controls) < floating (shadow) */
|
|
67
|
+
--u-canvas-bg-color: #F5F6F8;
|
|
68
|
+
--u-bg-color: #FFFFFF;
|
|
69
|
+
--u-panel-bg-color: #FFFFFF;
|
|
70
|
+
--u-input-bg-color: #FFFFFF;
|
|
71
|
+
--u-bg-color-raised: #F5F6F8; /* table header, toolbar strip, read-only field */
|
|
72
|
+
--u-bg-color-raised-hover: #E9EBEF;
|
|
73
|
+
--u-bg-color-hover: #EEF0F3;
|
|
74
|
+
--u-bg-color-active: #E6E8EC;
|
|
75
|
+
--u-bg-color-disabled: #F5F6F8;
|
|
76
|
+
--u-overlay-bg-color: rgba(17, 20, 24, 0.36);
|
|
77
|
+
|
|
78
|
+
/* Lines — a hairline for surfaces, a firmer line for the edge of a field (≥ 3:1, WCAG 1.4.11) */
|
|
79
|
+
--u-border-color: #E0E0E0;
|
|
80
|
+
--u-border-color-weak: #EAEBED;
|
|
81
|
+
--u-border-color-strong: #858C96;
|
|
82
|
+
--u-border-color-hover: #858C96;
|
|
83
|
+
--u-input-border-color: #858C96;
|
|
84
|
+
--u-input-border-color-hover: #5C6168;
|
|
85
|
+
--u-input-border-color-focus: var(--hs-accent-fill);
|
|
86
|
+
|
|
87
|
+
/* Ink */
|
|
88
|
+
--u-txt-color: #333232;
|
|
89
|
+
--u-txt-color-strong: #1F2023;
|
|
90
|
+
--u-txt-color-weak: #666666;
|
|
91
|
+
--u-txt-color-weaker: #6B6F75;
|
|
92
|
+
--u-txt-color-hover: #333232;
|
|
93
|
+
--u-txt-color-active: #333232;
|
|
94
|
+
--u-txt-color-disabled: #A6ABB2;
|
|
95
|
+
--u-icon-color: #666666;
|
|
96
|
+
--u-icon-color-hover: #333232;
|
|
97
|
+
--u-icon-color-active: #333232;
|
|
98
|
+
|
|
99
|
+
/* Action — the accent. One filled action per view; the rest are outlined. */
|
|
100
|
+
--u-primary-color-weakest: color-mix(in oklab, var(--hs-accent-fill) 16%, var(--u-bg-color));
|
|
101
|
+
--u-primary-color-weaker: color-mix(in oklab, var(--hs-accent-fill) 30%, var(--u-bg-color));
|
|
102
|
+
--u-primary-color-weak: color-mix(in oklab, var(--hs-accent-fill) 55%, var(--u-bg-color));
|
|
103
|
+
--u-primary-color: var(--hs-accent-fill);
|
|
104
|
+
--u-primary-color-strong: var(--hs-accent-ink);
|
|
105
|
+
--u-primary-txt-color: var(--hs-accent-contrast);
|
|
106
|
+
--u-primary-bg-color: var(--hs-accent-soft); /* selected rows, current item */
|
|
107
|
+
|
|
108
|
+
/* Second emphasis — the secondary seed (`color="secondary"`) */
|
|
109
|
+
--u-secondary-color-weakest: color-mix(in oklab, var(--hs-secondary-fill) 16%, var(--u-bg-color));
|
|
110
|
+
--u-secondary-color-weaker: color-mix(in oklab, var(--hs-secondary-fill) 30%, var(--u-bg-color));
|
|
111
|
+
--u-secondary-color-weak: color-mix(in oklab, var(--hs-secondary-fill) 55%, var(--u-bg-color));
|
|
112
|
+
--u-secondary-color: var(--hs-secondary-fill);
|
|
113
|
+
--u-secondary-color-strong: var(--hs-secondary-ink);
|
|
114
|
+
--u-secondary-txt-color: var(--hs-secondary-contrast);
|
|
115
|
+
--u-secondary-bg-color: var(--hs-secondary-soft);
|
|
116
|
+
|
|
117
|
+
/* Interaction — links, focus and the mark of a chosen option (a checked box or radio) follow the accent */
|
|
118
|
+
--u-link-txt-color: var(--hs-accent-ink);
|
|
119
|
+
--u-focus-ring-color: var(--hs-accent-fill);
|
|
120
|
+
--u-selection-color: var(--hs-accent-fill);
|
|
121
|
+
--u-selection-txt-color: var(--hs-accent-contrast); /* the check drawn on that fill */
|
|
122
|
+
|
|
123
|
+
/* Chart series — eight, in order (slot one first, never cycled). Slot one is the accent and slot two the
|
|
124
|
+
secondary, each held to the series lightness band; the other six are muted, warm-leaning hues chosen as a
|
|
125
|
+
set: OKLCH L 0.50–0.68, chroma ≥ 0.10, neighbours ΔE ≥ 15 for full colour vision and ≥ 8 under red–green
|
|
126
|
+
deficiency (Machado 2009), every slot at least ΔE 10 from a status colour — measured with the default seeds.
|
|
127
|
+
Slot six (light olive) is 2.8:1 on white — six or more series need a legend or labels. */
|
|
128
|
+
--u-chart-color-1: oklch(from var(--hs-accent) clamp(0.5, l, 0.66) c h);
|
|
129
|
+
--u-chart-color-2: oklch(from var(--hs-secondary) clamp(0.5, l, 0.66) c h);
|
|
130
|
+
--u-chart-color-3: #14938D;
|
|
131
|
+
--u-chart-color-4: #AF8020;
|
|
132
|
+
--u-chart-color-5: #7D4B92;
|
|
133
|
+
--u-chart-color-6: #86A645;
|
|
134
|
+
--u-chart-color-7: #C46E83;
|
|
135
|
+
--u-chart-color-8: #834B14;
|
|
136
|
+
|
|
137
|
+
/* Status — `-color-strong` is the text step (on surface and on its own tint), `-bg-color`
|
|
138
|
+
the tint, `-color` the solid fill (with `-txt-color` on top). */
|
|
139
|
+
--u-info-color-weakest: #D6E3FB;
|
|
140
|
+
--u-info-color-weaker: #A9C4F6;
|
|
141
|
+
--u-info-color-weak: #5B8DE8;
|
|
142
|
+
--u-info-color: #1F5FCC;
|
|
143
|
+
--u-info-color-strong: #1A55B8;
|
|
144
|
+
--u-info-bg-color: #E8F0FD;
|
|
145
|
+
--u-info-txt-color: #FFFFFF;
|
|
146
|
+
|
|
147
|
+
--u-success-color-weakest: #CDEBD6;
|
|
148
|
+
--u-success-color-weaker: #A3D8B4;
|
|
149
|
+
--u-success-color-weak: #4AA26A;
|
|
150
|
+
--u-success-color: #1A7F37;
|
|
151
|
+
--u-success-color-strong: #176F31;
|
|
152
|
+
--u-success-bg-color: #E6F4EA;
|
|
153
|
+
--u-success-txt-color: #FFFFFF;
|
|
154
|
+
|
|
155
|
+
--u-warning-color-weakest: #FBEBCF;
|
|
156
|
+
--u-warning-color-weaker: #F0D9B5;
|
|
157
|
+
--u-warning-color-weak: #E8B25A;
|
|
158
|
+
--u-warning-color: #E59A24;
|
|
159
|
+
--u-warning-color-strong: #A15C00;
|
|
160
|
+
--u-warning-bg-color: #FEF5E6;
|
|
161
|
+
--u-warning-txt-color: #1F2023;
|
|
162
|
+
|
|
163
|
+
--u-danger-color-weakest: #F9D4D0;
|
|
164
|
+
--u-danger-color-weaker: #F2AAA2;
|
|
165
|
+
--u-danger-color-weak: #DE6A5D;
|
|
166
|
+
--u-danger-color: #B42318;
|
|
167
|
+
--u-danger-color-strong: #B42318;
|
|
168
|
+
--u-danger-bg-color: #FDECEA;
|
|
169
|
+
--u-danger-txt-color: #FFFFFF;
|
|
170
|
+
|
|
171
|
+
/* Elevation — surfaces are flat (a hairline); one real shadow for things that float */
|
|
172
|
+
--u-shadow-color-weaker: rgba(16, 19, 24, 0.04);
|
|
173
|
+
--u-shadow-color-weak: rgba(16, 19, 24, 0.06);
|
|
174
|
+
--u-shadow-color-normal: rgba(16, 19, 24, 0.10);
|
|
175
|
+
--u-shadow-color-strong: rgba(16, 19, 24, 0.14);
|
|
176
|
+
--u-shadow-color-stronger: rgba(16, 19, 24, 0.18);
|
|
177
|
+
--u-shadow-sm: 0 1px 2px rgba(16, 19, 24, 0.06);
|
|
178
|
+
--u-shadow-md: 0 1px 2px rgba(16, 19, 24, 0.06);
|
|
179
|
+
--u-shadow-lg: 0 12px 32px rgba(16, 19, 24, 0.14), 0 2px 6px rgba(16, 19, 24, 0.06);
|
|
180
|
+
--u-shadow-xl: 0 16px 40px rgba(16, 19, 24, 0.18), 0 2px 8px rgba(16, 19, 24, 0.08);
|
|
181
|
+
|
|
182
|
+
/* Shell (`@iyulab/modern-app`) — a light sidebar on the surface; the current item is the accent tint */
|
|
183
|
+
--app-sidebar-bg: var(--u-bg-color);
|
|
184
|
+
--app-sidebar-fg: var(--u-txt-color);
|
|
185
|
+
--app-header-bg: var(--u-bg-color);
|
|
186
|
+
--app-header-fg: var(--u-txt-color);
|
|
187
|
+
--app-sidebar-active-bg: var(--hs-accent-soft);
|
|
188
|
+
--app-sidebar-active-fg: var(--hs-accent-ink);
|
|
189
|
+
--app-sidebar-group-active-fg: var(--hs-accent-ink);
|
|
190
|
+
|
|
191
|
+
/* The current tab — its text and its 2px bar */
|
|
192
|
+
--hs-tab-current-color: var(--hs-accent-ink);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/* ── cool · dark ─────────────────────────────────────────────────────────── */
|
|
196
|
+
:root[theme="dark"] {
|
|
197
|
+
--hs-accent-fill: oklch(from var(--hs-accent) max(l, 0.7) c h);
|
|
198
|
+
--hs-accent-contrast: #0E1013;
|
|
199
|
+
--hs-accent-soft: color-mix(in oklab, var(--hs-accent) 22%, var(--u-bg-color));
|
|
200
|
+
--hs-accent-ink: oklch(from var(--hs-accent) max(l, 0.8) c h);
|
|
201
|
+
--hs-secondary-fill: oklch(from var(--hs-secondary) max(l, 0.7) c h);
|
|
202
|
+
--hs-secondary-contrast: #0E1013;
|
|
203
|
+
--hs-secondary-soft: color-mix(in oklab, var(--hs-secondary) 24%, var(--u-bg-color));
|
|
204
|
+
--hs-secondary-ink: oklch(from var(--hs-secondary) max(l, 0.8) c h);
|
|
205
|
+
|
|
206
|
+
--u-neutral-0: #0E1013;
|
|
207
|
+
--u-neutral-50: #111418;
|
|
208
|
+
--u-neutral-100: #181B20;
|
|
209
|
+
--u-neutral-200: #1F2329;
|
|
210
|
+
--u-neutral-300: #2A2F36;
|
|
211
|
+
--u-neutral-400: #3D434C;
|
|
212
|
+
--u-neutral-500: #646B76;
|
|
213
|
+
--u-neutral-600: #8D939B;
|
|
214
|
+
--u-neutral-700: #A2A8B0;
|
|
215
|
+
--u-neutral-800: #C6CBD1;
|
|
216
|
+
--u-neutral-900: #E4E6E9;
|
|
217
|
+
--u-neutral-1000: #FFFFFF;
|
|
218
|
+
|
|
219
|
+
--u-canvas-bg-color: #111418;
|
|
220
|
+
--u-bg-color: #181B20;
|
|
221
|
+
--u-panel-bg-color: #181B20;
|
|
222
|
+
--u-input-bg-color: #181B20;
|
|
223
|
+
--u-bg-color-raised: #1F2329;
|
|
224
|
+
--u-bg-color-raised-hover: #282D34;
|
|
225
|
+
--u-bg-color-hover: #22262D;
|
|
226
|
+
--u-bg-color-active: #2A2F37;
|
|
227
|
+
--u-bg-color-disabled: #1C1F24;
|
|
228
|
+
--u-overlay-bg-color: rgba(0, 0, 0, 0.56);
|
|
229
|
+
|
|
230
|
+
--u-border-color: #2A2F36;
|
|
231
|
+
--u-border-color-weak: #23272D;
|
|
232
|
+
--u-border-color-strong: #646B76;
|
|
233
|
+
--u-border-color-hover: #646B76;
|
|
234
|
+
--u-input-border-color: #6B727D;
|
|
235
|
+
--u-input-border-color-hover: #A2A8B0;
|
|
236
|
+
|
|
237
|
+
--u-txt-color: #E4E6E9;
|
|
238
|
+
--u-txt-color-strong: #FFFFFF;
|
|
239
|
+
--u-txt-color-weak: #A2A8B0;
|
|
240
|
+
--u-txt-color-weaker: #8D939B;
|
|
241
|
+
--u-txt-color-hover: #E4E6E9;
|
|
242
|
+
--u-txt-color-active: #E4E6E9;
|
|
243
|
+
--u-txt-color-disabled: #575D66;
|
|
244
|
+
--u-icon-color: #A2A8B0;
|
|
245
|
+
--u-icon-color-hover: #E4E6E9;
|
|
246
|
+
--u-icon-color-active: #E4E6E9;
|
|
247
|
+
|
|
248
|
+
/* Chart series, dark — the same hues stepped into the dark band (L 0.52–0.66), every slot ≥ 3:1 on the
|
|
249
|
+
surface and the raised surface. */
|
|
250
|
+
--u-chart-color-1: oklch(from var(--hs-accent) clamp(0.6, l, 0.66) c h);
|
|
251
|
+
--u-chart-color-2: oklch(from var(--hs-secondary) clamp(0.6, l, 0.66) c h);
|
|
252
|
+
--u-chart-color-3: #04A19B;
|
|
253
|
+
--u-chart-color-4: #B8892D;
|
|
254
|
+
--u-chart-color-5: #9760AF;
|
|
255
|
+
--u-chart-color-6: #57833D;
|
|
256
|
+
--u-chart-color-7: #CF7188;
|
|
257
|
+
--u-chart-color-8: #9A5F1A;
|
|
258
|
+
|
|
259
|
+
--u-info-color-weakest: #1F3152;
|
|
260
|
+
--u-info-color-weaker: #2C4A7E;
|
|
261
|
+
--u-info-color-weak: #5E8BE0;
|
|
262
|
+
--u-info-color: #8DB3F7;
|
|
263
|
+
--u-info-color-strong: #8DB3F7;
|
|
264
|
+
--u-info-bg-color: #1B2A44;
|
|
265
|
+
--u-info-txt-color: #0E1013;
|
|
266
|
+
|
|
267
|
+
--u-success-color-weakest: #1A3826;
|
|
268
|
+
--u-success-color-weaker: #2B5A3E;
|
|
269
|
+
--u-success-color-weak: #4FB07D;
|
|
270
|
+
--u-success-color: #7DD8A5;
|
|
271
|
+
--u-success-color-strong: #7DD8A5;
|
|
272
|
+
--u-success-bg-color: #16301F;
|
|
273
|
+
--u-success-txt-color: #0E1013;
|
|
274
|
+
|
|
275
|
+
--u-warning-color-weakest: #3F2E12;
|
|
276
|
+
--u-warning-color-weaker: #5E451A;
|
|
277
|
+
--u-warning-color-weak: #C99140;
|
|
278
|
+
--u-warning-color: #F2B65A;
|
|
279
|
+
--u-warning-color-strong: #F2B65A;
|
|
280
|
+
--u-warning-bg-color: #3A2A10;
|
|
281
|
+
--u-warning-txt-color: #0E1013;
|
|
282
|
+
|
|
283
|
+
--u-danger-color-weakest: #4A1F1B;
|
|
284
|
+
--u-danger-color-weaker: #6E2C26;
|
|
285
|
+
--u-danger-color-weak: #E0675C;
|
|
286
|
+
--u-danger-color: #FF8A80;
|
|
287
|
+
--u-danger-color-strong: #FF8A80;
|
|
288
|
+
--u-danger-bg-color: #3D1A17;
|
|
289
|
+
--u-danger-txt-color: #1A0D0B;
|
|
290
|
+
|
|
291
|
+
--u-shadow-color-weaker: rgba(0, 0, 0, 0.24);
|
|
292
|
+
--u-shadow-color-weak: rgba(0, 0, 0, 0.32);
|
|
293
|
+
--u-shadow-color-normal: rgba(0, 0, 0, 0.40);
|
|
294
|
+
--u-shadow-color-strong: rgba(0, 0, 0, 0.50);
|
|
295
|
+
--u-shadow-color-stronger: rgba(0, 0, 0, 0.60);
|
|
296
|
+
--u-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.40);
|
|
297
|
+
--u-shadow-md: 0 1px 2px rgba(0, 0, 0, 0.40);
|
|
298
|
+
--u-shadow-lg: 0 12px 32px rgba(0, 0, 0, 0.55), 0 2px 6px rgba(0, 0, 0, 0.40);
|
|
299
|
+
--u-shadow-xl: 0 16px 40px rgba(0, 0, 0, 0.60), 0 2px 8px rgba(0, 0, 0, 0.45);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/* ── warm · light — the house before 0.8: warm grey, an ink main action, the accent for interaction only ── */
|
|
303
|
+
:root[hs-palette="warm"] {
|
|
304
|
+
--hs-accent: #2F6FEB;
|
|
305
|
+
|
|
31
306
|
--u-neutral-0: #FFFFFF;
|
|
32
307
|
--u-neutral-50: #F6F6F4;
|
|
33
308
|
--u-neutral-100: #F1F1EF;
|
|
@@ -41,28 +316,24 @@
|
|
|
41
316
|
--u-neutral-900: #18191B;
|
|
42
317
|
--u-neutral-1000: #0E0F10;
|
|
43
318
|
|
|
44
|
-
/* Depth — canvas (page) < surface (cards, tables, controls) < floating (shadow) */
|
|
45
319
|
--u-canvas-bg-color: #F6F6F4;
|
|
46
320
|
--u-bg-color: #FFFFFF;
|
|
47
321
|
--u-panel-bg-color: #FFFFFF;
|
|
48
322
|
--u-input-bg-color: #FFFFFF;
|
|
49
|
-
--u-bg-color-raised: #F1F1EF;
|
|
323
|
+
--u-bg-color-raised: #F1F1EF;
|
|
50
324
|
--u-bg-color-raised-hover: #E5E5E2;
|
|
51
325
|
--u-bg-color-hover: #F1F1EF;
|
|
52
326
|
--u-bg-color-active: #EAEAE7;
|
|
53
327
|
--u-bg-color-disabled: #F1F1EF;
|
|
54
328
|
--u-overlay-bg-color: rgba(24, 25, 27, 0.32);
|
|
55
329
|
|
|
56
|
-
/* Lines */
|
|
57
330
|
--u-border-color: #E3E3DF;
|
|
58
331
|
--u-border-color-weak: #ECECE9;
|
|
59
332
|
--u-border-color-strong: #8F9296;
|
|
60
333
|
--u-border-color-hover: #8F9296;
|
|
61
334
|
--u-input-border-color: #8F9296;
|
|
62
335
|
--u-input-border-color-hover: #5B5E63;
|
|
63
|
-
--u-input-border-color-focus: #2F6FEB;
|
|
64
336
|
|
|
65
|
-
/* Ink */
|
|
66
337
|
--u-txt-color: #18191B;
|
|
67
338
|
--u-txt-color-strong: #0E0F10;
|
|
68
339
|
--u-txt-color-weak: #5B5E63;
|
|
@@ -74,44 +345,13 @@
|
|
|
74
345
|
--u-icon-color-hover: #18191B;
|
|
75
346
|
--u-icon-color-active: #18191B;
|
|
76
347
|
|
|
77
|
-
/* Action — ink. The primary button is near-black; selection stays
|
|
348
|
+
/* Action — ink. The primary button is near-black; selection stays the accent. */
|
|
78
349
|
--u-primary-color-weakest: #E3E3DF;
|
|
79
350
|
--u-primary-color-weaker: #C8C9C5;
|
|
80
351
|
--u-primary-color-weak: #5B5E63;
|
|
81
352
|
--u-primary-color: #18191B;
|
|
82
353
|
--u-primary-color-strong: #18191B;
|
|
83
354
|
--u-primary-txt-color: #FFFFFF;
|
|
84
|
-
--u-primary-bg-color: #EEF3FD; /* selected rows, current item */
|
|
85
|
-
|
|
86
|
-
/* Interaction — blue, for links, focus and the mark of a chosen option (a checked box or radio) */
|
|
87
|
-
--u-link-txt-color: #1F5FCC;
|
|
88
|
-
--u-focus-ring-color: #2F6FEB;
|
|
89
|
-
--u-selection-color: #2F6FEB;
|
|
90
|
-
--u-selection-txt-color: #FFFFFF; /* the check drawn on that fill */
|
|
91
|
-
|
|
92
|
-
/* Chart series — eight, in order (slot one first, never cycled). Slot one is the interaction blue, so a
|
|
93
|
-
one-series chart draws in the colour the rest of the screen uses for "this is the thing"; the other seven
|
|
94
|
-
are muted, warm-leaning hues chosen as a set: OKLCH L 0.50–0.68, chroma ≥ 0.10, neighbours ΔE ≥ 15 for
|
|
95
|
-
full colour vision and ≥ 8 under red–green deficiency (Machado 2009), every slot at least ΔE 10 from a
|
|
96
|
-
status colour. Slot six (light olive) is 2.8:1 on white — six or more series need a legend or labels. */
|
|
97
|
-
--u-chart-color-1: #2F6FEB;
|
|
98
|
-
--u-chart-color-2: #B55F40;
|
|
99
|
-
--u-chart-color-3: #14938D;
|
|
100
|
-
--u-chart-color-4: #AF8020;
|
|
101
|
-
--u-chart-color-5: #7D4B92;
|
|
102
|
-
--u-chart-color-6: #86A645;
|
|
103
|
-
--u-chart-color-7: #C46E83;
|
|
104
|
-
--u-chart-color-8: #834B14;
|
|
105
|
-
|
|
106
|
-
/* Status — `-color-strong` is the text step (on surface and on its own tint), `-bg-color`
|
|
107
|
-
the tint, `-color` the solid fill (with `-txt-color` on top). */
|
|
108
|
-
--u-info-color-weakest: #D6E3FB;
|
|
109
|
-
--u-info-color-weaker: #A9C4F6;
|
|
110
|
-
--u-info-color-weak: #5B8DE8;
|
|
111
|
-
--u-info-color: #1F5FCC;
|
|
112
|
-
--u-info-color-strong: #1A55B8;
|
|
113
|
-
--u-info-bg-color: #E8F0FD;
|
|
114
|
-
--u-info-txt-color: #FFFFFF;
|
|
115
355
|
|
|
116
356
|
--u-success-color-weakest: #CDEBD9;
|
|
117
357
|
--u-success-color-weaker: #A3D8BA;
|
|
@@ -119,54 +359,28 @@
|
|
|
119
359
|
--u-success-color: #1B7A44;
|
|
120
360
|
--u-success-color-strong: #1B6E3E;
|
|
121
361
|
--u-success-bg-color: #E6F4EC;
|
|
122
|
-
--u-success-txt-color: #FFFFFF;
|
|
123
362
|
|
|
124
|
-
--u-warning-color-weakest: #FBEBCF;
|
|
125
363
|
--u-warning-color-weaker: #F5D9A3;
|
|
126
|
-
--u-warning-color-weak: #E8B25A;
|
|
127
|
-
--u-warning-color: #E59A24;
|
|
128
364
|
--u-warning-color-strong: #8A5100;
|
|
129
365
|
--u-warning-bg-color: #FDF3E1;
|
|
130
366
|
--u-warning-txt-color: #18191B;
|
|
131
367
|
|
|
132
|
-
--u-danger-color-weakest: #F9D4D0;
|
|
133
|
-
--u-danger-color-weaker: #F2AAA2;
|
|
134
|
-
--u-danger-color-weak: #DE6A5D;
|
|
135
|
-
--u-danger-color: #B42318;
|
|
136
|
-
--u-danger-color-strong: #B42318;
|
|
137
|
-
--u-danger-bg-color: #FDECEA;
|
|
138
|
-
--u-danger-txt-color: #FFFFFF;
|
|
139
|
-
|
|
140
|
-
/* Elevation — a hairline lift for surfaces, one real shadow for things that float */
|
|
141
368
|
--u-shadow-color-weaker: rgba(16, 17, 19, 0.04);
|
|
142
369
|
--u-shadow-color-weak: rgba(16, 17, 19, 0.06);
|
|
143
370
|
--u-shadow-color-normal: rgba(16, 17, 19, 0.10);
|
|
144
371
|
--u-shadow-color-strong: rgba(16, 17, 19, 0.14);
|
|
145
372
|
--u-shadow-color-stronger: rgba(16, 17, 19, 0.18);
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
--
|
|
149
|
-
--
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
--
|
|
153
|
-
--app-sidebar-fg: var(--u-txt-color-weak);
|
|
154
|
-
--app-header-bg: var(--u-bg-color);
|
|
155
|
-
--app-header-fg: var(--u-txt-color);
|
|
156
|
-
--app-sidebar-width: 232px;
|
|
157
|
-
--app-sidebar-active-bg: var(--hs-brand-soft);
|
|
158
|
-
--app-sidebar-active-fg: var(--hs-brand-ink);
|
|
159
|
-
--app-sidebar-group-active-fg: var(--hs-brand-ink);
|
|
160
|
-
|
|
161
|
-
/* Brand — the application's identity colour. The house default is neutral, so an
|
|
162
|
-
unbranded app looks finished; an application sets these three and nothing else. */
|
|
163
|
-
--hs-brand: #18191B;
|
|
164
|
-
--hs-brand-soft: #EAEAE7;
|
|
165
|
-
--hs-brand-ink: #18191B;
|
|
373
|
+
|
|
374
|
+
/* The shell keeps the neutral current item; the current tab is ink */
|
|
375
|
+
--app-sidebar-fg: var(--u-txt-color-weak);
|
|
376
|
+
--app-sidebar-active-bg: var(--u-bg-color-active);
|
|
377
|
+
--app-sidebar-active-fg: var(--u-txt-color);
|
|
378
|
+
--app-sidebar-group-active-fg: var(--u-txt-color);
|
|
379
|
+
--hs-tab-current-color: var(--u-txt-color);
|
|
166
380
|
}
|
|
167
381
|
|
|
168
|
-
/* ── dark
|
|
169
|
-
:root[theme="dark"] {
|
|
382
|
+
/* ── warm · dark ─────────────────────────────────────────────────────────── */
|
|
383
|
+
:root[hs-palette="warm"][theme="dark"] {
|
|
170
384
|
--u-neutral-0: #0E0F10;
|
|
171
385
|
--u-neutral-50: #121314;
|
|
172
386
|
--u-neutral-100: #1A1B1D;
|
|
@@ -197,7 +411,6 @@
|
|
|
197
411
|
--u-border-color-hover: #6A6D72;
|
|
198
412
|
--u-input-border-color: #6A6D72;
|
|
199
413
|
--u-input-border-color-hover: #A3A6AB;
|
|
200
|
-
--u-input-border-color-focus: #6E9CF7;
|
|
201
414
|
|
|
202
415
|
--u-txt-color: #EDEDEC;
|
|
203
416
|
--u-txt-color-strong: #FFFFFF;
|
|
@@ -216,32 +429,6 @@
|
|
|
216
429
|
--u-primary-color: #EDEDEC;
|
|
217
430
|
--u-primary-color-strong: #EDEDEC;
|
|
218
431
|
--u-primary-txt-color: #18191B;
|
|
219
|
-
--u-primary-bg-color: #1C2638;
|
|
220
|
-
|
|
221
|
-
--u-link-txt-color: #8DB3F7;
|
|
222
|
-
--u-focus-ring-color: #6E9CF7;
|
|
223
|
-
--u-selection-color: #6E9CF7;
|
|
224
|
-
--u-selection-txt-color: #0E0F10;
|
|
225
|
-
|
|
226
|
-
/* Chart series, dark — the same hues stepped into the dark band (L 0.52–0.66), every slot ≥ 3:1 on the
|
|
227
|
-
surface and the raised surface. Slot one is the dark interaction blue taken to the band's top (#6E9CF7
|
|
228
|
-
itself is lighter than a filled mark should be on this surface). */
|
|
229
|
-
--u-chart-color-1: #628FEA;
|
|
230
|
-
--u-chart-color-2: #C97152;
|
|
231
|
-
--u-chart-color-3: #04A19B;
|
|
232
|
-
--u-chart-color-4: #B8892D;
|
|
233
|
-
--u-chart-color-5: #9760AF;
|
|
234
|
-
--u-chart-color-6: #57833D;
|
|
235
|
-
--u-chart-color-7: #CF7188;
|
|
236
|
-
--u-chart-color-8: #9A5F1A;
|
|
237
|
-
|
|
238
|
-
--u-info-color-weakest: #1F3152;
|
|
239
|
-
--u-info-color-weaker: #2C4A7E;
|
|
240
|
-
--u-info-color-weak: #5E8BE0;
|
|
241
|
-
--u-info-color: #8DB3F7;
|
|
242
|
-
--u-info-color-strong: #8DB3F7;
|
|
243
|
-
--u-info-bg-color: #1B2A44;
|
|
244
|
-
--u-info-txt-color: #0E0F10;
|
|
245
432
|
|
|
246
433
|
--u-success-color-weakest: #1A3826;
|
|
247
434
|
--u-success-color-weaker: #2B5A3E;
|
|
@@ -249,58 +436,74 @@
|
|
|
249
436
|
--u-success-color: #7DD8A5;
|
|
250
437
|
--u-success-color-strong: #7DD8A5;
|
|
251
438
|
--u-success-bg-color: #16301F;
|
|
252
|
-
--u-success-txt-color: #0E0F10;
|
|
253
439
|
|
|
254
|
-
--u-warning-color-weakest: #3F2E12;
|
|
255
440
|
--u-warning-color-weaker: #5E451A;
|
|
256
|
-
--u-warning-color-weak: #C99140;
|
|
257
|
-
--u-warning-color: #F2B65A;
|
|
258
441
|
--u-warning-color-strong: #F2B65A;
|
|
259
442
|
--u-warning-bg-color: #3A2A10;
|
|
260
443
|
--u-warning-txt-color: #0E0F10;
|
|
261
444
|
|
|
262
|
-
--u-danger-color-weakest: #4A1F1B;
|
|
263
|
-
--u-danger-color-weaker: #6E2C26;
|
|
264
|
-
--u-danger-color-weak: #E0675C;
|
|
265
|
-
--u-danger-color: #FF8A80;
|
|
266
|
-
--u-danger-color-strong: #FF8A80;
|
|
267
|
-
--u-danger-bg-color: #3D1A17;
|
|
268
|
-
--u-danger-txt-color: #1A0D0B;
|
|
269
|
-
|
|
270
445
|
--u-shadow-color-weaker: rgba(0, 0, 0, 0.24);
|
|
271
446
|
--u-shadow-color-weak: rgba(0, 0, 0, 0.32);
|
|
272
447
|
--u-shadow-color-normal: rgba(0, 0, 0, 0.40);
|
|
273
448
|
--u-shadow-color-strong: rgba(0, 0, 0, 0.50);
|
|
274
449
|
--u-shadow-color-stronger: rgba(0, 0, 0, 0.60);
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
/* ── contrast · light — the cool screen with a dark shell ───────────────── *
|
|
453
|
+
* The sidebar re-scopes the neutral roles to these shell values (components.css), so everything drawn inside
|
|
454
|
+
* it — links, groups, a menu it opens — reads as one dark surface. */
|
|
455
|
+
:root[hs-palette="contrast"] {
|
|
456
|
+
--hs-shell-bg: #1F2937;
|
|
457
|
+
--hs-shell-raised: #273244;
|
|
458
|
+
--hs-shell-hover: #2B3647;
|
|
459
|
+
--hs-shell-active: #334155;
|
|
460
|
+
--hs-shell-line: #334155;
|
|
461
|
+
--hs-shell-ink: #E5E7EB;
|
|
462
|
+
--hs-shell-ink-weak: #A9B1BD;
|
|
463
|
+
--hs-shell-ink-weaker: #9AA3AF;
|
|
464
|
+
--hs-shell-current-bg: color-mix(in oklab, var(--hs-accent) 42%, var(--hs-shell-bg));
|
|
465
|
+
--hs-shell-current-ink: #FFFFFF;
|
|
466
|
+
|
|
467
|
+
--app-sidebar-bg: var(--hs-shell-bg);
|
|
468
|
+
--app-sidebar-fg: var(--hs-shell-ink);
|
|
469
|
+
--app-sidebar-active-bg: var(--hs-shell-current-bg);
|
|
470
|
+
--app-sidebar-active-fg: var(--hs-shell-current-ink);
|
|
471
|
+
--app-sidebar-group-active-fg: var(--hs-shell-current-ink);
|
|
472
|
+
}
|
|
279
473
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
--hs-
|
|
474
|
+
/* ── contrast · dark ─────────────────────────────────────────────────────── */
|
|
475
|
+
:root[hs-palette="contrast"][theme="dark"] {
|
|
476
|
+
--hs-shell-bg: #0B0F14;
|
|
477
|
+
--hs-shell-raised: #131A22;
|
|
478
|
+
--hs-shell-hover: #18202A;
|
|
479
|
+
--hs-shell-active: #212B37;
|
|
480
|
+
--hs-shell-line: #1E2630;
|
|
481
|
+
--hs-shell-ink: #E4E6E9;
|
|
482
|
+
--hs-shell-ink-weak: #A2A8B0;
|
|
483
|
+
--hs-shell-ink-weaker: #8D939B;
|
|
484
|
+
--hs-shell-current-ink: #FFFFFF;
|
|
283
485
|
}
|
|
284
486
|
|
|
285
|
-
/* ── mode-independent scale: shape,
|
|
487
|
+
/* ── mode-independent scale: shape, size, type ──────────────────────────── */
|
|
286
488
|
:root {
|
|
287
|
-
/* Shape —
|
|
489
|
+
/* Shape — mark 4 · control and menu item 8 · card and table 10 · status pill */
|
|
288
490
|
--u-radius-sm: 3px;
|
|
289
491
|
--u-radius-md: 4px;
|
|
290
|
-
--u-radius-lg:
|
|
492
|
+
--u-radius-lg: 8px;
|
|
291
493
|
--u-radius-xl: 10px;
|
|
292
494
|
--u-radius-2xl: 12px;
|
|
293
495
|
--u-radius-3xl: 16px;
|
|
294
496
|
|
|
295
|
-
/* Type — Pretendard; one ladder
|
|
296
|
-
tracking, so only the largest step is tightened
|
|
497
|
+
/* Type — Pretendard; one ladder 24 / 18 / 15 / 14 / 13 / 12 / 11. Korean gets no positive
|
|
498
|
+
tracking in running text, so only the largest step is tightened; the overline (a group label) is
|
|
499
|
+
spaced a little. */
|
|
297
500
|
--u-font-base: 'Pretendard Variable', Pretendard, -apple-system, BlinkMacSystemFont, 'Apple SD Gothic Neo',
|
|
298
501
|
'Noto Sans KR', 'Malgun Gothic', 'Segoe UI', system-ui, sans-serif;
|
|
299
502
|
--u-font-mono: 'JetBrains Mono', D2Coding, ui-monospace, 'Cascadia Code', Menlo, Consolas, monospace;
|
|
300
503
|
|
|
301
|
-
--u-text-display-size:
|
|
504
|
+
--u-text-display-size: 24px;
|
|
302
505
|
--u-text-display-weight: 700;
|
|
303
|
-
--u-text-display-leading: 1.
|
|
506
|
+
--u-text-display-leading: 1.333;
|
|
304
507
|
--u-text-display-tracking: -0.01em;
|
|
305
508
|
--u-text-title-size: 18px;
|
|
306
509
|
--u-text-title-weight: 700;
|
|
@@ -320,42 +523,44 @@
|
|
|
320
523
|
--u-text-label-tracking: 0;
|
|
321
524
|
--u-text-caption-size: 12px;
|
|
322
525
|
--u-text-caption-weight: 400;
|
|
323
|
-
--u-text-caption-leading: 1.
|
|
526
|
+
--u-text-caption-leading: 1.333;
|
|
324
527
|
--u-text-caption-tracking: 0;
|
|
325
528
|
--u-text-overline-size: 11px;
|
|
326
529
|
--u-text-overline-weight: 600;
|
|
327
|
-
--u-text-overline-leading: 1.
|
|
328
|
-
--u-text-overline-tracking: 0.
|
|
530
|
+
--u-text-overline-leading: 1.273;
|
|
531
|
+
--u-text-overline-tracking: 0.04em;
|
|
329
532
|
|
|
330
533
|
/* House-only scale — control heights and table rows (read by components.css · patterns.css) */
|
|
331
|
-
--hs-control-sm:
|
|
332
|
-
--hs-control-md:
|
|
534
|
+
--hs-control-sm: 32px;
|
|
535
|
+
--hs-control-md: 36px;
|
|
333
536
|
--hs-control-lg: 40px;
|
|
334
|
-
--hs-row:
|
|
335
|
-
--hs-row-compact:
|
|
336
|
-
--hs-page-padding:
|
|
537
|
+
--hs-row: 44px;
|
|
538
|
+
--hs-row-compact: 36px;
|
|
539
|
+
--hs-page-padding: 20px 32px 48px;
|
|
540
|
+
--hs-section-gap: 20px;
|
|
337
541
|
|
|
338
542
|
/* House type steps beyond the shared ladder — derived from it, so a rescaled ladder (density, a product system)
|
|
339
|
-
carries them along. Dense = the step between body and label (13 at 14/12):
|
|
340
|
-
|
|
543
|
+
carries them along. Dense = the step between body and label (13 at 14/12): secondary lines, table headers,
|
|
544
|
+
breadcrumbs. Hero = a headline figure, display + 4 (28 at 24). */
|
|
341
545
|
--hs-text-dense-size: calc((var(--u-text-body-size) + var(--u-text-label-size)) / 2);
|
|
342
|
-
--hs-text-hero-size: calc(var(--u-text-display-size) +
|
|
546
|
+
--hs-text-hero-size: calc(var(--u-text-display-size) + 4px);
|
|
343
547
|
|
|
344
548
|
/* Prose measure — a running paragraph stops around 70 characters a line (`.hs-prose`). */
|
|
345
549
|
--hs-measure: 70ch;
|
|
346
550
|
|
|
347
|
-
/* Field box (`@iyulab/components`) —
|
|
348
|
-
follows the control density with the buttons (resolved at the field:
|
|
349
|
-
--u-field-padding-block: calc(
|
|
551
|
+
/* Field box (`@iyulab/components`) — 36px fields beside 36px buttons; 40px inside form sections. In em, so the box
|
|
552
|
+
follows the control density with the buttons (resolved at the field: 6.5px / 12px at the default 14px). */
|
|
553
|
+
--u-field-padding-block: calc(6.5em / 14);
|
|
350
554
|
--u-field-padding-inline: calc(12em / 14);
|
|
351
|
-
--u-field-radius:
|
|
555
|
+
--u-field-radius: 8px;
|
|
352
556
|
|
|
353
|
-
/* Shell (`@iyulab/modern-app`) —
|
|
557
|
+
/* Shell (`@iyulab/modern-app`) — a 240px sidebar of 38px rows with 18px icons, a flat current item */
|
|
354
558
|
--app-main-padding: var(--hs-page-padding);
|
|
355
|
-
--app-sidebar-
|
|
356
|
-
--app-sidebar-item-
|
|
357
|
-
--app-sidebar-item-
|
|
358
|
-
--app-sidebar-
|
|
559
|
+
--app-sidebar-width: 240px;
|
|
560
|
+
--app-sidebar-item-radius: 8px;
|
|
561
|
+
--app-sidebar-item-gap: 10px;
|
|
562
|
+
--app-sidebar-item-padding: 8px 10px;
|
|
563
|
+
--app-sidebar-icon-size: 18px;
|
|
359
564
|
--app-sidebar-active-shadow: none;
|
|
360
565
|
--app-sidebar-active-shadow-hover: none;
|
|
361
566
|
}
|