@iyulab/house-style 0.1.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 +36 -0
- package/LICENSE +21 -0
- package/README.md +131 -0
- package/package.json +79 -0
- package/styles/components.css +125 -0
- package/styles/fonts.css +11 -0
- package/styles/index.css +11 -0
- package/styles/patterns.css +566 -0
- package/styles/tailwind-neutrals.css +77 -0
- package/styles/tailwind.css +78 -0
- package/styles/theme.css +7 -0
- package/styles/tokens.css +322 -0
|
@@ -0,0 +1,566 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @iyulab/house-style — layout patterns
|
|
3
|
+
* ==========================================================================
|
|
4
|
+
* Class-based patterns for the arrangements a line-of-business screen repeats and no single
|
|
5
|
+
* component owns: the page head, the filter bar, the stat strip, the plain data table, the
|
|
6
|
+
* callout, the form section, the side-sheet footer. They work in any framework (plain HTML,
|
|
7
|
+
* Lit, React) and read tokens only — no literal colours.
|
|
8
|
+
*
|
|
9
|
+
* Prefix `hs-`. Everything sits in `@layer iyu.house`; an application rule always wins.
|
|
10
|
+
*
|
|
11
|
+
* Screen recipes (the guide shows each one):
|
|
12
|
+
* list = .hs-page-head → .hs-filter-bar → .hs-stats → .hs-table-card (toolbar · table · pager)
|
|
13
|
+
* detail = side sheet: head (id · status · one primary action) → steps → .hs-stats → tabs → cards
|
|
14
|
+
* edit = side sheet with .hs-fieldset sections and a pinned .hs-sheet-footer
|
|
15
|
+
*
|
|
16
|
+
* Rules the patterns encode:
|
|
17
|
+
* · one ink (primary) button per view — the rest are outlined, plain or in a menu
|
|
18
|
+
* · conditions fold, results open — the table starts in the top third of the screen
|
|
19
|
+
* · numbers right-aligned in tabular figures; an empty value is an em dash
|
|
20
|
+
* · row actions appear on hover or selection, never as a red trash can on every row
|
|
21
|
+
* · a callout states its conclusion in the title; one callout per screen
|
|
22
|
+
* ========================================================================== */
|
|
23
|
+
|
|
24
|
+
@layer iyu.base, iyu.house;
|
|
25
|
+
|
|
26
|
+
@layer iyu.house {
|
|
27
|
+
|
|
28
|
+
/* ── Page ──────────────────────────────────────────────────────────────── */
|
|
29
|
+
.hs-page {
|
|
30
|
+
display: flex;
|
|
31
|
+
flex-direction: column;
|
|
32
|
+
gap: var(--u-space-lg, 16px);
|
|
33
|
+
min-width: 0;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/* Page head — eyebrow · title · one-line description on the left; on the right a scope
|
|
37
|
+
picker (data-wide filters such as a season or period), up to two secondary actions and
|
|
38
|
+
the single primary action, in that order. */
|
|
39
|
+
.hs-page-head {
|
|
40
|
+
display: flex;
|
|
41
|
+
align-items: flex-end;
|
|
42
|
+
justify-content: space-between;
|
|
43
|
+
gap: var(--u-space-lg, 16px);
|
|
44
|
+
flex-wrap: wrap;
|
|
45
|
+
}
|
|
46
|
+
.hs-page-head__eyebrow {
|
|
47
|
+
margin: 0 0 2px;
|
|
48
|
+
font-size: var(--u-text-label-size, 12px);
|
|
49
|
+
line-height: 16px;
|
|
50
|
+
color: var(--u-txt-color-weak);
|
|
51
|
+
}
|
|
52
|
+
.hs-page-head__title {
|
|
53
|
+
margin: 0;
|
|
54
|
+
font-size: var(--u-text-display-size, 22px);
|
|
55
|
+
line-height: var(--u-text-display-leading, 1.364);
|
|
56
|
+
font-weight: var(--u-text-display-weight, 700);
|
|
57
|
+
letter-spacing: var(--u-text-display-tracking, -0.01em);
|
|
58
|
+
color: var(--u-txt-color);
|
|
59
|
+
}
|
|
60
|
+
.hs-page-head__description {
|
|
61
|
+
margin: 2px 0 0;
|
|
62
|
+
font-size: var(--u-text-label-size, 12px);
|
|
63
|
+
line-height: 18px;
|
|
64
|
+
color: var(--u-txt-color-weak);
|
|
65
|
+
}
|
|
66
|
+
.hs-page-head__actions {
|
|
67
|
+
display: flex;
|
|
68
|
+
align-items: center;
|
|
69
|
+
gap: var(--u-space-sm, 8px);
|
|
70
|
+
flex-wrap: wrap;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/* ── Saved views — tabs above the filter bar, each with a count ─────────── */
|
|
74
|
+
.hs-views {
|
|
75
|
+
display: flex;
|
|
76
|
+
gap: var(--u-space-2xs, 4px);
|
|
77
|
+
border-bottom: 1px solid var(--u-border-color);
|
|
78
|
+
overflow-x: auto;
|
|
79
|
+
}
|
|
80
|
+
.hs-views__tab {
|
|
81
|
+
display: inline-flex;
|
|
82
|
+
align-items: center;
|
|
83
|
+
gap: 6px;
|
|
84
|
+
padding: var(--u-space-sm, 8px) var(--u-space-md, 12px);
|
|
85
|
+
margin-bottom: -1px;
|
|
86
|
+
border: 0;
|
|
87
|
+
border-bottom: 2px solid transparent;
|
|
88
|
+
background: none;
|
|
89
|
+
font: inherit;
|
|
90
|
+
font-size: 13px;
|
|
91
|
+
line-height: 20px;
|
|
92
|
+
color: var(--u-txt-color-weak);
|
|
93
|
+
white-space: nowrap;
|
|
94
|
+
cursor: pointer;
|
|
95
|
+
}
|
|
96
|
+
.hs-views__tab:hover {
|
|
97
|
+
color: var(--u-txt-color);
|
|
98
|
+
}
|
|
99
|
+
.hs-views__tab[aria-selected='true'],
|
|
100
|
+
.hs-views__tab[aria-current='page'] {
|
|
101
|
+
color: var(--u-txt-color);
|
|
102
|
+
border-bottom-color: var(--u-txt-color);
|
|
103
|
+
font-weight: 600;
|
|
104
|
+
}
|
|
105
|
+
.hs-views__tab:focus-visible {
|
|
106
|
+
outline: 2px solid var(--u-focus-ring-color);
|
|
107
|
+
outline-offset: -2px;
|
|
108
|
+
}
|
|
109
|
+
.hs-count {
|
|
110
|
+
display: inline-block;
|
|
111
|
+
min-width: 20px;
|
|
112
|
+
padding: 0 6px;
|
|
113
|
+
border-radius: var(--u-radius-pill, 9999px);
|
|
114
|
+
background: var(--u-bg-color-raised);
|
|
115
|
+
color: var(--u-txt-color-weak);
|
|
116
|
+
font-size: 11px;
|
|
117
|
+
line-height: 16px;
|
|
118
|
+
font-weight: 500;
|
|
119
|
+
text-align: center;
|
|
120
|
+
font-variant-numeric: tabular-nums;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/* ── Filter bar — search · up to three key filters · "Filters" panel · applied chips ── */
|
|
124
|
+
.hs-filter-bar {
|
|
125
|
+
display: flex;
|
|
126
|
+
flex-wrap: wrap;
|
|
127
|
+
align-items: center;
|
|
128
|
+
gap: var(--u-space-sm, 8px);
|
|
129
|
+
}
|
|
130
|
+
.hs-filter-bar__search {
|
|
131
|
+
flex: 0 1 360px;
|
|
132
|
+
min-width: 240px;
|
|
133
|
+
}
|
|
134
|
+
.hs-filter-bar__end {
|
|
135
|
+
margin-inline-start: auto;
|
|
136
|
+
}
|
|
137
|
+
.hs-chips {
|
|
138
|
+
display: flex;
|
|
139
|
+
flex-wrap: wrap;
|
|
140
|
+
align-items: center;
|
|
141
|
+
gap: var(--u-space-xs, 6px);
|
|
142
|
+
}
|
|
143
|
+
.hs-chips:empty {
|
|
144
|
+
display: none;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/* ── Stat strip — the result's totals as cells, not a sentence ───────────
|
|
148
|
+
* 3–5 cells: label → value → one supporting line. One hero value per screen at most. */
|
|
149
|
+
.hs-stats {
|
|
150
|
+
display: grid;
|
|
151
|
+
grid-auto-flow: column;
|
|
152
|
+
grid-auto-columns: minmax(0, 1fr);
|
|
153
|
+
background: var(--u-bg-color);
|
|
154
|
+
border: 1px solid var(--u-border-color);
|
|
155
|
+
border-radius: var(--u-radius-xl, 10px);
|
|
156
|
+
}
|
|
157
|
+
.hs-stat {
|
|
158
|
+
min-width: 0;
|
|
159
|
+
padding: var(--u-space-md, 12px) var(--u-space-lg, 16px);
|
|
160
|
+
border-inline-start: 1px solid var(--u-border-color);
|
|
161
|
+
}
|
|
162
|
+
.hs-stat:first-child {
|
|
163
|
+
border-inline-start: 0;
|
|
164
|
+
}
|
|
165
|
+
.hs-stat__label {
|
|
166
|
+
font-size: var(--u-text-label-size, 12px);
|
|
167
|
+
line-height: 16px;
|
|
168
|
+
font-weight: 500;
|
|
169
|
+
color: var(--u-txt-color-weak);
|
|
170
|
+
}
|
|
171
|
+
.hs-stat__value {
|
|
172
|
+
margin-top: 2px;
|
|
173
|
+
font-size: var(--u-text-title-size, 18px);
|
|
174
|
+
line-height: 26px;
|
|
175
|
+
font-weight: 700;
|
|
176
|
+
font-variant-numeric: tabular-nums;
|
|
177
|
+
white-space: nowrap;
|
|
178
|
+
overflow: hidden;
|
|
179
|
+
text-overflow: ellipsis;
|
|
180
|
+
color: var(--u-txt-color);
|
|
181
|
+
}
|
|
182
|
+
.hs-stat__unit {
|
|
183
|
+
margin-inline-start: 2px;
|
|
184
|
+
font-size: 12px;
|
|
185
|
+
font-weight: 500;
|
|
186
|
+
color: var(--u-txt-color-weak);
|
|
187
|
+
}
|
|
188
|
+
.hs-stat__sub {
|
|
189
|
+
font-size: 12px;
|
|
190
|
+
line-height: 18px;
|
|
191
|
+
color: var(--u-txt-color-weaker);
|
|
192
|
+
}
|
|
193
|
+
.hs-stat--hero .hs-stat__value {
|
|
194
|
+
font-size: 28px;
|
|
195
|
+
line-height: 34px;
|
|
196
|
+
letter-spacing: -0.01em;
|
|
197
|
+
}
|
|
198
|
+
.hs-stat--warning .hs-stat__value { color: var(--u-warning-color-strong); }
|
|
199
|
+
.hs-stat--danger .hs-stat__value { color: var(--u-danger-color-strong); }
|
|
200
|
+
.hs-stat--success .hs-stat__value { color: var(--u-success-color-strong); }
|
|
201
|
+
@container (max-width: 640px) {
|
|
202
|
+
.hs-stats { grid-auto-flow: row; }
|
|
203
|
+
.hs-stat { border-inline-start: 0; border-top: 1px solid var(--u-border-color); }
|
|
204
|
+
.hs-stat:first-child { border-top: 0; }
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/* ── Table card — toolbar · table · pager on one surface ──────────────── */
|
|
208
|
+
.hs-table-card {
|
|
209
|
+
background: var(--u-bg-color);
|
|
210
|
+
border: 1px solid var(--u-border-color);
|
|
211
|
+
border-radius: var(--u-radius-xl, 10px);
|
|
212
|
+
overflow: hidden;
|
|
213
|
+
min-width: 0;
|
|
214
|
+
}
|
|
215
|
+
.hs-table-card > flex-table {
|
|
216
|
+
border: 0;
|
|
217
|
+
}
|
|
218
|
+
.hs-table-toolbar {
|
|
219
|
+
display: flex;
|
|
220
|
+
align-items: center;
|
|
221
|
+
justify-content: space-between;
|
|
222
|
+
gap: var(--u-space-sm, 8px);
|
|
223
|
+
min-height: 48px;
|
|
224
|
+
padding: var(--u-space-sm, 8px) var(--u-space-md, 12px);
|
|
225
|
+
border-bottom: 1px solid var(--u-border-color);
|
|
226
|
+
flex-wrap: wrap;
|
|
227
|
+
}
|
|
228
|
+
/* With a selection the toolbar becomes the bulk-action bar. */
|
|
229
|
+
.hs-table-toolbar[data-selected],
|
|
230
|
+
.hs-table-toolbar--selected {
|
|
231
|
+
background: var(--u-primary-bg-color);
|
|
232
|
+
}
|
|
233
|
+
.hs-table-toolbar__title {
|
|
234
|
+
font-size: 13px;
|
|
235
|
+
font-weight: 600;
|
|
236
|
+
}
|
|
237
|
+
.hs-pager {
|
|
238
|
+
display: flex;
|
|
239
|
+
align-items: center;
|
|
240
|
+
justify-content: space-between;
|
|
241
|
+
gap: var(--u-space-sm, 8px);
|
|
242
|
+
padding: var(--u-space-sm, 8px) var(--u-space-md, 12px);
|
|
243
|
+
border-top: 1px solid var(--u-border-color);
|
|
244
|
+
font-size: 12px;
|
|
245
|
+
color: var(--u-txt-color-weak);
|
|
246
|
+
font-variant-numeric: tabular-nums;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/* ── Plain table — for small server-rendered tables that do not need a grid ── */
|
|
250
|
+
.hs-table {
|
|
251
|
+
width: 100%;
|
|
252
|
+
border-collapse: collapse;
|
|
253
|
+
font-size: 13px;
|
|
254
|
+
line-height: 20px;
|
|
255
|
+
color: var(--u-txt-color);
|
|
256
|
+
}
|
|
257
|
+
.hs-table th {
|
|
258
|
+
padding: var(--u-space-sm, 8px) var(--u-space-md, 12px);
|
|
259
|
+
text-align: start;
|
|
260
|
+
white-space: nowrap;
|
|
261
|
+
font-size: 12px;
|
|
262
|
+
line-height: 16px;
|
|
263
|
+
font-weight: 500;
|
|
264
|
+
color: var(--u-txt-color-weak);
|
|
265
|
+
background: var(--u-bg-color-raised);
|
|
266
|
+
border-bottom: 1px solid var(--u-border-color);
|
|
267
|
+
}
|
|
268
|
+
.hs-table td {
|
|
269
|
+
height: var(--hs-row, 40px);
|
|
270
|
+
padding: 0 var(--u-space-md, 12px);
|
|
271
|
+
border-bottom: 1px solid var(--u-border-color);
|
|
272
|
+
vertical-align: middle;
|
|
273
|
+
}
|
|
274
|
+
.hs-table tbody tr:last-child td { border-bottom: 0; }
|
|
275
|
+
.hs-table tbody tr:hover td { background: var(--u-bg-color-hover); }
|
|
276
|
+
.hs-table tr[aria-selected='true'] td { background: var(--u-primary-bg-color); }
|
|
277
|
+
.hs-table tfoot td {
|
|
278
|
+
height: var(--hs-row, 40px);
|
|
279
|
+
border-top: 1px solid var(--u-border-color);
|
|
280
|
+
font-weight: 600;
|
|
281
|
+
}
|
|
282
|
+
.hs-table--compact td { height: var(--hs-row-compact, 32px); }
|
|
283
|
+
.hs-table--top td { vertical-align: top; padding-block: var(--u-space-sm, 8px); height: auto; }
|
|
284
|
+
/* Cells (`th` too — header text aligns with its values) */
|
|
285
|
+
.hs-num,
|
|
286
|
+
.hs-table th.hs-num { text-align: end; font-variant-numeric: tabular-nums; white-space: nowrap; }
|
|
287
|
+
.hs-center,
|
|
288
|
+
.hs-table th.hs-center { text-align: center; }
|
|
289
|
+
.hs-nowrap { white-space: nowrap; }
|
|
290
|
+
.hs-muted { color: var(--u-txt-color-weak); }
|
|
291
|
+
.hs-strong { font-weight: 600; }
|
|
292
|
+
/* The row's identifier — bold ink, underline on hover; not a blue link repeated on every row. */
|
|
293
|
+
.hs-id {
|
|
294
|
+
font-weight: 600;
|
|
295
|
+
font-variant-numeric: tabular-nums;
|
|
296
|
+
color: var(--u-txt-color);
|
|
297
|
+
text-decoration: none;
|
|
298
|
+
}
|
|
299
|
+
a.hs-id:hover,
|
|
300
|
+
.hs-id:is(button):hover { text-decoration: underline; text-underline-offset: 3px; }
|
|
301
|
+
/* An empty value is shown, never left blank: `<span class="hs-empty">—</span>` */
|
|
302
|
+
.hs-empty { color: var(--u-txt-color-weaker); }
|
|
303
|
+
/* A run of rows that repeat the previous row's leading cells: fade the repeats. */
|
|
304
|
+
.hs-table .hs-continued td { color: var(--u-txt-color-weaker); }
|
|
305
|
+
.hs-table .hs-continued td.hs-keep { color: var(--u-txt-color); }
|
|
306
|
+
/* A group header row with its subtotal. */
|
|
307
|
+
.hs-table .hs-group td {
|
|
308
|
+
height: 32px;
|
|
309
|
+
background: var(--u-bg-color-raised);
|
|
310
|
+
font-size: 12px;
|
|
311
|
+
font-weight: 600;
|
|
312
|
+
color: var(--u-txt-color-weak);
|
|
313
|
+
}
|
|
314
|
+
/* Row actions — present for keyboard and assistive tech, shown on hover, focus or selection. */
|
|
315
|
+
.hs-row-actions {
|
|
316
|
+
display: inline-flex;
|
|
317
|
+
gap: 2px;
|
|
318
|
+
opacity: 0;
|
|
319
|
+
}
|
|
320
|
+
tr:hover .hs-row-actions,
|
|
321
|
+
tr:focus-within .hs-row-actions,
|
|
322
|
+
tr[aria-selected='true'] .hs-row-actions {
|
|
323
|
+
opacity: 1;
|
|
324
|
+
}
|
|
325
|
+
@media (hover: none) {
|
|
326
|
+
.hs-row-actions { opacity: 1; }
|
|
327
|
+
}
|
|
328
|
+
@media print {
|
|
329
|
+
.hs-row-actions { display: none; }
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/* ── Card — a titled surface for detail panels and dashboards ─────────── */
|
|
333
|
+
.hs-card {
|
|
334
|
+
background: var(--u-bg-color);
|
|
335
|
+
border: 1px solid var(--u-border-color);
|
|
336
|
+
border-radius: var(--u-radius-xl, 10px);
|
|
337
|
+
padding: var(--u-space-lg, 16px);
|
|
338
|
+
min-width: 0;
|
|
339
|
+
}
|
|
340
|
+
.hs-card__head {
|
|
341
|
+
display: flex;
|
|
342
|
+
align-items: center;
|
|
343
|
+
justify-content: space-between;
|
|
344
|
+
gap: var(--u-space-sm, 8px);
|
|
345
|
+
margin-bottom: var(--u-space-md, 12px);
|
|
346
|
+
}
|
|
347
|
+
.hs-card__title {
|
|
348
|
+
margin: 0;
|
|
349
|
+
font-size: var(--u-text-subtitle-size, 15px);
|
|
350
|
+
line-height: 22px;
|
|
351
|
+
font-weight: 600;
|
|
352
|
+
}
|
|
353
|
+
.hs-card__link {
|
|
354
|
+
font-size: 12px;
|
|
355
|
+
font-weight: 500;
|
|
356
|
+
color: var(--u-link-txt-color);
|
|
357
|
+
text-decoration: none;
|
|
358
|
+
}
|
|
359
|
+
.hs-card__link:hover { text-decoration: underline; }
|
|
360
|
+
a.hs-card,
|
|
361
|
+
.hs-card--link { cursor: pointer; transition: border-color 0.12s ease-out; }
|
|
362
|
+
a.hs-card:hover,
|
|
363
|
+
.hs-card--link:hover { border-color: var(--u-border-color-strong); }
|
|
364
|
+
@media (prefers-reduced-motion: reduce) {
|
|
365
|
+
a.hs-card, .hs-card--link { transition: none; }
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
/* Description list — label / value pairs inside a card. */
|
|
369
|
+
.hs-dl {
|
|
370
|
+
display: grid;
|
|
371
|
+
grid-template-columns: max-content minmax(0, 1fr);
|
|
372
|
+
gap: 6px var(--u-space-lg, 16px);
|
|
373
|
+
margin: 0;
|
|
374
|
+
font-size: 13px;
|
|
375
|
+
line-height: 20px;
|
|
376
|
+
}
|
|
377
|
+
.hs-dl > dt { color: var(--u-txt-color-weak); }
|
|
378
|
+
.hs-dl > dd { margin: 0; min-width: 0; }
|
|
379
|
+
|
|
380
|
+
/* Two-column detail: main column plus a 340px side panel once the container is wide. */
|
|
381
|
+
.hs-detail {
|
|
382
|
+
container: hs-detail / inline-size;
|
|
383
|
+
}
|
|
384
|
+
.hs-detail__cols {
|
|
385
|
+
display: grid;
|
|
386
|
+
grid-template-columns: minmax(0, 1fr);
|
|
387
|
+
gap: var(--u-space-lg, 16px);
|
|
388
|
+
align-items: start;
|
|
389
|
+
}
|
|
390
|
+
@container hs-detail (min-width: 960px) {
|
|
391
|
+
.hs-detail__cols { grid-template-columns: minmax(0, 1fr) 340px; }
|
|
392
|
+
}
|
|
393
|
+
.hs-grid-cards {
|
|
394
|
+
display: grid;
|
|
395
|
+
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
|
|
396
|
+
gap: var(--u-space-lg, 16px);
|
|
397
|
+
align-items: start;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
/* ── Callout — a conclusion in the title, two lines of body at most ──────
|
|
401
|
+
* No thick coloured edge: an icon and a tint carry the tone. `--note` is a person's note
|
|
402
|
+
* (a remark on a record), not a warning — it is neutral on purpose. */
|
|
403
|
+
.hs-callout {
|
|
404
|
+
display: grid;
|
|
405
|
+
grid-template-columns: auto minmax(0, 1fr) auto;
|
|
406
|
+
gap: var(--u-space-md, 12px);
|
|
407
|
+
align-items: start;
|
|
408
|
+
padding: var(--u-space-md, 12px) var(--u-space-lg, 16px);
|
|
409
|
+
border-radius: var(--u-radius-xl, 10px);
|
|
410
|
+
background: var(--u-bg-color-raised);
|
|
411
|
+
font-size: 13px;
|
|
412
|
+
line-height: 20px;
|
|
413
|
+
}
|
|
414
|
+
.hs-callout__icon { color: var(--u-txt-color-weak); line-height: 20px; }
|
|
415
|
+
.hs-callout__title { font-weight: 600; color: var(--u-txt-color); }
|
|
416
|
+
.hs-callout__body { color: var(--u-txt-color-weak); }
|
|
417
|
+
.hs-callout__actions { display: flex; gap: var(--u-space-sm, 8px); align-items: center; }
|
|
418
|
+
.hs-callout--info { background: var(--u-info-bg-color); }
|
|
419
|
+
.hs-callout--info .hs-callout__icon { color: var(--u-info-color-strong); }
|
|
420
|
+
.hs-callout--success { background: var(--u-success-bg-color); }
|
|
421
|
+
.hs-callout--success .hs-callout__icon { color: var(--u-success-color-strong); }
|
|
422
|
+
.hs-callout--warning { background: var(--u-warning-bg-color); }
|
|
423
|
+
.hs-callout--warning .hs-callout__icon { color: var(--u-warning-color-strong); }
|
|
424
|
+
.hs-callout--danger { background: var(--u-danger-bg-color); }
|
|
425
|
+
.hs-callout--danger .hs-callout__icon { color: var(--u-danger-color-strong); }
|
|
426
|
+
.hs-callout--note { background: var(--u-bg-color-raised); }
|
|
427
|
+
|
|
428
|
+
/* ── Form — label above, help below; sections instead of one long grid ── */
|
|
429
|
+
.hs-fieldset {
|
|
430
|
+
margin: 0;
|
|
431
|
+
padding: 0 0 var(--u-space-xl, 20px);
|
|
432
|
+
border: 0;
|
|
433
|
+
min-width: 0;
|
|
434
|
+
}
|
|
435
|
+
.hs-fieldset + .hs-fieldset {
|
|
436
|
+
padding-top: var(--u-space-xl, 20px);
|
|
437
|
+
border-top: 1px solid var(--u-border-color);
|
|
438
|
+
}
|
|
439
|
+
.hs-fieldset > * + * {
|
|
440
|
+
margin-top: var(--u-space-lg, 16px);
|
|
441
|
+
}
|
|
442
|
+
/* A rendered <legend> sits on the fieldset's top border; floating it puts it inside, as a
|
|
443
|
+
section heading, and the next child clears it. */
|
|
444
|
+
.hs-fieldset__legend {
|
|
445
|
+
float: inline-start;
|
|
446
|
+
width: 100%;
|
|
447
|
+
margin: 0 0 var(--u-space-md, 12px);
|
|
448
|
+
padding: 0;
|
|
449
|
+
font-size: 13px;
|
|
450
|
+
font-weight: 600;
|
|
451
|
+
color: var(--u-txt-color);
|
|
452
|
+
}
|
|
453
|
+
.hs-fieldset__legend + * {
|
|
454
|
+
clear: both;
|
|
455
|
+
margin-top: 0;
|
|
456
|
+
}
|
|
457
|
+
.hs-field {
|
|
458
|
+
display: grid;
|
|
459
|
+
gap: 6px;
|
|
460
|
+
align-content: start;
|
|
461
|
+
min-width: 0;
|
|
462
|
+
}
|
|
463
|
+
.hs-field__label {
|
|
464
|
+
font-size: var(--u-text-label-size, 12px);
|
|
465
|
+
line-height: 16px;
|
|
466
|
+
font-weight: 500;
|
|
467
|
+
color: var(--u-txt-color-weak);
|
|
468
|
+
}
|
|
469
|
+
.hs-field__required {
|
|
470
|
+
margin-inline-start: 2px;
|
|
471
|
+
color: var(--u-danger-color-strong);
|
|
472
|
+
}
|
|
473
|
+
.hs-field__help {
|
|
474
|
+
font-size: 12px;
|
|
475
|
+
line-height: 18px;
|
|
476
|
+
color: var(--u-txt-color-weaker);
|
|
477
|
+
}
|
|
478
|
+
.hs-field__error {
|
|
479
|
+
font-size: 12px;
|
|
480
|
+
line-height: 18px;
|
|
481
|
+
color: var(--u-danger-color-strong);
|
|
482
|
+
}
|
|
483
|
+
/* Form fields are 40px (the side-sheet and edit-form size); toolbars keep 32px. */
|
|
484
|
+
.hs-field {
|
|
485
|
+
--u-field-padding-block: 8.5px;
|
|
486
|
+
}
|
|
487
|
+
.hs-field :is(u-input, u-select, u-textarea, u-date-picker, u-date-range-picker) {
|
|
488
|
+
width: 100%;
|
|
489
|
+
--u-input-display: block;
|
|
490
|
+
--u-select-display: block;
|
|
491
|
+
}
|
|
492
|
+
/* Two or three columns — never four or more in a row. */
|
|
493
|
+
.hs-grid-2,
|
|
494
|
+
.hs-grid-3 {
|
|
495
|
+
display: grid;
|
|
496
|
+
gap: var(--u-space-md, 12px) var(--u-space-lg, 16px);
|
|
497
|
+
}
|
|
498
|
+
.hs-grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
|
499
|
+
.hs-grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
|
|
500
|
+
.hs-span-all { grid-column: 1 / -1; }
|
|
501
|
+
@container (max-width: 480px) {
|
|
502
|
+
.hs-grid-2, .hs-grid-3 { grid-template-columns: minmax(0, 1fr); }
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
/* ── Side sheet footer — change summary on the left, Cancel / Save on the right ── */
|
|
506
|
+
.hs-sheet-footer {
|
|
507
|
+
display: flex;
|
|
508
|
+
align-items: center;
|
|
509
|
+
justify-content: space-between;
|
|
510
|
+
gap: var(--u-space-sm, 8px);
|
|
511
|
+
padding: var(--u-space-md, 12px) var(--u-space-xl, 20px);
|
|
512
|
+
border-top: 1px solid var(--u-border-color);
|
|
513
|
+
background: var(--u-bg-color);
|
|
514
|
+
}
|
|
515
|
+
.hs-sheet-footer__summary {
|
|
516
|
+
font-size: 12px;
|
|
517
|
+
color: var(--u-txt-color-weak);
|
|
518
|
+
}
|
|
519
|
+
.hs-sheet-footer__actions {
|
|
520
|
+
display: flex;
|
|
521
|
+
gap: var(--u-space-sm, 8px);
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
/* ── Small marks ───────────────────────────────────────────────────────── */
|
|
525
|
+
/* A quiet attribute label next to an identifier (not a status — no colour). */
|
|
526
|
+
.hs-attr {
|
|
527
|
+
display: inline-flex;
|
|
528
|
+
align-items: center;
|
|
529
|
+
height: 18px;
|
|
530
|
+
padding: 0 5px;
|
|
531
|
+
border: 1px solid var(--u-border-color);
|
|
532
|
+
border-radius: var(--u-radius-md, 4px);
|
|
533
|
+
font-size: 11px;
|
|
534
|
+
line-height: 16px;
|
|
535
|
+
font-weight: 500;
|
|
536
|
+
color: var(--u-txt-color-weak);
|
|
537
|
+
white-space: nowrap;
|
|
538
|
+
vertical-align: middle;
|
|
539
|
+
}
|
|
540
|
+
/* Days left: neutral, soon (warning), overdue (danger). */
|
|
541
|
+
.hs-due {
|
|
542
|
+
display: inline-flex;
|
|
543
|
+
align-items: center;
|
|
544
|
+
height: 18px;
|
|
545
|
+
padding: 0 6px;
|
|
546
|
+
border-radius: var(--u-radius-pill, 9999px);
|
|
547
|
+
font-size: 11px;
|
|
548
|
+
font-weight: 600;
|
|
549
|
+
font-variant-numeric: tabular-nums;
|
|
550
|
+
background: var(--u-bg-color-raised);
|
|
551
|
+
color: var(--u-txt-color-weak);
|
|
552
|
+
white-space: nowrap;
|
|
553
|
+
}
|
|
554
|
+
.hs-due--soon { background: var(--u-warning-bg-color); color: var(--u-warning-color-strong); }
|
|
555
|
+
.hs-due--over { background: var(--u-danger-bg-color); color: var(--u-danger-color-strong); }
|
|
556
|
+
/* A keyboard hint. */
|
|
557
|
+
.hs-kbd {
|
|
558
|
+
padding: 0 4px;
|
|
559
|
+
border: 1px solid var(--u-border-color);
|
|
560
|
+
border-radius: var(--u-radius-md, 4px);
|
|
561
|
+
background: var(--u-canvas-bg-color);
|
|
562
|
+
font: 500 11px/16px var(--u-font-base);
|
|
563
|
+
color: var(--u-txt-color-weak);
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
} /* @layer iyu.house */
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @iyulab/house-style — Tailwind CSS v4: grey ramps follow the house neutrals (opt-in)
|
|
3
|
+
* ==========================================================================
|
|
4
|
+
* @import 'tailwindcss';
|
|
5
|
+
* @import '@iyulab/house-style/styles/tailwind.css';
|
|
6
|
+
* @import '@iyulab/house-style/styles/tailwind-neutrals.css';
|
|
7
|
+
*
|
|
8
|
+
* For an existing app whose markup already uses `text-gray-500`, `bg-slate-50`, `border-zinc-200`
|
|
9
|
+
* … in hundreds of places: instead of rewriting them to role utilities, point Tailwind's grey
|
|
10
|
+
* ramps at the house neutral ramp. They then follow the theme — including dark mode, where the
|
|
11
|
+
* house ramp is inverted (step 900 is the text colour in both modes), so `text-gray-900` stays
|
|
12
|
+
* readable and `bg-gray-50` stays a quiet tint.
|
|
13
|
+
*
|
|
14
|
+
* Steps are matched by the job Tailwind's step does, not by its number: Tailwind's `gray-500` is
|
|
15
|
+
* secondary text (4.8:1 on white) while the house `neutral-500` is a control border (3.1:1), so
|
|
16
|
+
* 400→500 (icons, placeholders) · 500→600 (secondary text) · 600→700 · 700→800 · 800→900.
|
|
17
|
+
*
|
|
18
|
+
* ⚠Because the ramp inverts, a grey used as an intentionally dark element (`bg-gray-900` for a
|
|
19
|
+
* tooltip) turns light in dark mode. New code should use the role utilities from `tailwind.css`.
|
|
20
|
+
* ========================================================================== */
|
|
21
|
+
@theme inline {
|
|
22
|
+
--color-gray-50: var(--u-neutral-50);
|
|
23
|
+
--color-gray-100: var(--u-neutral-100);
|
|
24
|
+
--color-gray-200: var(--u-neutral-200);
|
|
25
|
+
--color-gray-300: var(--u-neutral-300);
|
|
26
|
+
--color-gray-400: var(--u-neutral-500);
|
|
27
|
+
--color-gray-500: var(--u-neutral-600);
|
|
28
|
+
--color-gray-600: var(--u-neutral-700);
|
|
29
|
+
--color-gray-700: var(--u-neutral-800);
|
|
30
|
+
--color-gray-800: var(--u-neutral-900);
|
|
31
|
+
--color-gray-900: var(--u-neutral-900);
|
|
32
|
+
--color-gray-950: var(--u-neutral-1000);
|
|
33
|
+
--color-slate-50: var(--u-neutral-50);
|
|
34
|
+
--color-slate-100: var(--u-neutral-100);
|
|
35
|
+
--color-slate-200: var(--u-neutral-200);
|
|
36
|
+
--color-slate-300: var(--u-neutral-300);
|
|
37
|
+
--color-slate-400: var(--u-neutral-500);
|
|
38
|
+
--color-slate-500: var(--u-neutral-600);
|
|
39
|
+
--color-slate-600: var(--u-neutral-700);
|
|
40
|
+
--color-slate-700: var(--u-neutral-800);
|
|
41
|
+
--color-slate-800: var(--u-neutral-900);
|
|
42
|
+
--color-slate-900: var(--u-neutral-900);
|
|
43
|
+
--color-slate-950: var(--u-neutral-1000);
|
|
44
|
+
--color-zinc-50: var(--u-neutral-50);
|
|
45
|
+
--color-zinc-100: var(--u-neutral-100);
|
|
46
|
+
--color-zinc-200: var(--u-neutral-200);
|
|
47
|
+
--color-zinc-300: var(--u-neutral-300);
|
|
48
|
+
--color-zinc-400: var(--u-neutral-500);
|
|
49
|
+
--color-zinc-500: var(--u-neutral-600);
|
|
50
|
+
--color-zinc-600: var(--u-neutral-700);
|
|
51
|
+
--color-zinc-700: var(--u-neutral-800);
|
|
52
|
+
--color-zinc-800: var(--u-neutral-900);
|
|
53
|
+
--color-zinc-900: var(--u-neutral-900);
|
|
54
|
+
--color-zinc-950: var(--u-neutral-1000);
|
|
55
|
+
--color-neutral-50: var(--u-neutral-50);
|
|
56
|
+
--color-neutral-100: var(--u-neutral-100);
|
|
57
|
+
--color-neutral-200: var(--u-neutral-200);
|
|
58
|
+
--color-neutral-300: var(--u-neutral-300);
|
|
59
|
+
--color-neutral-400: var(--u-neutral-500);
|
|
60
|
+
--color-neutral-500: var(--u-neutral-600);
|
|
61
|
+
--color-neutral-600: var(--u-neutral-700);
|
|
62
|
+
--color-neutral-700: var(--u-neutral-800);
|
|
63
|
+
--color-neutral-800: var(--u-neutral-900);
|
|
64
|
+
--color-neutral-900: var(--u-neutral-900);
|
|
65
|
+
--color-neutral-950: var(--u-neutral-1000);
|
|
66
|
+
--color-stone-50: var(--u-neutral-50);
|
|
67
|
+
--color-stone-100: var(--u-neutral-100);
|
|
68
|
+
--color-stone-200: var(--u-neutral-200);
|
|
69
|
+
--color-stone-300: var(--u-neutral-300);
|
|
70
|
+
--color-stone-400: var(--u-neutral-500);
|
|
71
|
+
--color-stone-500: var(--u-neutral-600);
|
|
72
|
+
--color-stone-600: var(--u-neutral-700);
|
|
73
|
+
--color-stone-700: var(--u-neutral-800);
|
|
74
|
+
--color-stone-800: var(--u-neutral-900);
|
|
75
|
+
--color-stone-900: var(--u-neutral-900);
|
|
76
|
+
--color-stone-950: var(--u-neutral-1000);
|
|
77
|
+
}
|