@iyulab/house-style 0.1.2 → 0.1.4

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 CHANGED
@@ -1,5 +1,32 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.1.4] - 2026-10-07
4
+
5
+ ### Fixed
6
+
7
+ - **The control ladder follows the control density** (`--u-density`). Button font sizes were literal (md 13px, lg
8
+ 14px) and so were the field and button paddings, so a host that raised the density grew only some steps: with
9
+ `@iyulab/components` 2.13 (sm follows the density) a small button became larger than a default one (13.7 > 13px),
10
+ and buttons stopped lining up with fields. Font sizes are now steps of the density and paddings are em. At the
11
+ default 14px nothing changes — 12 / 13 / 14px and 28 / 32 / 40px; at 16px all three steps grow in order and
12
+ buttons and fields stay level.
13
+
14
+ ## [0.1.3] - 2026-10-06
15
+
16
+ ### Fixed
17
+
18
+ - **A sidebar group holding the current page keeps a readable header.** `@iyulab/modern-app` derived that header's
19
+ text from the active background, which this theme makes light (`--hs-brand-soft`), so the text sank into the
20
+ panel (about 1.6:1 light, 1.1:1 dark). The theme now sets `--app-sidebar-group-active-fg` to `--hs-brand-ink`, the
21
+ color it already uses for text on that background (`@iyulab/modern-app` 0.39 reads it).
22
+ - **Patterns follow the type ladder.** `patterns.css` set font sizes in px (11, 12, 13, 28 — 19 places) and flex-table
23
+ cells and headers did too, so a consumer who rescaled `--u-text-*-size` saw components and body text change while
24
+ tables, pagers, definition lists and stats stayed put. They now read the steps — label, caption and overline, plus
25
+ two house steps derived from the ladder: `--hs-text-dense-size` (between body and label — the 13px of table cells,
26
+ definition lists, callouts) and `--hs-text-hero-size` (display + 6px — the 28px headline figure). Each read keeps
27
+ the current px as its fallback, so nothing changes at the house ladder. Button and field font sizes stay literal:
28
+ they are terms of the 28/32/40 control-height formula.
29
+
3
30
  ## [0.1.2] - 2026-10-06
4
31
 
5
32
  ### Fixed
package/README.md CHANGED
@@ -77,6 +77,11 @@ Everything else — warm-grey neutrals, the ink primary action, blue for links a
77
77
  tints, the 22/18/15/14/13/12/11 type ladder, 28/32/40 controls, 40px table rows — comes from the
78
78
  theme and can be overridden token by token.
79
79
 
80
+ The type ladder is the `--u-text-*-size` steps plus two house steps derived from them —
81
+ `--hs-text-dense-size` (between body and label: table cells, definition lists, callouts) and
82
+ `--hs-text-hero-size` (display + 6px: a headline figure). Every pattern reads a step, so rescaling the
83
+ ladder (a larger mode, a product system) carries the patterns along.
84
+
80
85
  ## The guide
81
86
 
82
87
  **Live**: https://iyulab.github.io/house-style/ — this is the guide. There is no
@@ -130,6 +135,15 @@ npm run check:start-here -w @iyulab/house-style
130
135
  packed in place of the registry's — run it before tagging a release. The deploy workflow runs
131
136
  both on every push to `main`.
132
137
 
138
+ The guide itself is checked too: after a build, every page (the landing page and each category)
139
+ must draw its section in a browser, with no page errors — a build can drop the section modules and
140
+ still succeed. The deploy workflow runs it before uploading the site:
141
+
142
+ ```bash
143
+ npm run build -w @iyulab/house-style
144
+ npm run check:guide -w @iyulab/house-style
145
+ ```
146
+
133
147
  ## License
134
148
 
135
149
  MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iyulab/house-style",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
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": {
@@ -25,7 +25,9 @@
25
25
  "LICENSE"
26
26
  ],
27
27
  "sideEffects": [
28
- "**/*.css"
28
+ "**/*.css",
29
+ "./src/**",
30
+ "./src-app/**"
29
31
  ],
30
32
  "scripts": {
31
33
  "preversion": "node -e \"if(require('fs').existsSync('../../scripts/preversion-check.mjs'))require('child_process').execFileSync('node',['../../scripts/preversion-check.mjs'],{stdio:'inherit'})\"",
@@ -33,6 +35,8 @@
33
35
  "build": "npm run typecheck && vite build",
34
36
  "preview": "vite preview",
35
37
  "typecheck": "tsc --noEmit",
38
+ "check:guide": "node scripts/check-guide.mjs",
39
+ "check:a11y": "node scripts/check-a11y.mjs",
36
40
  "check:start-here": "node scripts/check-start-here.mjs",
37
41
  "check:start-here:local": "node scripts/check-start-here.mjs --local",
38
42
  "pretest": "node -e \"if(require('fs').existsSync('../../scripts/sibling-dist-check.js'))require('child_process').execFileSync('node',['../../scripts/sibling-dist-check.js'],{stdio:'inherit'})\"",
@@ -59,15 +63,16 @@
59
63
  },
60
64
  "devDependencies": {
61
65
  "@iyulab/components": "^2.0.0",
62
- "@iyulab/data-components": "^0.35.0",
63
- "@iyulab/enterprise": "^0.24.0",
64
- "@iyulab/modern-app": "^0.34.0",
65
- "@iyulab/router": "^0.19.0",
66
- "@iyulab/u-widgets": "^0.24.0",
66
+ "@iyulab/data-components": "^0.43.0",
67
+ "@iyulab/enterprise": "^0.26.0",
68
+ "@iyulab/modern-app": "^0.43.0",
69
+ "@iyulab/router": "^0.20.0",
70
+ "@iyulab/u-widgets": "^0.26.0",
67
71
  "@lit/react": "^1.0.8",
68
72
  "@types/node": "^26.1.1",
69
73
  "@types/react": "^19.2.14",
70
74
  "@types/react-dom": "^19.2.3",
75
+ "axe-core": "^4.14.0",
71
76
  "echarts": "^6.1.0",
72
77
  "lit": "^3.3.2",
73
78
  "msw": "^3.0.0",
@@ -31,21 +31,28 @@
31
31
 
32
32
  /* ── Button — 28 / 32 / 40, medium weight ─────────────────────────────── *
33
33
  * Height follows the components' own formula (1.5em line + 2 × padding + 2px border), so
34
- * these are padding values, not fixed heights: text and icon-only buttons stay equal. */
34
+ * these are padding values, not fixed heights: text and icon-only buttons stay equal.
35
+ * The font sizes are terms of that height formula (the control ladder 28/32/40), not steps of
36
+ * the text ladder — tying them to `--u-text-*` would change control heights whenever the text
37
+ * ladder is rescaled. They are steps of the control density instead (`--u-density`, the
38
+ * components' size axis): at the default 14px they are 12 / 13 / 14 and the heights 28/32/40;
39
+ * a host that raises the density (a field or touch mode) grows all three together and in order.
40
+ * Padding is in em for the same reason — the n/13, n/12, n/14 factors give the px values at the
41
+ * default density exactly. (sm takes the components' own size: density × 6/7.) */
35
42
  u-button:not([size]),
36
43
  u-button[size='md'] {
37
- font-size: 13px;
38
- --btn-padding-block: 5.25px; /* 19.5 + 10.5 + 2 = 32 */
39
- --btn-padding-inline: 12px;
44
+ font-size: calc(var(--u-density, 14px) * 13 / 14);
45
+ --btn-padding-block: calc(5.25em / 13); /* 13px: 19.5 + 10.5 + 2 = 32 */
46
+ --btn-padding-inline: calc(12em / 13);
40
47
  }
41
48
  u-button[size='sm'] {
42
- --btn-padding-block: 4px; /* 12px → 18 + 8 + 2 = 28 */
43
- --btn-padding-inline: 8px;
49
+ --btn-padding-block: calc(4em / 12); /* 12px: 18 + 8 + 2 = 28 */
50
+ --btn-padding-inline: calc(8em / 12);
44
51
  }
45
52
  u-button[size='lg'] {
46
- font-size: 14px;
47
- --btn-padding-block: 8.5px; /* 21 + 17 + 2 = 40 */
48
- --btn-padding-inline: 16px;
53
+ font-size: var(--u-density, 14px);
54
+ --btn-padding-block: calc(8.5em / 14); /* 14px: 21 + 17 + 2 = 40 */
55
+ --btn-padding-inline: calc(16em / 14);
49
56
  }
50
57
  u-button[appearance='link'] {
51
58
  --btn-padding-inline: 0;
@@ -55,11 +62,11 @@ u-button[appearance='link'] {
55
62
  * (Components 2.0 renders fields at 14px by default, so a field no longer grows with the
56
63
  * surrounding text; the house sets the box padding per size.) ── */
57
64
  :is(u-input, u-select, u-textarea, u-date-picker, u-date-range-picker)[size='sm'] {
58
- --u-field-padding-block: 4px; /* 12px → 18 + 8 + 2 = 28 */
65
+ --u-field-padding-block: calc(4em / 12); /* 12px: 18 + 8 + 2 = 28 */
59
66
  }
60
67
  :is(u-input, u-select, u-textarea, u-date-picker, u-date-range-picker)[size='lg'] {
61
- font-size: 14px;
62
- --u-field-padding-block: 8.5px; /* 21 + 17 + 2 = 40 */
68
+ font-size: var(--u-density, 14px); /* with the density, like md — the step is the padding */
69
+ --u-field-padding-block: calc(8.5em / 14); /* 14px: 21 + 17 + 2 = 40 */
63
70
  }
64
71
 
65
72
  /* ── Tag — 22px labels (12px text · 1px block padding · hairline) to sit inside 40px rows.
@@ -90,10 +97,10 @@ u-drawer::part(body) {
90
97
  * no zebra (hover and selection carry the row), tabular figures. ──────── */
91
98
  flex-table {
92
99
  --ft-font-family: var(--u-font-base);
93
- --ft-font-size: 13px;
100
+ --ft-font-size: var(--hs-text-dense-size, 13px);
94
101
  --ft-row-height: var(--hs-row);
95
102
  --ft-cell-padding-inline: 12px;
96
- --ft-header-font-size: 12px;
103
+ --ft-header-font-size: var(--u-text-label-size, 12px);
97
104
  --ft-header-font-weight: 500;
98
105
  --ft-header-text-color: var(--u-txt-color-weak);
99
106
  --ft-header-bg: var(--u-bg-color-raised);
@@ -87,7 +87,7 @@
87
87
  border-bottom: 2px solid transparent;
88
88
  background: none;
89
89
  font: inherit;
90
- font-size: 13px;
90
+ font-size: var(--hs-text-dense-size, 13px);
91
91
  line-height: 20px;
92
92
  color: var(--u-txt-color-weak);
93
93
  text-decoration: none; /* a tab may be a link (`aria-current="page"`) */
@@ -114,7 +114,7 @@
114
114
  border-radius: var(--u-radius-pill, 9999px);
115
115
  background: var(--u-bg-color-raised);
116
116
  color: var(--u-txt-color-weak);
117
- font-size: 11px;
117
+ font-size: var(--u-text-overline-size, 11px);
118
118
  line-height: 16px;
119
119
  font-weight: 500;
120
120
  text-align: center;
@@ -182,17 +182,17 @@
182
182
  }
183
183
  .hs-stat__unit {
184
184
  margin-inline-start: 2px;
185
- font-size: 12px;
185
+ font-size: var(--u-text-caption-size, 12px);
186
186
  font-weight: 500;
187
187
  color: var(--u-txt-color-weak);
188
188
  }
189
189
  .hs-stat__sub {
190
- font-size: 12px;
190
+ font-size: var(--u-text-caption-size, 12px);
191
191
  line-height: 18px;
192
192
  color: var(--u-txt-color-weaker);
193
193
  }
194
194
  .hs-stat--hero .hs-stat__value {
195
- font-size: 28px;
195
+ font-size: var(--hs-text-hero-size, 28px);
196
196
  line-height: 34px;
197
197
  letter-spacing: -0.01em;
198
198
  }
@@ -232,7 +232,7 @@
232
232
  background: var(--u-primary-bg-color);
233
233
  }
234
234
  .hs-table-toolbar__title {
235
- font-size: 13px;
235
+ font-size: var(--hs-text-dense-size, 13px);
236
236
  font-weight: 600;
237
237
  }
238
238
  .hs-pager {
@@ -242,7 +242,7 @@
242
242
  gap: var(--u-space-sm, 8px);
243
243
  padding: var(--u-space-sm, 8px) var(--u-space-md, 12px);
244
244
  border-top: 1px solid var(--u-border-color);
245
- font-size: 12px;
245
+ font-size: var(--u-text-label-size, 12px);
246
246
  color: var(--u-txt-color-weak);
247
247
  font-variant-numeric: tabular-nums;
248
248
  }
@@ -251,7 +251,7 @@
251
251
  .hs-table {
252
252
  width: 100%;
253
253
  border-collapse: collapse;
254
- font-size: 13px;
254
+ font-size: var(--hs-text-dense-size, 13px);
255
255
  line-height: 20px;
256
256
  color: var(--u-txt-color);
257
257
  }
@@ -259,7 +259,7 @@
259
259
  padding: var(--u-space-sm, 8px) var(--u-space-md, 12px);
260
260
  text-align: start;
261
261
  white-space: nowrap;
262
- font-size: 12px;
262
+ font-size: var(--u-text-label-size, 12px);
263
263
  line-height: 16px;
264
264
  font-weight: 500;
265
265
  color: var(--u-txt-color-weak);
@@ -309,7 +309,7 @@ a.hs-id:hover,
309
309
  .hs-table .hs-group td {
310
310
  height: 32px;
311
311
  background: var(--u-bg-color-raised);
312
- font-size: 12px;
312
+ font-size: var(--u-text-label-size, 12px);
313
313
  font-weight: 600;
314
314
  color: var(--u-txt-color-weak);
315
315
  }
@@ -353,7 +353,7 @@ tr[aria-selected='true'] .hs-row-actions {
353
353
  font-weight: 600;
354
354
  }
355
355
  .hs-card__link {
356
- font-size: 12px;
356
+ font-size: var(--u-text-label-size, 12px);
357
357
  font-weight: 500;
358
358
  color: var(--u-link-txt-color);
359
359
  text-decoration: none;
@@ -375,7 +375,7 @@ a.hs-card:hover,
375
375
  grid-template-columns: max-content minmax(0, 1fr);
376
376
  gap: 6px var(--u-space-lg, 16px);
377
377
  margin: 0;
378
- font-size: 13px;
378
+ font-size: var(--hs-text-dense-size, 13px);
379
379
  line-height: 20px;
380
380
  }
381
381
  .hs-dl > dt { color: var(--u-txt-color-weak); }
@@ -412,7 +412,7 @@ a.hs-card:hover,
412
412
  padding: var(--u-space-md, 12px) var(--u-space-lg, 16px);
413
413
  border-radius: var(--u-radius-xl, 10px);
414
414
  background: var(--u-bg-color-raised);
415
- font-size: 13px;
415
+ font-size: var(--hs-text-dense-size, 13px);
416
416
  line-height: 20px;
417
417
  }
418
418
  .hs-callout__icon { color: var(--u-txt-color-weak); line-height: 20px; }
@@ -450,7 +450,7 @@ a.hs-card:hover,
450
450
  width: 100%;
451
451
  margin: 0 0 var(--u-space-md, 12px);
452
452
  padding: 0;
453
- font-size: 13px;
453
+ font-size: var(--hs-text-dense-size, 13px);
454
454
  font-weight: 600;
455
455
  color: var(--u-txt-color);
456
456
  }
@@ -475,18 +475,18 @@ a.hs-card:hover,
475
475
  color: var(--u-danger-color-strong);
476
476
  }
477
477
  .hs-field__help {
478
- font-size: 12px;
478
+ font-size: var(--u-text-caption-size, 12px);
479
479
  line-height: 18px;
480
480
  color: var(--u-txt-color-weaker);
481
481
  }
482
482
  .hs-field__error {
483
- font-size: 12px;
483
+ font-size: var(--u-text-caption-size, 12px);
484
484
  line-height: 18px;
485
485
  color: var(--u-danger-color-strong);
486
486
  }
487
487
  /* Form fields are 40px (the side-sheet and edit-form size); toolbars keep 32px. */
488
488
  .hs-field {
489
- --u-field-padding-block: 8.5px;
489
+ --u-field-padding-block: calc(8.5em / 14); /* 14px: 21 + 17 + 2 = 40 — and with the density */
490
490
  }
491
491
  .hs-field :is(u-input, u-select, u-textarea, u-date-picker, u-date-range-picker) {
492
492
  width: 100%;
@@ -517,7 +517,7 @@ a.hs-card:hover,
517
517
  background: var(--u-bg-color);
518
518
  }
519
519
  .hs-sheet-footer__summary {
520
- font-size: 12px;
520
+ font-size: var(--u-text-caption-size, 12px);
521
521
  color: var(--u-txt-color-weak);
522
522
  }
523
523
  .hs-sheet-footer__actions {
@@ -534,7 +534,7 @@ a.hs-card:hover,
534
534
  padding: 0 5px;
535
535
  border: 1px solid var(--u-border-color);
536
536
  border-radius: var(--u-radius-md, 4px);
537
- font-size: 11px;
537
+ font-size: var(--u-text-overline-size, 11px);
538
538
  line-height: 16px;
539
539
  font-weight: 500;
540
540
  color: var(--u-txt-color-weak);
@@ -548,7 +548,7 @@ a.hs-card:hover,
548
548
  height: 18px;
549
549
  padding: 0 6px;
550
550
  border-radius: var(--u-radius-pill, 9999px);
551
- font-size: 11px;
551
+ font-size: var(--u-text-overline-size, 11px);
552
552
  font-weight: 600;
553
553
  font-variant-numeric: tabular-nums;
554
554
  background: var(--u-bg-color-raised);
package/styles/tokens.css CHANGED
@@ -140,6 +140,7 @@
140
140
  --app-sidebar-width: 232px;
141
141
  --app-sidebar-active-bg: var(--hs-brand-soft);
142
142
  --app-sidebar-active-fg: var(--hs-brand-ink);
143
+ --app-sidebar-group-active-fg: var(--hs-brand-ink);
143
144
 
144
145
  /* Brand — the application's identity colour. The house default is neutral, so an
145
146
  unbranded app looks finished; an application sets these three and nothing else. */
@@ -304,9 +305,16 @@
304
305
  --hs-row-compact: 32px;
305
306
  --hs-page-padding: 24px;
306
307
 
307
- /* Field box (`@iyulab/components`) — 32px fields beside 32px buttons; 40px inside form sections */
308
- --u-field-padding-block: 4.5px;
309
- --u-field-padding-inline: 12px;
308
+ /* House type steps beyond the shared ladder — derived from it, so a rescaled ladder (density, a product system)
309
+ carries them along. Dense = the step between body and label (13 at 14/12): table cells, definition lists,
310
+ callouts. Hero = a headline figure, display + 6 (28 at 22). */
311
+ --hs-text-dense-size: calc((var(--u-text-body-size) + var(--u-text-label-size)) / 2);
312
+ --hs-text-hero-size: calc(var(--u-text-display-size) + 6px);
313
+
314
+ /* Field box (`@iyulab/components`) — 32px fields beside 32px buttons; 40px inside form sections. In em, so the box
315
+ follows the control density with the buttons (resolved at the field: 4.5px / 12px at the default 14px). */
316
+ --u-field-padding-block: calc(4.5em / 14);
317
+ --u-field-padding-inline: calc(12em / 14);
310
318
  --u-field-radius: 6px;
311
319
 
312
320
  /* Shell (`@iyulab/modern-app`) — 32px navigation rows, 16px icons, a flat current item */