@webority/theme 0.127.0 → 0.129.0
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/README.md +8 -3
- package/dist/published-theme.json +2 -1
- package/dist/purge-safelist.json +55 -53
- package/dist/webority-theme.css +1 -1
- package/package.json +2 -2
- package/scss/_bootstrap.generated.scss +1 -1
- package/scss/_components.scss +33 -3
- package/scss/_tokens.generated.scss +395 -23
- package/scss/_variables.scss +12 -15
- package/scss/_wui-components.scss +7 -1
- package/scss/_wui-core.scss +7 -0
- package/scss/wui/_account-switcher.scss +70 -0
- package/scss/wui/_auth-layout.scss +77 -0
- package/scss/wui/_card-options.scss +45 -0
- package/scss/wui/_card.scss +5 -3
- package/scss/wui/_cell.scss +56 -0
- package/scss/wui/_choice.scss +6 -8
- package/scss/wui/_controls.scss +8 -14
- package/scss/wui/_data.scss +6 -1
- package/scss/wui/_dialog-motion.scss +90 -0
- package/scss/wui/_display.scss +12 -1
- package/scss/wui/_field-busy.scss +50 -0
- package/scss/wui/_field-floor.scss +0 -4
- package/scss/wui/_field-sizes.scss +55 -0
- package/scss/wui/_floating.scss +9 -2
- package/scss/wui/_inline-edit.scss +6 -0
- package/scss/wui/_interaction.scss +9 -1
- package/scss/wui/_overlays.scss +18 -1
- package/scss/wui/_pagination.scss +20 -2
- package/scss/wui/_rich-text.scss +5 -0
- package/scss/wui/_shell-parts.scss +17 -0
- package/scss/wui/_shell.scss +65 -0
- package/scss/wui/_typography.scss +25 -7
- package/scss/wui/_utilities.scss +35 -0
- package/scss/wui/_workspace.scss +12 -0
- package/token-meanings.json +15 -0
- package/scss/wui/_chat.scss +0 -156
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
@import "wui/navigation";
|
|
37
37
|
@import "wui/nav-list";
|
|
38
38
|
@import "wui/card";
|
|
39
|
+
@import "wui/card-options";
|
|
39
40
|
@import "wui/empty-state";
|
|
40
41
|
@import "wui/data";
|
|
41
42
|
@import "wui/pagination";
|
|
@@ -89,6 +90,7 @@
|
|
|
89
90
|
@import "wui/filter-popover";
|
|
90
91
|
@import "wui/metric-strip";
|
|
91
92
|
@import "wui/due-date";
|
|
93
|
+
@import "wui/cell";
|
|
92
94
|
|
|
93
95
|
// Country flags are NOT part of this aggregate. The 245 `.wui-flag-*` rules are about 187KB raw
|
|
94
96
|
// (38KB Brotli) of inlined SVG, and most sites never render a phone field or country picker.
|
|
@@ -96,15 +98,16 @@
|
|
|
96
98
|
// <wui-phone> and <wui-country-select> show an empty grey box where the flag should be.
|
|
97
99
|
@import "wui/shell";
|
|
98
100
|
@import "wui/shell-parts";
|
|
101
|
+
@import "wui/account-switcher";
|
|
99
102
|
@import "wui/dock";
|
|
100
103
|
@import "wui/consent-banner";
|
|
101
104
|
@import "wui/file-viewer";
|
|
102
105
|
@import "wui/lightbox";
|
|
103
106
|
@import "wui/toolbar";
|
|
104
107
|
@import "wui/theme-toggle";
|
|
108
|
+
@import "wui/auth-layout";
|
|
105
109
|
@import "wui/tree";
|
|
106
110
|
@import "wui/floating";
|
|
107
|
-
@import "wui/chat";
|
|
108
111
|
@import "wui/code-block";
|
|
109
112
|
// After `overlays`: anchors the shared modal shell to the top when it holds the palette card.
|
|
110
113
|
@import "wui/command-palette";
|
|
@@ -114,6 +117,9 @@
|
|
|
114
117
|
@import "wui/hover-card";
|
|
115
118
|
@import "wui/notification-center";
|
|
116
119
|
@import "wui/whats-new";
|
|
120
|
+
// Before field-floor, which restates the font sizes the size steps set.
|
|
121
|
+
@import "wui/field-busy";
|
|
122
|
+
@import "wui/field-sizes";
|
|
117
123
|
// After every component partial: restates each field's own font size with a 16px floor on touch screens.
|
|
118
124
|
@import "wui/field-floor";
|
|
119
125
|
// After every component partial: the shared focus ring and pressed wash settle ties with their hover rules.
|
package/scss/_wui-core.scss
CHANGED
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
@import "wui/navigation";
|
|
29
29
|
@import "wui/nav-list";
|
|
30
30
|
@import "wui/card";
|
|
31
|
+
@import "wui/card-options";
|
|
31
32
|
@import "wui/empty-state";
|
|
32
33
|
@import "wui/data";
|
|
33
34
|
@import "wui/pagination";
|
|
@@ -75,6 +76,7 @@
|
|
|
75
76
|
@import "wui/filter-popover";
|
|
76
77
|
@import "wui/metric-strip";
|
|
77
78
|
@import "wui/due-date";
|
|
79
|
+
@import "wui/cell";
|
|
78
80
|
|
|
79
81
|
// Country flags are NOT part of this layer. The 245 `.wui-flag-*` rules are about 187KB raw
|
|
80
82
|
// (38KB Brotli) of inlined SVG, and most sites never render a phone field or country picker.
|
|
@@ -82,10 +84,12 @@
|
|
|
82
84
|
// <wui-phone> and <wui-country-select> show an empty grey box where the flag should be.
|
|
83
85
|
@import "wui/shell";
|
|
84
86
|
@import "wui/shell-parts";
|
|
87
|
+
@import "wui/account-switcher";
|
|
85
88
|
@import "wui/consent-banner";
|
|
86
89
|
@import "wui/lightbox";
|
|
87
90
|
@import "wui/toolbar";
|
|
88
91
|
@import "wui/theme-toggle";
|
|
92
|
+
@import "wui/auth-layout";
|
|
89
93
|
@import "wui/floating";
|
|
90
94
|
@import "wui/code-block";
|
|
91
95
|
@import "wui/context-menu";
|
|
@@ -93,6 +97,9 @@
|
|
|
93
97
|
@import "wui/hover-card";
|
|
94
98
|
@import "wui/notification-center";
|
|
95
99
|
@import "wui/whats-new";
|
|
100
|
+
// Before field-floor, which restates the font sizes the size steps set.
|
|
101
|
+
@import "wui/field-busy";
|
|
102
|
+
@import "wui/field-sizes";
|
|
96
103
|
// After every component partial: restates each field's own font size with a 16px floor on touch screens.
|
|
97
104
|
@import "wui/field-floor";
|
|
98
105
|
// After every component partial: the shared focus ring and pressed wash settle ties with their hover rules.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// Account switcher: shared by React <AppAccountSwitcher> and Razor <app-account-switcher>.
|
|
2
|
+
// Rows are Bootstrap dropdown items inside the shell's user menu (.wui-usermenu-menu, see
|
|
3
|
+
// _shell-parts.scss), so they inherit that menu's padding and hover. Every rule here is scoped
|
|
4
|
+
// under .wui-account-switcher so it wins over Bootstrap's .dropdown-item specificity.
|
|
5
|
+
|
|
6
|
+
.wui-account-switcher {
|
|
7
|
+
padding-block: var(--wui-space-xxs);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.wui-account-switcher-label {
|
|
11
|
+
padding: var(--wui-space-sm);
|
|
12
|
+
font-size: var(--wui-fs-sm);
|
|
13
|
+
color: var(--color-text-muted);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.wui-account-switcher-list {
|
|
17
|
+
display: flex;
|
|
18
|
+
flex-direction: column;
|
|
19
|
+
max-height: 40vh;
|
|
20
|
+
overflow-y: auto;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.wui-account-switcher .wui-account-switcher-option {
|
|
24
|
+
display: flex;
|
|
25
|
+
align-items: center;
|
|
26
|
+
gap: var(--wui-space-sm);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.wui-account-switcher-option-text {
|
|
30
|
+
flex: 1 1 auto;
|
|
31
|
+
min-width: 0;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.wui-account-switcher-option-name {
|
|
35
|
+
display: block;
|
|
36
|
+
overflow: hidden;
|
|
37
|
+
text-overflow: ellipsis;
|
|
38
|
+
white-space: nowrap;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.wui-account-switcher-option-note {
|
|
42
|
+
display: block;
|
|
43
|
+
overflow: hidden;
|
|
44
|
+
font-size: var(--wui-fs-xs);
|
|
45
|
+
color: var(--color-text-muted);
|
|
46
|
+
text-overflow: ellipsis;
|
|
47
|
+
white-space: nowrap;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.wui-account-switcher-badge {
|
|
51
|
+
flex: none;
|
|
52
|
+
padding: var(--wui-space-xxs) var(--wui-space-sm);
|
|
53
|
+
border-radius: var(--wui-radius-pill);
|
|
54
|
+
background: var(--color-bg-subtle);
|
|
55
|
+
color: var(--color-text-muted);
|
|
56
|
+
font-size: var(--wui-fs-xs);
|
|
57
|
+
font-weight: var(--wui-fw-semibold);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// The current account keeps its tint through hover, so the tick is never the only cue.
|
|
61
|
+
.wui-account-switcher .wui-account-switcher-option.is-active,
|
|
62
|
+
.wui-account-switcher .wui-account-switcher-option.is-active:hover {
|
|
63
|
+
background: var(--color-primary-soft);
|
|
64
|
+
color: var(--color-primary-text);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.wui-account-switcher-tick {
|
|
68
|
+
flex: none;
|
|
69
|
+
color: var(--color-primary-text);
|
|
70
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// ── Auth layout ──
|
|
2
|
+
// AppAuthLayout / <app-auth-layout>: a sign-in page, centred by default. The form panel sits in
|
|
3
|
+
// the middle of the page; `.wui-auth-split` (variant="split") adds an aside on the right from the
|
|
4
|
+
// lg tier up, and below lg the aside is hidden so the form is alone and centred.
|
|
5
|
+
// <div class="wui-auth wui-auth-centred|wui-auth-split">
|
|
6
|
+
// <div class="wui-auth-main"><div class="wui-auth-panel">logo, body, footer</div></div>
|
|
7
|
+
// <aside class="wui-auth-aside">…</aside>
|
|
8
|
+
// The aside follows the form in the DOM and sits on the right; nothing reorders it.
|
|
9
|
+
//
|
|
10
|
+
// Part of the wui-components layer, see _wui-components.scss for load order.
|
|
11
|
+
|
|
12
|
+
.wui-auth {
|
|
13
|
+
display: grid;
|
|
14
|
+
grid-template-columns: minmax(0, 1fr);
|
|
15
|
+
min-height: var(--wui-auth-min-height, 100dvh);
|
|
16
|
+
background: var(--color-bg);
|
|
17
|
+
color: var(--color-text);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.wui-auth-main {
|
|
21
|
+
display: flex;
|
|
22
|
+
align-items: center;
|
|
23
|
+
justify-content: center;
|
|
24
|
+
min-width: 0;
|
|
25
|
+
padding: var(--wui-space-xl) var(--wui-space-lg);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.wui-auth-panel {
|
|
29
|
+
display: flex;
|
|
30
|
+
flex-direction: column;
|
|
31
|
+
gap: var(--wui-space-xl);
|
|
32
|
+
width: 100%;
|
|
33
|
+
max-width: var(--wui-auth-width, 420px);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.wui-auth-logo {
|
|
37
|
+
display: flex;
|
|
38
|
+
justify-content: center;
|
|
39
|
+
}
|
|
40
|
+
.wui-auth-logo img,
|
|
41
|
+
.wui-auth-logo svg {
|
|
42
|
+
max-width: 100%;
|
|
43
|
+
max-height: 48px;
|
|
44
|
+
height: auto;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.wui-auth-body {
|
|
48
|
+
padding: var(--wui-space-xl);
|
|
49
|
+
border: 1px solid var(--color-border);
|
|
50
|
+
border-radius: var(--wui-radius-lg);
|
|
51
|
+
background: var(--color-surface);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.wui-auth-footer {
|
|
55
|
+
color: var(--color-text-muted);
|
|
56
|
+
font-size: var(--wui-fs-sm);
|
|
57
|
+
text-align: center;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.wui-auth-aside {
|
|
61
|
+
display: none;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
@include media-breakpoint-up(lg) {
|
|
65
|
+
.wui-auth-split {
|
|
66
|
+
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
|
|
67
|
+
}
|
|
68
|
+
.wui-auth-split .wui-auth-aside {
|
|
69
|
+
display: flex;
|
|
70
|
+
flex-direction: column;
|
|
71
|
+
justify-content: center;
|
|
72
|
+
min-width: 0;
|
|
73
|
+
padding: var(--wui-space-3xl);
|
|
74
|
+
background: var(--color-primary-soft);
|
|
75
|
+
color: var(--color-text);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// Card options: `flush` (content runs to the card's rounded corners) and `divided`
|
|
2
|
+
// (a rule under the header).
|
|
3
|
+
//
|
|
4
|
+
// Part of the wui-components layer, see _wui-components.scss for the load
|
|
5
|
+
// order. This partial loads directly after `wui/card`, because its padding
|
|
6
|
+
// rules must win over the header rule in _card.scss.
|
|
7
|
+
|
|
8
|
+
// A consumer class can set --wui-card-divider-color to retune the rule.
|
|
9
|
+
.card {
|
|
10
|
+
--wui-card-divider-color: var(--color-border);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// The card's own border-radius clips the content, so a table or image keeps the corners.
|
|
14
|
+
.card-flush {
|
|
15
|
+
overflow: hidden;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// A 1px hairline stays raw: it is a rule, not a spacing or type value.
|
|
19
|
+
.card-divided > .card-header {
|
|
20
|
+
border-bottom: 1px solid var(--wui-card-divider-color);
|
|
21
|
+
}
|
|
22
|
+
// _card.scss removes the body's top padding under any header. A divided card keeps the
|
|
23
|
+
// body's padding step, so each padding class restores its own value here.
|
|
24
|
+
.card-divided > .card-header + .card-body {
|
|
25
|
+
padding-top: var(--bs-card-spacer-y);
|
|
26
|
+
}
|
|
27
|
+
.card-pad-sm.card-divided > .card-header + .card-body {
|
|
28
|
+
padding-top: var(--wui-space-md);
|
|
29
|
+
}
|
|
30
|
+
.card-pad-lg.card-divided > .card-header + .card-body {
|
|
31
|
+
padding-top: var(--wui-space-xl);
|
|
32
|
+
}
|
|
33
|
+
.card-pad-none.card-divided > .card-header + .card-body {
|
|
34
|
+
padding-top: 0;
|
|
35
|
+
}
|
|
36
|
+
.card-compact.card-divided > .card-header + .card-body {
|
|
37
|
+
padding-top: var(--wui-space-lg);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Last, so it wins every tie: flush clears the body only, as `.card-pad-none` does.
|
|
41
|
+
// The header and footer keep their padding.
|
|
42
|
+
.card.card-flush > .card-body,
|
|
43
|
+
.card.card-flush > .card-header + .card-body {
|
|
44
|
+
padding: 0;
|
|
45
|
+
}
|
package/scss/wui/_card.scss
CHANGED
|
@@ -46,11 +46,13 @@
|
|
|
46
46
|
}
|
|
47
47
|
// Bootstrap has its own `.card-title` (a bare margin-bottom) — these override it,
|
|
48
48
|
// so they must stay in the layer that loads after Bootstrap.
|
|
49
|
-
// A product sets its title type with --wui-card-title-fs and
|
|
50
|
-
.card-title
|
|
49
|
+
// A product sets its title type with --wui-card-title-font-family, -fs, -fw and -lh.
|
|
50
|
+
.card-title,
|
|
51
|
+
.result-title {
|
|
51
52
|
margin: 0;
|
|
53
|
+
font-family: var(--wui-card-title-font-family, inherit);
|
|
52
54
|
font-size: var(--wui-card-title-fs, 16px);
|
|
53
|
-
font-weight: 600;
|
|
55
|
+
font-weight: var(--wui-card-title-fw, 600);
|
|
54
56
|
line-height: var(--wui-card-title-lh, 1.3);
|
|
55
57
|
color: var(--color-text);
|
|
56
58
|
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// ── Cell ──
|
|
2
|
+
// AppCell / <app-cell>: one table or list cell with a primary line and an optional secondary line.
|
|
3
|
+
// Markup contract, shared by both surfaces and the rules below:
|
|
4
|
+
//
|
|
5
|
+
// Component: React AppCell Razor <app-cell>
|
|
6
|
+
// Props: primary string|node Razor: attribute `primary`, or the tag child content when `primary` is absent
|
|
7
|
+
// secondary string|node Razor: attribute `secondary`; absent or empty draws no second line
|
|
8
|
+
// href string when set the primary is an <a>, else a <span>
|
|
9
|
+
// mono bool, false monospace on the primary line only
|
|
10
|
+
// numeric bool, false right-aligned, tabular digits, both lines
|
|
11
|
+
// className string React; Razor uses plain `class`
|
|
12
|
+
// Markup (identical on both surfaces, class order fixed):
|
|
13
|
+
// <div class="wui-cell [wui-cell-numeric] [wui-cell-mono] [extra]" data-wui="AppCell">
|
|
14
|
+
// <a|span class="wui-cell-primary" [href="..."]>PRIMARY</a|span>
|
|
15
|
+
// <span class="wui-cell-secondary">SECONDARY</span> (omitted when no secondary)
|
|
16
|
+
// </div>
|
|
17
|
+
// Empty primary (null, undefined, "" and no child content) draws the placeholder "-" (React EMPTY_PLACEHOLDER from ../lib/emptyValue, Razor EmptyValue.Placeholder).
|
|
18
|
+
// 0 is real data and draws as "0".
|
|
19
|
+
// Classes (all new, all wui-*): wui-cell, wui-cell-primary, wui-cell-secondary, wui-cell-numeric, wui-cell-mono
|
|
20
|
+
//
|
|
21
|
+
// Part of the wui-components layer, see _wui-components.scss for load order.
|
|
22
|
+
|
|
23
|
+
.wui-cell {
|
|
24
|
+
display: block;
|
|
25
|
+
min-width: 0;
|
|
26
|
+
line-height: var(--wui-lh-heading);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.wui-cell-primary {
|
|
30
|
+
display: block;
|
|
31
|
+
font-weight: var(--wui-fw-medium);
|
|
32
|
+
color: var(--color-text);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
a.wui-cell-primary {
|
|
36
|
+
text-decoration: none;
|
|
37
|
+
|
|
38
|
+
&:hover {
|
|
39
|
+
text-decoration: underline;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.wui-cell-secondary {
|
|
44
|
+
display: block;
|
|
45
|
+
font-size: var(--wui-fs-sm);
|
|
46
|
+
color: var(--color-text-muted);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.wui-cell-numeric {
|
|
50
|
+
text-align: right;
|
|
51
|
+
font-variant-numeric: tabular-nums;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.wui-cell-mono > .wui-cell-primary {
|
|
55
|
+
font-family: var(--wui-font-mono);
|
|
56
|
+
}
|
package/scss/wui/_choice.scss
CHANGED
|
@@ -336,13 +336,6 @@
|
|
|
336
336
|
font-size: 16px;
|
|
337
337
|
border-radius: var(--wui-field-lg-radius);
|
|
338
338
|
}
|
|
339
|
-
// xl: the 52px select, the same height as an AppInput at size="xl". A literal height, as on the input.
|
|
340
|
-
.wui-search-select-xl .search-select-control {
|
|
341
|
-
height: 52px;
|
|
342
|
-
min-height: 52px;
|
|
343
|
-
font-size: 16px;
|
|
344
|
-
border-radius: var(--wui-field-lg-radius);
|
|
345
|
-
}
|
|
346
339
|
// Multi-select grows with its chips, so a size sets the FLOOR (min-height from the rule
|
|
347
340
|
// above) but never a fixed height — reset height:auto so a second row of chips can appear.
|
|
348
341
|
.search-select-sm .search-select-multi,
|
|
@@ -1238,7 +1231,8 @@ wui-timepicker[aria-invalid="true"] .timepicker.open .timepicker-trigger {
|
|
|
1238
1231
|
// NOT scoped under `.country-dropdown` — <wui-phone> renders the toggle inside
|
|
1239
1232
|
// `.phone-country-adornment`, with no such wrapper. Scoping it there left the
|
|
1240
1233
|
// button on raw UA styling (2px outset border + grey fill) inside the field.
|
|
1241
|
-
.country-toggle
|
|
1234
|
+
.country-toggle,
|
|
1235
|
+
.wui-phone-prefix {
|
|
1242
1236
|
display: flex;
|
|
1243
1237
|
align-items: center;
|
|
1244
1238
|
gap: 6px;
|
|
@@ -1276,6 +1270,10 @@ wui-timepicker[aria-invalid="true"] .timepicker.open .timepicker-trigger {
|
|
|
1276
1270
|
cursor: not-allowed;
|
|
1277
1271
|
opacity: var(--wui-disabled-opacity);
|
|
1278
1272
|
}
|
|
1273
|
+
// A locked country: the dial code is a static prefix, laid out like the toggle but not a control.
|
|
1274
|
+
.wui-phone-prefix {
|
|
1275
|
+
cursor: default;
|
|
1276
|
+
}
|
|
1279
1277
|
// Flag glyphs come from the generated .wui-flag-* classes (_flags.scss).
|
|
1280
1278
|
.app-phone-number-input .phone-chevron {
|
|
1281
1279
|
color: var(--color-text-muted);
|
package/scss/wui/_controls.scss
CHANGED
|
@@ -479,15 +479,6 @@
|
|
|
479
479
|
font-size: 16px;
|
|
480
480
|
border-radius: var(--wui-field-lg-radius);
|
|
481
481
|
}
|
|
482
|
-
// xl (size="xl"): the 52px control for large forms. A literal height, because the control-height
|
|
483
|
-
// ladder stops at 44px and its tokens live in the theme's token file. A floating label needs no
|
|
484
|
-
// rule of its own: it centres on the field's box, so it stays inside at 52px.
|
|
485
|
-
.wui-input-xl {
|
|
486
|
-
height: 52px;
|
|
487
|
-
padding: 9px 16px;
|
|
488
|
-
font-size: 16px;
|
|
489
|
-
border-radius: var(--wui-field-lg-radius);
|
|
490
|
-
}
|
|
491
482
|
.textarea,
|
|
492
483
|
textarea.form-control {
|
|
493
484
|
height: auto;
|
|
@@ -676,6 +667,8 @@ textarea.form-control.autosize {
|
|
|
676
667
|
// Tighten the space above the message: .field's 10px gap → effective 8px, without
|
|
677
668
|
// touching the label→control gap.
|
|
678
669
|
margin-top: -2px;
|
|
670
|
+
// Start-aligned, so a message under a centred container sits under the field's edge, not its middle.
|
|
671
|
+
text-align: start;
|
|
679
672
|
}
|
|
680
673
|
|
|
681
674
|
// The message line under a field: the hint and the error share one grid cell, so the error takes
|
|
@@ -915,8 +908,7 @@ $wui-field-error-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/
|
|
|
915
908
|
--wui-input-icon-size: 14px;
|
|
916
909
|
--wui-input-icon-gap: 10px;
|
|
917
910
|
}
|
|
918
|
-
.input-icon:has(> .input-lg)
|
|
919
|
-
.input-icon:has(> .wui-input-xl) {
|
|
911
|
+
.input-icon:has(> .input-lg) {
|
|
920
912
|
--wui-input-icon-slot: 48px;
|
|
921
913
|
--wui-input-icon-size: 18px;
|
|
922
914
|
--wui-input-icon-gap: 14px;
|
|
@@ -1069,6 +1061,8 @@ $wui-field-error-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/
|
|
|
1069
1061
|
// Soft-filled at rest, white on focus — one shared fill for the whole control so the
|
|
1070
1062
|
// prefix/suffix and the input body are always the SAME colour combination as the field.
|
|
1071
1063
|
background: var(--color-field-bg);
|
|
1064
|
+
// Clip the square inner input to the wrapper's rounded corners on hover and focus.
|
|
1065
|
+
overflow: clip;
|
|
1072
1066
|
transition:
|
|
1073
1067
|
border-color 0.12s ease,
|
|
1074
1068
|
background-color 0.12s ease;
|
|
@@ -1091,6 +1085,8 @@ $wui-field-error-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/
|
|
|
1091
1085
|
border: 0;
|
|
1092
1086
|
border-radius: 0;
|
|
1093
1087
|
background: transparent;
|
|
1088
|
+
// The wrapper's focus border is the cue (.input-affixed:focus-within above), so the inner outline would only poke past the corners.
|
|
1089
|
+
outline: none;
|
|
1094
1090
|
}
|
|
1095
1091
|
// A select in the affixed shell (AppSelect prefix/suffix): the custom element is the flex
|
|
1096
1092
|
// item, and its inner .input control already loses its own border through the rule above.
|
|
@@ -1250,6 +1246,7 @@ $wui-field-error-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/
|
|
|
1250
1246
|
margin-top: 2px;
|
|
1251
1247
|
font-size: 12px;
|
|
1252
1248
|
color: var(--color-text-subtle);
|
|
1249
|
+
text-align: start;
|
|
1253
1250
|
}
|
|
1254
1251
|
// Character counter — a right-aligned count under the field; turns danger at the limit.
|
|
1255
1252
|
.field-count {
|
|
@@ -1470,9 +1467,6 @@ wui-select[compact] {
|
|
|
1470
1467
|
.input-with-unit .num-input.input-lg {
|
|
1471
1468
|
height: calc(var(--wui-control-lg) - 2px);
|
|
1472
1469
|
}
|
|
1473
|
-
.input-with-unit .num-input.wui-input-xl {
|
|
1474
|
-
height: calc(52px - 2px);
|
|
1475
|
-
}
|
|
1476
1470
|
.input-with-unit .num-input:focus {
|
|
1477
1471
|
box-shadow: none;
|
|
1478
1472
|
}
|
package/scss/wui/_data.scss
CHANGED
|
@@ -97,10 +97,11 @@
|
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
// ── Table ──
|
|
100
|
-
// DataTable cell helpers
|
|
100
|
+
// DataTable cell helpers. End-aligned cells use tabular digits so the figures in a column line up.
|
|
101
101
|
.table-ledger .wui-cell-end,
|
|
102
102
|
.table-ledger thead th.wui-cell-end {
|
|
103
103
|
text-align: right;
|
|
104
|
+
font-variant-numeric: tabular-nums;
|
|
104
105
|
}
|
|
105
106
|
|
|
106
107
|
// Row expansion (renderExpanded) — a narrow leading toggle column, a chevron that rotates when
|
|
@@ -226,8 +227,12 @@
|
|
|
226
227
|
.table-ledger tbody tr:focus-within {
|
|
227
228
|
--bs-table-bg-state: var(--color-bg-muted);
|
|
228
229
|
}
|
|
230
|
+
// The identity block is a flex child of its cell: without a zero floor it keeps a long email's full
|
|
231
|
+
// width inside a phone card and the subline's truncation never starts. Column sizing is unaffected,
|
|
232
|
+
// because a min-width of zero lowers no min-content contribution.
|
|
229
233
|
.table-ledger .u-meta {
|
|
230
234
|
gap: 2px;
|
|
235
|
+
min-width: 0;
|
|
231
236
|
}
|
|
232
237
|
.table-ledger .u-name {
|
|
233
238
|
min-width: 0;
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
// so the slide never runs underneath it. Close stays Bootstrap's own quick fade of the modal.
|
|
11
11
|
// Side panels (offcanvas, drawers) keep their slide: they come from an edge by nature.
|
|
12
12
|
//
|
|
13
|
+
// The status icon in a dialog header springs in with the dialog (rules below).
|
|
13
14
|
// Imported after menu-motion, whose wui-menu-zoom keyframes it reuses.
|
|
14
15
|
|
|
15
16
|
:root {
|
|
@@ -27,8 +28,97 @@
|
|
|
27
28
|
animation: var(--wui-dialog-anim) var(--wui-dialog-anim-duration) var(--wui-dialog-anim-ease);
|
|
28
29
|
}
|
|
29
30
|
|
|
31
|
+
// The three beats of an SVG tone (error) run 600ms end to end and overlap, so the icon reads as
|
|
32
|
+
// one movement. The rules key on position, so a new SVG tone inherits the same beats.
|
|
33
|
+
// The origin is the icon's centre, not the viewBox corner, so every scale grows in place.
|
|
34
|
+
:root:not([data-wui-dialog-motion="slide"]) .modal.show wui-status-icon {
|
|
35
|
+
display: inline-flex;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
:root:not([data-wui-dialog-motion="slide"]) .modal.show wui-status-icon > svg > rect,
|
|
39
|
+
:root:not([data-wui-dialog-motion="slide"]) .modal.show wui-status-icon > svg > g {
|
|
40
|
+
transform-box: view-box;
|
|
41
|
+
transform-origin: 87px 87px;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
:root:not([data-wui-dialog-motion="slide"]) .modal.show wui-status-icon > svg > rect:first-child {
|
|
45
|
+
animation: wui-dialog-icon-halo 260ms var(--wui-ease-out) 0ms both;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
:root:not([data-wui-dialog-motion="slide"]) .modal.show wui-status-icon > svg > rect:nth-child(2) {
|
|
49
|
+
animation: wui-dialog-icon-ring 300ms var(--wui-ease-out) 140ms both;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
:root:not([data-wui-dialog-motion="slide"]) .modal.show wui-status-icon > svg > g {
|
|
53
|
+
animation: wui-dialog-icon-core 340ms var(--wui-ease-elastic) 260ms both;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Raster tones get one beat because they have no parts to stage.
|
|
57
|
+
:root:not([data-wui-dialog-motion="slide"]) .modal.show wui-status-icon > img {
|
|
58
|
+
animation: wui-dialog-icon-raster 340ms var(--wui-ease-elastic) 0ms both;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
@keyframes wui-dialog-icon-halo {
|
|
62
|
+
from {
|
|
63
|
+
opacity: 0;
|
|
64
|
+
transform: scale(0.7);
|
|
65
|
+
}
|
|
66
|
+
to {
|
|
67
|
+
opacity: 1;
|
|
68
|
+
transform: scale(1);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
@keyframes wui-dialog-icon-ring {
|
|
73
|
+
from {
|
|
74
|
+
opacity: 0;
|
|
75
|
+
transform: scale(0.8);
|
|
76
|
+
}
|
|
77
|
+
to {
|
|
78
|
+
opacity: 1;
|
|
79
|
+
transform: scale(1);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
@keyframes wui-dialog-icon-core {
|
|
84
|
+
from {
|
|
85
|
+
opacity: 0;
|
|
86
|
+
transform: scale(0.55);
|
|
87
|
+
}
|
|
88
|
+
60% {
|
|
89
|
+
opacity: 1;
|
|
90
|
+
}
|
|
91
|
+
to {
|
|
92
|
+
opacity: 1;
|
|
93
|
+
transform: scale(1);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
@keyframes wui-dialog-icon-raster {
|
|
98
|
+
from {
|
|
99
|
+
opacity: 0;
|
|
100
|
+
transform: scale(0.55);
|
|
101
|
+
}
|
|
102
|
+
to {
|
|
103
|
+
opacity: 1;
|
|
104
|
+
transform: scale(1);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
30
108
|
@media (prefers-reduced-motion: reduce) {
|
|
31
109
|
:root:not([data-wui-dialog-motion="slide"]) .modal.show .modal-dialog {
|
|
32
110
|
animation: none;
|
|
33
111
|
}
|
|
112
|
+
|
|
113
|
+
:root:not([data-wui-dialog-motion="slide"]) .modal.show wui-status-icon > svg > :is(rect, g) {
|
|
114
|
+
animation: none;
|
|
115
|
+
opacity: 1;
|
|
116
|
+
transform: none;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
:root:not([data-wui-dialog-motion="slide"]) .modal.show wui-status-icon > img {
|
|
120
|
+
animation: none;
|
|
121
|
+
opacity: 1;
|
|
122
|
+
transform: none;
|
|
123
|
+
}
|
|
34
124
|
}
|
package/scss/wui/_display.scss
CHANGED
|
@@ -63,6 +63,8 @@
|
|
|
63
63
|
}
|
|
64
64
|
.kpi-value {
|
|
65
65
|
margin-top: 6px;
|
|
66
|
+
// A product sets the figure's face with --wui-kpi-value-font-family; unset, it inherits the page font.
|
|
67
|
+
font-family: var(--wui-kpi-value-font-family, inherit);
|
|
66
68
|
// The value ("main heading") size flows from one var, so a size tier (sm/md/lg,
|
|
67
69
|
// spotlight) or a custom `valueSize` (px) can drive it. Default (md) is 24px.
|
|
68
70
|
font-size: var(--wui-kpi-value-size, 24px);
|
|
@@ -188,7 +190,7 @@
|
|
|
188
190
|
}
|
|
189
191
|
.kpi.kpi-spotlight .kpi-value {
|
|
190
192
|
margin-top: 14px;
|
|
191
|
-
//
|
|
193
|
+
// The face comes from --wui-kpi-value-font-family on .kpi-value, as on every other tile.
|
|
192
194
|
// Size comes from --wui-kpi-value-size (36px default, set on the spotlight root above), so a
|
|
193
195
|
// custom `valueSize` (px) can tame a too-large headline.
|
|
194
196
|
line-height: 1;
|
|
@@ -1494,6 +1496,15 @@ button.wui-link {
|
|
|
1494
1496
|
z-index: 0;
|
|
1495
1497
|
white-space: var(--wui-link-label-white-space, nowrap);
|
|
1496
1498
|
}
|
|
1499
|
+
// maxLines: the label wraps and stops at that many lines, the clamp drawing the ellipsis. The
|
|
1500
|
+
// underline sits 1px inside the label's bottom edge, so overflow: hidden does not clip it.
|
|
1501
|
+
.wui-link--clamp .wui-link__label {
|
|
1502
|
+
white-space: normal;
|
|
1503
|
+
display: -webkit-box;
|
|
1504
|
+
-webkit-box-orient: vertical;
|
|
1505
|
+
-webkit-line-clamp: var(--wui-link-max-lines, none);
|
|
1506
|
+
overflow: hidden;
|
|
1507
|
+
}
|
|
1497
1508
|
// A link in a table cell may wrap: a nowrap label runs under the pinned actions column.
|
|
1498
1509
|
.table-ledger td .wui-link__label {
|
|
1499
1510
|
--wui-link-label-white-space: normal;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// The busy state of a form field (React loading, Razor loading, <wui-*> loading). Part of the wui-components layer, see _wui-components.scss for load order.
|
|
2
|
+
|
|
3
|
+
@property --wui-busy-angle {
|
|
4
|
+
syntax: "<angle>";
|
|
5
|
+
inherits: false;
|
|
6
|
+
initial-value: 0deg;
|
|
7
|
+
}
|
|
8
|
+
@keyframes wui-field-busy-spin {
|
|
9
|
+
to {
|
|
10
|
+
--wui-busy-angle: 360deg;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.wui-field-busy {
|
|
15
|
+
cursor: progress;
|
|
16
|
+
pointer-events: none;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.input.wui-field-busy,
|
|
20
|
+
.textarea.wui-field-busy,
|
|
21
|
+
.form-control.wui-field-busy,
|
|
22
|
+
.select.wui-field-busy {
|
|
23
|
+
padding-inline-end: var(--wui-space-2xl);
|
|
24
|
+
background-repeat: no-repeat;
|
|
25
|
+
background-position: right 12px center;
|
|
26
|
+
background-size: 18px 18px;
|
|
27
|
+
background-image:
|
|
28
|
+
radial-gradient(circle, var(--color-surface) 0 5px, transparent 5.5px),
|
|
29
|
+
conic-gradient(from var(--wui-busy-angle), transparent 0 30%, var(--color-primary) 30% 100%);
|
|
30
|
+
animation: wui-field-busy-spin 0.7s linear infinite;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@media (prefers-reduced-motion: reduce) {
|
|
34
|
+
.input.wui-field-busy,
|
|
35
|
+
.textarea.wui-field-busy,
|
|
36
|
+
.form-control.wui-field-busy,
|
|
37
|
+
.select.wui-field-busy {
|
|
38
|
+
animation: none;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.form-check-input.wui-field-busy,
|
|
43
|
+
.segmented.wui-field-busy,
|
|
44
|
+
.struct-card.wui-field-busy,
|
|
45
|
+
.choice-chip.wui-field-busy,
|
|
46
|
+
.wui-rating.wui-field-busy,
|
|
47
|
+
.slider.wui-field-busy,
|
|
48
|
+
.otp.wui-field-busy {
|
|
49
|
+
opacity: var(--wui-disabled-opacity);
|
|
50
|
+
}
|