@webority/theme 0.12.3 → 0.12.5
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/wui/_choice.scss +40 -10
- package/scss/wui/_controls.scss +13 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webority/theme",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.5",
|
|
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/wui/_choice.scss
CHANGED
|
@@ -353,14 +353,21 @@
|
|
|
353
353
|
height: 40px;
|
|
354
354
|
border: 1px solid var(--color-border);
|
|
355
355
|
border-radius: var(--radius);
|
|
356
|
-
|
|
356
|
+
// AppInput's field model: muted resting fill that lifts to a clean surface on focus.
|
|
357
|
+
background: var(--color-field-bg);
|
|
357
358
|
color: var(--color-text-subtle);
|
|
358
359
|
}
|
|
359
360
|
.search-select-search {
|
|
360
361
|
position: relative;
|
|
361
362
|
}
|
|
363
|
+
// Hover and focus follow AppInput, as the phone country search does: a stronger border on hover,
|
|
364
|
+
// then a clean surface fill + soft primary border on focus.
|
|
365
|
+
.search-select-search:hover:not(:focus-within) {
|
|
366
|
+
border-color: var(--color-border-strong);
|
|
367
|
+
}
|
|
362
368
|
.search-select-search:focus-within {
|
|
363
|
-
background: var(--color-
|
|
369
|
+
background: var(--color-surface);
|
|
370
|
+
border-color: var(--wui-primary-30);
|
|
364
371
|
}
|
|
365
372
|
.search-select-search:focus-within svg {
|
|
366
373
|
color: var(--color-primary);
|
|
@@ -395,6 +402,10 @@
|
|
|
395
402
|
color: var(--color-text);
|
|
396
403
|
background: transparent;
|
|
397
404
|
}
|
|
405
|
+
// AppInput's placeholder colour, not the browser default grey.
|
|
406
|
+
.search-select-input::placeholder {
|
|
407
|
+
color: var(--color-text-subtle);
|
|
408
|
+
}
|
|
398
409
|
.search-select-options {
|
|
399
410
|
max-height: 300px;
|
|
400
411
|
overflow-y: auto;
|
|
@@ -927,9 +938,13 @@ button.datepicker-month:hover {
|
|
|
927
938
|
border-color 0.12s,
|
|
928
939
|
background-color 0.12s;
|
|
929
940
|
}
|
|
930
|
-
// Not while invalid — an errored control holds its red border
|
|
931
|
-
//
|
|
932
|
-
.
|
|
941
|
+
// Not while invalid — an errored control holds its white fill and red border on hover. Two
|
|
942
|
+
// sources mark it invalid: the `error` prop sets aria-invalid on the host, and the element's own
|
|
943
|
+
// live validation marks only the inner input. Exclude both, or hovering a live-validation error
|
|
944
|
+
// turns the field grey.
|
|
945
|
+
.app-phone-number-input
|
|
946
|
+
wui-phone:not([aria-invalid="true"])
|
|
947
|
+
.phone-input-wrap:hover:not(:focus-within):not(:has(> .input.error)):not(:has(> .input.is-invalid)):not(:has(> .input[aria-invalid="true"])) {
|
|
933
948
|
background: var(--color-field-bg);
|
|
934
949
|
border-color: var(--color-border-strong);
|
|
935
950
|
}
|
|
@@ -944,11 +959,20 @@ button.datepicker-month:hover {
|
|
|
944
959
|
}
|
|
945
960
|
.app-phone-number-input .phone-input-wrap:has(.input.error),
|
|
946
961
|
.app-phone-number-input .phone-input-wrap:has(.input.is-invalid),
|
|
962
|
+
.app-phone-number-input .phone-input-wrap:has(.input[aria-invalid="true"]),
|
|
947
963
|
// An explicit `error` prop sets aria-invalid on the host <wui-phone> (React + Razor); redden the
|
|
948
964
|
// shell for it too, not just the internal live-validation state above.
|
|
949
965
|
.app-phone-number-input wui-phone[aria-invalid="true"] .phone-input-wrap {
|
|
950
|
-
// Match AppInput's
|
|
966
|
+
// Match AppInput's invalid state exactly: clean surface fill + soft danger border (danger at
|
|
967
|
+
// 30%, mirroring primary-30 focus).
|
|
968
|
+
background: var(--color-surface);
|
|
951
969
|
border-color: color-mix(in srgb, var(--color-danger) 30%, transparent);
|
|
970
|
+
// AppInput's trailing error glyph, drawn on the shell (the inner input stays transparent).
|
|
971
|
+
padding-right: 41px;
|
|
972
|
+
background-image: $wui-field-error-glyph;
|
|
973
|
+
background-repeat: no-repeat;
|
|
974
|
+
background-position: right 14px center;
|
|
975
|
+
background-size: 18px;
|
|
952
976
|
}
|
|
953
977
|
// The live-validation error renders INSIDE <wui-phone> (after .phone-input-wrap), not as a
|
|
954
978
|
// direct child of .field — so .field's 4px column gap can't separate it from the control, and
|
|
@@ -969,6 +993,7 @@ wui-date-range[aria-invalid="true"] .daterange-trigger,
|
|
|
969
993
|
wui-date-range[aria-invalid="true"] .daterange.open .daterange-trigger,
|
|
970
994
|
wui-timepicker[aria-invalid="true"] .timepicker-trigger,
|
|
971
995
|
wui-timepicker[aria-invalid="true"] .timepicker.open .timepicker-trigger {
|
|
996
|
+
background: var(--color-surface);
|
|
972
997
|
border-color: color-mix(in srgb, var(--color-danger) 30%, transparent);
|
|
973
998
|
}
|
|
974
999
|
// The inner control drops its own chrome — the shell carries it.
|
|
@@ -1139,7 +1164,8 @@ wui-timepicker[aria-invalid="true"] .timepicker.open .timepicker-trigger {
|
|
|
1139
1164
|
border-radius: var(--radius);
|
|
1140
1165
|
font-size: 14px;
|
|
1141
1166
|
color: var(--color-text);
|
|
1142
|
-
|
|
1167
|
+
// AppInput's field model: muted resting fill that lifts to a clean surface on focus.
|
|
1168
|
+
background: var(--color-field-bg);
|
|
1143
1169
|
outline: none;
|
|
1144
1170
|
}
|
|
1145
1171
|
.dropdown-search-input:hover:not(:focus) {
|
|
@@ -1147,10 +1173,14 @@ wui-timepicker[aria-invalid="true"] .timepicker.open .timepicker-trigger {
|
|
|
1147
1173
|
border-color: var(--color-border-strong);
|
|
1148
1174
|
}
|
|
1149
1175
|
// Border is the focus cue everywhere else in the system — no glow ring here.
|
|
1150
|
-
//
|
|
1176
|
+
// AppInput's exact focus: clean surface fill + its soft primary border token.
|
|
1151
1177
|
.dropdown-search-input:focus {
|
|
1152
|
-
background: var(--color-
|
|
1153
|
-
border-color:
|
|
1178
|
+
background: var(--color-surface);
|
|
1179
|
+
border-color: var(--wui-primary-30);
|
|
1180
|
+
}
|
|
1181
|
+
// AppInput's placeholder colour, not the browser default grey.
|
|
1182
|
+
.dropdown-search-input::placeholder {
|
|
1183
|
+
color: var(--color-text-subtle);
|
|
1154
1184
|
}
|
|
1155
1185
|
.country-list-scroll {
|
|
1156
1186
|
max-height: 250px;
|
package/scss/wui/_controls.scss
CHANGED
|
@@ -325,9 +325,14 @@ textarea.form-control.autosize {
|
|
|
325
325
|
// OPEN (datepicker/date-range/time-picker triggers set aria-expanded on the trigger, but carry
|
|
326
326
|
// their `.open` class on the WRAPPER, not the trigger) must keep its open white fill — without
|
|
327
327
|
// this the resting-hover grey repaints over it the moment the cursor sits on the open trigger.
|
|
328
|
+
// `:not(.phone-input-wrap > .input)`: the phone shell owns the fill and border, so its inner input
|
|
329
|
+
// must stay transparent. This rule's specificity beats that shell's transparent rule, so without
|
|
330
|
+
// the exclusion the number half of an errored phone field turned grey on hover.
|
|
328
331
|
.form-control:hover:not(:focus):not(:disabled):not([readonly]):not([aria-invalid="true"]):not(.is-invalid):not(.error),
|
|
329
332
|
.form-select:hover:not(:focus):not(:disabled):not([aria-invalid="true"]):not(.is-invalid):not(.error),
|
|
330
|
-
.input:hover:not(:focus):not(:disabled):not([readonly]):not([aria-invalid="true"]):not(.is-invalid):not(.error):not(.open):not([aria-expanded="true"])
|
|
333
|
+
.input:hover:not(:focus):not(:disabled):not([readonly]):not([aria-invalid="true"]):not(.is-invalid):not(.error):not(.open):not([aria-expanded="true"]):not(
|
|
334
|
+
.phone-input-wrap > .input
|
|
335
|
+
),
|
|
331
336
|
.select:hover:not(:focus):not(:disabled):not([aria-invalid="true"]):not(.is-invalid):not(.error),
|
|
332
337
|
.textarea:hover:not(:focus):not(:disabled):not([readonly]):not([aria-invalid="true"]):not(.is-invalid):not(.error) {
|
|
333
338
|
background-color: var(--color-field-bg);
|
|
@@ -590,6 +595,9 @@ textarea.form-control.autosize {
|
|
|
590
595
|
pointer-events: none;
|
|
591
596
|
}
|
|
592
597
|
|
|
598
|
+
// The trailing error glyph, shared by every field that shows one (the phone shell draws it too).
|
|
599
|
+
$wui-field-error-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23F8285A' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cline x1='12' y1='8' x2='12' y2='12'/%3E%3Cline x1='12' y1='16' x2='12.01' y2='16'/%3E%3C/svg%3E");
|
|
600
|
+
|
|
593
601
|
// Trailing error glyph on a PLAIN field only (child combinator). Shell-wrapped
|
|
594
602
|
// inputs sit one level deeper and keep their own right edge.
|
|
595
603
|
// Note: background-image here re-applies after the shared invalid rule zeroed BS's SVG.
|
|
@@ -600,7 +608,7 @@ textarea.form-control.autosize {
|
|
|
600
608
|
.field > .input.is-invalid,
|
|
601
609
|
.field > .input[aria-invalid="true"] {
|
|
602
610
|
padding-right: 41px;
|
|
603
|
-
background-image:
|
|
611
|
+
background-image: $wui-field-error-glyph;
|
|
604
612
|
background-repeat: no-repeat;
|
|
605
613
|
background-position: right 14px center;
|
|
606
614
|
background-size: 18px;
|
|
@@ -1141,7 +1149,9 @@ wui-select[compact] {
|
|
|
1141
1149
|
.num-wrap:has(.num-input[aria-invalid="true"]) {
|
|
1142
1150
|
// Soft invalid border — match AppInput / AppPhoneNumberInput exactly (danger at 30%,
|
|
1143
1151
|
// mirroring the primary-30 focus border), not the solid full-strength danger this used to
|
|
1144
|
-
// carry, so every field's error border reads the same light red.
|
|
1152
|
+
// carry, so every field's error border reads the same light red. Clean surface fill, as
|
|
1153
|
+
// AppInput's invalid state.
|
|
1154
|
+
background: var(--color-surface);
|
|
1145
1155
|
border-color: color-mix(in srgb, var(--color-danger) 30%, transparent);
|
|
1146
1156
|
}
|
|
1147
1157
|
|