@webority/theme 0.9.0 → 0.9.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/dist/webority-theme.css +1 -1
- package/package.json +1 -1
- package/scss/_components.scss +21 -0
- package/scss/wui/_choice.scss +22 -5
- package/scss/wui/_controls.scss +28 -3
- package/scss/wui/_overlays.scss +10 -15
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webority/theme",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.2",
|
|
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
|
@@ -109,6 +109,25 @@
|
|
|
109
109
|
--bs-btn-disabled-border-color: var(--wui-danger-strong);
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
+
// Secondary-danger — the destructive counterpart of .btn-secondary: a soft red wash
|
|
113
|
+
// instead of a solid red fill, for a quieter destructive action (e.g. a "Remove" that
|
|
114
|
+
// shouldn't shout like a solid .btn-danger). Mirrors .btn-secondary exactly — low-alpha
|
|
115
|
+
// tint deepening on hover/press, no border — but keyed off the danger tokens. The label
|
|
116
|
+
// uses --wui-danger-text (the AA-safe error red designed to read on a light red tint),
|
|
117
|
+
// not the brighter --color-danger. Disabled falls through to the shared neutral-grey
|
|
118
|
+
// state below (it is not .btn-danger), like .btn-secondary.
|
|
119
|
+
.btn-secondary-danger {
|
|
120
|
+
--bs-btn-color: var(--wui-danger-text);
|
|
121
|
+
--bs-btn-bg: color-mix(in srgb, var(--color-danger) 12%, transparent);
|
|
122
|
+
--bs-btn-border-color: transparent;
|
|
123
|
+
--bs-btn-hover-color: var(--wui-danger-text);
|
|
124
|
+
--bs-btn-hover-bg: color-mix(in srgb, var(--color-danger) 18%, transparent);
|
|
125
|
+
--bs-btn-hover-border-color: transparent;
|
|
126
|
+
--bs-btn-active-color: var(--wui-danger-text);
|
|
127
|
+
--bs-btn-active-bg: color-mix(in srgb, var(--color-danger) 26%, transparent);
|
|
128
|
+
--bs-btn-active-border-color: transparent;
|
|
129
|
+
}
|
|
130
|
+
|
|
112
131
|
// Soft neutral tinted button — a quieter alternative to .btn-light for a secondary
|
|
113
132
|
// action that shouldn't compete with a primary/danger CTA in the same row.
|
|
114
133
|
.btn-subtle {
|
|
@@ -177,6 +196,8 @@
|
|
|
177
196
|
// key the wash and the label off the accent (text) colour so the hue still shows.
|
|
178
197
|
.btn-secondary.is-loading:disabled,
|
|
179
198
|
.btn-secondary.is-loading.disabled,
|
|
199
|
+
.btn-secondary-danger.is-loading:disabled,
|
|
200
|
+
.btn-secondary-danger.is-loading.disabled,
|
|
180
201
|
.btn-ghost.is-loading:disabled,
|
|
181
202
|
.btn-ghost.is-loading.disabled,
|
|
182
203
|
.btn-subtle.is-loading:disabled,
|
package/scss/wui/_choice.scss
CHANGED
|
@@ -107,6 +107,12 @@
|
|
|
107
107
|
opacity: 1;
|
|
108
108
|
transform: scale(1);
|
|
109
109
|
}
|
|
110
|
+
// The tick reads a touch bolder than the icon's default 1.5 hairline, so the confirmation
|
|
111
|
+
// stays crisp at the small top-corner size (CSS beats the glyph's stroke-width attribute;
|
|
112
|
+
// applies on both surfaces since both render the same stroke-based check).
|
|
113
|
+
.struct-card-check svg path {
|
|
114
|
+
stroke-width: 2.25;
|
|
115
|
+
}
|
|
110
116
|
|
|
111
117
|
// Tile variant: big centered illustration + label. Opt in with
|
|
112
118
|
// className="struct-card-tile".
|
|
@@ -171,8 +177,10 @@
|
|
|
171
177
|
cursor: not-allowed;
|
|
172
178
|
opacity: 0.6;
|
|
173
179
|
}
|
|
174
|
-
.search-select-control:hover:not(:disabled):not(.open) {
|
|
180
|
+
.search-select-control:hover:not(:disabled):not(.open):not([aria-invalid="true"]) {
|
|
175
181
|
// Not while open — an open control keeps its active (primary) border, not the grey hover one.
|
|
182
|
+
// Not while invalid — an errored control (aria-invalid mirrored from the host) holds its red
|
|
183
|
+
// border on hover rather than reverting to the grey hover one.
|
|
176
184
|
border-color: var(--color-border-strong);
|
|
177
185
|
}
|
|
178
186
|
.search-select-control.open {
|
|
@@ -484,7 +492,12 @@
|
|
|
484
492
|
--wui-datepicker-width: 100%;
|
|
485
493
|
}
|
|
486
494
|
.datepicker.open .datepicker-trigger {
|
|
487
|
-
|
|
495
|
+
// While the calendar is open the trigger reads as a focused field — clean white surface, not
|
|
496
|
+
// the muted resting fill. Opening moves focus INTO the popup, so :focus drops off the trigger;
|
|
497
|
+
// this .open rule keeps it white (matching .search-select-control.open) instead of snapping
|
|
498
|
+
// back to grey the moment the dropdown appears. It stays white on close too (_close refocuses
|
|
499
|
+
// the trigger → :focus), greying only on an outside click that blurs it.
|
|
500
|
+
background-color: var(--color-surface);
|
|
488
501
|
border-color: color-mix(in srgb, var(--color-primary) 30%, transparent);
|
|
489
502
|
box-shadow: none;
|
|
490
503
|
}
|
|
@@ -805,7 +818,8 @@ button.datepicker-month:hover {
|
|
|
805
818
|
color: var(--color-text-subtle);
|
|
806
819
|
}
|
|
807
820
|
.daterange.open .daterange-trigger {
|
|
808
|
-
|
|
821
|
+
// Stay white while the two-month popover is open — see the note on .datepicker.open above.
|
|
822
|
+
background-color: var(--color-surface);
|
|
809
823
|
border-color: color-mix(in srgb, var(--color-primary) 30%, transparent);
|
|
810
824
|
box-shadow: none;
|
|
811
825
|
}
|
|
@@ -906,7 +920,9 @@ button.datepicker-month:hover {
|
|
|
906
920
|
border-color 0.12s,
|
|
907
921
|
background-color 0.12s;
|
|
908
922
|
}
|
|
909
|
-
|
|
923
|
+
// Not while invalid — an errored control holds its red border/fill on hover (the host carries
|
|
924
|
+
// aria-invalid, so scope the hover treatment to a non-invalid host).
|
|
925
|
+
.app-phone-number-input wui-phone:not([aria-invalid="true"]) .phone-input-wrap:hover:not(:focus-within) {
|
|
910
926
|
background: var(--color-field-bg);
|
|
911
927
|
border-color: var(--color-border-strong);
|
|
912
928
|
}
|
|
@@ -1256,7 +1272,8 @@ wui-timepicker[aria-invalid="true"] .timepicker.open .timepicker-trigger {
|
|
|
1256
1272
|
--wui-timepicker-width: 100%;
|
|
1257
1273
|
}
|
|
1258
1274
|
.timepicker.open .timepicker-trigger {
|
|
1259
|
-
|
|
1275
|
+
// Stay white while the time list is open — see the note on .datepicker.open above.
|
|
1276
|
+
background-color: var(--color-surface);
|
|
1260
1277
|
border-color: color-mix(in srgb, var(--color-primary) 30%, transparent);
|
|
1261
1278
|
box-shadow: none;
|
|
1262
1279
|
}
|
package/scss/wui/_controls.scss
CHANGED
|
@@ -52,6 +52,23 @@
|
|
|
52
52
|
user-select: none;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
// Checkbox / radio / switch hint & error sit BELOW the label on their own line, indented to
|
|
56
|
+
// align under the label text (past the glyph + gap) — not inline beside it. `.form-check` is a
|
|
57
|
+
// flex row for glyph+label; a full-width flex basis wraps the message to a second line.
|
|
58
|
+
.form-check {
|
|
59
|
+
flex-wrap: wrap;
|
|
60
|
+
--wui-check-hint-indent: 28px; // 20px glyph + 8px gap
|
|
61
|
+
}
|
|
62
|
+
.form-switch {
|
|
63
|
+
--wui-check-hint-indent: 48px; // 40px track + 8px gap
|
|
64
|
+
}
|
|
65
|
+
.form-check > .field-hint,
|
|
66
|
+
.form-check > .field-error {
|
|
67
|
+
flex-basis: 100%;
|
|
68
|
+
margin-top: 2px;
|
|
69
|
+
padding-left: var(--wui-check-hint-indent);
|
|
70
|
+
}
|
|
71
|
+
|
|
55
72
|
// Glyph — shared by BS form-check-input and the wui-check alias.
|
|
56
73
|
.form-check-input,
|
|
57
74
|
.wui-check,
|
|
@@ -299,9 +316,13 @@ textarea.form-control.autosize {
|
|
|
299
316
|
overflow: hidden;
|
|
300
317
|
}
|
|
301
318
|
// Hover/error guards: without them the hover fill repaints over an invalid border.
|
|
319
|
+
// `:not([aria-expanded="true"])` on the `.input` line: a combobox/dialog trigger whose popup is
|
|
320
|
+
// OPEN (datepicker/date-range/time-picker triggers set aria-expanded on the trigger, but carry
|
|
321
|
+
// their `.open` class on the WRAPPER, not the trigger) must keep its open white fill — without
|
|
322
|
+
// this the resting-hover grey repaints over it the moment the cursor sits on the open trigger.
|
|
302
323
|
.form-control:hover:not(:focus):not(:disabled):not([readonly]):not([aria-invalid="true"]):not(.is-invalid):not(.error),
|
|
303
324
|
.form-select:hover:not(:focus):not(:disabled):not([aria-invalid="true"]):not(.is-invalid):not(.error),
|
|
304
|
-
.input:hover:not(:focus):not(:disabled):not([readonly]):not([aria-invalid="true"]):not(.is-invalid):not(.error):not(.open),
|
|
325
|
+
.input:hover:not(:focus):not(:disabled):not([readonly]):not([aria-invalid="true"]):not(.is-invalid):not(.error):not(.open):not([aria-expanded="true"]),
|
|
305
326
|
.select:hover:not(:focus):not(:disabled):not([aria-invalid="true"]):not(.is-invalid):not(.error),
|
|
306
327
|
.textarea:hover:not(:focus):not(:disabled):not([readonly]):not([aria-invalid="true"]):not(.is-invalid):not(.error) {
|
|
307
328
|
background-color: var(--color-field-bg);
|
|
@@ -1052,7 +1073,9 @@ wui-select[compact] {
|
|
|
1052
1073
|
background-color 0.12s;
|
|
1053
1074
|
overflow: hidden;
|
|
1054
1075
|
}
|
|
1055
|
-
|
|
1076
|
+
// Not while invalid — an errored control holds its red border/fill on hover rather than
|
|
1077
|
+
// reverting to the grey hover one (matches AppInput, whose hover rule excludes the error state).
|
|
1078
|
+
.num-wrap:hover:not(:focus-within):not(:has(.num-input.error)):not(:has(.num-input.is-invalid)):not(:has(.num-input[aria-invalid="true"])) {
|
|
1056
1079
|
background: var(--color-field-bg);
|
|
1057
1080
|
border-color: var(--color-border-strong);
|
|
1058
1081
|
}
|
|
@@ -1286,7 +1309,9 @@ wui-select[compact] {
|
|
|
1286
1309
|
pointer-events: none;
|
|
1287
1310
|
}
|
|
1288
1311
|
.choice-chip.checked {
|
|
1289
|
-
border
|
|
1312
|
+
// Match AppChoiceCard's checked border: a soft primary-30 edge, not the
|
|
1313
|
+
// full-strength primary line (they read as the same selection language).
|
|
1314
|
+
border-color: color-mix(in srgb, var(--color-primary) 30%, transparent);
|
|
1290
1315
|
background: var(--color-primary-soft);
|
|
1291
1316
|
color: var(--color-primary);
|
|
1292
1317
|
}
|
package/scss/wui/_overlays.scss
CHANGED
|
@@ -309,12 +309,6 @@
|
|
|
309
309
|
line-height: 0;
|
|
310
310
|
margin-bottom: 22px;
|
|
311
311
|
}
|
|
312
|
-
// Lift the badge off the modal surface with a soft outer shadow. `drop-shadow` traces
|
|
313
|
-
// the SVG's circular alpha (a `box-shadow` would cast a square), and takes no spread —
|
|
314
|
-
// so this is authored spread-free rather than reusing the `--wui-shadow-overlay` token.
|
|
315
|
-
.wui-confirm-icon svg {
|
|
316
|
-
filter: drop-shadow(0 10px 18px rgba(7, 20, 55, 0.18));
|
|
317
|
-
}
|
|
318
312
|
// Icon size tracks the copy: a title+message dialog keeps the full 80px badge (set on
|
|
319
313
|
// the element), but a lone title (no message) is one line and gets a smaller badge.
|
|
320
314
|
// `.wui-confirm-msg` is a real element rendered only when a message exists, so `:has()`
|
|
@@ -345,17 +339,18 @@
|
|
|
345
339
|
.wui-modal-footer:has(.wui-confirm-actions) {
|
|
346
340
|
border-top: none;
|
|
347
341
|
padding-top: 0;
|
|
348
|
-
|
|
342
|
+
// The full-width CTA row makes the footer's insets read as a frame, so the gap below the
|
|
343
|
+
// buttons matches the 22px on their left and right (the base footer's 16px bottom looked
|
|
344
|
+
// cramped against the equal side gaps).
|
|
345
|
+
padding-bottom: 22px;
|
|
346
|
+
}
|
|
347
|
+
// Layout ONLY — the two CTAs share the row equally. Their chrome (radius, height, type
|
|
348
|
+
// scale, weight, padding) comes entirely from AppButton, so a confirm button reads identically
|
|
349
|
+
// to an AppButton anywhere else in the app. No separate button styling lives here: the dialog
|
|
350
|
+
// used to re-skin its buttons (10px radius, 14px/500 type, forced height), which made the confirm
|
|
351
|
+
// CTAs look like a different button than every other AppButton.
|
|
349
352
|
.wui-confirm-actions .btn {
|
|
350
353
|
flex: 1;
|
|
351
|
-
min-height: var(--wui-control-height);
|
|
352
|
-
height: var(--wui-control-height);
|
|
353
|
-
border-radius: var(--radius);
|
|
354
|
-
corner-shape: squircle;
|
|
355
|
-
padding-left: 16px;
|
|
356
|
-
padding-right: 16px;
|
|
357
|
-
font-size: 14px;
|
|
358
|
-
font-weight: 500;
|
|
359
354
|
}
|
|
360
355
|
|
|
361
356
|
// ── Tooltip ──
|