@webority/theme 0.7.4 → 0.7.6
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 +108 -6
- package/dist/webority-theme.css +1 -1
- package/package.json +1 -1
- package/scss/_components.scss +108 -475
- package/scss/_marketing.scss +337 -0
- package/scss/_tokens.scss +111 -98
- package/scss/_variables.scss +92 -87
- package/scss/_wui-aliases.scss +111 -103
- package/scss/wui/_card.scss +138 -0
- package/scss/wui/_choice.scss +124 -2
- package/scss/wui/_controls.scss +236 -11
- package/scss/wui/_data.scss +26 -13
- package/scss/wui/_display.scss +160 -1
- package/scss/wui/_flow.scss +216 -7
- package/scss/wui/_media.scss +264 -14
- package/scss/wui/_navigation.scss +28 -1
- package/scss/wui/_overlays.scss +45 -1
- package/scss/wui/_typography.scss +16 -0
- package/scss/wui/_utilities.scss +253 -6
package/scss/wui/_display.scss
CHANGED
|
@@ -260,6 +260,92 @@ a.info-row:hover .info-value {
|
|
|
260
260
|
text-decoration: underline;
|
|
261
261
|
}
|
|
262
262
|
|
|
263
|
+
// ============================================================================
|
|
264
|
+
// Labeled key-value grid — record details, definitions, attributes.
|
|
265
|
+
// ============================================================================
|
|
266
|
+
.descs {
|
|
267
|
+
display: flex;
|
|
268
|
+
flex-direction: column;
|
|
269
|
+
gap: 0;
|
|
270
|
+
}
|
|
271
|
+
.descs-title {
|
|
272
|
+
font-size: 14px;
|
|
273
|
+
font-weight: 600;
|
|
274
|
+
color: var(--color-text);
|
|
275
|
+
padding: 0 0 12px 0;
|
|
276
|
+
}
|
|
277
|
+
.descs-list {
|
|
278
|
+
display: grid;
|
|
279
|
+
grid-template-columns: repeat(var(--descs-cols, 2), 1fr);
|
|
280
|
+
gap: 0;
|
|
281
|
+
margin: 0;
|
|
282
|
+
padding: 0;
|
|
283
|
+
}
|
|
284
|
+
.descs-item {
|
|
285
|
+
display: contents;
|
|
286
|
+
grid-column: span var(--descs-span, 1);
|
|
287
|
+
}
|
|
288
|
+
.descs-label {
|
|
289
|
+
font-size: 12px;
|
|
290
|
+
font-weight: 600;
|
|
291
|
+
text-transform: uppercase;
|
|
292
|
+
letter-spacing: 0.04em;
|
|
293
|
+
color: var(--color-text-subtle);
|
|
294
|
+
padding: 12px 16px;
|
|
295
|
+
border-bottom: 1px solid var(--color-border);
|
|
296
|
+
margin: 0;
|
|
297
|
+
}
|
|
298
|
+
.descs-value {
|
|
299
|
+
font-size: 14px;
|
|
300
|
+
font-weight: 500;
|
|
301
|
+
color: var(--color-text);
|
|
302
|
+
padding: 12px 16px;
|
|
303
|
+
border-bottom: 1px solid var(--color-border);
|
|
304
|
+
margin: 0;
|
|
305
|
+
word-break: break-word;
|
|
306
|
+
}
|
|
307
|
+
// A blank value reads as a muted "no value", not a broken row.
|
|
308
|
+
.descs-value.is-empty {
|
|
309
|
+
font-weight: 400;
|
|
310
|
+
color: var(--color-text-subtle);
|
|
311
|
+
}
|
|
312
|
+
// Small size variant.
|
|
313
|
+
.descs-sm .descs-label,
|
|
314
|
+
.descs-sm .descs-value {
|
|
315
|
+
font-size: 12px;
|
|
316
|
+
padding: 8px 12px;
|
|
317
|
+
}
|
|
318
|
+
// Bordered variant removes inner dividers (only outer border on cells).
|
|
319
|
+
.descs-bordered .descs-label,
|
|
320
|
+
.descs-bordered .descs-value {
|
|
321
|
+
border-bottom: none;
|
|
322
|
+
border-right: 1px solid var(--color-border);
|
|
323
|
+
}
|
|
324
|
+
.descs-bordered .descs-item:last-child .descs-label,
|
|
325
|
+
.descs-bordered .descs-item:last-child .descs-value {
|
|
326
|
+
border-right: none;
|
|
327
|
+
}
|
|
328
|
+
.descs-bordered .descs-list > :nth-child(2n-1) {
|
|
329
|
+
border-bottom: 1px solid var(--color-border);
|
|
330
|
+
}
|
|
331
|
+
// Column variants — set the grid-template-columns.
|
|
332
|
+
.descs-col-1 .descs-list {
|
|
333
|
+
--descs-cols: 1;
|
|
334
|
+
}
|
|
335
|
+
.descs-col-2 .descs-list {
|
|
336
|
+
--descs-cols: 2;
|
|
337
|
+
}
|
|
338
|
+
.descs-col-3 .descs-list {
|
|
339
|
+
--descs-cols: 3;
|
|
340
|
+
}
|
|
341
|
+
// Media-breakpoint collapse to single column under md.
|
|
342
|
+
@include media-breakpoint-down(sm) {
|
|
343
|
+
.descs-col-2 .descs-list,
|
|
344
|
+
.descs-col-3 .descs-list {
|
|
345
|
+
--descs-cols: 1;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
263
349
|
// ============================================================================
|
|
264
350
|
// Segmented control — 2–4 mutually-exclusive options shown side by side.
|
|
265
351
|
// The theme toggle (light/dark/system) is the canonical use.
|
|
@@ -712,4 +798,77 @@ a.info-row:hover .info-value {
|
|
|
712
798
|
}
|
|
713
799
|
}
|
|
714
800
|
|
|
715
|
-
// ============================================================================
|
|
801
|
+
// ============================================================================
|
|
802
|
+
// Result / outcome screen — post-checkout success, verification done, or error states.
|
|
803
|
+
// Distinct from AppEmptyState (which is a card/section "nothing here yet") — this is
|
|
804
|
+
// a self-contained result panel with a prominent status, heading, and actions.
|
|
805
|
+
// ============================================================================
|
|
806
|
+
.result {
|
|
807
|
+
text-align: center;
|
|
808
|
+
padding: 48px 24px;
|
|
809
|
+
color: var(--color-text-subtle);
|
|
810
|
+
}
|
|
811
|
+
.result-icon {
|
|
812
|
+
width: 64px;
|
|
813
|
+
height: 64px;
|
|
814
|
+
border-radius: var(--radius-lg);
|
|
815
|
+
display: inline-flex;
|
|
816
|
+
align-items: center;
|
|
817
|
+
justify-content: center;
|
|
818
|
+
margin-bottom: 24px;
|
|
819
|
+
}
|
|
820
|
+
.result-code {
|
|
821
|
+
font-size: 72px;
|
|
822
|
+
font-weight: 700;
|
|
823
|
+
line-height: 1;
|
|
824
|
+
margin-bottom: 20px;
|
|
825
|
+
color: var(--color-text-subtle);
|
|
826
|
+
letter-spacing: -0.04em;
|
|
827
|
+
}
|
|
828
|
+
.result-title {
|
|
829
|
+
font-size: 24px;
|
|
830
|
+
font-weight: 700;
|
|
831
|
+
line-height: 1.35;
|
|
832
|
+
color: var(--color-text);
|
|
833
|
+
margin: 0 0 12px 0;
|
|
834
|
+
}
|
|
835
|
+
.result-subtitle {
|
|
836
|
+
font-size: 16px;
|
|
837
|
+
line-height: 1.5;
|
|
838
|
+
color: var(--color-text-muted);
|
|
839
|
+
margin: 0 0 20px 0;
|
|
840
|
+
}
|
|
841
|
+
.result-actions {
|
|
842
|
+
margin-top: 20px;
|
|
843
|
+
display: flex;
|
|
844
|
+
align-items: center;
|
|
845
|
+
justify-content: center;
|
|
846
|
+
flex-wrap: wrap;
|
|
847
|
+
gap: 12px;
|
|
848
|
+
}
|
|
849
|
+
.result-extra {
|
|
850
|
+
margin-top: 24px;
|
|
851
|
+
font-size: 14px;
|
|
852
|
+
line-height: 1.5;
|
|
853
|
+
color: var(--color-text-muted);
|
|
854
|
+
}
|
|
855
|
+
// Tone variants — success/danger/warning/info for icon-driven results, muted for code numerics.
|
|
856
|
+
.result-success .result-icon {
|
|
857
|
+
background: var(--color-success-soft);
|
|
858
|
+
color: var(--color-success-text);
|
|
859
|
+
}
|
|
860
|
+
.result-danger .result-icon {
|
|
861
|
+
background: var(--color-danger-soft);
|
|
862
|
+
color: var(--color-danger-text);
|
|
863
|
+
}
|
|
864
|
+
.result-warning .result-icon {
|
|
865
|
+
background: var(--color-warning-soft);
|
|
866
|
+
color: var(--color-warning-text);
|
|
867
|
+
}
|
|
868
|
+
.result-info .result-icon {
|
|
869
|
+
background: var(--color-info-soft);
|
|
870
|
+
color: var(--color-info-text);
|
|
871
|
+
}
|
|
872
|
+
.result-muted .result-code {
|
|
873
|
+
color: var(--color-text-muted);
|
|
874
|
+
}
|
package/scss/wui/_flow.scss
CHANGED
|
@@ -10,6 +10,10 @@
|
|
|
10
10
|
// .stepper-journey — wide: 40px dot beside a label + title, for a page masthead.
|
|
11
11
|
// ============================================================================
|
|
12
12
|
.stepper {
|
|
13
|
+
// Full width so the flex:1 steps spread evenly across the container. Without it,
|
|
14
|
+
// a stepper dropped into a flex/grid parent shrinks to its content and the steps
|
|
15
|
+
// bunch at one edge, colliding their labels.
|
|
16
|
+
width: 100%;
|
|
13
17
|
display: flex;
|
|
14
18
|
align-items: flex-start;
|
|
15
19
|
gap: 0;
|
|
@@ -79,27 +83,61 @@
|
|
|
79
83
|
.step.done .step-label {
|
|
80
84
|
color: var(--color-text);
|
|
81
85
|
}
|
|
82
|
-
//
|
|
86
|
+
// An interactive step — an <a> deep-linking back to a stage, or a <button> in a
|
|
87
|
+
// JS-driven wizard. A button needs its chrome stripped so it reads as a step.
|
|
88
|
+
button.step {
|
|
89
|
+
border: none;
|
|
90
|
+
background: none;
|
|
91
|
+
padding: 0;
|
|
92
|
+
font: inherit;
|
|
93
|
+
color: inherit;
|
|
94
|
+
}
|
|
83
95
|
a.step {
|
|
84
96
|
text-decoration: none;
|
|
97
|
+
}
|
|
98
|
+
a.step,
|
|
99
|
+
button.step {
|
|
85
100
|
cursor: pointer;
|
|
86
101
|
}
|
|
87
|
-
a.step:hover .step-circle
|
|
102
|
+
a.step:hover .step-circle,
|
|
103
|
+
button.step:hover .step-circle {
|
|
88
104
|
box-shadow: 0 0 0 4px var(--color-primary-soft);
|
|
89
105
|
transform: scale(1.04);
|
|
90
106
|
}
|
|
91
|
-
a.step:hover .step-label
|
|
107
|
+
a.step:hover .step-label,
|
|
108
|
+
button.step:hover .step-label {
|
|
92
109
|
color: var(--color-primary);
|
|
93
110
|
}
|
|
94
|
-
a.step:focus-visible
|
|
111
|
+
a.step:focus-visible,
|
|
112
|
+
button.step:focus-visible {
|
|
95
113
|
outline: none;
|
|
96
114
|
}
|
|
97
|
-
// The ring moves onto the circle: an outline on the <a> would box the whole column.
|
|
98
|
-
a.step:focus-visible .step-circle
|
|
115
|
+
// The ring moves onto the circle: an outline on the <a>/<button> would box the whole column.
|
|
116
|
+
a.step:focus-visible .step-circle,
|
|
117
|
+
button.step:focus-visible .step-circle {
|
|
99
118
|
box-shadow:
|
|
100
119
|
0 0 0 4px var(--color-primary-soft),
|
|
101
120
|
0 0 0 6px var(--color-primary);
|
|
102
121
|
}
|
|
122
|
+
// A step that failed its stage — a red circle with an alert, so an invalid step
|
|
123
|
+
// reads as wrong at a glance rather than merely "not done".
|
|
124
|
+
.step.error .step-circle {
|
|
125
|
+
border-color: var(--color-danger);
|
|
126
|
+
background: var(--color-danger);
|
|
127
|
+
color: var(--color-on-scrim);
|
|
128
|
+
}
|
|
129
|
+
.step.error .step-label {
|
|
130
|
+
color: var(--color-danger-text);
|
|
131
|
+
}
|
|
132
|
+
// A secondary line under the label — a short "what this step is for". Muted and
|
|
133
|
+
// narrow so it never competes with the label it explains.
|
|
134
|
+
.step-desc {
|
|
135
|
+
max-width: 130px;
|
|
136
|
+
font-size: 12px;
|
|
137
|
+
line-height: 1.3;
|
|
138
|
+
color: var(--color-text-muted);
|
|
139
|
+
overflow-wrap: break-word;
|
|
140
|
+
}
|
|
103
141
|
|
|
104
142
|
.stepper-journey {
|
|
105
143
|
display: flex;
|
|
@@ -166,6 +204,15 @@ a.step:focus-visible .step-circle {
|
|
|
166
204
|
.stepper-journey .step.active .step-index {
|
|
167
205
|
color: var(--color-primary);
|
|
168
206
|
}
|
|
207
|
+
.stepper-journey .step.error .step-circle {
|
|
208
|
+
background: var(--color-danger-soft);
|
|
209
|
+
color: var(--color-danger-text);
|
|
210
|
+
box-shadow: none;
|
|
211
|
+
transform: none;
|
|
212
|
+
}
|
|
213
|
+
.stepper-journey .step.error .step-index {
|
|
214
|
+
color: var(--color-danger-text);
|
|
215
|
+
}
|
|
169
216
|
.stepper-journey .step-label {
|
|
170
217
|
max-width: none;
|
|
171
218
|
margin-top: 8px;
|
|
@@ -176,6 +223,15 @@ a.step:focus-visible .step-circle {
|
|
|
176
223
|
text-overflow: ellipsis;
|
|
177
224
|
color: var(--color-text);
|
|
178
225
|
}
|
|
226
|
+
// In the journey bar the description sits inside the text column, under the label —
|
|
227
|
+
// wider and left-aligned to match, not the centred compact treatment.
|
|
228
|
+
.stepper-journey .step-desc {
|
|
229
|
+
max-width: none;
|
|
230
|
+
margin-top: 2px;
|
|
231
|
+
white-space: nowrap;
|
|
232
|
+
overflow: hidden;
|
|
233
|
+
text-overflow: ellipsis;
|
|
234
|
+
}
|
|
179
235
|
.stepper-journey .step-line {
|
|
180
236
|
flex: none;
|
|
181
237
|
width: 32px;
|
|
@@ -199,8 +255,86 @@ a.step:focus-visible .step-circle {
|
|
|
199
255
|
display: none;
|
|
200
256
|
}
|
|
201
257
|
}
|
|
258
|
+
// Vertical orientation. The steps run down a side rail instead of across — for a
|
|
259
|
+
// narrow column, a drawer, or a settings wizard.
|
|
260
|
+
// ----------------------------------------------------------------------------
|
|
261
|
+
.stepper-vertical {
|
|
262
|
+
flex-direction: column;
|
|
263
|
+
align-items: stretch;
|
|
264
|
+
// The gap between steps; kept in sync with the ::after `bottom` so the connector
|
|
265
|
+
// spans it exactly and still meets the next circle.
|
|
266
|
+
gap: 18px;
|
|
267
|
+
padding: 0;
|
|
268
|
+
}
|
|
269
|
+
// Each compact step becomes a two-column row: the circle in a fixed rail on the
|
|
270
|
+
// left, the label and its description stacked on the right.
|
|
271
|
+
.stepper-vertical .step {
|
|
272
|
+
display: grid;
|
|
273
|
+
grid-template-columns: 28px 1fr;
|
|
274
|
+
column-gap: 12px;
|
|
275
|
+
// No gap between the label and its description — they read as one block; the
|
|
276
|
+
// base .step gap of 10px is for the horizontal circle→label spacing.
|
|
277
|
+
row-gap: 0;
|
|
278
|
+
align-items: start;
|
|
279
|
+
text-align: left;
|
|
280
|
+
}
|
|
281
|
+
// The circle spans the whole text block rather than sitting in the first row: a
|
|
282
|
+
// row sized to the 28px circle would leave dead space below a single-line label
|
|
283
|
+
// before the description. Spanning lets each row size to its text instead.
|
|
284
|
+
.stepper-vertical .step-circle {
|
|
285
|
+
grid-column: 1;
|
|
286
|
+
grid-row: 1 / -1;
|
|
287
|
+
align-self: start;
|
|
288
|
+
}
|
|
289
|
+
.stepper-vertical .step-label {
|
|
290
|
+
grid-column: 2;
|
|
291
|
+
grid-row: 1;
|
|
292
|
+
max-width: none;
|
|
293
|
+
// Centred against the circle when the step has no description (single 28px row);
|
|
294
|
+
// a no-op when a description makes the row size to the label.
|
|
295
|
+
align-self: center;
|
|
296
|
+
}
|
|
297
|
+
.stepper-vertical .step-desc {
|
|
298
|
+
grid-column: 2;
|
|
299
|
+
grid-row: 2;
|
|
300
|
+
max-width: none;
|
|
301
|
+
}
|
|
302
|
+
// The compact connector is horizontal (::before); redraw it as a vertical segment
|
|
303
|
+
// down the circle's centre, from below one circle to the top of the next.
|
|
304
|
+
.stepper-vertical .step + .step::before {
|
|
305
|
+
content: none;
|
|
306
|
+
}
|
|
307
|
+
.stepper-vertical .step:not(:last-child)::after {
|
|
308
|
+
content: "";
|
|
309
|
+
position: absolute;
|
|
310
|
+
// 13px = half the 28px circle minus 1 for the 2px line's own width.
|
|
311
|
+
left: 13px;
|
|
312
|
+
top: 28px;
|
|
313
|
+
// Reaches through the 18px inter-step gap to meet the next circle's top; keep
|
|
314
|
+
// this in sync with the .stepper-vertical `gap`.
|
|
315
|
+
bottom: -18px;
|
|
316
|
+
width: 2px;
|
|
317
|
+
background: var(--color-border);
|
|
318
|
+
z-index: 0;
|
|
319
|
+
}
|
|
320
|
+
.stepper-vertical .step.done:not(:last-child)::after {
|
|
321
|
+
background: var(--color-primary);
|
|
322
|
+
}
|
|
323
|
+
// The journey bar stacked vertically reuses its own narrow-width treatment: a plain
|
|
324
|
+
// column with the horizontal connectors dropped (a real vertical rail here would
|
|
325
|
+
// fight the two-line text blocks for alignment).
|
|
326
|
+
.stepper-journey.stepper-vertical {
|
|
327
|
+
flex-direction: column;
|
|
328
|
+
align-items: stretch;
|
|
329
|
+
gap: 10px;
|
|
330
|
+
}
|
|
331
|
+
.stepper-journey.stepper-vertical .step-line {
|
|
332
|
+
display: none;
|
|
333
|
+
}
|
|
334
|
+
|
|
202
335
|
@media (prefers-reduced-motion: reduce) {
|
|
203
336
|
a.step:hover .step-circle,
|
|
337
|
+
button.step:hover .step-circle,
|
|
204
338
|
.stepper-journey .step-circle {
|
|
205
339
|
transition: none;
|
|
206
340
|
transform: none;
|
|
@@ -407,4 +541,79 @@ a.step:focus-visible .step-circle {
|
|
|
407
541
|
text-align: center;
|
|
408
542
|
}
|
|
409
543
|
|
|
410
|
-
// ============================================================================
|
|
544
|
+
// ============================================================================
|
|
545
|
+
// Form layout helpers — section, row (grid), actions footer.
|
|
546
|
+
//
|
|
547
|
+
// AppFormSection wraps related fields with a title + description intro.
|
|
548
|
+
// AppFormRow arranges fields in a responsive grid (1/2/3 columns).
|
|
549
|
+
// AppFormActions is an action button footer, optionally sticky-bottom.
|
|
550
|
+
// ============================================================================
|
|
551
|
+
.form-section {
|
|
552
|
+
display: flex;
|
|
553
|
+
flex-direction: column;
|
|
554
|
+
gap: 20px;
|
|
555
|
+
}
|
|
556
|
+
.form-section-head {
|
|
557
|
+
display: flex;
|
|
558
|
+
flex-direction: column;
|
|
559
|
+
gap: 6px;
|
|
560
|
+
}
|
|
561
|
+
.form-section-title {
|
|
562
|
+
margin: 0;
|
|
563
|
+
font-size: 17px;
|
|
564
|
+
font-weight: 600;
|
|
565
|
+
line-height: 1.3;
|
|
566
|
+
color: var(--color-text);
|
|
567
|
+
}
|
|
568
|
+
.form-section-desc {
|
|
569
|
+
margin: 0;
|
|
570
|
+
font-size: 14px;
|
|
571
|
+
line-height: 1.4;
|
|
572
|
+
color: var(--color-text-muted);
|
|
573
|
+
}
|
|
574
|
+
.form-section-body {
|
|
575
|
+
display: flex;
|
|
576
|
+
flex-direction: column;
|
|
577
|
+
gap: 16px;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
// ============================================================================
|
|
581
|
+
.form-row-grid {
|
|
582
|
+
display: grid;
|
|
583
|
+
grid-template-columns: repeat(var(--form-cols, 2), minmax(0, 1fr));
|
|
584
|
+
gap: 16px;
|
|
585
|
+
align-items: start;
|
|
586
|
+
}
|
|
587
|
+
// Below md, collapse to 1 column.
|
|
588
|
+
@include media-breakpoint-down(md) {
|
|
589
|
+
.form-row-grid.form-row-grid {
|
|
590
|
+
grid-template-columns: 1fr;
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
// ============================================================================
|
|
595
|
+
.form-actions {
|
|
596
|
+
display: flex;
|
|
597
|
+
align-items: center;
|
|
598
|
+
gap: 12px;
|
|
599
|
+
justify-content: flex-end;
|
|
600
|
+
}
|
|
601
|
+
.form-actions-start {
|
|
602
|
+
justify-content: flex-start;
|
|
603
|
+
}
|
|
604
|
+
.form-actions-between {
|
|
605
|
+
justify-content: space-between;
|
|
606
|
+
}
|
|
607
|
+
.form-actions-sticky {
|
|
608
|
+
position: sticky;
|
|
609
|
+
bottom: 0;
|
|
610
|
+
padding: 16px 0;
|
|
611
|
+
margin-top: 24px;
|
|
612
|
+
border-top: 1px solid var(--color-border);
|
|
613
|
+
background: var(--color-surface);
|
|
614
|
+
}
|
|
615
|
+
@media (prefers-reduced-motion: reduce) {
|
|
616
|
+
.form-actions-sticky {
|
|
617
|
+
transition: none;
|
|
618
|
+
}
|
|
619
|
+
}
|