@webority/theme 0.25.0 → 0.26.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/dist/purge-safelist.json +76 -2
- package/dist/webority-theme.css +1 -1
- package/fonts/sans/WeboritySans-Bold.woff2 +0 -0
- package/fonts/sans/WeboritySans-BoldItalic.woff2 +0 -0
- package/fonts/sans/WeboritySans-Medium.woff2 +0 -0
- package/fonts/sans/WeboritySans-Regular.woff2 +0 -0
- package/fonts/sans/WeboritySans-RegularItalic.woff2 +0 -0
- package/fonts/sans/WeboritySans-SemiBold.woff2 +0 -0
- package/package.json +1 -1
- package/scss/_fonts.scss +2 -1
- package/scss/_wui-components.scss +1 -0
- package/scss/wui/_data.scss +8 -6
- package/scss/wui/_kanban.scss +434 -0
- package/scss/wui/_modal-remote.scss +53 -1
- package/scss/wui/_overlays.scss +39 -0
- package/scss/wui/_shell-parts.scss +500 -0
- package/scss/wui/_shell.scss +11 -0
- package/scss/wui/_table-server.scss +37 -0
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webority/theme",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.26.0",
|
|
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/_fonts.scss
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// Webority Sans and Webority Serif, shipped with the theme. URLs are relative to the compiled CSS:
|
|
2
2
|
// dist/webority-theme.css reads ../fonts (the npm package) and wwwroot/css/webority-theme.css reads
|
|
3
3
|
// ../fonts (the Razor static web asset, _content/Webority.Ui.Razor/fonts). Sans is SIL OFL 1.1
|
|
4
|
-
// (fonts/sans/OFL.txt travels with it).
|
|
4
|
+
// (fonts/sans/OFL.txt travels with it). The sans files are the webority-fonts Latin cut (Latin, ₹, basic
|
|
5
|
+
// Greek, arrows), about 42 KB each; a character outside it falls back to the next font in the stack.
|
|
5
6
|
@font-face {
|
|
6
7
|
font-family: 'Webority Sans';
|
|
7
8
|
font-style: normal;
|
package/scss/wui/_data.scss
CHANGED
|
@@ -791,12 +791,14 @@
|
|
|
791
791
|
outline-offset: -2px;
|
|
792
792
|
}
|
|
793
793
|
|
|
794
|
-
// Stacked on phones (AppDataTable `stackOnMobile`, Razor `stack-on-mobile`): below
|
|
795
|
-
// card. The first column (after the library's select/expand cells) leads the card at full
|
|
796
|
-
// every other cell is a "label: value" line from its data-label, the select checkbox sits in
|
|
797
|
-
// card's top corner and the row actions close the card. The header row is visually hidden, not
|
|
798
|
-
// removed, so the column names stay available to assistive technology.
|
|
799
|
-
|
|
794
|
+
// Stacked on phones (AppDataTable `stackOnMobile`, Razor `stack-on-mobile`): below md (768px) each
|
|
795
|
+
// row is a card. The first column (after the library's select/expand cells) leads the card at full
|
|
796
|
+
// width, every other cell is a "label: value" line from its data-label, the select checkbox sits in
|
|
797
|
+
// the card's top corner and the row actions close the card. The header row is visually hidden, not
|
|
798
|
+
// removed, so the column names stay available to assistive technology. 768 matches the phone shell
|
|
799
|
+
// (its bottom tab bar shows below the same width): a ledger squeezed into a 600px column scrolled
|
|
800
|
+
// sideways while the rest of the page was already in its phone layout.
|
|
801
|
+
@include media-breakpoint-down(md) {
|
|
800
802
|
// Cards flow with the page: no sideways scroll, and no maxHeight scroll box (an inline
|
|
801
803
|
// max-height from `maxHeight` has to be overridden, hence !important).
|
|
802
804
|
.table-wrap:has(> .table-ledger.wui-table-stack) {
|
|
@@ -0,0 +1,434 @@
|
|
|
1
|
+
// ── Kanban board ──
|
|
2
|
+
// AppKanban / <app-kanban> over <wui-kanban>. The library owns the column shell, the card shell
|
|
3
|
+
// and every drag state; card CONTENT is the product's. State lives in data attributes the element
|
|
4
|
+
// writes (data-wui-drop, data-wui-over, data-wui-dragging, data-collapsed, aria-busy), never in
|
|
5
|
+
// classes, so a React re-render never wipes it.
|
|
6
|
+
//
|
|
7
|
+
// Below md the board is one column per screen: a scroll-snapped strip with a column switcher
|
|
8
|
+
// above it. The board scrolls inside itself, so the page never scrolls sideways.
|
|
9
|
+
//
|
|
10
|
+
// Part of the wui-components layer, see _wui-components.scss for load order.
|
|
11
|
+
|
|
12
|
+
.wui-kanban {
|
|
13
|
+
--wui-kanban-column-width: 288px;
|
|
14
|
+
--wui-kanban-collapsed-width: 56px;
|
|
15
|
+
--wui-kanban-gap: 16px;
|
|
16
|
+
display: block;
|
|
17
|
+
position: relative;
|
|
18
|
+
min-width: 0;
|
|
19
|
+
max-width: 100%;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.wui-kanban-board {
|
|
23
|
+
display: flex;
|
|
24
|
+
align-items: flex-start;
|
|
25
|
+
gap: var(--wui-kanban-gap);
|
|
26
|
+
overflow-x: auto;
|
|
27
|
+
overscroll-behavior-x: contain;
|
|
28
|
+
padding-bottom: 8px;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.wui-kanban-column {
|
|
32
|
+
display: flex;
|
|
33
|
+
flex-direction: column;
|
|
34
|
+
flex: 1 0 var(--wui-kanban-column-width);
|
|
35
|
+
min-width: 0;
|
|
36
|
+
max-width: 100%;
|
|
37
|
+
background: var(--color-bg-subtle);
|
|
38
|
+
border: 1px solid var(--color-border-light);
|
|
39
|
+
border-radius: var(--wui-radius-lg);
|
|
40
|
+
transition:
|
|
41
|
+
background-color 160ms var(--wui-ease-ui),
|
|
42
|
+
border-color 160ms var(--wui-ease-ui);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// ── Column head ──
|
|
46
|
+
.wui-kanban-head {
|
|
47
|
+
display: flex;
|
|
48
|
+
flex-wrap: wrap;
|
|
49
|
+
align-items: center;
|
|
50
|
+
gap: 6px 8px;
|
|
51
|
+
padding: 12px 12px 8px;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.wui-kanban-dot {
|
|
55
|
+
flex: none;
|
|
56
|
+
width: 10px;
|
|
57
|
+
height: 10px;
|
|
58
|
+
border-radius: 50%;
|
|
59
|
+
background: var(--color-text-subtle);
|
|
60
|
+
}
|
|
61
|
+
.wui-kanban-column[data-tone="primary"] .wui-kanban-dot {
|
|
62
|
+
background: var(--color-primary);
|
|
63
|
+
}
|
|
64
|
+
.wui-kanban-column[data-tone="info"] .wui-kanban-dot {
|
|
65
|
+
background: var(--color-info);
|
|
66
|
+
}
|
|
67
|
+
.wui-kanban-column[data-tone="success"] .wui-kanban-dot {
|
|
68
|
+
background: var(--color-success);
|
|
69
|
+
}
|
|
70
|
+
.wui-kanban-column[data-tone="warning"] .wui-kanban-dot {
|
|
71
|
+
background: var(--color-warning);
|
|
72
|
+
}
|
|
73
|
+
.wui-kanban-column[data-tone="danger"] .wui-kanban-dot {
|
|
74
|
+
background: var(--color-danger);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.wui-kanban-title {
|
|
78
|
+
flex: 1 1 auto;
|
|
79
|
+
min-width: 0;
|
|
80
|
+
margin: 0;
|
|
81
|
+
font-size: 0.9375rem;
|
|
82
|
+
font-weight: 600;
|
|
83
|
+
line-height: 1.3;
|
|
84
|
+
color: var(--color-text);
|
|
85
|
+
overflow-wrap: anywhere;
|
|
86
|
+
|
|
87
|
+
a {
|
|
88
|
+
color: inherit;
|
|
89
|
+
text-decoration: none;
|
|
90
|
+
}
|
|
91
|
+
a:hover {
|
|
92
|
+
text-decoration: underline;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.wui-kanban-count {
|
|
97
|
+
flex: none;
|
|
98
|
+
min-width: 24px;
|
|
99
|
+
padding: 1px 8px;
|
|
100
|
+
border-radius: 999px;
|
|
101
|
+
background: var(--color-surface);
|
|
102
|
+
border: 1px solid var(--color-border);
|
|
103
|
+
color: var(--color-text-muted);
|
|
104
|
+
font-size: 0.75rem;
|
|
105
|
+
font-weight: 600;
|
|
106
|
+
line-height: 1.5;
|
|
107
|
+
text-align: center;
|
|
108
|
+
font-variant-numeric: tabular-nums;
|
|
109
|
+
}
|
|
110
|
+
.wui-kanban-count:empty {
|
|
111
|
+
display: none;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.wui-kanban-collapse {
|
|
115
|
+
display: inline-grid;
|
|
116
|
+
place-items: center;
|
|
117
|
+
flex: none;
|
|
118
|
+
width: 32px;
|
|
119
|
+
height: 32px;
|
|
120
|
+
padding: 0;
|
|
121
|
+
border: 0;
|
|
122
|
+
border-radius: var(--wui-radius);
|
|
123
|
+
background: transparent;
|
|
124
|
+
color: var(--color-text-muted);
|
|
125
|
+
cursor: pointer;
|
|
126
|
+
|
|
127
|
+
svg {
|
|
128
|
+
transition: transform 160ms var(--wui-ease-ui);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
.wui-kanban-collapse:hover {
|
|
132
|
+
background: var(--color-bg-muted);
|
|
133
|
+
color: var(--color-text);
|
|
134
|
+
}
|
|
135
|
+
.wui-kanban-collapse:focus-visible,
|
|
136
|
+
.wui-kanban-switch:focus-visible {
|
|
137
|
+
outline: 2px solid var(--color-primary);
|
|
138
|
+
outline-offset: 2px;
|
|
139
|
+
}
|
|
140
|
+
@media (pointer: coarse) {
|
|
141
|
+
.wui-kanban-collapse {
|
|
142
|
+
width: 44px;
|
|
143
|
+
height: 44px;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.wui-kanban-summary {
|
|
148
|
+
flex: 1 0 100%;
|
|
149
|
+
padding-left: 18px;
|
|
150
|
+
color: var(--color-text-muted);
|
|
151
|
+
font-size: 0.8125rem;
|
|
152
|
+
font-weight: 500;
|
|
153
|
+
font-variant-numeric: tabular-nums;
|
|
154
|
+
}
|
|
155
|
+
.wui-kanban-summary:empty {
|
|
156
|
+
display: none;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// ── Body, cards, empty state ──
|
|
160
|
+
.wui-kanban-body {
|
|
161
|
+
display: flex;
|
|
162
|
+
flex-direction: column;
|
|
163
|
+
gap: 8px;
|
|
164
|
+
min-height: 64px;
|
|
165
|
+
padding: 0 8px 8px;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
.wui-kanban-empty {
|
|
169
|
+
margin: 0 8px 8px;
|
|
170
|
+
padding: 16px 8px;
|
|
171
|
+
border: 1px dashed var(--color-border);
|
|
172
|
+
border-radius: var(--wui-radius);
|
|
173
|
+
color: var(--color-text-muted);
|
|
174
|
+
font-size: 0.8125rem;
|
|
175
|
+
text-align: center;
|
|
176
|
+
}
|
|
177
|
+
.wui-kanban-card {
|
|
178
|
+
position: relative;
|
|
179
|
+
min-height: 44px;
|
|
180
|
+
padding: 12px;
|
|
181
|
+
background: var(--color-surface);
|
|
182
|
+
border: 1px solid var(--color-border);
|
|
183
|
+
border-radius: var(--wui-radius);
|
|
184
|
+
color: var(--color-text);
|
|
185
|
+
cursor: grab;
|
|
186
|
+
touch-action: manipulation;
|
|
187
|
+
user-select: none;
|
|
188
|
+
-webkit-user-select: none;
|
|
189
|
+
transition:
|
|
190
|
+
box-shadow 160ms var(--wui-ease-ui),
|
|
191
|
+
opacity 160ms var(--wui-ease-ui);
|
|
192
|
+
}
|
|
193
|
+
.wui-kanban-card:hover {
|
|
194
|
+
border-color: var(--color-border-strong);
|
|
195
|
+
}
|
|
196
|
+
.wui-kanban-card:focus-visible {
|
|
197
|
+
outline: 2px solid var(--color-primary);
|
|
198
|
+
outline-offset: 2px;
|
|
199
|
+
}
|
|
200
|
+
.wui-kanban-card[hidden] {
|
|
201
|
+
display: none;
|
|
202
|
+
}
|
|
203
|
+
.wui-kanban[readonly] .wui-kanban-card,
|
|
204
|
+
.wui-kanban-card[data-wui-locked] {
|
|
205
|
+
cursor: default;
|
|
206
|
+
}
|
|
207
|
+
// The card while it is carried: its place stays, as a faint outline.
|
|
208
|
+
.wui-kanban-card[data-wui-dragging] {
|
|
209
|
+
opacity: 0.35;
|
|
210
|
+
border-style: dashed;
|
|
211
|
+
}
|
|
212
|
+
// Picked up by keyboard: the card itself shows it is lifted.
|
|
213
|
+
.wui-kanban-card[data-wui-lifted] {
|
|
214
|
+
box-shadow: var(--wui-shadow-overlay);
|
|
215
|
+
outline: 2px solid var(--color-primary);
|
|
216
|
+
outline-offset: 2px;
|
|
217
|
+
}
|
|
218
|
+
// Saving: the card cannot move again until the server answers.
|
|
219
|
+
.wui-kanban-card[aria-busy="true"] {
|
|
220
|
+
cursor: progress;
|
|
221
|
+
opacity: 0.7;
|
|
222
|
+
}
|
|
223
|
+
.wui-kanban-card[aria-busy="true"]::after {
|
|
224
|
+
content: "";
|
|
225
|
+
position: absolute;
|
|
226
|
+
inset: auto 0 0;
|
|
227
|
+
height: 3px;
|
|
228
|
+
border-radius: 0 0 var(--wui-radius) var(--wui-radius);
|
|
229
|
+
background: linear-gradient(90deg, transparent, var(--color-primary), transparent);
|
|
230
|
+
background-size: 200% 100%;
|
|
231
|
+
animation: wui-kanban-saving 1.1s linear infinite;
|
|
232
|
+
}
|
|
233
|
+
@keyframes wui-kanban-saving {
|
|
234
|
+
from {
|
|
235
|
+
background-position: 100% 0;
|
|
236
|
+
}
|
|
237
|
+
to {
|
|
238
|
+
background-position: -100% 0;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
.wui-kanban-ghost {
|
|
243
|
+
position: fixed;
|
|
244
|
+
top: 0;
|
|
245
|
+
left: 0;
|
|
246
|
+
z-index: var(--wui-z-tooltip);
|
|
247
|
+
margin: 0;
|
|
248
|
+
pointer-events: none;
|
|
249
|
+
cursor: grabbing;
|
|
250
|
+
box-shadow: var(--wui-shadow-overlay);
|
|
251
|
+
rotate: 2deg;
|
|
252
|
+
}
|
|
253
|
+
.wui-kanban[data-wui-dragging] {
|
|
254
|
+
cursor: grabbing;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// ── Drop states, while a card is carried ──
|
|
258
|
+
.wui-kanban-drop-note {
|
|
259
|
+
margin: 0 8px 8px;
|
|
260
|
+
padding: 8px 10px;
|
|
261
|
+
border-radius: var(--wui-radius);
|
|
262
|
+
background: var(--color-surface);
|
|
263
|
+
color: var(--color-text-muted);
|
|
264
|
+
font-size: 0.8125rem;
|
|
265
|
+
line-height: 1.4;
|
|
266
|
+
}
|
|
267
|
+
.wui-kanban-column[data-wui-drop="ok"] {
|
|
268
|
+
border: 1px dashed var(--color-primary);
|
|
269
|
+
}
|
|
270
|
+
.wui-kanban-column[data-wui-drop="ok"][data-wui-over],
|
|
271
|
+
.wui-kanban-column[data-wui-drop="ok"][data-wui-target] {
|
|
272
|
+
background: var(--color-primary-soft);
|
|
273
|
+
border-style: solid;
|
|
274
|
+
}
|
|
275
|
+
.wui-kanban-column[data-wui-drop="ok"] .wui-kanban-drop-note {
|
|
276
|
+
color: var(--color-text);
|
|
277
|
+
}
|
|
278
|
+
// Refused: hatched and locked, with the reason in the note.
|
|
279
|
+
.wui-kanban-column[data-wui-drop="refused"] {
|
|
280
|
+
border-color: var(--color-border);
|
|
281
|
+
background-image: repeating-linear-gradient(
|
|
282
|
+
135deg,
|
|
283
|
+
var(--color-bg-muted) 0 8px,
|
|
284
|
+
transparent 8px 16px
|
|
285
|
+
);
|
|
286
|
+
cursor: not-allowed;
|
|
287
|
+
}
|
|
288
|
+
.wui-kanban-column[data-wui-drop="refused"] .wui-kanban-body {
|
|
289
|
+
opacity: 0.55;
|
|
290
|
+
}
|
|
291
|
+
.wui-kanban-column[data-wui-drop="refused"] .wui-kanban-drop-note {
|
|
292
|
+
color: var(--color-danger-text);
|
|
293
|
+
border: 1px solid var(--color-danger-soft);
|
|
294
|
+
}
|
|
295
|
+
.wui-kanban-column[data-wui-drop="refused"][data-wui-over],
|
|
296
|
+
.wui-kanban-column[data-wui-drop="refused"][data-wui-target] {
|
|
297
|
+
border-color: var(--color-danger);
|
|
298
|
+
}
|
|
299
|
+
.wui-kanban-column[data-wui-drop="source"][data-wui-target] {
|
|
300
|
+
border: 1px dashed var(--color-border-strong);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// ── Collapsed column: a narrow strip that still takes drops ──
|
|
304
|
+
.wui-kanban-column[data-collapsed] {
|
|
305
|
+
flex: 0 0 var(--wui-kanban-collapsed-width);
|
|
306
|
+
align-self: stretch;
|
|
307
|
+
|
|
308
|
+
.wui-kanban-head {
|
|
309
|
+
flex-direction: column;
|
|
310
|
+
flex-wrap: nowrap;
|
|
311
|
+
padding: 10px 6px;
|
|
312
|
+
}
|
|
313
|
+
.wui-kanban-title {
|
|
314
|
+
writing-mode: vertical-rl;
|
|
315
|
+
flex: none;
|
|
316
|
+
white-space: nowrap;
|
|
317
|
+
}
|
|
318
|
+
.wui-kanban-collapse {
|
|
319
|
+
order: -1;
|
|
320
|
+
}
|
|
321
|
+
.wui-kanban-collapse svg {
|
|
322
|
+
transform: rotate(180deg);
|
|
323
|
+
}
|
|
324
|
+
.wui-kanban-summary,
|
|
325
|
+
.wui-kanban-body,
|
|
326
|
+
.wui-kanban-empty {
|
|
327
|
+
display: none;
|
|
328
|
+
}
|
|
329
|
+
.wui-kanban-drop-note {
|
|
330
|
+
margin: 0 4px 8px;
|
|
331
|
+
padding: 6px 4px;
|
|
332
|
+
font-size: 0.75rem;
|
|
333
|
+
writing-mode: vertical-rl;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// ── Phone column switcher (hidden from md up) ──
|
|
338
|
+
.wui-kanban-switcher {
|
|
339
|
+
display: none;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
@media (max-width: 767.98px) {
|
|
343
|
+
.wui-kanban-switcher {
|
|
344
|
+
display: flex;
|
|
345
|
+
gap: 6px;
|
|
346
|
+
margin-bottom: 12px;
|
|
347
|
+
overflow-x: auto;
|
|
348
|
+
scrollbar-width: none;
|
|
349
|
+
}
|
|
350
|
+
.wui-kanban-switch {
|
|
351
|
+
display: inline-flex;
|
|
352
|
+
align-items: center;
|
|
353
|
+
gap: 6px;
|
|
354
|
+
flex: none;
|
|
355
|
+
min-height: 44px;
|
|
356
|
+
padding: 0 14px;
|
|
357
|
+
border: 1px solid var(--color-border);
|
|
358
|
+
border-radius: 999px;
|
|
359
|
+
background: var(--color-surface);
|
|
360
|
+
color: var(--color-text-muted);
|
|
361
|
+
font-size: 0.875rem;
|
|
362
|
+
font-weight: 500;
|
|
363
|
+
white-space: nowrap;
|
|
364
|
+
cursor: pointer;
|
|
365
|
+
}
|
|
366
|
+
// A long column title shortens rather than widening its pill.
|
|
367
|
+
.wui-kanban-switch-title {
|
|
368
|
+
max-width: 14ch;
|
|
369
|
+
overflow: hidden;
|
|
370
|
+
text-overflow: ellipsis;
|
|
371
|
+
white-space: nowrap;
|
|
372
|
+
}
|
|
373
|
+
.wui-kanban-switch[aria-current="true"] {
|
|
374
|
+
border-color: var(--color-primary);
|
|
375
|
+
background: var(--color-primary-soft);
|
|
376
|
+
color: var(--color-text);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
.wui-kanban-board {
|
|
380
|
+
gap: 12px;
|
|
381
|
+
scroll-snap-type: x mandatory;
|
|
382
|
+
scrollbar-width: none;
|
|
383
|
+
}
|
|
384
|
+
.wui-kanban-board::-webkit-scrollbar,
|
|
385
|
+
.wui-kanban-switcher::-webkit-scrollbar {
|
|
386
|
+
display: none;
|
|
387
|
+
}
|
|
388
|
+
// Collapse is a wide-screen space saver: on a phone every column is full width.
|
|
389
|
+
.wui-kanban-column,
|
|
390
|
+
.wui-kanban-column[data-collapsed] {
|
|
391
|
+
flex: 0 0 100%;
|
|
392
|
+
scroll-snap-align: start;
|
|
393
|
+
align-self: flex-start;
|
|
394
|
+
|
|
395
|
+
.wui-kanban-head {
|
|
396
|
+
flex-direction: row;
|
|
397
|
+
flex-wrap: wrap;
|
|
398
|
+
padding: 12px 12px 8px;
|
|
399
|
+
}
|
|
400
|
+
.wui-kanban-title {
|
|
401
|
+
writing-mode: horizontal-tb;
|
|
402
|
+
flex: 1 1 auto;
|
|
403
|
+
white-space: normal;
|
|
404
|
+
}
|
|
405
|
+
.wui-kanban-collapse {
|
|
406
|
+
display: none;
|
|
407
|
+
}
|
|
408
|
+
.wui-kanban-summary {
|
|
409
|
+
display: block;
|
|
410
|
+
}
|
|
411
|
+
.wui-kanban-body {
|
|
412
|
+
display: flex;
|
|
413
|
+
}
|
|
414
|
+
.wui-kanban-empty:not([hidden]) {
|
|
415
|
+
display: block;
|
|
416
|
+
}
|
|
417
|
+
.wui-kanban-drop-note {
|
|
418
|
+
writing-mode: horizontal-tb;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
.wui-kanban-summary:empty {
|
|
422
|
+
display: none;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
@media (prefers-reduced-motion: reduce) {
|
|
427
|
+
.wui-kanban-ghost {
|
|
428
|
+
rotate: none;
|
|
429
|
+
}
|
|
430
|
+
.wui-kanban-card[aria-busy="true"]::after {
|
|
431
|
+
animation: none;
|
|
432
|
+
background: var(--color-primary);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
@@ -1,3 +1,55 @@
|
|
|
1
|
-
// Server-loaded modal: loading skeleton, error state and the
|
|
1
|
+
// Server-loaded modal: loading skeleton, error state and the submit-failure alert. The fullscreen
|
|
2
|
+
// size lives with the modal itself in _overlays.scss, since a page modal uses it too.
|
|
2
3
|
//
|
|
3
4
|
// Part of the wui-components layer; imported after its base partial (see _wui-components.scss).
|
|
5
|
+
|
|
6
|
+
// The loading card: three shimmer lines in the body while the fragment is on its way. The
|
|
7
|
+
// `.skeleton` shimmer is the shared utility; this only shapes the lines.
|
|
8
|
+
.wui-modal-loading {
|
|
9
|
+
display: flex;
|
|
10
|
+
flex-direction: column;
|
|
11
|
+
gap: 12px;
|
|
12
|
+
padding: 4px 0 8px;
|
|
13
|
+
}
|
|
14
|
+
.wui-modal-skeleton {
|
|
15
|
+
height: 14px;
|
|
16
|
+
border-radius: var(--radius-sm);
|
|
17
|
+
}
|
|
18
|
+
.wui-modal-skeleton--short {
|
|
19
|
+
width: 60%;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// The error card: a centred message with Close and Try again, in place of the content that did
|
|
23
|
+
// not load. The dialog stays open so the user decides what happens next.
|
|
24
|
+
.wui-modal-state {
|
|
25
|
+
display: flex;
|
|
26
|
+
flex-direction: column;
|
|
27
|
+
align-items: center;
|
|
28
|
+
gap: 8px;
|
|
29
|
+
padding: 16px 8px 8px;
|
|
30
|
+
text-align: center;
|
|
31
|
+
}
|
|
32
|
+
.wui-modal-state-title {
|
|
33
|
+
margin: 0;
|
|
34
|
+
font-size: 16px;
|
|
35
|
+
font-weight: 600;
|
|
36
|
+
color: var(--color-text);
|
|
37
|
+
}
|
|
38
|
+
.wui-modal-state-text {
|
|
39
|
+
margin: 0;
|
|
40
|
+
max-width: 40ch;
|
|
41
|
+
font-size: 14px;
|
|
42
|
+
color: var(--color-text-muted);
|
|
43
|
+
}
|
|
44
|
+
.wui-modal-state-actions {
|
|
45
|
+
display: flex;
|
|
46
|
+
flex-wrap: wrap;
|
|
47
|
+
justify-content: center;
|
|
48
|
+
gap: 10px;
|
|
49
|
+
margin-top: 12px;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// A failed submit keeps the form and says so above it.
|
|
53
|
+
.wui-modal-submit-error {
|
|
54
|
+
margin-bottom: 16px;
|
|
55
|
+
}
|
package/scss/wui/_overlays.scss
CHANGED
|
@@ -296,6 +296,45 @@
|
|
|
296
296
|
}
|
|
297
297
|
}
|
|
298
298
|
|
|
299
|
+
// Fullscreen size: the card is the whole viewport. Both surfaces put `wui-modal-fullscreen` on the
|
|
300
|
+
// `.modal` shell (Razor's size="fullscreen", React's size="fullscreen"); neither sets a max-width.
|
|
301
|
+
// Header and footer are flex: none, so they stay pinned while the body scrolls between them, and
|
|
302
|
+
// they pad past a notch or home indicator. `100dvh` follows the phone's collapsing toolbar; `100vh`
|
|
303
|
+
// is the fallback for a browser without dynamic viewport units.
|
|
304
|
+
// 100vw, not the shell's 100%: the document reserves a stable scrollbar gutter, which a fixed box's
|
|
305
|
+
// 100% leaves uncovered, so a fullscreen card would stop short of the right edge.
|
|
306
|
+
.modal.wui-modal-shell.wui-modal-fullscreen {
|
|
307
|
+
width: 100vw;
|
|
308
|
+
padding: 0;
|
|
309
|
+
}
|
|
310
|
+
.modal.wui-modal-shell.wui-modal-fullscreen .modal-dialog.wui-rb-dialog {
|
|
311
|
+
width: 100%;
|
|
312
|
+
height: 100%;
|
|
313
|
+
align-items: stretch;
|
|
314
|
+
}
|
|
315
|
+
.wui-modal-fullscreen .wui-modal {
|
|
316
|
+
width: 100vw;
|
|
317
|
+
max-width: none;
|
|
318
|
+
height: 100vh;
|
|
319
|
+
height: 100dvh;
|
|
320
|
+
max-height: none;
|
|
321
|
+
border-radius: 0;
|
|
322
|
+
}
|
|
323
|
+
.wui-modal-fullscreen .wui-modal-header {
|
|
324
|
+
padding-top: max(16px, env(safe-area-inset-top));
|
|
325
|
+
padding-left: max(20px, env(safe-area-inset-left));
|
|
326
|
+
padding-right: max(20px, env(safe-area-inset-right));
|
|
327
|
+
}
|
|
328
|
+
.wui-modal-fullscreen .wui-modal-body {
|
|
329
|
+
padding-left: max(22px, env(safe-area-inset-left));
|
|
330
|
+
padding-right: max(22px, env(safe-area-inset-right));
|
|
331
|
+
}
|
|
332
|
+
.wui-modal-fullscreen .wui-modal-footer {
|
|
333
|
+
padding-bottom: max(16px, env(safe-area-inset-bottom));
|
|
334
|
+
padding-left: max(22px, env(safe-area-inset-left));
|
|
335
|
+
padding-right: max(22px, env(safe-area-inset-right));
|
|
336
|
+
}
|
|
337
|
+
|
|
299
338
|
// ── Confirm dialog ──
|
|
300
339
|
// Confirmation dialog — centred status icon + title + message, two equal
|
|
301
340
|
// side-by-side CTAs. Runs headerless (Modal hideHeader), so the body
|