@webority/theme 0.8.1 → 0.8.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 +6 -6
- package/scss/wui/_choice.scss +19 -4
- package/scss/wui/_controls.scss +40 -8
- package/scss/wui/_display.scss +21 -5
- package/scss/wui/_flow.scss +14 -6
- package/scss/wui/_media.scss +24 -13
- package/scss/wui/_overlays.scss +8 -1
- package/scss/wui/_typography.scss +9 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webority/theme",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.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
|
@@ -170,9 +170,9 @@
|
|
|
170
170
|
// sizes step font-size, horizontal padding and radius together (vertical size
|
|
171
171
|
// comes from --wui-control-height, so a button lines up with an input). Weight
|
|
172
172
|
// is 600 on every rung — buttons read as a deliberate action, not body text.
|
|
173
|
-
// Medium (default): 15px / 600, 24px side padding,
|
|
173
|
+
// Medium (default): 15px / 600, 24px side padding, 22px squircle radius, 45px tall.
|
|
174
174
|
.btn {
|
|
175
|
-
--bs-btn-border-radius:
|
|
175
|
+
--bs-btn-border-radius: 22px;
|
|
176
176
|
--bs-btn-font-size: 0.9375rem;
|
|
177
177
|
--bs-btn-font-weight: 600;
|
|
178
178
|
--bs-btn-padding-x: 1.5rem;
|
|
@@ -180,10 +180,10 @@
|
|
|
180
180
|
// keep a plain border-radius arc — not a cross-browser design contract.
|
|
181
181
|
corner-shape: squircle;
|
|
182
182
|
}
|
|
183
|
-
// Small: 14px, 18px side padding,
|
|
183
|
+
// Small: 14px, 18px side padding, 17px squircle radius (proportional to md), 35px tall.
|
|
184
184
|
.btn-sm:not(.btn-icon),
|
|
185
185
|
.btn-group-sm > .btn:not(.btn-icon) {
|
|
186
|
-
--bs-btn-border-radius:
|
|
186
|
+
--bs-btn-border-radius: 17px;
|
|
187
187
|
--bs-btn-font-size: 0.875rem;
|
|
188
188
|
--bs-btn-padding-x: 1.125rem;
|
|
189
189
|
display: inline-flex;
|
|
@@ -191,10 +191,10 @@
|
|
|
191
191
|
justify-content: center;
|
|
192
192
|
min-height: 35px;
|
|
193
193
|
}
|
|
194
|
-
// Large: 17px, 32px side padding,
|
|
194
|
+
// Large: 17px, 32px side padding, 27px squircle radius (proportional to md), 55px tall — a spacious CTA.
|
|
195
195
|
.btn-lg:not(.btn-icon),
|
|
196
196
|
.btn-group-lg > .btn:not(.btn-icon) {
|
|
197
|
-
--bs-btn-border-radius:
|
|
197
|
+
--bs-btn-border-radius: 27px;
|
|
198
198
|
--bs-btn-font-size: 1.0625rem;
|
|
199
199
|
--bs-btn-padding-x: 2rem;
|
|
200
200
|
display: inline-flex;
|
package/scss/wui/_choice.scss
CHANGED
|
@@ -894,7 +894,8 @@ button.datepicker-month:hover {
|
|
|
894
894
|
border: 1px solid var(--color-border);
|
|
895
895
|
border-radius: var(--radius);
|
|
896
896
|
corner-shape: squircle;
|
|
897
|
-
|
|
897
|
+
// Match AppInput exactly: muted resting fill that lifts to a clean surface on focus.
|
|
898
|
+
background: var(--color-bg-muted);
|
|
898
899
|
// Clip the inner control to the shell's rounded shape — a full-height child was painting
|
|
899
900
|
// over the squircle border at the bottom, which read as a cut-off bottom edge. The dial
|
|
900
901
|
// dropdown is position:fixed, so it is unaffected by this.
|
|
@@ -907,10 +908,10 @@ button.datepicker-month:hover {
|
|
|
907
908
|
background: var(--color-bg-muted);
|
|
908
909
|
border-color: var(--color-border-strong);
|
|
909
910
|
}
|
|
910
|
-
// Match AppInput's focus: a soft primary border
|
|
911
|
+
// Match AppInput's focus: clean surface fill + a soft primary border.
|
|
911
912
|
.app-phone-number-input .phone-input-wrap:focus-within {
|
|
912
|
-
background: var(--color-
|
|
913
|
-
border-color:
|
|
913
|
+
background: var(--color-surface);
|
|
914
|
+
border-color: var(--wui-primary-30);
|
|
914
915
|
}
|
|
915
916
|
.app-phone-number-input .phone-input-wrap:has(> .input:disabled) {
|
|
916
917
|
background: var(--color-bg-muted);
|
|
@@ -998,6 +999,20 @@ button.datepicker-month:hover {
|
|
|
998
999
|
font-weight: 500;
|
|
999
1000
|
color: var(--color-text);
|
|
1000
1001
|
}
|
|
1002
|
+
// Country-adornment toggles (AppPhoneNumberInput showFlag / showDialCode). Driven
|
|
1003
|
+
// by a host attribute so it survives <wui-phone>'s innerHTML re-renders; the flex
|
|
1004
|
+
// gap collapses on its own, leaving no gap where a hidden glyph sat.
|
|
1005
|
+
.app-phone-number-input wui-phone[hide-flag] [data-flag] {
|
|
1006
|
+
display: none;
|
|
1007
|
+
}
|
|
1008
|
+
.app-phone-number-input wui-phone[hide-dial] [data-dial] {
|
|
1009
|
+
display: none;
|
|
1010
|
+
}
|
|
1011
|
+
// Both hidden → the country toggle is just the chevron; drop its leading pad so
|
|
1012
|
+
// the number sits flush like a plain input's.
|
|
1013
|
+
.app-phone-number-input wui-phone[hide-flag][hide-dial] .phone-country-adornment {
|
|
1014
|
+
padding-left: 10px;
|
|
1015
|
+
}
|
|
1001
1016
|
|
|
1002
1017
|
// Menu, search field and rows all share the .search-select language so the
|
|
1003
1018
|
// country picker reads as the same component family as every other picker.
|
package/scss/wui/_controls.scss
CHANGED
|
@@ -999,7 +999,8 @@ wui-select[compact] {
|
|
|
999
999
|
border: 1px solid var(--color-border);
|
|
1000
1000
|
border-radius: var(--radius-lg);
|
|
1001
1001
|
corner-shape: squircle;
|
|
1002
|
-
|
|
1002
|
+
// Match AppInput exactly: muted resting fill that lifts to a clean surface on focus.
|
|
1003
|
+
background: var(--color-bg-muted);
|
|
1003
1004
|
transition:
|
|
1004
1005
|
border-color 0.12s,
|
|
1005
1006
|
background-color 0.12s;
|
|
@@ -1010,8 +1011,8 @@ wui-select[compact] {
|
|
|
1010
1011
|
border-color: var(--color-border-strong);
|
|
1011
1012
|
}
|
|
1012
1013
|
.num-wrap:focus-within {
|
|
1013
|
-
background: var(--color-
|
|
1014
|
-
border-color:
|
|
1014
|
+
background: var(--color-surface);
|
|
1015
|
+
border-color: var(--wui-primary-30);
|
|
1015
1016
|
}
|
|
1016
1017
|
.num-wrap:has(.num-input.error) {
|
|
1017
1018
|
border-color: var(--color-danger);
|
|
@@ -1019,25 +1020,34 @@ wui-select[compact] {
|
|
|
1019
1020
|
|
|
1020
1021
|
// Numeric input inside the stepper — plain text field, no native spinner.
|
|
1021
1022
|
// Flows seamlessly between the stepper buttons; the wrapper carries the border.
|
|
1023
|
+
// The value reads as the segmented centre cell — centred + semibold like the
|
|
1024
|
+
// reference: minus | value | plus, three even cells divided by the button borders.
|
|
1022
1025
|
.num-wrap .num-input {
|
|
1023
1026
|
flex: 1;
|
|
1024
1027
|
border: none;
|
|
1025
1028
|
border-radius: 0;
|
|
1026
1029
|
background: transparent;
|
|
1027
1030
|
min-width: 0;
|
|
1031
|
+
text-align: center;
|
|
1032
|
+
font-weight: 600;
|
|
1033
|
+
color: var(--color-text);
|
|
1028
1034
|
}
|
|
1029
1035
|
.num-wrap .num-input:focus {
|
|
1030
1036
|
box-shadow: none;
|
|
1031
1037
|
}
|
|
1032
1038
|
|
|
1033
1039
|
// Stepper buttons — decrease/increase the value by step.
|
|
1034
|
-
// Positioned left and right
|
|
1035
|
-
// control is disabled.
|
|
1040
|
+
// Positioned left (minus, :first-child) and right (plus, :last-child) of the
|
|
1041
|
+
// input; disabled at min/max or when the control is disabled. Each carries the
|
|
1042
|
+
// divider on its input-facing edge so the value sits in its own segment.
|
|
1036
1043
|
.num-btn {
|
|
1037
1044
|
display: grid;
|
|
1038
1045
|
place-items: center;
|
|
1039
|
-
width:
|
|
1040
|
-
height: 100
|
|
1046
|
+
width: 44px;
|
|
1047
|
+
// Fill the field height and centre the glyph. `height: 100%` resolved to auto
|
|
1048
|
+
// against the wrap's content-based height and left the button icon-tall, pinned
|
|
1049
|
+
// to the top; align-self:stretch fills the full field so place-items centres it.
|
|
1050
|
+
align-self: stretch;
|
|
1041
1051
|
border: none;
|
|
1042
1052
|
background: transparent;
|
|
1043
1053
|
padding: 0;
|
|
@@ -1064,10 +1074,32 @@ wui-select[compact] {
|
|
|
1064
1074
|
cursor: not-allowed;
|
|
1065
1075
|
opacity: 0.5;
|
|
1066
1076
|
}
|
|
1067
|
-
|
|
1077
|
+
// Segment dividers: minus divides on its right, plus on its left — so the value
|
|
1078
|
+
// cell is bounded on both sides. (DOM order is minus, input, [unit], plus on both
|
|
1079
|
+
// surfaces, so :first-child / :last-child land on the two buttons.)
|
|
1080
|
+
.num-btn:first-child {
|
|
1081
|
+
border-right: 1px solid var(--color-border);
|
|
1082
|
+
}
|
|
1083
|
+
.num-btn:last-child {
|
|
1068
1084
|
border-left: 1px solid var(--color-border);
|
|
1069
1085
|
}
|
|
1070
1086
|
|
|
1087
|
+
// ── Size variants ── the inner input carries .input-sm / .input-lg (height +
|
|
1088
|
+
// font), the wrapper carries .num-wrap-sm / .num-wrap-lg to scale the button
|
|
1089
|
+
// cells to match. Default (md) uses the base 44px cell above.
|
|
1090
|
+
.num-wrap-sm .num-btn {
|
|
1091
|
+
width: 36px;
|
|
1092
|
+
}
|
|
1093
|
+
.num-wrap-sm .num-input {
|
|
1094
|
+
font-size: 13px;
|
|
1095
|
+
}
|
|
1096
|
+
.num-wrap-lg .num-btn {
|
|
1097
|
+
width: 52px;
|
|
1098
|
+
}
|
|
1099
|
+
.num-wrap-lg .num-input {
|
|
1100
|
+
font-size: 16px;
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1071
1103
|
// Affix (unit) in the num-wrap — a trailing pill after the input.
|
|
1072
1104
|
.num-wrap .affix {
|
|
1073
1105
|
background: var(--color-bg-muted);
|
package/scss/wui/_display.scss
CHANGED
|
@@ -63,7 +63,9 @@
|
|
|
63
63
|
}
|
|
64
64
|
.kpi-value {
|
|
65
65
|
margin-top: 6px;
|
|
66
|
-
|
|
66
|
+
// The value ("main heading") size flows from one var, so a size tier (sm/md/lg,
|
|
67
|
+
// spotlight) or a custom `valueSize` (px) can drive it. Default (md) is 28px.
|
|
68
|
+
font-size: var(--wui-kpi-value-size, 28px);
|
|
67
69
|
font-weight: 700;
|
|
68
70
|
// Large numerals need negative tracking to stop reading as separate digits;
|
|
69
71
|
// tabular figures stop a live-updating value from shifting width.
|
|
@@ -133,17 +135,29 @@
|
|
|
133
135
|
background: var(--color-warning-soft);
|
|
134
136
|
}
|
|
135
137
|
|
|
138
|
+
// Compact size — dense dashboards and tight cards. Shrinks the value + chrome.
|
|
139
|
+
.kpi.kpi-sm {
|
|
140
|
+
padding: 12px 14px;
|
|
141
|
+
--wui-kpi-value-size: 22px;
|
|
142
|
+
}
|
|
143
|
+
.kpi.kpi-sm .kpi-label {
|
|
144
|
+
font-size: 12px;
|
|
145
|
+
}
|
|
146
|
+
.kpi.kpi-sm .kpi-icon {
|
|
147
|
+
width: 32px;
|
|
148
|
+
height: 32px;
|
|
149
|
+
margin-bottom: 8px;
|
|
150
|
+
}
|
|
151
|
+
|
|
136
152
|
// Hero size — the single headline stat above a dashboard. Enlarges the value and its
|
|
137
153
|
// chrome; orthogonal to variant/inline/attention, so it composes with all of them.
|
|
138
154
|
.kpi.kpi-lg {
|
|
139
155
|
padding: 20px;
|
|
156
|
+
--wui-kpi-value-size: 40px;
|
|
140
157
|
}
|
|
141
158
|
.kpi.kpi-lg .kpi-label {
|
|
142
159
|
font-size: 14px;
|
|
143
160
|
}
|
|
144
|
-
.kpi.kpi-lg .kpi-value {
|
|
145
|
-
font-size: 40px;
|
|
146
|
-
}
|
|
147
161
|
.kpi.kpi-lg .kpi-icon {
|
|
148
162
|
width: 44px;
|
|
149
163
|
height: 44px;
|
|
@@ -158,6 +172,7 @@
|
|
|
158
172
|
grid-template-columns: minmax(0, 1fr) auto;
|
|
159
173
|
column-gap: 16px;
|
|
160
174
|
padding: 22px 24px;
|
|
175
|
+
--wui-kpi-value-size: 44px;
|
|
161
176
|
}
|
|
162
177
|
.kpi.kpi-spotlight .kpi-icon {
|
|
163
178
|
grid-column: 2;
|
|
@@ -183,8 +198,9 @@
|
|
|
183
198
|
// The editorial serif is this variant's signature (see the reference tile), so the value gets
|
|
184
199
|
// a serif stack directly — not --wui-font-display, which defaults to the body sans and so would
|
|
185
200
|
// never read as serif. A product that wants its own face overrides this one selector.
|
|
201
|
+
// Size comes from --wui-kpi-value-size (44px default, set on the spotlight root above), so a
|
|
202
|
+
// custom `valueSize` (px) can tame a too-large headline.
|
|
186
203
|
font-family: Georgia, 'Times New Roman', 'Noto Serif', serif;
|
|
187
|
-
font-size: 44px;
|
|
188
204
|
line-height: 1;
|
|
189
205
|
font-weight: 600;
|
|
190
206
|
}
|
package/scss/wui/_flow.scss
CHANGED
|
@@ -830,16 +830,24 @@ wui-wizard-step[hidden] {
|
|
|
830
830
|
// A resting min-height so the footer doesn't jump as steps of different length
|
|
831
831
|
// swap in; content taller than this simply grows the panel.
|
|
832
832
|
min-height: 96px;
|
|
833
|
+
// A rounded squircle card around the step content. The surface (border + fill +
|
|
834
|
+
// padding) is what makes the radius visible — a radius on a border/background-less
|
|
835
|
+
// box shows nothing.
|
|
836
|
+
padding: 20px 24px;
|
|
837
|
+
border: 1px solid var(--color-border);
|
|
838
|
+
border-radius: 22px;
|
|
839
|
+
corner-shape: squircle;
|
|
840
|
+
background: var(--color-surface);
|
|
833
841
|
}
|
|
834
842
|
.wizard-footer {
|
|
835
|
-
// The
|
|
836
|
-
//
|
|
837
|
-
//
|
|
838
|
-
|
|
839
|
-
|
|
843
|
+
// The Back/Skip/Next/Finish bar sits at the END of the wizard content — NOT
|
|
844
|
+
// viewport-pinned. A transparent sticky bar (the old behaviour) pinned to the
|
|
845
|
+
// viewport bottom collided with a page/app footer below the wizard, burying the
|
|
846
|
+
// buttons behind it. Inline keeps them in the flow, always clear of a page footer.
|
|
847
|
+
// (For a wizard inside its OWN fixed-height scroll panel, a product can opt back
|
|
848
|
+
// into sticky on its container.)
|
|
840
849
|
margin-top: 24px;
|
|
841
850
|
padding: 16px 0;
|
|
842
|
-
z-index: 1;
|
|
843
851
|
}
|
|
844
852
|
.wizard-footer-actions {
|
|
845
853
|
display: flex;
|
package/scss/wui/_media.scss
CHANGED
|
@@ -527,16 +527,23 @@
|
|
|
527
527
|
border-radius: var(--radius-lg);
|
|
528
528
|
corner-shape: squircle;
|
|
529
529
|
border: 1px solid var(--color-border);
|
|
530
|
-
|
|
530
|
+
// Match AppInput: muted resting fill, lifts to a clean surface on focus.
|
|
531
|
+
background: var(--color-bg-muted);
|
|
531
532
|
overflow: hidden;
|
|
532
533
|
cursor: pointer;
|
|
533
534
|
transition:
|
|
534
535
|
border-color 0.12s,
|
|
535
536
|
box-shadow 0.12s;
|
|
536
537
|
}
|
|
537
|
-
.file-input:hover {
|
|
538
|
+
.file-input:hover:not(:focus-within) {
|
|
539
|
+
background: var(--color-bg-muted);
|
|
538
540
|
border-color: var(--color-border-strong);
|
|
539
541
|
}
|
|
542
|
+
.file-input:focus-within {
|
|
543
|
+
background: var(--color-surface);
|
|
544
|
+
border-color: var(--wui-primary-30);
|
|
545
|
+
box-shadow: none;
|
|
546
|
+
}
|
|
540
547
|
.file-input-btn {
|
|
541
548
|
display: inline-flex;
|
|
542
549
|
align-items: center;
|
|
@@ -579,21 +586,25 @@
|
|
|
579
586
|
width: 100%;
|
|
580
587
|
padding: 20px;
|
|
581
588
|
text-align: center;
|
|
582
|
-
|
|
583
|
-
border
|
|
589
|
+
// Match AppInput: muted resting fill + resting border (dashed kept as the dropzone
|
|
590
|
+
// affordance), border-strong on hover, primary border + surface lift on focus/drag.
|
|
591
|
+
background: var(--color-bg-muted);
|
|
592
|
+
border: 1px dashed var(--color-border);
|
|
584
593
|
transition:
|
|
585
594
|
border-color 0.15s ease,
|
|
586
595
|
background-color 0.15s ease;
|
|
587
596
|
}
|
|
588
|
-
// Hover
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
597
|
+
// Hover mirrors AppInput hover — border-strong, fill unchanged.
|
|
598
|
+
.file-input.file-input-tall:hover:not(:focus-within):not(.dragging) {
|
|
599
|
+
border-color: var(--color-border-strong);
|
|
600
|
+
background: var(--color-bg-muted);
|
|
601
|
+
}
|
|
602
|
+
// Focus and drag-over mirror AppInput focus — soft primary border, lift onto a clean surface.
|
|
592
603
|
.file-input.file-input-tall:focus-within,
|
|
593
604
|
.file-input.file-input-tall:active,
|
|
594
605
|
.file-input.file-input-tall.dragging {
|
|
595
|
-
border-color:
|
|
596
|
-
background: var(--color-
|
|
606
|
+
border-color: var(--wui-primary-30);
|
|
607
|
+
background: var(--color-surface);
|
|
597
608
|
box-shadow: none;
|
|
598
609
|
}
|
|
599
610
|
// A rejected file (wrong type / too large) turns the dropzone border danger to match the
|
|
@@ -639,11 +650,11 @@
|
|
|
639
650
|
.file-input.file-input-tall.has-files:hover,
|
|
640
651
|
.file-input.file-input-tall.has-files:focus-within {
|
|
641
652
|
border-color: var(--color-border-strong);
|
|
642
|
-
background: var(--color-bg-
|
|
653
|
+
background: var(--color-bg-muted);
|
|
643
654
|
}
|
|
644
655
|
.file-input.file-input-tall.has-files.dragging {
|
|
645
|
-
border-color:
|
|
646
|
-
background: var(--color-
|
|
656
|
+
border-color: var(--wui-primary-30);
|
|
657
|
+
background: var(--color-surface);
|
|
647
658
|
}
|
|
648
659
|
// Width presets — put a .file-w-* class on the field (React className / Razor class) to cap the
|
|
649
660
|
// dropzone to a fixed width instead of the full column. Mirror of the datepicker .date-w-* set.
|
package/scss/wui/_overlays.scss
CHANGED
|
@@ -15,8 +15,15 @@
|
|
|
15
15
|
// Do NOT put layout on backdropClassName — that targets a sibling, not
|
|
16
16
|
// .modal.
|
|
17
17
|
.modal-backdrop.wui-modal-dim {
|
|
18
|
-
|
|
18
|
+
// Frost the page behind the dialog — the blur is the star, so the dim is kept
|
|
19
|
+
// SOFT (a heavy scrim would flatten the blur into a muddy grey). A lighter dim
|
|
20
|
+
// over a strong blur reads as clean frosted glass; the modal is still clearly
|
|
21
|
+
// the one live surface. The dialog sits in `.modal` (a higher z-index sibling),
|
|
22
|
+
// so it is never blurred.
|
|
23
|
+
background: color-mix(in srgb, var(--color-scrim) 55%, transparent);
|
|
19
24
|
z-index: var(--wui-z-modal-backdrop);
|
|
25
|
+
backdrop-filter: blur(12px);
|
|
26
|
+
-webkit-backdrop-filter: blur(12px);
|
|
20
27
|
}
|
|
21
28
|
.modal.wui-modal-shell {
|
|
22
29
|
--bs-modal-bg: transparent;
|
|
@@ -68,8 +68,17 @@
|
|
|
68
68
|
}
|
|
69
69
|
.chip-ic {
|
|
70
70
|
display: inline-flex;
|
|
71
|
+
align-items: center;
|
|
72
|
+
justify-content: center;
|
|
73
|
+
line-height: 0;
|
|
71
74
|
color: var(--color-text-subtle);
|
|
72
75
|
}
|
|
76
|
+
// Bootstrap Icons carry a -.125em baseline nudge meant for inline-with-text use;
|
|
77
|
+
// inside the chip's flex row it just drops the glyph below the label's centre.
|
|
78
|
+
// Reset it so a library-icon leading glyph lines up with the label.
|
|
79
|
+
.chip-ic .bi::before {
|
|
80
|
+
vertical-align: middle;
|
|
81
|
+
}
|
|
73
82
|
.chip-avatar {
|
|
74
83
|
display: inline-flex;
|
|
75
84
|
width: 18px;
|