@lifecorner/angular-ui-kit 3.27.0 → 3.27.2
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/fesm2022/lifecorner-angular-ui-kit-callout.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-callout.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-chat.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-chat.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-datepicker.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-datepicker.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-document-viewer.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-document-viewer.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-gallery.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-gallery.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-input.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-input.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-kanban-board.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-kanban-board.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-log-viewer.mjs +4 -4
- package/fesm2022/lifecorner-angular-ui-kit-log-viewer.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-notification-center.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-notification-center.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-rich-text-editor.mjs +4 -4
- package/fesm2022/lifecorner-angular-ui-kit-rich-text-editor.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-select.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-select.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-table.mjs +4 -4
- package/fesm2022/lifecorner-angular-ui-kit-table.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-tag-input.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-tag-input.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-textarea.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-textarea.mjs.map +1 -1
- package/package.json +1 -1
- package/src/styles/_theme-dark.scss +154 -137
- package/src/styles/_theme-light.scss +158 -138
- package/src/styles/focus-indicators.spec.ts +17 -8
- package/src/styles/theme-contrast.spec.ts +116 -2
- package/src/styles/theme-modes.spec.ts +40 -0
- package/src/styles/touch-targets-contrast.spec.ts +289 -0
|
@@ -14,9 +14,14 @@
|
|
|
14
14
|
@use './tokens/animation' as *;
|
|
15
15
|
@use './tokens/size' as *;
|
|
16
16
|
|
|
17
|
-
//
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
// Every colour token of the light theme: --color-*, --gradient-*, --shadow-*,
|
|
18
|
+
// --elevation-*, --accent-line and --app-background-image (request 043, F-25).
|
|
19
|
+
// The root rule below emits them, and `.lc-header--light` emits them a second
|
|
20
|
+
// time: derived tokens (`--color-primary: var(--color-primary-500)`) resolve
|
|
21
|
+
// where they are declared, so only the full set on the header gives its slot
|
|
22
|
+
// content (buttons, links, the theme toggle, the account menu) the light
|
|
23
|
+
// values inside a dark page.
|
|
24
|
+
@mixin -light-theme-colors {
|
|
20
25
|
// ============================================================================
|
|
21
26
|
// Colors - Primary
|
|
22
27
|
// ============================================================================
|
|
@@ -91,65 +96,6 @@
|
|
|
91
96
|
--color-accent-rust: #{$color-accent-rust};
|
|
92
97
|
--color-accent-violet: #{$color-accent-violet};
|
|
93
98
|
|
|
94
|
-
// ============================================================================
|
|
95
|
-
// Spacing
|
|
96
|
-
// ============================================================================
|
|
97
|
-
--spacing-0: #{$spacing-0};
|
|
98
|
-
--spacing-0-5: #{$spacing-0-5};
|
|
99
|
-
--spacing-1: #{$spacing-1};
|
|
100
|
-
--spacing-1-5: #{$spacing-1-5};
|
|
101
|
-
--spacing-2: #{$spacing-2};
|
|
102
|
-
--spacing-2-5: #{$spacing-2-5};
|
|
103
|
-
--spacing-3: #{$spacing-3};
|
|
104
|
-
--spacing-3-5: #{$spacing-3-5};
|
|
105
|
-
--spacing-4: #{$spacing-4};
|
|
106
|
-
--spacing-5: #{$spacing-5};
|
|
107
|
-
--spacing-6: #{$spacing-6};
|
|
108
|
-
--spacing-7: #{$spacing-7};
|
|
109
|
-
--spacing-8: #{$spacing-8};
|
|
110
|
-
--spacing-9: #{$spacing-9};
|
|
111
|
-
--spacing-10: #{$spacing-10};
|
|
112
|
-
--spacing-11: #{$spacing-11};
|
|
113
|
-
--spacing-12: #{$spacing-12};
|
|
114
|
-
--spacing-14: #{$spacing-14};
|
|
115
|
-
--spacing-16: #{$spacing-16};
|
|
116
|
-
|
|
117
|
-
// ============================================================================
|
|
118
|
-
// Typography - Font Families
|
|
119
|
-
// ============================================================================
|
|
120
|
-
--typography-font-family-base: #{$typography-font-family-base};
|
|
121
|
-
--typography-font-family-mono: #{$typography-font-family-mono};
|
|
122
|
-
|
|
123
|
-
// ============================================================================
|
|
124
|
-
// Typography - Font Sizes
|
|
125
|
-
// ============================================================================
|
|
126
|
-
--typography-font-size-xs: #{$typography-font-size-xs};
|
|
127
|
-
--typography-font-size-sm: #{$typography-font-size-sm};
|
|
128
|
-
--typography-font-size-base: #{$typography-font-size-base};
|
|
129
|
-
--typography-font-size-lg: #{$typography-font-size-lg};
|
|
130
|
-
--typography-font-size-xl: #{$typography-font-size-xl};
|
|
131
|
-
--typography-font-size-2xl: #{$typography-font-size-2xl};
|
|
132
|
-
--typography-font-size-3xl: #{$typography-font-size-3xl};
|
|
133
|
-
--typography-font-size-4xl: #{$typography-font-size-4xl};
|
|
134
|
-
--typography-font-size-5xl: #{$typography-font-size-5xl};
|
|
135
|
-
--typography-font-size-6xl: #{$typography-font-size-6xl};
|
|
136
|
-
--typography-font-size-7xl: #{$typography-font-size-7xl};
|
|
137
|
-
|
|
138
|
-
// ============================================================================
|
|
139
|
-
// Typography - Font Weights
|
|
140
|
-
// ============================================================================
|
|
141
|
-
--typography-font-weight-normal: #{$typography-font-weight-normal};
|
|
142
|
-
--typography-font-weight-medium: #{$typography-font-weight-medium};
|
|
143
|
-
--typography-font-weight-semibold: #{$typography-font-weight-semibold};
|
|
144
|
-
--typography-font-weight-bold: #{$typography-font-weight-bold};
|
|
145
|
-
|
|
146
|
-
// ============================================================================
|
|
147
|
-
// Typography - Line Heights
|
|
148
|
-
// ============================================================================
|
|
149
|
-
--typography-line-height-tight: #{$typography-line-height-tight};
|
|
150
|
-
--typography-line-height-normal: #{$typography-line-height-normal};
|
|
151
|
-
--typography-line-height-relaxed: #{$typography-line-height-relaxed};
|
|
152
|
-
|
|
153
99
|
// ============================================================================
|
|
154
100
|
// Elevation (Box Shadows) — light-tuned
|
|
155
101
|
// ============================================================================
|
|
@@ -162,58 +108,6 @@
|
|
|
162
108
|
--elevation-3: 0 4px 6px -2px rgba(16, 24, 40, 0.05), 0 12px 16px -4px rgba(16, 24, 40, 0.10);
|
|
163
109
|
--elevation-4: 0 8px 8px -4px rgba(16, 24, 40, 0.04), 0 20px 24px -4px rgba(16, 24, 40, 0.10);
|
|
164
110
|
|
|
165
|
-
// ============================================================================
|
|
166
|
-
// Border Radius
|
|
167
|
-
// ============================================================================
|
|
168
|
-
--border-radius-none: #{$border-radius-none};
|
|
169
|
-
--border-radius-sm: #{$border-radius-sm};
|
|
170
|
-
--border-radius-md: #{$border-radius-md};
|
|
171
|
-
--border-radius-lg: #{$border-radius-lg};
|
|
172
|
-
--border-radius-xl: #{$border-radius-xl};
|
|
173
|
-
--border-radius-2xl: #{$border-radius-2xl};
|
|
174
|
-
--border-radius-full: #{$border-radius-full};
|
|
175
|
-
|
|
176
|
-
// ============================================================================
|
|
177
|
-
// Animation
|
|
178
|
-
// ============================================================================
|
|
179
|
-
--animation-duration-base: #{$animation-duration-fast};
|
|
180
|
-
--animation-easing-ease-in: #{$animation-easing-ease-in};
|
|
181
|
-
--animation-easing-ease-out: #{$animation-easing-ease-out};
|
|
182
|
-
--animation-easing-ease-in-out: #{$animation-easing-ease-in-out};
|
|
183
|
-
|
|
184
|
-
// ============================================================================
|
|
185
|
-
// Size - Interactive Elements
|
|
186
|
-
// ============================================================================
|
|
187
|
-
--size-interactive-xs-height: #{$size-interactive-xs-height};
|
|
188
|
-
--size-interactive-xs-padding: #{$size-interactive-xs-padding};
|
|
189
|
-
--size-interactive-xs-font-size: #{$size-interactive-xs-font-size};
|
|
190
|
-
|
|
191
|
-
--size-interactive-sm-height: #{$size-interactive-sm-height};
|
|
192
|
-
--size-interactive-sm-padding: #{$size-interactive-sm-padding};
|
|
193
|
-
--size-interactive-sm-font-size: #{$size-interactive-sm-font-size};
|
|
194
|
-
|
|
195
|
-
--size-interactive-md-height: #{$size-interactive-md-height};
|
|
196
|
-
--size-interactive-md-padding: #{$size-interactive-md-padding};
|
|
197
|
-
--size-interactive-md-font-size: #{$size-interactive-md-font-size};
|
|
198
|
-
|
|
199
|
-
--size-interactive-lg-height: #{$size-interactive-lg-height};
|
|
200
|
-
--size-interactive-lg-padding: #{$size-interactive-lg-padding};
|
|
201
|
-
--size-interactive-lg-font-size: #{$size-interactive-lg-font-size};
|
|
202
|
-
|
|
203
|
-
// ============================================================================
|
|
204
|
-
// Size - Minimum Touch Target
|
|
205
|
-
// ============================================================================
|
|
206
|
-
--size-min-touch-width: #{$size-min-touch-width};
|
|
207
|
-
--size-min-touch-height: #{$size-min-touch-height};
|
|
208
|
-
|
|
209
|
-
// ============================================================================
|
|
210
|
-
// Layout - Content Width
|
|
211
|
-
// ============================================================================
|
|
212
|
-
// Canonical cap for page content. `lc-container size="xxl"` reads this, so an
|
|
213
|
-
// app shell that centres its own content against the same custom property
|
|
214
|
-
// stays in lockstep with the container instead of hard-coding a width.
|
|
215
|
-
--lc-content-max-width: #{$size-content-max-width};
|
|
216
|
-
|
|
217
111
|
// ============================================================================
|
|
218
112
|
// Semantic Color Mappings for Light Theme (DS2.0 — mirrors dark token names)
|
|
219
113
|
// ============================================================================
|
|
@@ -415,6 +309,147 @@
|
|
|
415
309
|
--color-skeleton: #e6eff1;
|
|
416
310
|
--color-skeleton-highlight: #f2f7f8;
|
|
417
311
|
|
|
312
|
+
// Semantic color scale aliases — map the numeric scale some components use
|
|
313
|
+
// onto the three canonical semantic shades so they always resolve.
|
|
314
|
+
--color-error-50: #{$color-error-light};
|
|
315
|
+
--color-error-100: #{$color-error-light};
|
|
316
|
+
--color-error-500: var(--color-error-default);
|
|
317
|
+
--color-error-600: var(--color-error-default);
|
|
318
|
+
--color-error-700: var(--color-error-dark);
|
|
319
|
+
--color-error-800: #5a0707; // Darker shade for active state
|
|
320
|
+
--color-success-50: #{$color-success-light};
|
|
321
|
+
--color-success-100: #{$color-success-light};
|
|
322
|
+
--color-success-500: var(--color-success-default);
|
|
323
|
+
--color-success-600: var(--color-success-default);
|
|
324
|
+
--color-success-700: var(--color-success-dark);
|
|
325
|
+
--color-warning-50: #{$color-warning-light};
|
|
326
|
+
--color-warning-100: #{$color-warning-light};
|
|
327
|
+
--color-warning-500: var(--color-warning-default);
|
|
328
|
+
--color-warning-600: var(--color-warning-default);
|
|
329
|
+
--color-warning-700: var(--color-warning-dark);
|
|
330
|
+
--color-info-50: #{$color-info-light};
|
|
331
|
+
--color-info-100: #{$color-info-light};
|
|
332
|
+
--color-info-500: var(--color-info-default);
|
|
333
|
+
--color-info-600: var(--color-info-default);
|
|
334
|
+
--color-info-700: var(--color-info-dark);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// Default theme (light) on :root
|
|
338
|
+
:root,
|
|
339
|
+
:root.light {
|
|
340
|
+
@include -light-theme-colors;
|
|
341
|
+
|
|
342
|
+
// ============================================================================
|
|
343
|
+
// Spacing
|
|
344
|
+
// ============================================================================
|
|
345
|
+
--spacing-0: #{$spacing-0};
|
|
346
|
+
--spacing-0-5: #{$spacing-0-5};
|
|
347
|
+
--spacing-1: #{$spacing-1};
|
|
348
|
+
--spacing-1-5: #{$spacing-1-5};
|
|
349
|
+
--spacing-2: #{$spacing-2};
|
|
350
|
+
--spacing-2-5: #{$spacing-2-5};
|
|
351
|
+
--spacing-3: #{$spacing-3};
|
|
352
|
+
--spacing-3-5: #{$spacing-3-5};
|
|
353
|
+
--spacing-4: #{$spacing-4};
|
|
354
|
+
--spacing-5: #{$spacing-5};
|
|
355
|
+
--spacing-6: #{$spacing-6};
|
|
356
|
+
--spacing-7: #{$spacing-7};
|
|
357
|
+
--spacing-8: #{$spacing-8};
|
|
358
|
+
--spacing-9: #{$spacing-9};
|
|
359
|
+
--spacing-10: #{$spacing-10};
|
|
360
|
+
--spacing-11: #{$spacing-11};
|
|
361
|
+
--spacing-12: #{$spacing-12};
|
|
362
|
+
--spacing-14: #{$spacing-14};
|
|
363
|
+
--spacing-16: #{$spacing-16};
|
|
364
|
+
|
|
365
|
+
// ============================================================================
|
|
366
|
+
// Typography - Font Families
|
|
367
|
+
// ============================================================================
|
|
368
|
+
--typography-font-family-base: #{$typography-font-family-base};
|
|
369
|
+
--typography-font-family-mono: #{$typography-font-family-mono};
|
|
370
|
+
|
|
371
|
+
// ============================================================================
|
|
372
|
+
// Typography - Font Sizes
|
|
373
|
+
// ============================================================================
|
|
374
|
+
--typography-font-size-xs: #{$typography-font-size-xs};
|
|
375
|
+
--typography-font-size-sm: #{$typography-font-size-sm};
|
|
376
|
+
--typography-font-size-base: #{$typography-font-size-base};
|
|
377
|
+
--typography-font-size-lg: #{$typography-font-size-lg};
|
|
378
|
+
--typography-font-size-xl: #{$typography-font-size-xl};
|
|
379
|
+
--typography-font-size-2xl: #{$typography-font-size-2xl};
|
|
380
|
+
--typography-font-size-3xl: #{$typography-font-size-3xl};
|
|
381
|
+
--typography-font-size-4xl: #{$typography-font-size-4xl};
|
|
382
|
+
--typography-font-size-5xl: #{$typography-font-size-5xl};
|
|
383
|
+
--typography-font-size-6xl: #{$typography-font-size-6xl};
|
|
384
|
+
--typography-font-size-7xl: #{$typography-font-size-7xl};
|
|
385
|
+
|
|
386
|
+
// ============================================================================
|
|
387
|
+
// Typography - Font Weights
|
|
388
|
+
// ============================================================================
|
|
389
|
+
--typography-font-weight-normal: #{$typography-font-weight-normal};
|
|
390
|
+
--typography-font-weight-medium: #{$typography-font-weight-medium};
|
|
391
|
+
--typography-font-weight-semibold: #{$typography-font-weight-semibold};
|
|
392
|
+
--typography-font-weight-bold: #{$typography-font-weight-bold};
|
|
393
|
+
|
|
394
|
+
// ============================================================================
|
|
395
|
+
// Typography - Line Heights
|
|
396
|
+
// ============================================================================
|
|
397
|
+
--typography-line-height-tight: #{$typography-line-height-tight};
|
|
398
|
+
--typography-line-height-normal: #{$typography-line-height-normal};
|
|
399
|
+
--typography-line-height-relaxed: #{$typography-line-height-relaxed};
|
|
400
|
+
|
|
401
|
+
// ============================================================================
|
|
402
|
+
// Border Radius
|
|
403
|
+
// ============================================================================
|
|
404
|
+
--border-radius-none: #{$border-radius-none};
|
|
405
|
+
--border-radius-sm: #{$border-radius-sm};
|
|
406
|
+
--border-radius-md: #{$border-radius-md};
|
|
407
|
+
--border-radius-lg: #{$border-radius-lg};
|
|
408
|
+
--border-radius-xl: #{$border-radius-xl};
|
|
409
|
+
--border-radius-2xl: #{$border-radius-2xl};
|
|
410
|
+
--border-radius-full: #{$border-radius-full};
|
|
411
|
+
|
|
412
|
+
// ============================================================================
|
|
413
|
+
// Animation
|
|
414
|
+
// ============================================================================
|
|
415
|
+
--animation-duration-base: #{$animation-duration-fast};
|
|
416
|
+
--animation-easing-ease-in: #{$animation-easing-ease-in};
|
|
417
|
+
--animation-easing-ease-out: #{$animation-easing-ease-out};
|
|
418
|
+
--animation-easing-ease-in-out: #{$animation-easing-ease-in-out};
|
|
419
|
+
|
|
420
|
+
// ============================================================================
|
|
421
|
+
// Size - Interactive Elements
|
|
422
|
+
// ============================================================================
|
|
423
|
+
--size-interactive-xs-height: #{$size-interactive-xs-height};
|
|
424
|
+
--size-interactive-xs-padding: #{$size-interactive-xs-padding};
|
|
425
|
+
--size-interactive-xs-font-size: #{$size-interactive-xs-font-size};
|
|
426
|
+
|
|
427
|
+
--size-interactive-sm-height: #{$size-interactive-sm-height};
|
|
428
|
+
--size-interactive-sm-padding: #{$size-interactive-sm-padding};
|
|
429
|
+
--size-interactive-sm-font-size: #{$size-interactive-sm-font-size};
|
|
430
|
+
|
|
431
|
+
--size-interactive-md-height: #{$size-interactive-md-height};
|
|
432
|
+
--size-interactive-md-padding: #{$size-interactive-md-padding};
|
|
433
|
+
--size-interactive-md-font-size: #{$size-interactive-md-font-size};
|
|
434
|
+
|
|
435
|
+
--size-interactive-lg-height: #{$size-interactive-lg-height};
|
|
436
|
+
--size-interactive-lg-padding: #{$size-interactive-lg-padding};
|
|
437
|
+
--size-interactive-lg-font-size: #{$size-interactive-lg-font-size};
|
|
438
|
+
|
|
439
|
+
// ============================================================================
|
|
440
|
+
// Size - Minimum Touch Target
|
|
441
|
+
// ============================================================================
|
|
442
|
+
--size-min-touch-width: #{$size-min-touch-width};
|
|
443
|
+
--size-min-touch-height: #{$size-min-touch-height};
|
|
444
|
+
|
|
445
|
+
// ============================================================================
|
|
446
|
+
// Layout - Content Width
|
|
447
|
+
// ============================================================================
|
|
448
|
+
// Canonical cap for page content. `lc-container size="xxl"` reads this, so an
|
|
449
|
+
// app shell that centres its own content against the same custom property
|
|
450
|
+
// stays in lockstep with the container instead of hard-coding a width.
|
|
451
|
+
--lc-content-max-width: #{$size-content-max-width};
|
|
452
|
+
|
|
418
453
|
// ============================================================================
|
|
419
454
|
// Short Aliases for Common Usage (Component Convenience)
|
|
420
455
|
// ============================================================================
|
|
@@ -441,28 +476,13 @@
|
|
|
441
476
|
--line-height-normal: var(--typography-line-height-normal);
|
|
442
477
|
--line-height-relaxed: var(--typography-line-height-relaxed);
|
|
443
478
|
--animation-timing-ease: var(--animation-easing-ease-in-out);
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
--color-success-50: #{$color-success-light};
|
|
454
|
-
--color-success-100: #{$color-success-light};
|
|
455
|
-
--color-success-500: var(--color-success-default);
|
|
456
|
-
--color-success-600: var(--color-success-default);
|
|
457
|
-
--color-success-700: var(--color-success-dark);
|
|
458
|
-
--color-warning-50: #{$color-warning-light};
|
|
459
|
-
--color-warning-100: #{$color-warning-light};
|
|
460
|
-
--color-warning-500: var(--color-warning-default);
|
|
461
|
-
--color-warning-600: var(--color-warning-default);
|
|
462
|
-
--color-warning-700: var(--color-warning-dark);
|
|
463
|
-
--color-info-50: #{$color-info-light};
|
|
464
|
-
--color-info-100: #{$color-info-light};
|
|
465
|
-
--color-info-500: var(--color-info-default);
|
|
466
|
-
--color-info-600: var(--color-info-default);
|
|
467
|
-
--color-info-700: var(--color-info-dark);
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
// `<lc-header theme="light">` keeps the light palette inside a dark page
|
|
482
|
+
// (request 043, F-25): its slot buttons and primary inks measured 1.05:1
|
|
483
|
+
// (outline) and 1.59:1 (link) there; with the tokens re-declared they match a
|
|
484
|
+
// light page (17.12:1, 6.21:1). A root-level token override does not reach
|
|
485
|
+
// inside a themed header.
|
|
486
|
+
.lc-header--light {
|
|
487
|
+
@include -light-theme-colors;
|
|
468
488
|
}
|
|
@@ -44,7 +44,9 @@ const rings: [string, string, string][] = [
|
|
|
44
44
|
['document-viewer/document-viewer.component.scss', '.doc-viewer__btn', '2px'],
|
|
45
45
|
['document-viewer/document-viewer.component.scss', '.doc-viewer__download-btn', '2px'],
|
|
46
46
|
['filter-bar/filter-bar.component.scss', '.lc-filter-bar__toggle-btn', '-2px'],
|
|
47
|
-
|
|
47
|
+
// 2px → 0 by review 043 r1 F3: the button grew from 20 to 24 px (2 px padding
|
|
48
|
+
// inside a −2 px margin), so offset 0 draws the ring where 2 px round 20 px did.
|
|
49
|
+
['select/select.component.scss', '.lc-select__clear', '0'],
|
|
48
50
|
['gallery/gallery.component.scss', '.gallery__filter-btn', '2px'],
|
|
49
51
|
['log-viewer/log-viewer.component.scss', '.lc-log-viewer__level-pill', '2px'],
|
|
50
52
|
['callout/callout.component.scss', '.callout__dismiss', '2px'],
|
|
@@ -171,14 +173,21 @@ describe('Focus indicators (request 042)', () => {
|
|
|
171
173
|
|
|
172
174
|
describe('D-6: focus wins over hover in every field with the pattern (F-19)', () => {
|
|
173
175
|
// [sheet, hover selector after the fix, declarations it keeps]
|
|
176
|
+
// Request 043 (F-23, design D-5) changed the first seven rows on purpose:
|
|
177
|
+
// they also exclude the error class (an error field kept no error border
|
|
178
|
+
// under the pointer), and the textarea/datepicker outline hover moved from
|
|
179
|
+
// --color-primary-400 (1.89:1 light) to --color-text-secondary (7.55:1).
|
|
180
|
+
// Request 044 (F-31, design D-3) changed the three filled rows on purpose:
|
|
181
|
+
// their hover border is --color-text-secondary too (it was --color-border,
|
|
182
|
+
// 1.23:1 light, or none in the textarea), the 3:1 boundary of the outline.
|
|
174
183
|
const hovers: [string, string, Record<string, string>][] = [
|
|
175
|
-
['textarea/textarea.component.scss', '.lc-textarea--outline:hover:not(:disabled):not(:read-only):not(:focus)', { 'border-color': 'var(--color-
|
|
176
|
-
['textarea/textarea.component.scss', '.lc-textarea--filled:hover:not(:disabled):not(:read-only):not(:focus)', { 'background-color': 'var(--color-surface-hover)' }],
|
|
177
|
-
['datepicker/datepicker.component.scss', '.lc-datepicker:hover:not(:disabled):not([readonly]):not(:focus)', { 'border-color': 'var(--color-
|
|
178
|
-
['datepicker/datepicker.component.scss', '.lc-datepicker.lc-datepicker--filled:hover:not(:disabled):not([readonly]):not(:focus)', { 'background-color': 'var(--color-surface-hover)', 'border-color': 'var(--color-
|
|
179
|
-
['input/input.component.scss', '.input-container:hover:not(.input-disabled):not(.input-readonly):not(:focus-within)', { 'border-color': 'var(--color-text-secondary)' }],
|
|
180
|
-
['select/select.component.scss', '.lc-select:hover:not(.lc-select--disabled):not(:focus)', { 'border-color': 'var(--color-text-secondary)' }],
|
|
181
|
-
['select/select.component.scss', '.lc-select.lc-select--filled:hover:not(.lc-select--disabled):not(:focus)', { 'background-color': 'var(--color-surface-hover)', 'border-color': 'var(--color-
|
|
184
|
+
['textarea/textarea.component.scss', '.lc-textarea--outline:hover:not(:disabled):not(:read-only):not(.lc-textarea--error):not(:focus)', { 'border-color': 'var(--color-text-secondary)' }],
|
|
185
|
+
['textarea/textarea.component.scss', '.lc-textarea--filled:hover:not(:disabled):not(:read-only):not(.lc-textarea--error):not(:focus)', { 'background-color': 'var(--color-surface-hover)', 'border-color': 'var(--color-text-secondary)' }],
|
|
186
|
+
['datepicker/datepicker.component.scss', '.lc-datepicker:hover:not(:disabled):not([readonly]):not(.lc-datepicker--error):not(:focus)', { 'border-color': 'var(--color-text-secondary)' }],
|
|
187
|
+
['datepicker/datepicker.component.scss', '.lc-datepicker.lc-datepicker--filled:hover:not(:disabled):not([readonly]):not(.lc-datepicker--error):not(:focus)', { 'background-color': 'var(--color-surface-hover)', 'border-color': 'var(--color-text-secondary)' }],
|
|
188
|
+
['input/input.component.scss', '.input-container:hover:not(.input-disabled):not(.input-readonly):not(.input-invalid):not(:focus-within)', { 'border-color': 'var(--color-text-secondary)' }],
|
|
189
|
+
['select/select.component.scss', '.lc-select:hover:not(.lc-select--disabled):not(.lc-select--error):not(:focus)', { 'border-color': 'var(--color-text-secondary)' }],
|
|
190
|
+
['select/select.component.scss', '.lc-select.lc-select--filled:hover:not(.lc-select--disabled):not(.lc-select--error):not(:focus)', { 'background-color': 'var(--color-surface-hover)', 'border-color': 'var(--color-text-secondary)' }],
|
|
182
191
|
['search-input/search-input.component.scss', '.search-input:hover:not(.search-input--disabled):not(:focus-within)', { 'border-color': 'var(--color-text-secondary)' }],
|
|
183
192
|
['tag-input/tag-input.component.scss', '.lc-tag-input__container:hover:not(.lc-tag-input__container--focused)', { 'border-color': 'var(--color-text-secondary)' }],
|
|
184
193
|
['date-range-picker/date-range-picker.component.scss', '.lc-drp__field:hover:not(.lc-drp__field--disabled):not(:focus-within)', { 'border-color': 'var(--color-text-secondary)' }],
|
|
@@ -981,9 +981,21 @@ describe('Component pairings of 3.22.4 (request 034)', () => {
|
|
|
981
981
|
['diff', '.lc-diff__num', { color: secondary }],
|
|
982
982
|
// F-4: the lc-badge primary pair with a primary border.
|
|
983
983
|
['card', '.card__badge--primary', { 'background-color': 'var(--color-primary-subtle)', color: 'var(--color-on-primary-subtle)', border: '1px solid var(--color-primary-500)' }],
|
|
984
|
-
// F-5: a
|
|
984
|
+
// F-5: a hit area into half of each gap; the visible pill is unchanged.
|
|
985
|
+
// Request 043 (F-22) raised it from 40 to 44 px high (and at least 44 wide):
|
|
986
|
+
// the spacing exception is no longer relied on.
|
|
985
987
|
['log', '.lc-log-viewer__level-pill', { position: 'relative', padding: '0.125rem 0.5rem', 'font-size': '0.6875rem' }],
|
|
986
|
-
[
|
|
988
|
+
[
|
|
989
|
+
'log',
|
|
990
|
+
'.lc-log-viewer__level-pill::before',
|
|
991
|
+
{
|
|
992
|
+
content: '""',
|
|
993
|
+
position: 'absolute',
|
|
994
|
+
'inset-inline': 'min(-0.125rem, (100% - var(--size-min-touch-height, 2.75rem)) / 2)',
|
|
995
|
+
top: 'calc(50% - var(--size-min-touch-height, 2.75rem) / 2)',
|
|
996
|
+
bottom: 'calc(50% - var(--size-min-touch-height, 2.75rem) / 2)',
|
|
997
|
+
},
|
|
998
|
+
],
|
|
987
999
|
// F-7: three text steps instead of opacity, in the log and the terminal.
|
|
988
1000
|
['log', '.lc-log-viewer__line--debug', { color: secondary }],
|
|
989
1001
|
...meta.map((m): Row => ['log', `.lc-log-viewer__${m}`, { color: secondary }]),
|
|
@@ -1778,3 +1790,105 @@ describe('Component pairings of 3.25.0 (request 039)', () => {
|
|
|
1778
1790
|
});
|
|
1779
1791
|
});
|
|
1780
1792
|
});
|
|
1793
|
+
|
|
1794
|
+
/**
|
|
1795
|
+
* Request 044 (3.27.2, F-31, design 044 §5): the filled select, textarea and
|
|
1796
|
+
* datepicker draw the field boundary of the outline variant, --color-field-border
|
|
1797
|
+
* at rest and --color-text-secondary on hover (it was transparent at rest and
|
|
1798
|
+
* --color-border, 1.23 / 1.29, or nothing on hover). Pages are the background,
|
|
1799
|
+
* surface and surface-2; the field's own fill (--color-surface-sunken at rest,
|
|
1800
|
+
* --color-surface-hover on hover) is composited over each page.
|
|
1801
|
+
*/
|
|
1802
|
+
describe('Component pairings of 3.27.2 (request 044)', () => {
|
|
1803
|
+
const lib = (path: string) => resolve(__dirname, '../lib', path);
|
|
1804
|
+
const fields = {
|
|
1805
|
+
select: {
|
|
1806
|
+
css: compile(lib('select/select.component.scss')).css,
|
|
1807
|
+
rest: '.lc-select.lc-select--filled',
|
|
1808
|
+
hover: '.lc-select.lc-select--filled:hover:not(.lc-select--disabled):not(.lc-select--error):not(:focus)',
|
|
1809
|
+
error: '.lc-select.lc-select--error',
|
|
1810
|
+
},
|
|
1811
|
+
textarea: {
|
|
1812
|
+
css: compile(lib('textarea/textarea.component.scss')).css,
|
|
1813
|
+
rest: '.lc-textarea--filled',
|
|
1814
|
+
hover: '.lc-textarea--filled:hover:not(:disabled):not(:read-only):not(.lc-textarea--error):not(:focus)',
|
|
1815
|
+
error: '.lc-textarea--error',
|
|
1816
|
+
},
|
|
1817
|
+
datepicker: {
|
|
1818
|
+
css: compile(lib('datepicker/datepicker.component.scss')).css,
|
|
1819
|
+
rest: '.lc-datepicker.lc-datepicker--filled',
|
|
1820
|
+
hover: '.lc-datepicker.lc-datepicker--filled:hover:not(:disabled):not([readonly]):not(.lc-datepicker--error):not(:focus)',
|
|
1821
|
+
error: '.lc-datepicker.lc-datepicker--filled.lc-datepicker--error',
|
|
1822
|
+
},
|
|
1823
|
+
};
|
|
1824
|
+
type Field = keyof typeof fields;
|
|
1825
|
+
const names = Object.keys(fields) as Field[];
|
|
1826
|
+
|
|
1827
|
+
const forcedBlock = /@media \(forced-colors: active\) \{((?:[^{}]*\{[^{}]*\})*)\s*\}/g;
|
|
1828
|
+
const rulesOf = (css: string) =>
|
|
1829
|
+
[...css.replace(forcedBlock, '').matchAll(/([^{}]+)\{([^{}]*)\}/g)].map((m) => ({
|
|
1830
|
+
selectors: m[1].split(/,(?![^(]*\))/).map((s) => s.trim()),
|
|
1831
|
+
body: m[2],
|
|
1832
|
+
}));
|
|
1833
|
+
const decls = (body: string): Record<string, string> =>
|
|
1834
|
+
Object.fromEntries([...body.matchAll(/([\w-]+):\s*([^;]+);/g)].map((m) => [m[1], m[2].replace(/\s+/g, ' ').trim()]));
|
|
1835
|
+
/** Every rule naming `selector`, merged in source order, forced-colours blocks left out. */
|
|
1836
|
+
const fills = (field: Field, selector: string): Record<string, string> => {
|
|
1837
|
+
const found = rulesOf(fields[field].css).filter((r) => r.selectors.includes(selector));
|
|
1838
|
+
expect([field, selector, found.length > 0]).toEqual([field, selector, true]);
|
|
1839
|
+
return Object.assign({}, ...found.map((r) => decls(r.body)));
|
|
1840
|
+
};
|
|
1841
|
+
const token = (value: string) => value.match(/^var\((--[\w-]+)\)$/)?.[1] ?? `not a token: ${value}`;
|
|
1842
|
+
const floor = (n: number) => Math.floor(n * 100) / 100;
|
|
1843
|
+
|
|
1844
|
+
it.each(names)('AC-8, AC-9: filled %s: field border on the sunken fill at rest, text-secondary on the hover fill', (field) => {
|
|
1845
|
+
const rest = fills(field, fields[field].rest);
|
|
1846
|
+
const hover = fills(field, fields[field].hover);
|
|
1847
|
+
expect([rest['background-color'], rest['border-color']]).toEqual(['var(--color-surface-sunken)', 'var(--color-field-border)']);
|
|
1848
|
+
expect([hover['background-color'], hover['border-color']]).toEqual(['var(--color-surface-hover)', 'var(--color-text-secondary)']);
|
|
1849
|
+
expect(fills(field, fields[field].error)['border-color']).toBe('var(--color-error-600)');
|
|
1850
|
+
});
|
|
1851
|
+
|
|
1852
|
+
// [light, dark] per page (background, surface, surface-2), design 044 §5.
|
|
1853
|
+
const expected = {
|
|
1854
|
+
restOnPage: [[4.83, 4.83, 4.62], [7.31, 6.7, 5.56]],
|
|
1855
|
+
restOnFill: [[4.39, 4.39, 4.39], [7.02, 7.02, 7.02]],
|
|
1856
|
+
hoverOnPage: [[7.55, 7.55, 7.23], [12.16, 11.15, 9.25]],
|
|
1857
|
+
hoverOnFill: [[6.86, 6.86, 6.86], [11.05, 9.97, 8.17]],
|
|
1858
|
+
// §5 quotes the page (background) only: 8.39 light, 9.47 dark.
|
|
1859
|
+
errorOnPage: [[8.39, 8.39, 8.02], [9.47, 8.68, 7.21]],
|
|
1860
|
+
errorOnFill: [[7.62, 7.62, 7.62], [9.09, 9.09, 9.09]],
|
|
1861
|
+
};
|
|
1862
|
+
|
|
1863
|
+
describe.each(palettes.map(([name, tokens], i) => [name, tokens, i] as const))('%s palette', (_palette, tokens, i) => {
|
|
1864
|
+
const c = (name: string) => color(tokens, name);
|
|
1865
|
+
|
|
1866
|
+
function measure(field: Field) {
|
|
1867
|
+
const pages = ['--color-background', '--color-surface', '--color-surface-2'].map(c);
|
|
1868
|
+
const rest = fills(field, fields[field].rest);
|
|
1869
|
+
const hover = fills(field, fields[field].hover);
|
|
1870
|
+
const error = fills(field, fields[field].error);
|
|
1871
|
+
const on = (ink: string, bases: Rgba[]) => bases.map((b) => floor(ratio(over(c(token(ink)), b), b)));
|
|
1872
|
+
const restFill = pages.map((p) => over(c(token(rest['background-color'])), p));
|
|
1873
|
+
const hoverFill = pages.map((p) => over(c(token(hover['background-color'])), p));
|
|
1874
|
+
return {
|
|
1875
|
+
restOnPage: on(rest['border-color'], pages),
|
|
1876
|
+
restOnFill: on(rest['border-color'], restFill),
|
|
1877
|
+
hoverOnPage: on(hover['border-color'], pages),
|
|
1878
|
+
hoverOnFill: on(hover['border-color'], hoverFill),
|
|
1879
|
+
errorOnPage: on(error['border-color'], pages),
|
|
1880
|
+
errorOnFill: on(error['border-color'], restFill),
|
|
1881
|
+
};
|
|
1882
|
+
}
|
|
1883
|
+
|
|
1884
|
+
it.each(names)('AC-8, AC-9: filled %s: the design 044 §5 ratios, all ≥ 3:1, hover ≥ rest', (field) => {
|
|
1885
|
+
const m = measure(field);
|
|
1886
|
+
for (const key of Object.keys(expected) as (keyof typeof expected)[]) {
|
|
1887
|
+
expect([key, m[key]]).toEqual([key, expected[key][i]]);
|
|
1888
|
+
expect(Math.min(...m[key])).toBeGreaterThanOrEqual(3);
|
|
1889
|
+
}
|
|
1890
|
+
m.hoverOnPage.forEach((r, page) => expect(r).toBeGreaterThanOrEqual(m.restOnPage[page]));
|
|
1891
|
+
m.hoverOnFill.forEach((r, page) => expect(r).toBeGreaterThanOrEqual(m.restOnFill[page]));
|
|
1892
|
+
});
|
|
1893
|
+
});
|
|
1894
|
+
});
|
|
@@ -58,3 +58,43 @@ describe('Theme modes', () => {
|
|
|
58
58
|
expect(tokens['--app-background-image']).toContain('rgba(78, 63, 132, 0.14)');
|
|
59
59
|
});
|
|
60
60
|
});
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Request 043 (F-25, design D-7): a header with `theme="light"` / `"dark"`
|
|
64
|
+
* re-declares every colour token of that theme, so its slot content (buttons,
|
|
65
|
+
* links, the theme toggle, the account menu) resolves the header's palette
|
|
66
|
+
* instead of the page's. Derived tokens resolve where they are declared, so
|
|
67
|
+
* the set must be complete.
|
|
68
|
+
*/
|
|
69
|
+
describe('Theme scope of a themed header', () => {
|
|
70
|
+
const COLOUR = /^--(color-|gradient-|shadow-|elevation-|accent-line$|app-background-image$)/;
|
|
71
|
+
const colours = (tokens: Record<string, string>) =>
|
|
72
|
+
Object.fromEntries(Object.entries(tokens).filter(([name]) => COLOUR.test(name)));
|
|
73
|
+
|
|
74
|
+
it('AC-6: .lc-header--light declares exactly the colour tokens of the light root (172), with the same values', () => {
|
|
75
|
+
const root = tokensOf(light, ':root,');
|
|
76
|
+
const header = tokensOf(light, '\n.lc-header--light {');
|
|
77
|
+
expect(Object.keys(header)).toHaveLength(172);
|
|
78
|
+
expect(header).toEqual(colours(root));
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it('AC-7: .lc-header--dark declares exactly the colour tokens of the dark root (172), with the same values', () => {
|
|
82
|
+
const root = tokensOf(dark, ':root.dark,');
|
|
83
|
+
const header = tokensOf(dark, '\n.lc-header--dark {');
|
|
84
|
+
expect(Object.keys(header)).toHaveLength(172);
|
|
85
|
+
expect(header).toEqual(colours(root));
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('AC-12: the root rules still declare the full token set (252 per theme), colours and the rest', () => {
|
|
89
|
+
expect(Object.keys(tokensOf(light, ':root,'))).toHaveLength(252);
|
|
90
|
+
expect(Object.keys(tokensOf(dark, ':root.dark,'))).toHaveLength(252);
|
|
91
|
+
expect(Object.keys(colours(tokensOf(light, ':root,')))).toHaveLength(172);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it('scopes only the header: each theme file emits the header rule once, after its root rules', () => {
|
|
95
|
+
expect(light.match(/\.lc-header--light \{/g)).toHaveLength(1);
|
|
96
|
+
expect(dark.match(/\.lc-header--dark \{/g)).toHaveLength(1);
|
|
97
|
+
expect(light.indexOf('.lc-header--light {')).toBeGreaterThan(light.indexOf(':root,'));
|
|
98
|
+
expect(dark.indexOf('.lc-header--dark {')).toBeGreaterThan(dark.indexOf(':root.system {'));
|
|
99
|
+
});
|
|
100
|
+
});
|