@visns-studio/visns-components 6.20.1 → 6.23.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/package.json +1 -1
- package/src/components/DataGrid.jsx +15 -2
- package/src/components/Navigation.jsx +10 -1
- package/src/components/columns/SelectFilterEditor.jsx +372 -0
- package/src/components/controls/DataGridSearch.jsx +6 -1
- package/src/components/layout/AnchoredMenu.jsx +131 -0
- package/src/components/layout/BandedList.jsx +158 -0
- package/src/components/layout/FactsBand.jsx +150 -0
- package/src/components/layout/PageHeader.jsx +90 -0
- package/src/components/layout/ScrollRegion.jsx +53 -0
- package/src/components/layout/StatStrip.jsx +170 -0
- package/src/components/layout/useContainedHeight.js +82 -0
- package/src/components/navigation/TabStrip.jsx +156 -0
- package/src/components/phone/ZoomPhoneBadge.jsx +625 -0
- package/src/components/phone/phonePresenceEndpoints.js +34 -0
- package/src/components/phone/phonePresenceHelpers.js +298 -0
- package/src/components/phone/useZoomPhoneLive.js +165 -0
- package/src/components/sms/SmsClientConversations.jsx +8 -0
- package/src/components/sms/SmsInbox.jsx +11 -0
- package/src/components/sms/SmsThreadPanel.jsx +258 -29
- package/src/components/sms/smsHelpers.js +95 -0
- package/src/components/styles/AnchoredMenu.module.scss +43 -0
- package/src/components/styles/BandedList.module.scss +278 -0
- package/src/components/styles/DataGrid.module.scss +10 -0
- package/src/components/styles/FactsBand.module.scss +108 -0
- package/src/components/styles/GenericDetail.module.scss +12 -2
- package/src/components/styles/PageHeader.module.scss +98 -0
- package/src/components/styles/ScrollRegion.module.scss +20 -0
- package/src/components/styles/Sms.module.scss +131 -0
- package/src/components/styles/StatStrip.module.scss +183 -0
- package/src/components/styles/TabStrip.module.scss +96 -0
- package/src/components/styles/Vault.module.scss +46 -0
- package/src/components/styles/ZoomPhone.module.scss +550 -0
- package/src/components/styles/_surface.scss +49 -0
- package/src/components/styles/global-datagrid.css +23 -0
- package/src/components/vault/VaultAccessLog.jsx +24 -0
- package/src/components/vault/VaultShareModal.jsx +126 -5
- package/src/components/vault/vaultShares.js +67 -3
- package/src/index.js +88 -2
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
@use 'surface' as *;
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* StatStrip — the row of labelled figures that sits above a list.
|
|
5
|
+
*
|
|
6
|
+
* Two shapes, because the screens it was lifted from genuinely draw two and
|
|
7
|
+
* neither is wrong:
|
|
8
|
+
*
|
|
9
|
+
* `joined` one card, cells separated by a hairline. The grid's `gap: 1px`
|
|
10
|
+
* is the container's own background showing through, which is how
|
|
11
|
+
* the rules stay exactly one device pixel at any zoom. Reads as a
|
|
12
|
+
* single statement about the set below it.
|
|
13
|
+
* `tiles` separate bordered tiles with real space between them. Reads as
|
|
14
|
+
* independent figures, which is what a dashboard wants — and is
|
|
15
|
+
* the only one of the two that can carry a per-tile emphasis skin
|
|
16
|
+
* without the tint bleeding across a shared border.
|
|
17
|
+
*
|
|
18
|
+
* The track width is a custom property rather than a fixed value so a page can
|
|
19
|
+
* reflow the strip from its own media query (`--vs-stat-min`), or replace the
|
|
20
|
+
* track list outright (`--vs-stat-columns`) for the cases auto-fit cannot
|
|
21
|
+
* express — "exactly two columns on a phone" being the one that keeps coming
|
|
22
|
+
* up.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
.strip {
|
|
26
|
+
@include surface-tokens;
|
|
27
|
+
|
|
28
|
+
display: grid;
|
|
29
|
+
grid-template-columns: var(
|
|
30
|
+
--vs-stat-columns,
|
|
31
|
+
repeat(auto-fit, minmax(var(--vs-stat-min, 10rem), 1fr))
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/* One card, hairline-separated. */
|
|
36
|
+
.joined {
|
|
37
|
+
gap: 1px;
|
|
38
|
+
overflow: hidden;
|
|
39
|
+
background: var(--pr-line);
|
|
40
|
+
border: 1px solid var(--pr-line);
|
|
41
|
+
border-radius: var(--pr-radius);
|
|
42
|
+
box-shadow: var(--pr-shadow);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/* Separate tiles. */
|
|
46
|
+
.tiles {
|
|
47
|
+
gap: var(--spacing-md, 1rem);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/* -------------------------------------------------------------------------- */
|
|
51
|
+
/* one figure */
|
|
52
|
+
/* -------------------------------------------------------------------------- */
|
|
53
|
+
|
|
54
|
+
.stat {
|
|
55
|
+
@include surface-tokens;
|
|
56
|
+
|
|
57
|
+
display: flex;
|
|
58
|
+
flex-direction: column;
|
|
59
|
+
gap: 0.15rem;
|
|
60
|
+
min-width: 0;
|
|
61
|
+
padding: 0.85rem var(--spacing-md, 1rem);
|
|
62
|
+
background: var(--pr-surface);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.tiles .stat {
|
|
66
|
+
border: 1px solid var(--pr-line);
|
|
67
|
+
border-radius: var(--pr-radius);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/* A stat that navigates. It is a real <button>, so everything a button brings
|
|
71
|
+
with it — the browser's font, the centred text, the 2px agent border — has
|
|
72
|
+
to be unwound before it can pass for a cell. */
|
|
73
|
+
.interactive {
|
|
74
|
+
color: inherit;
|
|
75
|
+
font: inherit;
|
|
76
|
+
text-align: left;
|
|
77
|
+
text-decoration: none;
|
|
78
|
+
border: 0;
|
|
79
|
+
cursor: pointer;
|
|
80
|
+
transition: background var(--speed, 160ms) var(--ease, ease);
|
|
81
|
+
|
|
82
|
+
&:hover {
|
|
83
|
+
background: var(--pr-quiet);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
&:focus-visible {
|
|
87
|
+
outline: 2px solid var(--pr-accent);
|
|
88
|
+
outline-offset: -2px;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.tiles .interactive {
|
|
93
|
+
border: 1px solid var(--pr-line);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.label {
|
|
97
|
+
color: var(--pr-muted);
|
|
98
|
+
font-size: var(--font-size-xs, 0.75rem);
|
|
99
|
+
letter-spacing: 0.02em;
|
|
100
|
+
text-transform: uppercase;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/* The label carries a little more weight inside a hairline grid, where there is
|
|
104
|
+
no border to tell one cell from the next. */
|
|
105
|
+
.joined .label {
|
|
106
|
+
font-weight: 600;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.value {
|
|
110
|
+
font-size: 1.35rem;
|
|
111
|
+
font-weight: var(--font-weight-bold, 700);
|
|
112
|
+
/* Tabular figures so a column of money lines up on the decimal point. */
|
|
113
|
+
font-variant-numeric: tabular-nums;
|
|
114
|
+
line-height: 1.2;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/* In a tile the figure is the tile's whole content, so it takes the heading
|
|
118
|
+
colour. In a hairline grid it sits in a run of cells and inherits the page's
|
|
119
|
+
ink instead, or the run reads as six headings. */
|
|
120
|
+
.tiles .value {
|
|
121
|
+
color: var(--pr-heading);
|
|
122
|
+
line-height: 1.15;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/* `/mo`, `%`, `h` — the unit rides with the figure at small print rather than
|
|
126
|
+
being sized up with it. */
|
|
127
|
+
.unit {
|
|
128
|
+
margin-left: 0.15rem;
|
|
129
|
+
color: var(--pr-muted);
|
|
130
|
+
font-size: 0.8rem;
|
|
131
|
+
font-weight: 400;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.note {
|
|
135
|
+
color: var(--pr-muted);
|
|
136
|
+
font-size: var(--font-size-xs, 0.75rem);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/* -------------------------------------------------------------------------- */
|
|
140
|
+
/* tone and emphasis */
|
|
141
|
+
/* -------------------------------------------------------------------------- */
|
|
142
|
+
|
|
143
|
+
/* `tone` colours the FIGURE. Applied by the caller only when the figure is
|
|
144
|
+
non-zero — a tile that is permanently red is a tile nobody reads. */
|
|
145
|
+
.toneAccent {
|
|
146
|
+
color: var(--pr-accent);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.toneHeading {
|
|
150
|
+
color: var(--pr-heading);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.toneWarn {
|
|
154
|
+
color: var(--pr-warn);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.toneDanger {
|
|
158
|
+
color: var(--pr-danger);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/* A note that has to carry the weight rather than the figure above it — "3
|
|
162
|
+
unpriced" hanging off a money total. */
|
|
163
|
+
.noteWarn {
|
|
164
|
+
color: var(--pr-warn);
|
|
165
|
+
font-weight: var(--font-weight-semibold, 600);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/* `emphasis` skins the whole TILE, and only in the `tiles` variant: a tint
|
|
169
|
+
inside a hairline grid would bleed to the cell edges and read as a broken
|
|
170
|
+
border rather than as a warning. */
|
|
171
|
+
.tiles .emphasisWarn {
|
|
172
|
+
background: color-mix(in srgb, var(--pr-warn) 7%, var(--pr-surface));
|
|
173
|
+
border-color: color-mix(in srgb, var(--pr-warn) 42%, var(--pr-line));
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
.tiles .emphasisDanger {
|
|
177
|
+
background: color-mix(in srgb, var(--pr-danger) 5%, var(--pr-surface));
|
|
178
|
+
border-color: color-mix(in srgb, var(--pr-danger) 40%, var(--pr-line));
|
|
179
|
+
|
|
180
|
+
.value {
|
|
181
|
+
color: var(--pr-danger);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
@use 'surface' as *;
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* TabStrip — the underline tabs.
|
|
5
|
+
*
|
|
6
|
+
* The visual language GenericIndex draws, as a component that can be used on its
|
|
7
|
+
* own. Three bespoke screens had rebuilt it by hand, each with the note "the
|
|
8
|
+
* library's tabs are wired to their own state machine, so what is shared is the
|
|
9
|
+
* LOOK, not the code" — which was true, and is the reason this exists: the look
|
|
10
|
+
* belongs in the library even when the state machine does not.
|
|
11
|
+
*
|
|
12
|
+
* The full-width rule is on the STRIP rather than on each tab, and the active
|
|
13
|
+
* tab pulls itself down over it by a pixel, so its underline sits ON that line
|
|
14
|
+
* instead of floating above it.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
.strip {
|
|
18
|
+
@include surface-tokens;
|
|
19
|
+
|
|
20
|
+
display: flex;
|
|
21
|
+
flex-wrap: wrap;
|
|
22
|
+
gap: var(--spacing-md, 1rem);
|
|
23
|
+
border-bottom: 1px solid var(--pr-line);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.tab {
|
|
27
|
+
display: inline-flex;
|
|
28
|
+
gap: 0.4rem;
|
|
29
|
+
align-items: center;
|
|
30
|
+
padding: 0.6rem 0.15rem;
|
|
31
|
+
/* Sits over the strip's own rule. */
|
|
32
|
+
margin-bottom: -1px;
|
|
33
|
+
color: var(--pr-muted);
|
|
34
|
+
font-family: inherit;
|
|
35
|
+
font-size: var(--font-size-sm, 0.8125rem);
|
|
36
|
+
font-weight: var(--font-weight-semibold, 600);
|
|
37
|
+
white-space: nowrap;
|
|
38
|
+
background: none;
|
|
39
|
+
border: 0;
|
|
40
|
+
/* Drawn transparent rather than added on activation, so a tab does not shift
|
|
41
|
+
by 2px the moment it is selected. */
|
|
42
|
+
border-bottom: 2px solid transparent;
|
|
43
|
+
cursor: pointer;
|
|
44
|
+
transition:
|
|
45
|
+
color var(--speed, 160ms) var(--ease, ease),
|
|
46
|
+
border-color var(--speed, 160ms) var(--ease, ease);
|
|
47
|
+
|
|
48
|
+
&:hover:not(:disabled) {
|
|
49
|
+
color: var(--pr-heading);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
&:focus-visible {
|
|
53
|
+
outline: 2px solid var(--pr-accent);
|
|
54
|
+
outline-offset: 2px;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
&:disabled {
|
|
58
|
+
cursor: default;
|
|
59
|
+
opacity: 0.5;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.active {
|
|
64
|
+
color: var(--pr-heading);
|
|
65
|
+
border-bottom-color: var(--pr-accent);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/* -------------------------------------------------------------------------- */
|
|
69
|
+
/* the count on a tab */
|
|
70
|
+
/* -------------------------------------------------------------------------- */
|
|
71
|
+
|
|
72
|
+
/* A count rides along where a tab has one worth pre-empting — it is the
|
|
73
|
+
difference between "go and look at Service health" and "go and look at Service
|
|
74
|
+
health, there are 21 things wrong".
|
|
75
|
+
*
|
|
76
|
+
* Two tones, and the distinction matters: `quiet` is HOW MANY (four tickets on
|
|
77
|
+
* this contact), `danger` is HOW MANY ARE WRONG (twenty-one devices offline). A
|
|
78
|
+
* red pill on a plain count is an alarm about nothing. */
|
|
79
|
+
.badge {
|
|
80
|
+
padding: 0.05rem 0.35rem;
|
|
81
|
+
font-size: var(--font-size-xs, 0.75rem);
|
|
82
|
+
font-variant-numeric: tabular-nums;
|
|
83
|
+
border-radius: var(--radius-pill, 999px);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.badgeQuiet {
|
|
87
|
+
color: var(--pr-muted);
|
|
88
|
+
background: var(--pr-quiet);
|
|
89
|
+
border: 1px solid var(--pr-line);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.badgeDanger {
|
|
93
|
+
color: #fff;
|
|
94
|
+
background: var(--pr-danger);
|
|
95
|
+
border: 1px solid transparent;
|
|
96
|
+
}
|
|
@@ -41,6 +41,11 @@ $vault-mono: 'SFMono-Regular', 'Menlo', 'Consolas', monospace;
|
|
|
41
41
|
--v-tint: color-mix(in srgb, var(--v-primary) 12%, var(--v-background));
|
|
42
42
|
--v-ok: rgb(31, 122, 71);
|
|
43
43
|
--v-bad: rgb(190, 62, 62);
|
|
44
|
+
// Between the two: something did not happen, and nothing is broken or at
|
|
45
|
+
// risk because of it. Its one user is "the link could not be emailed" —
|
|
46
|
+
// the link itself is fine and on screen right above the line, so painting
|
|
47
|
+
// that in --v-bad would read as "your credential is in trouble".
|
|
48
|
+
--v-warn: rgb(176, 106, 20);
|
|
44
49
|
}
|
|
45
50
|
|
|
46
51
|
// Undo anything a host may have imposed on a generic element. Applied to every
|
|
@@ -2312,6 +2317,47 @@ input.checkControl {
|
|
|
2312
2317
|
}
|
|
2313
2318
|
}
|
|
2314
2319
|
|
|
2320
|
+
// "Also emailed to dana@acme.example." Quiet, and under the URL rather than
|
|
2321
|
+
// instead of it: the copy-the-link flow is what actually happened, the email is
|
|
2322
|
+
// a convenience on top of it.
|
|
2323
|
+
.shareEmailed {
|
|
2324
|
+
display: flex;
|
|
2325
|
+
gap: 0.35rem;
|
|
2326
|
+
align-items: flex-start;
|
|
2327
|
+
margin: 0;
|
|
2328
|
+
color: var(--v-ok);
|
|
2329
|
+
font-size: 0.78rem;
|
|
2330
|
+
line-height: 1.45;
|
|
2331
|
+
|
|
2332
|
+
svg {
|
|
2333
|
+
flex-shrink: 0;
|
|
2334
|
+
margin-top: 0.15rem;
|
|
2335
|
+
}
|
|
2336
|
+
}
|
|
2337
|
+
|
|
2338
|
+
// The send failed. Louder than the line above, because the sender is about to
|
|
2339
|
+
// close a dialog believing the recipient has the link — but not red: the link
|
|
2340
|
+
// is on screen and copyable, and nothing about the credential is at risk.
|
|
2341
|
+
.shareEmailFailed {
|
|
2342
|
+
display: flex;
|
|
2343
|
+
gap: 0.35rem;
|
|
2344
|
+
align-items: flex-start;
|
|
2345
|
+
margin: 0;
|
|
2346
|
+
padding: 0.5rem 0.6rem;
|
|
2347
|
+
border: 1px solid color-mix(in srgb, var(--v-warn) 40%, transparent);
|
|
2348
|
+
border-radius: var(--v-btn-br);
|
|
2349
|
+
background: color-mix(in srgb, var(--v-warn) 10%, var(--v-background));
|
|
2350
|
+
color: var(--v-warn);
|
|
2351
|
+
font-size: 0.78rem;
|
|
2352
|
+
font-weight: 500;
|
|
2353
|
+
line-height: 1.45;
|
|
2354
|
+
|
|
2355
|
+
svg {
|
|
2356
|
+
flex-shrink: 0;
|
|
2357
|
+
margin-top: 0.15rem;
|
|
2358
|
+
}
|
|
2359
|
+
}
|
|
2360
|
+
|
|
2315
2361
|
.shareList {
|
|
2316
2362
|
display: flex;
|
|
2317
2363
|
flex-direction: column;
|