@webority/theme 0.0.10 → 0.2.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 +11 -4
- package/dist/webority-theme.css +1 -1
- package/package.json +2 -1
- package/scss/_components.scss +61 -82
- package/scss/_flags.scss +270 -0
- package/scss/_tokens.scss +37 -19
- package/scss/_variables.scss +27 -24
- package/scss/_wui-aliases.scss +3 -1
- package/scss/_wui-components.scss +468 -99
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webority/theme",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.2.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": {
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"bootstrap": "5.3.3",
|
|
31
|
+
"country-flag-icons": "^1.6.20",
|
|
31
32
|
"sass": "~1.77.8"
|
|
32
33
|
},
|
|
33
34
|
"scripts": {
|
package/scss/_components.scss
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// =====================================================================
|
|
2
|
-
//
|
|
2
|
+
// Webority UI — shared custom component CSS.
|
|
3
3
|
// Imported AFTER Bootstrap. Anything that needs to render identically
|
|
4
4
|
// on the Razor marketing site AND the React customer portal lives here.
|
|
5
5
|
// Per-project styling (page layouts, route-specific tweaks) stays in
|
|
@@ -7,13 +7,6 @@
|
|
|
7
7
|
// =====================================================================
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
// ---- Brand wordmark / logo ------------------------------------------
|
|
11
|
-
.lumex-logo {
|
|
12
|
-
height: 2rem;
|
|
13
|
-
width: auto;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
|
|
17
10
|
// ---- Section helpers ------------------------------------------------
|
|
18
11
|
// Marketing + portal both use vertically-padded sections with the
|
|
19
12
|
// brand's spacing rhythm. Bootstrap's py-* gets you part-way; these
|
|
@@ -72,14 +65,23 @@
|
|
|
72
65
|
// ---- Button polish (used by both Razor + React) ---------------------
|
|
73
66
|
// Flat buttons — no drop shadow. Active-press feedback (1px nudge) is
|
|
74
67
|
// retained because it's a tactile signal, not a depth cue.
|
|
68
|
+
// Default-size buttons match the shared control height so a button next to an
|
|
69
|
+
// input in a filter bar or form row lines up exactly. sm/lg opt out — they are
|
|
70
|
+
// deliberately a different size.
|
|
71
|
+
.btn:not(.btn-sm):not(.btn-lg):not(.btn-pill):not(.btn-pill-sm):not(.u-action):not(.btn-icon) {
|
|
72
|
+
display: inline-flex;
|
|
73
|
+
align-items: center;
|
|
74
|
+
justify-content: center;
|
|
75
|
+
min-height: var(--wui-control-height);
|
|
76
|
+
}
|
|
77
|
+
|
|
75
78
|
.btn-primary {
|
|
76
|
-
// Pin hover/active to the
|
|
77
|
-
// Bootstrap
|
|
78
|
-
|
|
79
|
-
--bs-btn-hover-
|
|
80
|
-
--bs-btn-
|
|
81
|
-
--bs-btn-active-
|
|
82
|
-
--bs-btn-active-border-color: #2440C4;
|
|
79
|
+
// Pin hover/active to the pressed-primary token so a rebrand tracks
|
|
80
|
+
// automatically instead of Bootstrap auto-shading $primary off-spec.
|
|
81
|
+
--bs-btn-hover-bg: var(--wui-primary-pressed);
|
|
82
|
+
--bs-btn-hover-border-color: var(--wui-primary-pressed);
|
|
83
|
+
--bs-btn-active-bg: var(--wui-primary-pressed);
|
|
84
|
+
--bs-btn-active-border-color: var(--wui-primary-pressed);
|
|
83
85
|
&:active:not(:disabled) {
|
|
84
86
|
transform: translateY(1px);
|
|
85
87
|
}
|
|
@@ -139,17 +141,17 @@
|
|
|
139
141
|
// (src/components/marketing/brand/watch-demo-button.tsx):
|
|
140
142
|
// - border : rgba(13, 24, 43, 0.15) (foreground/15 in marketing-root)
|
|
141
143
|
// - bg : rgba(255, 255, 255, 0.6) (surface/60)
|
|
142
|
-
// - text :
|
|
144
|
+
// - text : --wui-text-heading (text-foreground in marketing-root)
|
|
143
145
|
// - blur : 4px (backdrop-blur-sm)
|
|
144
146
|
// - hover bg: #ffffff (hover:bg-surface = full opacity)
|
|
145
147
|
.btn-ghost-dark {
|
|
146
|
-
--bs-btn-color:
|
|
148
|
+
--bs-btn-color: var(--wui-text-heading);
|
|
147
149
|
--bs-btn-bg: rgba(255, 255, 255, 0.60);
|
|
148
150
|
--bs-btn-border-color: rgba(13, 24, 43, 0.15);
|
|
149
|
-
--bs-btn-hover-color:
|
|
151
|
+
--bs-btn-hover-color: var(--wui-text-heading);
|
|
150
152
|
--bs-btn-hover-bg: #ffffff;
|
|
151
153
|
--bs-btn-hover-border-color: rgba(13, 24, 43, 0.20);
|
|
152
|
-
--bs-btn-active-color:
|
|
154
|
+
--bs-btn-active-color: var(--wui-text-heading);
|
|
153
155
|
--bs-btn-active-bg: #ffffff;
|
|
154
156
|
--bs-btn-active-border-color: rgba(13, 24, 43, 0.20);
|
|
155
157
|
backdrop-filter: blur(4px);
|
|
@@ -170,10 +172,10 @@
|
|
|
170
172
|
}
|
|
171
173
|
|
|
172
174
|
|
|
173
|
-
// ---- Inputs
|
|
175
|
+
// ---- Inputs ---------------------------------------------------------
|
|
174
176
|
// 5 locked states — default / hover / focus / disabled / error —
|
|
175
177
|
// matching the reference `<Input>` component. Bootstrap drives the base
|
|
176
|
-
// look via $input-* vars in
|
|
178
|
+
// look via $input-* vars in _variables.scss; these blocks add the
|
|
177
179
|
// hover-border-darken cue and the leading/trailing-slot wrapper.
|
|
178
180
|
//
|
|
179
181
|
// The error state is driven by `aria-invalid="true"` (NOT by Bootstrap's
|
|
@@ -219,16 +221,16 @@
|
|
|
219
221
|
// / error states are visible regardless of which child has focus.
|
|
220
222
|
//
|
|
221
223
|
// Usage:
|
|
222
|
-
// <div class="
|
|
223
|
-
// <span class="
|
|
224
|
+
// <div class="wui-input-group">
|
|
225
|
+
// <span class="wui-input-leading"><i class="bi bi-currency-dollar"></i></span>
|
|
224
226
|
// <input type="text" class="form-control" placeholder="0.00" />
|
|
225
227
|
// </div>
|
|
226
228
|
//
|
|
227
|
-
// <div class="
|
|
229
|
+
// <div class="wui-input-group">
|
|
228
230
|
// <input type="password" class="form-control" placeholder="Password" />
|
|
229
|
-
// <button type="button" class="
|
|
231
|
+
// <button type="button" class="wui-input-trailing"><i class="bi bi-eye"></i></button>
|
|
230
232
|
// </div>
|
|
231
|
-
.
|
|
233
|
+
.wui-input-group {
|
|
232
234
|
display: flex;
|
|
233
235
|
align-items: center;
|
|
234
236
|
gap: 0.5rem;
|
|
@@ -236,30 +238,30 @@
|
|
|
236
238
|
height: calc(2.5rem + 2px); // 40px box + 1px border each side
|
|
237
239
|
background: var(--wui-bg-light, #FFFFFF);
|
|
238
240
|
border: 1px solid var(--bs-border-color);
|
|
239
|
-
border-radius:
|
|
241
|
+
border-radius: var(--radius); // matches the bare input radius
|
|
240
242
|
transition: border-color 0.15s ease;
|
|
241
243
|
|
|
242
244
|
|
|
243
245
|
}
|
|
244
|
-
.
|
|
246
|
+
.wui-input-group:hover:not(:focus-within):not(.is-disabled) {
|
|
245
247
|
border-color: rgba(120, 130, 157, 0.6);
|
|
246
248
|
}
|
|
247
|
-
.
|
|
248
|
-
border-color: var(--wui-primary
|
|
249
|
+
.wui-input-group:focus-within {
|
|
250
|
+
border-color: var(--wui-primary);
|
|
249
251
|
}
|
|
250
|
-
.
|
|
251
|
-
.
|
|
252
|
-
background: var(--wui-bg-muted
|
|
252
|
+
.wui-input-group.is-disabled,
|
|
253
|
+
.wui-input-group:has(input:disabled) {
|
|
254
|
+
background: var(--wui-bg-muted);
|
|
253
255
|
cursor: not-allowed;
|
|
254
256
|
border-color: var(--bs-border-color);
|
|
255
257
|
}
|
|
256
|
-
.
|
|
257
|
-
.
|
|
258
|
+
.wui-input-group.has-error,
|
|
259
|
+
.wui-input-group:has(input[aria-invalid="true"]) {
|
|
258
260
|
border-color: var(--bs-danger);
|
|
259
261
|
}
|
|
260
262
|
|
|
261
263
|
// Strip the bare input's own chrome — the wrapper carries it all.
|
|
262
|
-
.
|
|
264
|
+
.wui-input-group > .form-control {
|
|
263
265
|
flex: 1 1 auto;
|
|
264
266
|
min-width: 0;
|
|
265
267
|
height: 100%;
|
|
@@ -270,8 +272,8 @@
|
|
|
270
272
|
box-shadow: none !important;
|
|
271
273
|
border-radius: 0;
|
|
272
274
|
}
|
|
273
|
-
.
|
|
274
|
-
.
|
|
275
|
+
.wui-input-group > .form-control:focus,
|
|
276
|
+
.wui-input-group > .form-control:hover {
|
|
275
277
|
border: 0;
|
|
276
278
|
box-shadow: none !important;
|
|
277
279
|
background: transparent;
|
|
@@ -279,12 +281,12 @@
|
|
|
279
281
|
|
|
280
282
|
// Leading + trailing slots — flex children that hold icons or buttons.
|
|
281
283
|
// Default muted color, inherits hover/focus state from the wrapper.
|
|
282
|
-
.
|
|
283
|
-
.
|
|
284
|
+
.wui-input-leading,
|
|
285
|
+
.wui-input-trailing {
|
|
284
286
|
display: inline-flex;
|
|
285
287
|
align-items: center;
|
|
286
288
|
justify-content: center;
|
|
287
|
-
color: var(--wui-text-3
|
|
289
|
+
color: var(--wui-text-3);
|
|
288
290
|
flex-shrink: 0;
|
|
289
291
|
font-size: 1rem;
|
|
290
292
|
line-height: 1;
|
|
@@ -293,8 +295,8 @@
|
|
|
293
295
|
|
|
294
296
|
// When the trailing slot is a button (clear, toggle, etc.), reset
|
|
295
297
|
// button chrome and re-enable pointer events.
|
|
296
|
-
button.
|
|
297
|
-
button.
|
|
298
|
+
button.wui-input-trailing,
|
|
299
|
+
button.wui-input-leading {
|
|
298
300
|
background: transparent;
|
|
299
301
|
border: 0;
|
|
300
302
|
padding: 0;
|
|
@@ -302,12 +304,12 @@ button.lumex-input-leading {
|
|
|
302
304
|
cursor: pointer;
|
|
303
305
|
transition: color 0.15s ease;
|
|
304
306
|
}
|
|
305
|
-
button.
|
|
306
|
-
button.
|
|
307
|
-
color: var(--wui-text-1
|
|
307
|
+
button.wui-input-trailing:hover,
|
|
308
|
+
button.wui-input-leading:hover {
|
|
309
|
+
color: var(--wui-text-1);
|
|
308
310
|
}
|
|
309
|
-
button.
|
|
310
|
-
button.
|
|
311
|
+
button.wui-input-trailing:focus-visible,
|
|
312
|
+
button.wui-input-leading:focus-visible {
|
|
311
313
|
outline: none;
|
|
312
314
|
color: var(--wui-primary);
|
|
313
315
|
border-radius: 9999px;
|
|
@@ -356,38 +358,15 @@ button.lumex-input-leading:focus-visible {
|
|
|
356
358
|
|
|
357
359
|
|
|
358
360
|
// ---- Squircle corners (iOS-style) -----------------------------------
|
|
359
|
-
//
|
|
360
|
-
//
|
|
361
|
-
//
|
|
362
|
-
//
|
|
363
|
-
// Older browsers ignore the property and fall back to standard
|
|
364
|
-
// border-radius — no breakage.
|
|
365
|
-
//
|
|
366
|
-
// Apply by default to EVERY element, then explicitly opt
|
|
367
|
-
// `.rounded-circle` and `.rounded-pill` back to `round` — squircle on
|
|
368
|
-
// a 50% / 9999px radius reads as a subtly rounded square rather than a
|
|
369
|
-
// true circle/pill.
|
|
370
|
-
* {
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
}
|
|
374
|
-
.rounded-circle,
|
|
375
|
-
.rounded-pill {
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
// Named opt-in utilities — preserved for places where authors want a
|
|
381
|
-
// specific squircle radius without relying on Bootstrap's $border-radius.
|
|
361
|
+
// Named opt-in utilities for a specific squircle radius without relying
|
|
362
|
+
// on Bootstrap's $border-radius. A consuming product can layer a global
|
|
363
|
+
// `corner-shape: squircle` rule on top (Chrome 138+ / Safari 16+; older
|
|
364
|
+
// browsers fall back to the plain border-radius — no breakage).
|
|
382
365
|
.btn-squircle {
|
|
383
366
|
border-radius: 16px;
|
|
384
|
-
|
|
385
|
-
|
|
386
367
|
}
|
|
387
368
|
.rounded-squircle {
|
|
388
369
|
border-radius: 32px;
|
|
389
|
-
|
|
390
|
-
|
|
391
370
|
}
|
|
392
371
|
|
|
393
372
|
|
|
@@ -396,7 +375,7 @@ button.lumex-input-leading:focus-visible {
|
|
|
396
375
|
.hero-wash {
|
|
397
376
|
background:
|
|
398
377
|
radial-gradient(80% 50% at 50% 0%,
|
|
399
|
-
|
|
378
|
+
color-mix(in srgb, var(--wui-primary) 8%, transparent), transparent 70%),
|
|
400
379
|
var(--wui-bg-elevated);
|
|
401
380
|
}
|
|
402
381
|
|
|
@@ -592,7 +571,7 @@ body {
|
|
|
592
571
|
}
|
|
593
572
|
* {
|
|
594
573
|
scrollbar-width: thin;
|
|
595
|
-
scrollbar-color:
|
|
574
|
+
scrollbar-color: var(--wui-scrollbar) transparent;
|
|
596
575
|
}
|
|
597
576
|
*::-webkit-scrollbar {
|
|
598
577
|
width: 8px;
|
|
@@ -602,7 +581,7 @@ body {
|
|
|
602
581
|
background: transparent;
|
|
603
582
|
}
|
|
604
583
|
*::-webkit-scrollbar-thumb {
|
|
605
|
-
background-color:
|
|
584
|
+
background-color: var(--wui-scrollbar);
|
|
606
585
|
border-radius: 9999px;
|
|
607
586
|
border: 2px solid transparent;
|
|
608
587
|
background-clip: padding-box;
|
|
@@ -611,11 +590,11 @@ body {
|
|
|
611
590
|
transition: background-color 220ms ease;
|
|
612
591
|
}
|
|
613
592
|
*::-webkit-scrollbar-thumb:hover {
|
|
614
|
-
background-color:
|
|
593
|
+
background-color: var(--wui-scrollbar-hover);
|
|
615
594
|
background-clip: padding-box;
|
|
616
595
|
}
|
|
617
596
|
*::-webkit-scrollbar-thumb:active {
|
|
618
|
-
background-color:
|
|
597
|
+
background-color: var(--wui-scrollbar-active);
|
|
619
598
|
background-clip: padding-box;
|
|
620
599
|
}
|
|
621
600
|
*::-webkit-scrollbar-corner {
|
|
@@ -625,10 +604,10 @@ body {
|
|
|
625
604
|
// While the page is actively scrolling, give the thumb a slight extra
|
|
626
605
|
// pop so the user can track its position more easily.
|
|
627
606
|
html.is-scrolling * {
|
|
628
|
-
scrollbar-color:
|
|
607
|
+
scrollbar-color: var(--wui-scrollbar-hover) transparent;
|
|
629
608
|
}
|
|
630
609
|
html.is-scrolling *::-webkit-scrollbar-thumb {
|
|
631
|
-
background-color:
|
|
610
|
+
background-color: var(--wui-scrollbar-hover);
|
|
632
611
|
}
|
|
633
612
|
|
|
634
613
|
// Utility: completely hide a scrollbar (e.g., for marquee/horizontal
|