@visns-studio/visns-components 6.1.2 → 6.1.4
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/package.json
CHANGED
|
@@ -91,7 +91,7 @@
|
|
|
91
91
|
"react-dom": "^17.0.0 || ^18.0.0"
|
|
92
92
|
},
|
|
93
93
|
"name": "@visns-studio/visns-components",
|
|
94
|
-
"version": "6.1.
|
|
94
|
+
"version": "6.1.4",
|
|
95
95
|
"description": "Various packages to assist in the development of our Custom Applications.",
|
|
96
96
|
"main": "src/index.js",
|
|
97
97
|
"files": [
|
|
@@ -19,6 +19,12 @@ const Login = ({
|
|
|
19
19
|
}) => {
|
|
20
20
|
const location = useLocation();
|
|
21
21
|
const navigate = useNavigate();
|
|
22
|
+
|
|
23
|
+
// Brand copy comes from the consuming project — this library is shared
|
|
24
|
+
// across every VISNS CRM, so nothing project-specific may be hardcoded
|
|
25
|
+
// here. Absent entries simply don't render (except the sign-in hint,
|
|
26
|
+
// which falls back to a generic line).
|
|
27
|
+
const branding = config.branding || {};
|
|
22
28
|
const [isLoading, setIsLoading] = useState(false);
|
|
23
29
|
const [showPassword, setShowPassword] = useState(false);
|
|
24
30
|
|
|
@@ -189,28 +195,39 @@ const Login = ({
|
|
|
189
195
|
}
|
|
190
196
|
aria-hidden="true"
|
|
191
197
|
>
|
|
192
|
-
|
|
193
|
-
<
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
198
|
+
{(branding.eyebrow || branding.name || branding.tagline) && (
|
|
199
|
+
<div className={styles.brandInk}>
|
|
200
|
+
{branding.eyebrow && (
|
|
201
|
+
<p className={styles.eyebrow}>{branding.eyebrow}</p>
|
|
202
|
+
)}
|
|
203
|
+
{branding.name && (
|
|
204
|
+
<p className={styles.brandLine}>{branding.name}</p>
|
|
205
|
+
)}
|
|
206
|
+
{branding.tagline && (
|
|
207
|
+
<p className={styles.brandSub}>{branding.tagline}</p>
|
|
208
|
+
)}
|
|
209
|
+
</div>
|
|
210
|
+
)}
|
|
200
211
|
</aside>
|
|
201
212
|
|
|
202
213
|
<main className={styles.panel}>
|
|
203
214
|
<div className={styles.panelInner}>
|
|
204
|
-
<img
|
|
215
|
+
<img
|
|
216
|
+
src={logo}
|
|
217
|
+
alt={branding.name || 'Logo'}
|
|
218
|
+
className={styles.logo}
|
|
219
|
+
/>
|
|
205
220
|
|
|
206
221
|
<h1 className={styles.title}>Sign in</h1>
|
|
207
222
|
<p className={styles.subtitle}>
|
|
208
|
-
|
|
223
|
+
{branding.signInHint ||
|
|
224
|
+
(ssoAvailable
|
|
225
|
+
? 'Use your Microsoft account to continue.'
|
|
226
|
+
: 'Sign in with your email and password.')}
|
|
209
227
|
</p>
|
|
210
228
|
|
|
211
|
-
{/*
|
|
212
|
-
|
|
213
|
-
without a Microsoft sign-in. */}
|
|
229
|
+
{/* SSO leads when configured; the email form stays
|
|
230
|
+
available underneath for accounts without it. */}
|
|
214
231
|
{renderSsoButton()}
|
|
215
232
|
|
|
216
233
|
{ssoAvailable && !showEmail && (
|
|
@@ -320,9 +337,9 @@ const Login = ({
|
|
|
320
337
|
</div>
|
|
321
338
|
</div>
|
|
322
339
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
340
|
+
{branding.footer && (
|
|
341
|
+
<p className={styles.foot}>{branding.footer}</p>
|
|
342
|
+
)}
|
|
326
343
|
</div>
|
|
327
344
|
</main>
|
|
328
345
|
</div>
|
|
@@ -6,8 +6,11 @@
|
|
|
6
6
|
width: 100%;
|
|
7
7
|
z-index: 995;
|
|
8
8
|
/* Was 0.35rem — too tight to read as a deliberate bar. Enough room that
|
|
9
|
-
the nav sits in it rather than being crushed by it.
|
|
10
|
-
|
|
9
|
+
the nav sits in it rather than being crushed by it.
|
|
10
|
+
This is the element that actually draws the bar, so `--nav-bar-padding`
|
|
11
|
+
— the density hook for the bar's own height — belongs here rather than
|
|
12
|
+
in Navigation.module.scss, where the rest of the set is documented. */
|
|
13
|
+
padding: var(--nav-bar-padding, var(--spacing-sm) var(--spacing-md));
|
|
11
14
|
/* Separates the bar from the page when content scrolls under it. */
|
|
12
15
|
box-shadow: var(--shadow-sm);
|
|
13
16
|
}
|
|
@@ -19,7 +22,7 @@
|
|
|
19
22
|
top: 0;
|
|
20
23
|
width: 100%;
|
|
21
24
|
z-index: 995;
|
|
22
|
-
padding: 0.35rem 1rem;
|
|
25
|
+
padding: var(--nav-bar-padding, 0.35rem 1rem);
|
|
23
26
|
}
|
|
24
27
|
|
|
25
28
|
.content {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Sign in.
|
|
3
3
|
*
|
|
4
4
|
* An asymmetric split: the company's own completed work on the left, the form
|
|
5
5
|
* on the right. Colours are taken from that photograph and the logo rather
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
/* Local aliases only — every brand value comes from the consuming app's
|
|
16
16
|
token layer so this library stays reusable. The fallbacks are neutral
|
|
17
17
|
on purpose: a project that defines nothing gets a plain, working sign
|
|
18
|
-
in rather than
|
|
18
|
+
in rather than any one project's colours. */
|
|
19
19
|
--ink: var(--header-color, #10192a);
|
|
20
20
|
--navy: var(--primary-color, #26364a);
|
|
21
21
|
--navy-deep: var(--primary-color-darker, #16202e);
|
|
@@ -55,8 +55,8 @@
|
|
|
55
55
|
//
|
|
56
56
|
// The foot is a near-solid plate rather than a fade. The brand line has to
|
|
57
57
|
// hold against whatever the photograph is doing behind it, and this one is
|
|
58
|
-
// bright exactly where the type sits, which left
|
|
59
|
-
// into the
|
|
58
|
+
// bright exactly where the type sits, which left the brand line washing
|
|
59
|
+
// into the photograph. Held high — 0.88 still at 18%, which is where the ink
|
|
60
60
|
// block ends — so the whole block reads on one ground, then released
|
|
61
61
|
// quickly to 0.06 at the top, so the sky above is still a photograph and
|
|
62
62
|
// not a tint.
|
|
@@ -439,7 +439,7 @@
|
|
|
439
439
|
}
|
|
440
440
|
}
|
|
441
441
|
|
|
442
|
-
/* Primary.
|
|
442
|
+
/* Primary. SSO is the main way in when configured, so it carries the fill
|
|
443
443
|
and sits above the fold of the form. */
|
|
444
444
|
.sso {
|
|
445
445
|
display: flex;
|
|
@@ -1,20 +1,67 @@
|
|
|
1
|
+
/* ============================================================================
|
|
2
|
+
Navigation density hooks
|
|
3
|
+
----------------------------------------------------------------------------
|
|
4
|
+
The bar ships one density — the values below — and every project that sets
|
|
5
|
+
none of these variables keeps exactly that rendering. A project that wants a
|
|
6
|
+
slimmer (or roomier) bar overrides the hooks on `:root` in its own global
|
|
7
|
+
stylesheet; nothing here needs a fork, a prop, or a class of its own.
|
|
8
|
+
|
|
9
|
+
Every declaration in this file that carries one of these is written
|
|
10
|
+
`var(--hook, <the value it always had>)`, so an unset hook is a no-op.
|
|
11
|
+
|
|
12
|
+
--nav-bar-padding the header bar's own padding. Lives on the
|
|
13
|
+
header wrapper in GenericMain.module.scss
|
|
14
|
+
(`.header` / `.headerAlternate`), which is the
|
|
15
|
+
element that actually draws the bar — this file
|
|
16
|
+
only styles its contents.
|
|
17
|
+
default: var(--spacing-sm) var(--spacing-md)
|
|
18
|
+
(.headerAlternate: 0.35rem 1rem)
|
|
19
|
+
--nav-bar-gap gap between the bar's three columns — logo,
|
|
20
|
+
navigation, actions. default: var(--padding)
|
|
21
|
+
--nav-logo-padding padding inside the logo tile. default: 0
|
|
22
|
+
--nav-logo-gap space either side of the logo's hairline
|
|
23
|
+
divider. default: var(--spacing-md)
|
|
24
|
+
--nav-item-gap gap between top-level nav items. default: 0.5rem
|
|
25
|
+
--nav-item-padding padding on a nav item's link/span/button.
|
|
26
|
+
default: 0.55rem 0.7rem
|
|
27
|
+
--nav-item-font-size nav item type size. default: var(--font-size-sm)
|
|
28
|
+
--nav-action-size the square action chips on the right.
|
|
29
|
+
default: 36px
|
|
30
|
+
--nav-action-size-sm the smaller chip variant, and the minimum slot
|
|
31
|
+
a chip sits in. default: 32px
|
|
32
|
+
--nav-action-gap space between action chips. default: 2px
|
|
33
|
+
--nav-action-padding padding of the pill that groups the action
|
|
34
|
+
chips. default: 4px
|
|
35
|
+
--nav-dropdown-item-padding padding on a dropdown menu row.
|
|
36
|
+
default: 8px 20px
|
|
37
|
+
|
|
38
|
+
Two deliberate omissions: the icon-to-label gap inside a nav item and the
|
|
39
|
+
padding on the chips themselves are internal alignment, not density — the
|
|
40
|
+
chips are fixed squares centring their icon, so their padding changes
|
|
41
|
+
nothing. The sidebar layout (`.aside--cms`) is a different surface and keeps
|
|
42
|
+
its own sizing.
|
|
43
|
+
|
|
44
|
+
Note that below 960px the bar tightens its own gaps; a project setting these
|
|
45
|
+
hooks tighter than those values stays tighter at every width.
|
|
46
|
+
========================================================================= */
|
|
47
|
+
|
|
1
48
|
.hwrap {
|
|
2
49
|
display: grid;
|
|
3
50
|
grid-template-columns: auto auto 1fr auto;
|
|
4
51
|
align-items: center;
|
|
5
|
-
gap: var(--padding);
|
|
52
|
+
gap: var(--nav-bar-gap, var(--padding));
|
|
6
53
|
width: 100%;
|
|
7
54
|
position: relative; /* Establish a positioning context */
|
|
8
55
|
|
|
9
56
|
.logo {
|
|
10
57
|
width: var(--logo-width);
|
|
11
|
-
padding: 0;
|
|
58
|
+
padding: var(--nav-logo-padding, 0);
|
|
12
59
|
margin: 0;
|
|
13
60
|
line-height: 1.45;
|
|
14
61
|
/* The mark and the navigation were butted together, reading as one
|
|
15
62
|
run of items. A hairline gives the logo its own territory. */
|
|
16
|
-
margin-right: var(--spacing-md);
|
|
17
|
-
padding-right: var(--spacing-md);
|
|
63
|
+
margin-right: var(--nav-logo-gap, var(--spacing-md));
|
|
64
|
+
padding-right: var(--nav-logo-gap, var(--spacing-md));
|
|
18
65
|
border-right: 1px solid rgba(255, 255, 255, 0.18);
|
|
19
66
|
|
|
20
67
|
.logoButton {
|
|
@@ -73,7 +120,7 @@
|
|
|
73
120
|
display: flex;
|
|
74
121
|
flex-wrap: nowrap;
|
|
75
122
|
flex-direction: row;
|
|
76
|
-
gap: 0.5rem;
|
|
123
|
+
gap: var(--nav-item-gap, 0.5rem);
|
|
77
124
|
margin: 0;
|
|
78
125
|
list-style: none;
|
|
79
126
|
align-items: center;
|
|
@@ -105,7 +152,7 @@
|
|
|
105
152
|
a,
|
|
106
153
|
span,
|
|
107
154
|
button {
|
|
108
|
-
font-size: var(--font-size-sm);
|
|
155
|
+
font-size: var(--nav-item-font-size, var(--font-size-sm));
|
|
109
156
|
font-weight: var(--font-weight-medium);
|
|
110
157
|
display: flex;
|
|
111
158
|
flex-wrap: nowrap;
|
|
@@ -114,7 +161,7 @@
|
|
|
114
161
|
box-sizing: border-box;
|
|
115
162
|
/* Was 0.35em/0.5em — a tap target under the 44px guideline and
|
|
116
163
|
visually cramped against the taller header. */
|
|
117
|
-
padding: 0.55rem 0.7rem;
|
|
164
|
+
padding: var(--nav-item-padding, 0.55rem 0.7rem);
|
|
118
165
|
margin: 0;
|
|
119
166
|
line-height: 1;
|
|
120
167
|
text-decoration: none;
|
|
@@ -216,7 +263,7 @@
|
|
|
216
263
|
> a,
|
|
217
264
|
> button {
|
|
218
265
|
width: 100%;
|
|
219
|
-
padding: 8px 20px;
|
|
266
|
+
padding: var(--nav-dropdown-item-padding, 8px 20px);
|
|
220
267
|
box-sizing: border-box;
|
|
221
268
|
display: block;
|
|
222
269
|
text-decoration: none;
|
|
@@ -321,7 +368,7 @@
|
|
|
321
368
|
|
|
322
369
|
a {
|
|
323
370
|
width: 100%;
|
|
324
|
-
padding: 8px 20px;
|
|
371
|
+
padding: var(--nav-dropdown-item-padding, 8px 20px);
|
|
325
372
|
box-sizing: border-box;
|
|
326
373
|
display: block;
|
|
327
374
|
text-decoration: none;
|
|
@@ -369,7 +416,7 @@
|
|
|
369
416
|
border-radius: var(--radius-pill);
|
|
370
417
|
/* An even ring around the chips; any more and the group reads as a
|
|
371
418
|
separate control rather than a container for them. */
|
|
372
|
-
padding: 4px;
|
|
419
|
+
padding: var(--nav-action-padding, 4px);
|
|
373
420
|
max-width: 100%;
|
|
374
421
|
overflow-x: auto;
|
|
375
422
|
scrollbar-width: none;
|
|
@@ -383,18 +430,18 @@
|
|
|
383
430
|
flex-direction: row;
|
|
384
431
|
align-items: center;
|
|
385
432
|
justify-content: flex-end;
|
|
386
|
-
gap: 2px;
|
|
433
|
+
gap: var(--nav-action-gap, 2px);
|
|
387
434
|
position: relative;
|
|
388
435
|
z-index: 1001;
|
|
389
436
|
|
|
390
437
|
li {
|
|
391
|
-
margin: 0 2px;
|
|
438
|
+
margin: 0 var(--nav-action-gap, 2px);
|
|
392
439
|
position: relative;
|
|
393
440
|
display: flex;
|
|
394
441
|
align-items: center;
|
|
395
442
|
flex-shrink: 0;
|
|
396
|
-
min-width: 32px; // Reduced from 40px for better spacing
|
|
397
|
-
min-height: 32px; // Reduced from 40px for better spacing
|
|
443
|
+
min-width: var(--nav-action-size-sm, 32px); // Reduced from 40px for better spacing
|
|
444
|
+
min-height: var(--nav-action-size-sm, 32px); // Reduced from 40px for better spacing
|
|
398
445
|
justify-content: center;
|
|
399
446
|
z-index: 1002;
|
|
400
447
|
}
|
|
@@ -424,14 +471,14 @@
|
|
|
424
471
|
align-items: center;
|
|
425
472
|
justify-content: center;
|
|
426
473
|
/* 32px was below the 44px guideline and awkward to hit. */
|
|
427
|
-
width: 36px;
|
|
428
|
-
height: 36px;
|
|
474
|
+
width: var(--nav-action-size, 36px);
|
|
475
|
+
height: var(--nav-action-size, 36px);
|
|
429
476
|
position: relative;
|
|
430
477
|
z-index: 1003;
|
|
431
478
|
appearance: none;
|
|
432
479
|
|
|
433
480
|
/* Brand red on hover, matching the rest of the bar. A neutral
|
|
434
|
-
white lift read as a system default rather than a
|
|
481
|
+
white lift read as a system default rather than a project
|
|
435
482
|
control, and left this cluster looking unrelated to everything
|
|
436
483
|
around it. */
|
|
437
484
|
&:hover,
|
|
@@ -463,9 +510,9 @@
|
|
|
463
510
|
}
|
|
464
511
|
|
|
465
512
|
li button {
|
|
466
|
-
width: 36px;
|
|
467
|
-
height: 36px;
|
|
468
|
-
min-width: 36px;
|
|
513
|
+
width: var(--nav-action-size, 36px);
|
|
514
|
+
height: var(--nav-action-size, 36px);
|
|
515
|
+
min-width: var(--nav-action-size, 36px);
|
|
469
516
|
padding: 0;
|
|
470
517
|
border-radius: var(--radius-pill) !important;
|
|
471
518
|
background: none;
|
|
@@ -494,8 +541,8 @@
|
|
|
494
541
|
display: flex;
|
|
495
542
|
align-items: center;
|
|
496
543
|
justify-content: center;
|
|
497
|
-
width: 32px; // Reduced from 36px
|
|
498
|
-
height: 32px; // Reduced from 36px
|
|
544
|
+
width: var(--nav-action-size-sm, 32px); // Reduced from 36px
|
|
545
|
+
height: var(--nav-action-size-sm, 32px); // Reduced from 36px
|
|
499
546
|
outline: none;
|
|
500
547
|
appearance: none;
|
|
501
548
|
position: relative;
|
|
@@ -535,18 +582,18 @@
|
|
|
535
582
|
flex-direction: row;
|
|
536
583
|
align-items: center;
|
|
537
584
|
justify-content: flex-end;
|
|
538
|
-
gap: 2px;
|
|
585
|
+
gap: var(--nav-action-gap, 2px);
|
|
539
586
|
position: relative;
|
|
540
587
|
z-index: 1001;
|
|
541
588
|
|
|
542
589
|
li {
|
|
543
|
-
margin: 0 2px;
|
|
590
|
+
margin: 0 var(--nav-action-gap, 2px);
|
|
544
591
|
position: relative;
|
|
545
592
|
display: flex;
|
|
546
593
|
align-items: center;
|
|
547
594
|
flex-shrink: 0;
|
|
548
|
-
min-width: 32px; // Reduced from 40px for better spacing
|
|
549
|
-
min-height: 32px; // Reduced from 40px for better spacing
|
|
595
|
+
min-width: var(--nav-action-size-sm, 32px); // Reduced from 40px for better spacing
|
|
596
|
+
min-height: var(--nav-action-size-sm, 32px); // Reduced from 40px for better spacing
|
|
550
597
|
justify-content: center;
|
|
551
598
|
z-index: 1002;
|
|
552
599
|
}
|
|
@@ -563,8 +610,8 @@
|
|
|
563
610
|
display: flex;
|
|
564
611
|
align-items: center;
|
|
565
612
|
justify-content: center;
|
|
566
|
-
width: 32px; // Reduced from 36px
|
|
567
|
-
height: 32px; // Reduced from 36px
|
|
613
|
+
width: var(--nav-action-size-sm, 32px); // Reduced from 36px
|
|
614
|
+
height: var(--nav-action-size-sm, 32px); // Reduced from 36px
|
|
568
615
|
position: relative;
|
|
569
616
|
z-index: 1003;
|
|
570
617
|
transform: translateZ(0) translateX(0) translateY(0); // Force compositor layer
|
|
@@ -600,8 +647,8 @@
|
|
|
600
647
|
display: flex;
|
|
601
648
|
align-items: center;
|
|
602
649
|
justify-content: center;
|
|
603
|
-
width: 32px; // Reduced from 36px
|
|
604
|
-
height: 32px; // Reduced from 36px
|
|
650
|
+
width: var(--nav-action-size-sm, 32px); // Reduced from 36px
|
|
651
|
+
height: var(--nav-action-size-sm, 32px); // Reduced from 36px
|
|
605
652
|
outline: none;
|
|
606
653
|
appearance: none;
|
|
607
654
|
position: relative;
|