@webority/theme 0.7.3 → 0.7.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/dist/webority-theme.css +1 -1
- package/package.json +1 -1
- package/scss/_components.scss +78 -95
- package/scss/_tokens.scss +30 -24
- package/scss/_variables.scss +69 -80
- package/scss/_wui-aliases.scss +2 -1
- package/scss/wui/_choice.scss +4 -4
- package/scss/wui/_controls.scss +164 -248
- package/scss/wui/_data.scss +39 -0
- package/scss/wui/_display.scss +88 -0
- package/scss/wui/_overlays.scss +2 -2
- package/scss/wui/_scrollbar.scss +13 -11
- package/scss/wui/_shell.scss +3 -3
- package/scss/wui/_utilities.scss +27 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webority/theme",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.4",
|
|
4
4
|
"description": "Webority shared design system — Bootstrap 5.3 SCSS overrides, --wui-* tokens, and shared component CSS. The single source of brand chrome for React portals and Razor sites.",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"publishConfig": {
|
package/scss/_components.scss
CHANGED
|
@@ -153,6 +153,37 @@
|
|
|
153
153
|
--bs-btn-disabled-border-color: var(--wui-danger-strong);
|
|
154
154
|
}
|
|
155
155
|
|
|
156
|
+
// Soft neutral tinted button — a quieter alternative to .btn-light for a secondary
|
|
157
|
+
// action that shouldn't compete with a primary/danger CTA in the same row.
|
|
158
|
+
.btn-subtle {
|
|
159
|
+
--bs-btn-bg: var(--color-bg-muted);
|
|
160
|
+
--bs-btn-color: var(--color-text);
|
|
161
|
+
--bs-btn-border-color: transparent;
|
|
162
|
+
--bs-btn-hover-bg: var(--color-border);
|
|
163
|
+
--bs-btn-hover-color: var(--color-text);
|
|
164
|
+
--bs-btn-hover-border-color: transparent;
|
|
165
|
+
--bs-btn-active-bg: var(--color-border-strong);
|
|
166
|
+
--bs-btn-active-color: var(--color-text);
|
|
167
|
+
--bs-btn-active-border-color: transparent;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Light outline for a dark banner/hero CTA, where .btn-outline-primary's brand-coloured
|
|
171
|
+
// border/text would disappear against a dark background. White is used directly (not a
|
|
172
|
+
// token) because it's the one colour that reads on any dark surface, brand-independent.
|
|
173
|
+
.btn-outline-light {
|
|
174
|
+
--bs-btn-color: #fff;
|
|
175
|
+
--bs-btn-bg: transparent;
|
|
176
|
+
--bs-btn-border-color: rgba(255, 255, 255, 0.6);
|
|
177
|
+
--bs-btn-hover-color: #fff;
|
|
178
|
+
--bs-btn-hover-bg: rgba(255, 255, 255, 0.15);
|
|
179
|
+
--bs-btn-hover-border-color: #fff;
|
|
180
|
+
--bs-btn-active-color: #fff;
|
|
181
|
+
--bs-btn-active-bg: rgba(255, 255, 255, 0.25);
|
|
182
|
+
--bs-btn-active-border-color: #fff;
|
|
183
|
+
--bs-btn-disabled-color: rgba(255, 255, 255, 0.5);
|
|
184
|
+
--bs-btn-disabled-border-color: rgba(255, 255, 255, 0.3);
|
|
185
|
+
}
|
|
186
|
+
|
|
156
187
|
// Themed disabled state (fleet default). Bootstrap's own disabled look is just the
|
|
157
188
|
// variant's colour at --bs-btn-disabled-opacity (.65) — barely different from the active
|
|
158
189
|
// button on a tinted brand palette. Give the ordinary case a real desaturated/muted look
|
|
@@ -180,9 +211,8 @@
|
|
|
180
211
|
// sm/lg are re-asserted so they keep their own rung instead of the base value.
|
|
181
212
|
.btn {
|
|
182
213
|
--bs-btn-border-radius: var(--wui-radius);
|
|
183
|
-
//
|
|
184
|
-
//
|
|
185
|
-
// fall back to the plain border-radius arc — no breakage.
|
|
214
|
+
// Progressive enhancement only (Chrome/Safari recent). Unsupported engines
|
|
215
|
+
// keep a plain border-radius arc — not a cross-browser design contract.
|
|
186
216
|
corner-shape: squircle;
|
|
187
217
|
}
|
|
188
218
|
.btn-sm,
|
|
@@ -358,11 +388,10 @@
|
|
|
358
388
|
}
|
|
359
389
|
|
|
360
390
|
|
|
361
|
-
// ---- Card
|
|
362
|
-
//
|
|
363
|
-
//
|
|
364
|
-
//
|
|
365
|
-
// tactile signal, not a depth cue). No box-shadow, here or on hover.
|
|
391
|
+
// ---- Card hover-lift (name is historical) -----------------------------
|
|
392
|
+
// `.card-lifted` does NOT cast a shadow — in-page cards stay flat. It only
|
|
393
|
+
// nudges 1px on hover (tactile signal). API prop stays `lifted` / class
|
|
394
|
+
// `card-lifted` so call sites don't break (TASK-06086).
|
|
366
395
|
.card-lifted {
|
|
367
396
|
transition: transform 0.2s var(--wui-ease-out-quart);
|
|
368
397
|
&:hover {
|
|
@@ -398,50 +427,9 @@
|
|
|
398
427
|
|
|
399
428
|
|
|
400
429
|
// ---- Inputs ---------------------------------------------------------
|
|
401
|
-
//
|
|
402
|
-
//
|
|
403
|
-
//
|
|
404
|
-
// hover-border-darken cue and the leading/trailing-slot wrapper.
|
|
405
|
-
//
|
|
406
|
-
// The error state is driven by `aria-invalid="true"` (NOT by Bootstrap's
|
|
407
|
-
// .is-invalid class) so accessibility tooling and visual cue stay in
|
|
408
|
-
// sync without extra markup.
|
|
409
|
-
|
|
410
|
-
.form-control,
|
|
411
|
-
.form-select {
|
|
412
|
-
// Radius follows the token ladder (see component-radii note) rather than the
|
|
413
|
-
// compiled $input-border-radius, so a product's --wui-radius override reaches
|
|
414
|
-
// the raw Bootstrap inputs the way it already reaches the .input primitive.
|
|
415
|
-
border-radius: var(--wui-radius);
|
|
416
|
-
transition: border-color 0.15s ease;
|
|
417
|
-
}
|
|
418
|
-
.form-control:hover:not(:focus):not(:disabled):not([readonly]):not([aria-invalid="true"]),
|
|
419
|
-
.form-select:hover:not(:focus):not(:disabled):not([aria-invalid="true"]) {
|
|
420
|
-
border-color: var(--color-border-strong); // --wui-text-3 @ 60%
|
|
421
|
-
}
|
|
422
|
-
.form-control[aria-invalid="true"],
|
|
423
|
-
.form-select[aria-invalid="true"] {
|
|
424
|
-
border-color: var(--bs-danger);
|
|
425
|
-
}
|
|
426
|
-
.form-control[aria-invalid="true"]:focus,
|
|
427
|
-
.form-select[aria-invalid="true"]:focus {
|
|
428
|
-
border-color: var(--bs-danger);
|
|
429
|
-
box-shadow: none;
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
// Optional helper class for forms that prefer the explicit Bootstrap
|
|
433
|
-
// validation pattern. Mirrors aria-invalid styling.
|
|
434
|
-
.form-control.is-invalid,
|
|
435
|
-
.form-select.is-invalid {
|
|
436
|
-
border-color: var(--bs-danger);
|
|
437
|
-
background-image: none; // kill Bootstrap's exclamation-mark SVG
|
|
438
|
-
padding-right: 0.875rem;
|
|
439
|
-
}
|
|
440
|
-
.form-control.is-invalid:focus,
|
|
441
|
-
.form-select.is-invalid:focus {
|
|
442
|
-
border-color: var(--bs-danger);
|
|
443
|
-
box-shadow: none;
|
|
444
|
-
}
|
|
430
|
+
// Field chrome (height, hover, focus, invalid) lives in wui/_controls.scss on
|
|
431
|
+
// `.form-control` / `.form-select` with `.input` as an alias — one skin, not two
|
|
432
|
+
// (TASK-06079). This partial only keeps the marketing-side input-group shell.
|
|
445
433
|
|
|
446
434
|
|
|
447
435
|
// ---- Input group (leading / trailing slots) ------------------------
|
|
@@ -464,33 +452,32 @@
|
|
|
464
452
|
align-items: center;
|
|
465
453
|
gap: 0.5rem;
|
|
466
454
|
padding-inline: 0.875rem;
|
|
467
|
-
height:
|
|
468
|
-
background: var(--
|
|
469
|
-
border: 1px solid var(--
|
|
470
|
-
border-radius: var(--radius);
|
|
455
|
+
height: var(--wui-control-height);
|
|
456
|
+
background: var(--color-surface);
|
|
457
|
+
border: 1px solid var(--color-border);
|
|
458
|
+
border-radius: var(--radius);
|
|
471
459
|
transition: border-color 0.15s ease;
|
|
472
|
-
|
|
473
|
-
|
|
474
460
|
}
|
|
475
461
|
.wui-input-group:hover:not(:focus-within):not(.is-disabled) {
|
|
476
|
-
border-color:
|
|
462
|
+
border-color: var(--color-border-strong);
|
|
477
463
|
}
|
|
478
464
|
.wui-input-group:focus-within {
|
|
479
|
-
border-color: var(--
|
|
465
|
+
border-color: var(--color-primary);
|
|
480
466
|
}
|
|
481
467
|
.wui-input-group.is-disabled,
|
|
482
468
|
.wui-input-group:has(input:disabled) {
|
|
483
|
-
background: var(--
|
|
469
|
+
background: var(--color-bg-muted);
|
|
484
470
|
cursor: not-allowed;
|
|
485
|
-
border-color: var(--
|
|
471
|
+
border-color: var(--color-border);
|
|
486
472
|
}
|
|
487
473
|
.wui-input-group.has-error,
|
|
488
474
|
.wui-input-group:has(input[aria-invalid="true"]) {
|
|
489
|
-
border-color: var(--
|
|
475
|
+
border-color: color-mix(in srgb, var(--color-danger) 45%, var(--color-surface));
|
|
490
476
|
}
|
|
491
477
|
|
|
492
478
|
// Strip the bare input's own chrome — the wrapper carries it all.
|
|
493
|
-
.wui-input-group > .form-control
|
|
479
|
+
.wui-input-group > .form-control,
|
|
480
|
+
.wui-input-group > .input {
|
|
494
481
|
flex: 1 1 auto;
|
|
495
482
|
min-width: 0;
|
|
496
483
|
height: 100%;
|
|
@@ -502,7 +489,9 @@
|
|
|
502
489
|
border-radius: 0;
|
|
503
490
|
}
|
|
504
491
|
.wui-input-group > .form-control:focus,
|
|
505
|
-
.wui-input-group > .form-control:hover
|
|
492
|
+
.wui-input-group > .form-control:hover,
|
|
493
|
+
.wui-input-group > .input:focus,
|
|
494
|
+
.wui-input-group > .input:hover {
|
|
506
495
|
border: 0;
|
|
507
496
|
box-shadow: none !important;
|
|
508
497
|
background: transparent;
|
|
@@ -782,39 +771,31 @@ button.wui-input-leading:focus-visible {
|
|
|
782
771
|
}
|
|
783
772
|
|
|
784
773
|
|
|
785
|
-
// ----
|
|
786
|
-
//
|
|
774
|
+
// ---- Native scrollbars (document + opt-in) --------------------------
|
|
775
|
+
// Scoped to html/body and `.wui-scroll` — never `*` (TASK-06085). Global
|
|
776
|
+
// `*` restyled every nested scroller (modals, tiny panels) and fought
|
|
777
|
+
// component-local rails. AppScrollbar uses `.wui-scroll` (see wui/_scrollbar).
|
|
787
778
|
//
|
|
788
|
-
//
|
|
789
|
-
//
|
|
790
|
-
//
|
|
791
|
-
// - Pill thumb with a 2px transparent border (visual cushion)
|
|
792
|
-
// - `scrollbar-gutter: stable` on <html>/<body> so the page never
|
|
793
|
-
// shifts when scrollable content grows/shrinks. Internal containers
|
|
794
|
-
// (avatars, badges, rounded buttons) intentionally skip the gutter
|
|
795
|
-
// reservation — applying it everywhere would push centered glyphs
|
|
796
|
-
// off-center inside rounded boxes.
|
|
797
|
-
//
|
|
798
|
-
// `wwwroot/js/scroll-state.js` toggles `html.is-scrolling` for ~800ms
|
|
799
|
-
// after each scroll event; the thumb gets an extra opacity bump while
|
|
800
|
-
// the class is on, giving subtle "I'm scrolling now" feedback without
|
|
801
|
-
// sacrificing the always-visible affordance.
|
|
779
|
+
// `scrollbar-gutter: stable` only on the document so internal boxes do not
|
|
780
|
+
// push centered glyphs off-center. `html.is-scrolling` (scroll-state.js)
|
|
781
|
+
// brightens the document thumb while the page is scrolling.
|
|
802
782
|
html,
|
|
803
783
|
body {
|
|
804
784
|
scrollbar-gutter: stable;
|
|
805
|
-
}
|
|
806
|
-
* {
|
|
807
785
|
scrollbar-width: thin;
|
|
808
786
|
scrollbar-color: var(--wui-scrollbar) transparent;
|
|
809
787
|
}
|
|
810
|
-
|
|
788
|
+
html::-webkit-scrollbar,
|
|
789
|
+
body::-webkit-scrollbar {
|
|
811
790
|
width: 8px;
|
|
812
791
|
height: 8px;
|
|
813
792
|
}
|
|
814
|
-
|
|
793
|
+
html::-webkit-scrollbar-track,
|
|
794
|
+
body::-webkit-scrollbar-track {
|
|
815
795
|
background: transparent;
|
|
816
796
|
}
|
|
817
|
-
|
|
797
|
+
html::-webkit-scrollbar-thumb,
|
|
798
|
+
body::-webkit-scrollbar-thumb {
|
|
818
799
|
background-color: var(--wui-scrollbar);
|
|
819
800
|
border-radius: 9999px;
|
|
820
801
|
border: 2px solid transparent;
|
|
@@ -823,29 +804,31 @@ body {
|
|
|
823
804
|
min-width: 36px;
|
|
824
805
|
transition: background-color 220ms ease;
|
|
825
806
|
}
|
|
826
|
-
|
|
807
|
+
html::-webkit-scrollbar-thumb:hover,
|
|
808
|
+
body::-webkit-scrollbar-thumb:hover {
|
|
827
809
|
background-color: var(--wui-scrollbar-hover);
|
|
828
810
|
background-clip: padding-box;
|
|
829
811
|
}
|
|
830
|
-
|
|
812
|
+
html::-webkit-scrollbar-thumb:active,
|
|
813
|
+
body::-webkit-scrollbar-thumb:active {
|
|
831
814
|
background-color: var(--wui-scrollbar-active);
|
|
832
815
|
background-clip: padding-box;
|
|
833
816
|
}
|
|
834
|
-
|
|
817
|
+
html::-webkit-scrollbar-corner,
|
|
818
|
+
body::-webkit-scrollbar-corner {
|
|
835
819
|
background: transparent;
|
|
836
820
|
}
|
|
837
821
|
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
html.is-scrolling * {
|
|
822
|
+
html.is-scrolling,
|
|
823
|
+
html.is-scrolling body {
|
|
841
824
|
scrollbar-color: var(--wui-scrollbar-hover) transparent;
|
|
842
825
|
}
|
|
843
|
-
html.is-scrolling
|
|
826
|
+
html.is-scrolling::-webkit-scrollbar-thumb,
|
|
827
|
+
html.is-scrolling body::-webkit-scrollbar-thumb {
|
|
844
828
|
background-color: var(--wui-scrollbar-hover);
|
|
845
829
|
}
|
|
846
830
|
|
|
847
|
-
//
|
|
848
|
-
// carousels where the rail itself is visually intrusive).
|
|
831
|
+
// Hide a scrollbar (marquee / horizontal carousels).
|
|
849
832
|
.scrollbar-hide {
|
|
850
833
|
scrollbar-width: none;
|
|
851
834
|
}
|
package/scss/_tokens.scss
CHANGED
|
@@ -55,19 +55,14 @@
|
|
|
55
55
|
// Used by the tab ink-bar so a tab switch springs into place rather than sliding flat.
|
|
56
56
|
--wui-ease-elastic: cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
57
57
|
|
|
58
|
-
// Elevation
|
|
59
|
-
//
|
|
60
|
-
//
|
|
61
|
-
--wui-shadow-card:
|
|
62
|
-
--wui-shadow-card-lifted:
|
|
63
|
-
--wui-shadow-card-lifted-hover:
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
// border, not a shadow); only things that float above the page lift —
|
|
67
|
-
// menus, popovers, modals. One ink (the heading navy) so every overlay
|
|
68
|
-
// casts the same light; components must never hand-roll a shadow.
|
|
69
|
-
--wui-shadow-overlay: 0 8px 28px -6px rgba(7, 20, 55, 0.14);
|
|
70
|
-
--wui-shadow-overlay-lg: 0 24px 60px -16px rgba(7, 20, 55, 0.28);
|
|
58
|
+
// Elevation (TASK-06080). In-page card tokens are flat (none). Overlay
|
|
59
|
+
// rungs match $wui-shadow-overlay* in _variables.scss — one ink for menus,
|
|
60
|
+
// popovers, modals. Do not hand-roll a third shadow.
|
|
61
|
+
--wui-shadow-card: none;
|
|
62
|
+
--wui-shadow-card-lifted: none;
|
|
63
|
+
--wui-shadow-card-lifted-hover: none;
|
|
64
|
+
--wui-shadow-overlay: #{$wui-shadow-overlay};
|
|
65
|
+
--wui-shadow-overlay-lg: #{$wui-shadow-overlay-lg};
|
|
71
66
|
|
|
72
67
|
// One height for every form control. Buttons, inputs and selects share form
|
|
73
68
|
// rows, so they must line up — they were 46.8px and 45px, which reads as a
|
|
@@ -111,10 +106,10 @@
|
|
|
111
106
|
--wui-neutral-bg-light: #F9FBFC;
|
|
112
107
|
|
|
113
108
|
// ---- Accent-dark -----------------------------------------------
|
|
114
|
-
//
|
|
115
|
-
//
|
|
116
|
-
//
|
|
117
|
-
--wui-accent-dark:
|
|
109
|
+
// Darker primary for pressed/hover accents in CSS (not SCSS $link-hover).
|
|
110
|
+
// Aliased onto --wui-primary-pressed so a product that rebrands the pressed
|
|
111
|
+
// token once also updates this name (was a frozen indigo hex).
|
|
112
|
+
--wui-accent-dark: var(--wui-primary-pressed);
|
|
118
113
|
|
|
119
114
|
// ---- Container width + responsive padding ----------------------
|
|
120
115
|
// The standalone design uses a 1512px max canvas with generous side
|
|
@@ -223,16 +218,27 @@
|
|
|
223
218
|
--wui-font-display: var(--bs-body-font-family);
|
|
224
219
|
|
|
225
220
|
// ---- Z-index scale -------------------------------------------------
|
|
226
|
-
//
|
|
227
|
-
//
|
|
221
|
+
// One page-level ladder. Local stacking inside a component (1, 5, 10, 40…) is
|
|
222
|
+
// NOT on this scale — only fixed/portalled layers that compete across the page.
|
|
223
|
+
//
|
|
224
|
+
// Why not Bootstrap's raw 1040/1050 for modals? App shell sticky chrome uses
|
|
225
|
+
// 1040–1045; a BS-height modal would paint under the mobile drawer. Modals are
|
|
226
|
+
// elevated to 1500+ so the shell never covers a dialog. Portalled menus
|
|
227
|
+
// (select / date / phone / infotip) sit at 1600 so a combobox inside a modal
|
|
228
|
+
// is not trapped under the dialog. Never invent a third number in component CSS —
|
|
229
|
+
// pick a rung from this list (TASK-06078).
|
|
228
230
|
--wui-z-dropdown: 1000;
|
|
229
231
|
--wui-z-sticky: 1020;
|
|
230
232
|
--wui-z-fixed: 1030;
|
|
231
|
-
--wui-z-
|
|
232
|
-
--wui-z-
|
|
233
|
-
--wui-z-
|
|
234
|
-
--wui-z-
|
|
235
|
-
--wui-z-
|
|
233
|
+
--wui-z-shell: 1040; // splash, shell base chrome
|
|
234
|
+
--wui-z-shell-scrim: 1044; // mobile drawer scrim
|
|
235
|
+
--wui-z-shell-drawer: 1045; // mobile sidebar drawer
|
|
236
|
+
--wui-z-modal-backdrop: 1500;
|
|
237
|
+
--wui-z-modal: 1505;
|
|
238
|
+
--wui-z-menu: 1600; // portalled select/date/phone menus + infotip
|
|
239
|
+
--wui-z-popover: 1600; // same rung as --wui-z-menu (above modal)
|
|
240
|
+
--wui-z-tooltip: 1650;
|
|
241
|
+
--wui-z-toast: 1700;
|
|
236
242
|
}
|
|
237
243
|
|
|
238
244
|
// Bootstrap md / xl (not invented px)
|
package/scss/_variables.scss
CHANGED
|
@@ -37,9 +37,9 @@ $theme-colors: (
|
|
|
37
37
|
);
|
|
38
38
|
|
|
39
39
|
// Brand helper — set a product's primary ONCE and have the theme-colour map
|
|
40
|
-
// (so every .btn-primary / .bg-primary / .text-primary utility)
|
|
41
|
-
// follow, instead of overriding each in turn. Call it in
|
|
42
|
-
// pre-bootstrap variables, BEFORE
|
|
40
|
+
// (so every .btn-primary / .bg-primary / .text-primary utility), $link-color,
|
|
41
|
+
// and $link-hover-color follow, instead of overriding each in turn. Call it in
|
|
42
|
+
// the product's pre-bootstrap variables, BEFORE `bootstrap/scss/bootstrap`, e.g.:
|
|
43
43
|
//
|
|
44
44
|
// @include wui-brand-primary(#0EA5E9);
|
|
45
45
|
// @import "bootstrap/scss/bootstrap";
|
|
@@ -51,12 +51,13 @@ $theme-colors: (
|
|
|
51
51
|
$primary: $primary !global;
|
|
52
52
|
$theme-colors: map-merge($theme-colors, ("primary": $primary)) !global;
|
|
53
53
|
$link-color: $primary !global;
|
|
54
|
+
$link-hover-color: mix(black, $primary, 12%) !global;
|
|
54
55
|
}
|
|
55
56
|
|
|
56
57
|
|
|
57
58
|
// ---- Body / text ----------------------------------------------------
|
|
59
|
+
// $body-bg left at Bootstrap's $white — do not restate pure defaults here.
|
|
58
60
|
$body-color: #252F4A; // text-1 from locked palette
|
|
59
|
-
$body-bg: #FFFFFF;
|
|
60
61
|
$body-secondary-color: #4B5675;
|
|
61
62
|
$body-tertiary-color: #687088; // AA on white (matches --wui-text-3); #78829D was only 3.5:1
|
|
62
63
|
$body-secondary-bg: #F9FBFC;
|
|
@@ -70,81 +71,71 @@ $border-color-translucent: rgba(13, 24, 43, 0.08);
|
|
|
70
71
|
// One ladder; every component derives from it (Bootstrap's own model). Set a
|
|
71
72
|
// component's radius by pointing it at a rung, never by hardcoding a px value —
|
|
72
73
|
// that is what let buttons drift to ~3x Bootstrap's.
|
|
73
|
-
|
|
74
|
-
$border-radius-
|
|
75
|
-
$border-radius
|
|
76
|
-
$border-radius-
|
|
77
|
-
$border-radius-
|
|
78
|
-
$border-radius-
|
|
74
|
+
// Only rungs that DIFFER from Bootstrap 5.3 are set: BS is 0.375/0.25/0.5/1/2rem;
|
|
75
|
+
// $border-radius-xl (1rem) and the font-weight ladder match BS and are left alone.
|
|
76
|
+
$border-radius: 0.5rem; // 8px — buttons, inputs, dropdowns (BS 0.375)
|
|
77
|
+
$border-radius-sm: 0.375rem; // 6px (BS 0.25)
|
|
78
|
+
$border-radius-lg: 0.75rem; // 12px — cards, toasts (BS 0.5)
|
|
79
|
+
$border-radius-2xl: 1.5rem; // 24px (BS 2rem via $border-radius-xxl)
|
|
80
|
+
$border-radius-pill: 9999px; // same visual as BS 50rem; explicit for token clarity
|
|
79
81
|
|
|
80
82
|
|
|
81
83
|
// ---- Typography -----------------------------------------------------
|
|
84
|
+
// Font-size base (1rem) and font-weight 300–700 match Bootstrap — not restated.
|
|
85
|
+
// h1/h2/h6 match Bootstrap's $font-size-base multipliers at 1rem — not restated;
|
|
86
|
+
// only h3–h5 are tighter than Bootstrap's scale.
|
|
82
87
|
$font-family-sans-serif: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
|
83
88
|
$font-family-monospace: 'JetBrains Mono', SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
|
84
89
|
|
|
85
|
-
$
|
|
86
|
-
$line-height-base: 1.55;
|
|
90
|
+
$line-height-base: 1.55; // BS 1.5
|
|
87
91
|
|
|
88
|
-
$font-weight
|
|
89
|
-
$font-weight-normal: 400;
|
|
90
|
-
$font-weight-medium: 500;
|
|
91
|
-
$font-weight-semibold: 600;
|
|
92
|
-
$font-weight-bold: 700;
|
|
93
|
-
|
|
94
|
-
$headings-font-weight: 600;
|
|
95
|
-
$headings-line-height: 1.2;
|
|
92
|
+
$headings-font-weight: 600; // BS 500
|
|
96
93
|
$headings-letter-spacing: -0.02em;
|
|
97
94
|
$headings-color: #071437;
|
|
98
95
|
|
|
99
96
|
$display-font-weight: 500;
|
|
100
97
|
$display-line-height: 1.05;
|
|
101
98
|
|
|
102
|
-
$
|
|
103
|
-
$
|
|
104
|
-
$
|
|
105
|
-
$h4-font-size: 1.25rem; // 20px
|
|
106
|
-
$h5-font-size: 1.125rem; // 18px
|
|
107
|
-
$h6-font-size: 1rem; // 16px
|
|
99
|
+
$h3-font-size: 1.5rem; // 24px (BS 1.75rem)
|
|
100
|
+
$h4-font-size: 1.25rem; // 20px (BS 1.5rem)
|
|
101
|
+
$h5-font-size: 1.125rem; // 18px (BS 1.25rem)
|
|
108
102
|
|
|
109
103
|
|
|
110
104
|
// ---- Spacing --------------------------------------------------------
|
|
111
|
-
// Bootstrap
|
|
112
|
-
// for hero / section padding so
|
|
113
|
-
$spacer
|
|
105
|
+
// Bootstrap ladder is 0/.25/.5/1/1.5/3rem ($spacer = 1rem). We replace the map
|
|
106
|
+
// with the same 0–5 rungs plus 6/7/8/10/12 for hero / section padding so
|
|
107
|
+
// utilities like `py-8` exist. No need to restate $spacer itself.
|
|
114
108
|
$spacers: (
|
|
115
109
|
0: 0,
|
|
116
|
-
1:
|
|
117
|
-
2:
|
|
118
|
-
3:
|
|
119
|
-
4:
|
|
120
|
-
5:
|
|
121
|
-
6:
|
|
122
|
-
7:
|
|
123
|
-
8:
|
|
124
|
-
10:
|
|
125
|
-
12:
|
|
110
|
+
1: 0.25rem, // 4px
|
|
111
|
+
2: 0.5rem, // 8px
|
|
112
|
+
3: 1rem, // 16px
|
|
113
|
+
4: 1.5rem, // 24px
|
|
114
|
+
5: 3rem, // 48px
|
|
115
|
+
6: 4.5rem, // 72px
|
|
116
|
+
7: 5rem, // 80px
|
|
117
|
+
8: 6rem, // 96px
|
|
118
|
+
10: 8rem, // 128px
|
|
119
|
+
12: 10rem, // 160px
|
|
126
120
|
);
|
|
127
121
|
|
|
128
|
-
|
|
129
|
-
//
|
|
130
|
-
//
|
|
131
|
-
//
|
|
132
|
-
// breathe properly on large monitors.
|
|
133
|
-
$container-max-widths: (
|
|
134
|
-
sm: 540px,
|
|
135
|
-
md: 720px,
|
|
136
|
-
lg: 960px,
|
|
137
|
-
xl: 1140px,
|
|
138
|
-
xxl: 1320px,
|
|
139
|
-
);
|
|
122
|
+
// $container-max-widths is intentionally NOT overridden — Bootstrap's
|
|
123
|
+
// 540/720/960/1140/1320 map is already what we want. The wider marketing
|
|
124
|
+
// canvas (1512px) is `.container-cloves` + `--wui-container-max` in tokens,
|
|
125
|
+
// not Bootstrap's stepped `.container`.
|
|
140
126
|
|
|
141
127
|
|
|
142
128
|
// ---- Shadows --------------------------------------------------------
|
|
143
|
-
//
|
|
144
|
-
//
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
$
|
|
129
|
+
// Elevation rule (TASK-06080): in-page surfaces are FLAT (borders only).
|
|
130
|
+
// Bootstrap utility ladder (.shadow / .shadow-sm / .shadow-lg) is zeroed so
|
|
131
|
+
// products cannot reintroduce random depth. Floating UI (dropdown / modal /
|
|
132
|
+
// toast) uses the overlay rungs — same values as --wui-shadow-overlay* in tokens.
|
|
133
|
+
$wui-shadow-overlay: 0 8px 28px -6px rgba(7, 20, 55, 0.14);
|
|
134
|
+
$wui-shadow-overlay-lg: 0 24px 60px -16px rgba(7, 20, 55, 0.28);
|
|
135
|
+
|
|
136
|
+
$box-shadow-sm: none;
|
|
137
|
+
$box-shadow: none;
|
|
138
|
+
$box-shadow-lg: none;
|
|
148
139
|
|
|
149
140
|
|
|
150
141
|
// ---- Buttons --------------------------------------------------------
|
|
@@ -162,34 +153,29 @@ $btn-transition: color 0.15s ease, background-color 0.15s ease, border-c
|
|
|
162
153
|
|
|
163
154
|
|
|
164
155
|
// ---- Forms ----------------------------------------------------------
|
|
165
|
-
//
|
|
166
|
-
//
|
|
167
|
-
//
|
|
168
|
-
// Error is driven by `aria-invalid="true"` (no separate .is-invalid
|
|
169
|
-
// class needed for the visual change).
|
|
156
|
+
// Bootstrap `.form-control` is the field skin; post-CSS in wui/_controls.scss
|
|
157
|
+
// layers shared height / hover / focus / invalid on `.form-control` and the
|
|
158
|
+
// `.input` alias together (TASK-06079). Here only $input-* BS vars.
|
|
170
159
|
$input-bg: #FFFFFF;
|
|
171
160
|
$input-disabled-bg: #F5F6FA; // --wui-bg-muted
|
|
172
161
|
$input-border-color: $border-color;
|
|
173
162
|
// $input-focus-border-color is intentionally NOT overridden. Setting it to $primary here
|
|
174
163
|
// captures the LIBRARY's $primary (this file compiles before a product's brand override),
|
|
175
|
-
// leaking indigo into every product
|
|
176
|
-
//
|
|
177
|
-
// var(--wui-primary), which the product overrides at runtime.
|
|
164
|
+
// leaking indigo into every product. Bootstrap's !default derives it from brand $primary;
|
|
165
|
+
// post-CSS focus uses var(--color-primary) so runtime rebrand tracks.
|
|
178
166
|
$input-focus-box-shadow: none; // border IS the focus cue
|
|
179
167
|
$input-focus-color: $body-color;
|
|
180
|
-
$input-padding-y: 0.5rem; //
|
|
181
|
-
$input-padding-x: 0.875rem; // 14px
|
|
182
|
-
$input-border-radius: $border-radius;
|
|
168
|
+
$input-padding-y: 0.5rem; // filler inside --wui-control-height (44px)
|
|
169
|
+
$input-padding-x: 0.875rem; // 14px
|
|
170
|
+
$input-border-radius: $border-radius;
|
|
183
171
|
$input-placeholder-color: #99A1B7; // --wui-text-4
|
|
184
172
|
|
|
185
173
|
|
|
186
174
|
// ---- Cards ----------------------------------------------------------
|
|
187
175
|
$card-border-color: $border-color;
|
|
188
176
|
$card-border-radius: $border-radius-lg;
|
|
189
|
-
// Flat surfaces — no drop shadow on default .card. Depth is
|
|
190
|
-
//
|
|
191
|
-
// utility (in _components.scss) only when a card legitimately
|
|
192
|
-
// needs to sit "above" the page (currently disabled — set to `none`).
|
|
177
|
+
// Flat surfaces — no drop shadow on default .card. Depth is border + tint.
|
|
178
|
+
// `.card-lifted` is a 1px hover translate only (not a shadow).
|
|
193
179
|
$card-box-shadow: none;
|
|
194
180
|
$card-spacer-y: 1.5rem;
|
|
195
181
|
$card-spacer-x: 1.5rem;
|
|
@@ -199,23 +185,26 @@ $card-spacer-x: 1.5rem;
|
|
|
199
185
|
$nav-link-font-weight: 500;
|
|
200
186
|
$dropdown-border-color: $border-color;
|
|
201
187
|
$dropdown-border-radius: $border-radius;
|
|
202
|
-
$dropdown-box-shadow: $
|
|
188
|
+
$dropdown-box-shadow: $wui-shadow-overlay;
|
|
203
189
|
|
|
204
190
|
|
|
205
191
|
// ---- Modals + toasts ------------------------------------------------
|
|
206
192
|
$modal-content-border-color: $border-color;
|
|
207
|
-
$modal-content-border-radius: $border-radius-xl
|
|
208
|
-
$modal-content-box-shadow-xs: $
|
|
193
|
+
$modal-content-border-radius: 1rem; // BS $border-radius-xl (1rem) — literal because we do not restate that rung
|
|
194
|
+
$modal-content-box-shadow-xs: $wui-shadow-overlay-lg;
|
|
209
195
|
|
|
210
196
|
$toast-border-color: $border-color;
|
|
211
197
|
$toast-border-radius: $border-radius-lg;
|
|
212
|
-
$toast-box-shadow: $
|
|
198
|
+
$toast-box-shadow: $wui-shadow-overlay-lg;
|
|
213
199
|
|
|
214
200
|
|
|
215
201
|
// ---- Links ----------------------------------------------------------
|
|
216
|
-
$link-color
|
|
217
|
-
|
|
218
|
-
$
|
|
202
|
+
// $link-color left at Bootstrap's default ($primary) so it tracks brand $primary.
|
|
203
|
+
// Hover is a darkened mix of $primary — never a hard-coded indigo — so a product
|
|
204
|
+
// that sets $primary (or calls wui-brand-primary) gets a matching hover. Approximate
|
|
205
|
+
// of Bootstrap's shift-color($link-color, 20%) without importing BS functions here.
|
|
206
|
+
$link-hover-color: mix(black, $primary, 12%);
|
|
207
|
+
$link-decoration: none; // BS default is underline
|
|
219
208
|
$link-hover-decoration: underline;
|
|
220
209
|
|
|
221
210
|
|
|
@@ -224,8 +213,8 @@ $link-hover-decoration: underline;
|
|
|
224
213
|
// LIBRARY's $primary (this file compiles before a product's brand override), so the ring
|
|
225
214
|
// leaked indigo into every product. Bootstrap's !default `rgba($primary, $focus-ring-opacity)`
|
|
226
215
|
// is evaluated after the brand override, so it tracks the brand correctly.
|
|
227
|
-
$focus-ring-
|
|
228
|
-
$focus-ring-
|
|
216
|
+
// $focus-ring-blur matches BS (0) — not restated.
|
|
217
|
+
$focus-ring-width: 3px; // BS 0.25rem (4px)
|
|
229
218
|
|
|
230
219
|
|
|
231
220
|
// ---- Table ----------------------------------------------------------
|
package/scss/_wui-aliases.scss
CHANGED
|
@@ -97,7 +97,8 @@
|
|
|
97
97
|
--color-scrim: color-mix(in srgb, var(--wui-text-heading) 62%, transparent);
|
|
98
98
|
--color-on-scrim: var(--wui-bg-light);
|
|
99
99
|
|
|
100
|
-
// Elevation — in-page
|
|
100
|
+
// Elevation — in-page flat; only floating overlays lift (matches zeroed BS
|
|
101
|
+
// $box-shadow* utilities and --wui-shadow-card* none — TASK-06080).
|
|
101
102
|
--shadow-sm: none;
|
|
102
103
|
--shadow-md: none;
|
|
103
104
|
--shadow-lg: none;
|
package/scss/wui/_choice.scss
CHANGED
|
@@ -318,7 +318,7 @@
|
|
|
318
318
|
// scrollable modal / table card. Sits above the modal layer.
|
|
319
319
|
.search-select-menu-fixed {
|
|
320
320
|
position: fixed;
|
|
321
|
-
z-index:
|
|
321
|
+
z-index: var(--wui-z-menu);
|
|
322
322
|
right: auto;
|
|
323
323
|
top: auto;
|
|
324
324
|
left: auto;
|
|
@@ -483,7 +483,7 @@
|
|
|
483
483
|
// sits above the modal layer.
|
|
484
484
|
.datepicker-pop {
|
|
485
485
|
position: fixed;
|
|
486
|
-
z-index:
|
|
486
|
+
z-index: var(--wui-z-menu);
|
|
487
487
|
width: 312px;
|
|
488
488
|
max-width: calc(100vw - 16px);
|
|
489
489
|
padding: 18px;
|
|
@@ -801,7 +801,7 @@ button.datepicker-month:hover {
|
|
|
801
801
|
}
|
|
802
802
|
.daterange-pop {
|
|
803
803
|
position: fixed;
|
|
804
|
-
z-index:
|
|
804
|
+
z-index: var(--wui-z-menu);
|
|
805
805
|
width: 620px;
|
|
806
806
|
max-width: calc(100vw - 16px);
|
|
807
807
|
padding: 18px;
|
|
@@ -998,7 +998,7 @@ button.datepicker-month:hover {
|
|
|
998
998
|
// modal layer, matching .search-select-menu-fixed and .datepicker-pop.
|
|
999
999
|
.country-dropdown-menu {
|
|
1000
1000
|
position: fixed;
|
|
1001
|
-
z-index:
|
|
1001
|
+
z-index: var(--wui-z-menu);
|
|
1002
1002
|
width: 320px;
|
|
1003
1003
|
max-width: calc(100vw - 16px);
|
|
1004
1004
|
padding: 4px;
|