@visns-studio/visns-components 6.17.1 → 6.20.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 +10 -7
- package/src/components/AssociationManager.jsx +344 -177
- package/src/components/AsyncSelect.jsx +2 -2
- package/src/components/Autocomplete.jsx +57 -12
- package/src/components/Breadcrumb.jsx +23 -4
- package/src/components/ClientAssociationManager.jsx +321 -145
- package/src/components/DataGrid.jsx +625 -20
- package/src/components/DropZone.jsx +4 -1
- package/src/components/Form.jsx +233 -6
- package/src/components/MultiSelect.jsx +2 -2
- package/src/components/Navigation.jsx +45 -25
- package/src/components/TableFilter.jsx +172 -12
- package/src/components/UniversalSearch.jsx +390 -0
- package/src/components/auth/Login.jsx +164 -8
- package/src/components/auth/Profile.jsx +209 -22
- package/src/components/auth/authEndpoints.js +4 -0
- package/src/components/auth/webauthn.js +194 -0
- package/src/components/columns/ColumnRenderers.jsx +6 -1
- package/src/components/controls/DataGridSearch.jsx +11 -5
- package/src/components/generic/GenericAuth.jsx +6 -0
- package/src/components/generic/GenericDashboard.jsx +93 -36
- package/src/components/generic/GenericDetail.jsx +146 -61
- package/src/components/generic/GenericIndex.jsx +134 -38
- package/src/components/generic/GenericSettings.jsx +220 -0
- package/src/components/generic/StandardModal.jsx +165 -8
- package/src/components/generic/dashboardChartDefaults.js +230 -0
- package/src/components/generic/shared/indexLayout.js +38 -0
- package/src/components/navActive.js +25 -0
- package/src/components/settings/IntegrationsManager.jsx +474 -0
- package/src/components/sms/SmsLineSettings.jsx +16 -12
- package/src/components/styles/AssociationManager.module.scss +4 -363
- package/src/components/styles/AuditLog.module.scss +6 -6
- package/src/components/styles/AuditLogs.module.scss +3 -3
- package/src/components/styles/Autocomplete.module.scss +7 -7
- package/src/components/styles/BusinessCardOcr.module.scss +6 -1
- package/src/components/styles/CallQueueSettings.module.scss +4 -1
- package/src/components/styles/CameraPlacement.module.scss +19 -19
- package/src/components/styles/CategorizedDropZone.module.scss +6 -1
- package/src/components/styles/ClientAssociationManager.module.scss +5 -289
- package/src/components/styles/ClientAuth.module.scss +1 -1
- package/src/components/styles/DataGrid.module.scss +455 -8
- package/src/components/styles/Field.module.scss +32 -24
- package/src/components/styles/Form.module.scss +123 -3
- package/src/components/styles/GenericDashboard.module.scss +612 -825
- package/src/components/styles/GenericDetail.module.scss +406 -61
- package/src/components/styles/GenericDynamic.module.scss +25 -25
- package/src/components/styles/GenericEditableTable.module.scss +33 -33
- package/src/components/styles/GenericFormBuilder.module.scss +119 -119
- package/src/components/styles/GenericIndex.module.scss +483 -38
- package/src/components/styles/GenericMain.module.scss +6 -3
- package/src/components/styles/GenericQuote.module.scss +399 -81
- package/src/components/styles/GenericReport.module.scss +8 -8
- package/src/components/styles/GenericSettings.module.scss +209 -0
- package/src/components/styles/GenericSort.module.scss +9 -9
- package/src/components/styles/Integrations.module.scss +321 -0
- package/src/components/styles/List.module.scss +4 -4
- package/src/components/styles/Login.module.scss +57 -0
- package/src/components/styles/MultiSelect.module.scss +4 -4
- package/src/components/styles/Navigation.module.scss +12 -12
- package/src/components/styles/Notification.module.scss +12 -8
- package/src/components/styles/NotificationList.module.scss +5 -5
- package/src/components/styles/Profile.module.scss +5 -5
- package/src/components/styles/QrCode.module.scss +4 -4
- package/src/components/styles/QuickAction.module.scss +20 -20
- package/src/components/styles/SortableQuoteItems.module.scss +4 -4
- package/src/components/styles/TableFilter.module.scss +128 -17
- package/src/components/styles/TicketConversation.module.scss +497 -0
- package/src/components/styles/UniversalSearch.module.scss +229 -0
- package/src/components/styles/Vault.module.scss +413 -0
- package/src/components/styles/_associationManager.scss +467 -0
- package/src/components/styles/_authBrandPanel.scss +15 -9
- package/src/components/styles/_controls.scss +43 -39
- package/src/components/styles/global-datagrid.css +196 -0
- package/src/components/styles/global.css +168 -17
- package/src/components/tickets/TicketConversation.jsx +455 -0
- package/src/components/utils/rowActionSettings.js +117 -0
- package/src/components/vault/VaultClientPicker.jsx +183 -0
- package/src/components/vault/VaultEntryForm.jsx +23 -0
- package/src/components/vault/VaultManager.jsx +382 -34
- package/src/components/vault/VaultShareModal.jsx +454 -0
- package/src/components/vault/vaultEndpoints.js +16 -2
- package/src/components/vault/vaultShares.js +247 -0
- package/src/index.js +35 -0
- package/src/utils/fetchUtil.js +38 -14
|
@@ -54,56 +54,69 @@
|
|
|
54
54
|
gap: 1rem;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
57
|
+
/* ----------------------------------------------------------------------------
|
|
58
|
+
The card set.
|
|
59
|
+
|
|
60
|
+
One surface, one radius, one hairline, one elevation. Before this the four
|
|
61
|
+
cards on the same page disagreed on all four: two radii (`--br` and a
|
|
62
|
+
literal 6px), two borders (a WHITE `rgba(--item-color-rgb, 1)` — i.e. no
|
|
63
|
+
visible edge at all — and a hardcoded `#dadce0`), and three shadows
|
|
64
|
+
(`0 10px 50px`, which at 5% over a near-white ground is a smudge nobody can
|
|
65
|
+
see, and a `0 4px 0` hard offset that reads as a 90s button).
|
|
66
|
+
|
|
67
|
+
The border is what does the work now that the page ground is the warm stone
|
|
68
|
+
rather than a near-white: a card needs one edge, not a 50px blur.
|
|
69
|
+
`--shadow-sm` is the single elevation token and is deliberately quiet — the
|
|
70
|
+
contrast between white and the ground carries the lift.
|
|
71
|
+
|
|
72
|
+
`overflow: visible` is load-bearing on every one of these: the filter
|
|
73
|
+
selects, the row-action popovers and the contact tooltips all render inside
|
|
74
|
+
a card and have to escape it. Clipping happens one level in, on the grid's
|
|
75
|
+
own container, where nothing needs to overflow.
|
|
76
|
+
-------------------------------------------------------------------------- */
|
|
77
|
+
|
|
78
|
+
@mixin card-surface {
|
|
79
|
+
background: var(--item-color, #fff);
|
|
80
|
+
border: 1px solid var(--border-color, #e1e1e1);
|
|
81
|
+
border-radius: var(--card-radius, 10px);
|
|
82
|
+
box-shadow: var(
|
|
83
|
+
--shadow-sm,
|
|
84
|
+
0 1px 2px rgba(var(--primary-rgb, 27, 57, 51), 0.08),
|
|
85
|
+
0 2px 8px rgba(var(--primary-rgb, 27, 57, 51), 0.06)
|
|
86
|
+
);
|
|
62
87
|
box-sizing: border-box;
|
|
63
88
|
overflow: visible;
|
|
64
89
|
position: relative;
|
|
65
|
-
padding: 20px;
|
|
66
90
|
margin: 8px 0;
|
|
67
|
-
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.grid__three {
|
|
94
|
+
@include card-surface;
|
|
95
|
+
width: 33%;
|
|
96
|
+
padding: 20px;
|
|
68
97
|
}
|
|
69
98
|
|
|
70
99
|
.grid__half {
|
|
100
|
+
@include card-surface;
|
|
71
101
|
width: 50%;
|
|
72
|
-
background: var(--item-color);
|
|
73
|
-
border-radius: 6px;
|
|
74
|
-
border: 1px solid #dadce0;
|
|
75
|
-
box-sizing: border-box;
|
|
76
|
-
overflow: visible;
|
|
77
|
-
position: relative;
|
|
78
102
|
padding: 20px;
|
|
79
|
-
margin: 8px 0;
|
|
80
|
-
box-shadow: 0 4px 0 rgba(var(--primary-color), 0.05);
|
|
81
103
|
}
|
|
82
104
|
|
|
83
105
|
.grid__full {
|
|
106
|
+
@include card-surface;
|
|
84
107
|
width: 100%;
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
padding: 2px;
|
|
92
|
-
margin: 8px 0;
|
|
93
|
-
box-shadow: 0 10px 50px rgba(var(--primary-rgb), 0.05);
|
|
108
|
+
/* Was 2px. Two pixels of card showing between the card's own border and
|
|
109
|
+
whatever it wraps is the "bit of padding" that made the grid look like
|
|
110
|
+
it did not line up with its own corners — the outer radius curving
|
|
111
|
+
around a square inner edge three pixels away. A card whose only child is
|
|
112
|
+
a full-bleed surface has no padding of its own; the child brings its. */
|
|
113
|
+
padding: 0;
|
|
94
114
|
}
|
|
95
115
|
|
|
96
116
|
.grid__dashfull {
|
|
117
|
+
@include card-surface;
|
|
97
118
|
width: 100%;
|
|
98
|
-
background: var(--item-color);
|
|
99
|
-
border-radius: 6px;
|
|
100
|
-
border: 1px solid #dadce0;
|
|
101
|
-
box-sizing: border-box;
|
|
102
|
-
overflow: visible;
|
|
103
|
-
position: relative;
|
|
104
119
|
padding: 20px;
|
|
105
|
-
margin: 8px 0;
|
|
106
|
-
box-shadow: 0 10px 50px rgba(var(--primary-rgb), 0.05);
|
|
107
120
|
}
|
|
108
121
|
|
|
109
122
|
.grid__subrow {
|
|
@@ -196,14 +209,14 @@
|
|
|
196
209
|
|
|
197
210
|
.grid__subnav__alternate {
|
|
198
211
|
flex: 1;
|
|
199
|
-
background: rgba(var(--item-color-rgb), 0.05);
|
|
212
|
+
background: rgba(var(--item-color-rgb, 255, 255, 255), 0.05);
|
|
200
213
|
border-radius: var(--br);
|
|
201
|
-
border: 1px solid rgba(var(--item-color-rgb), 1
|
|
214
|
+
border: 1px solid rgba(var(--item-color-rgb, 255, 255, 255), 1);
|
|
202
215
|
box-sizing: border-box;
|
|
203
216
|
padding: 5px;
|
|
204
217
|
margin: 8px 0;
|
|
205
218
|
height: auto;
|
|
206
|
-
box-shadow: 0 10px 50px rgba(var(--primary-rgb), 0.05);
|
|
219
|
+
box-shadow: 0 10px 50px rgba(var(--primary-rgb, 27, 57, 51), 0.05);
|
|
207
220
|
}
|
|
208
221
|
|
|
209
222
|
.grid__subnav__alternate > ul {
|
|
@@ -226,7 +239,7 @@
|
|
|
226
239
|
box-sizing: border-box;
|
|
227
240
|
display: block;
|
|
228
241
|
text-decoration: none;
|
|
229
|
-
background: rgba(var(--item-color-rgb), 1
|
|
242
|
+
background: rgba(var(--item-color-rgb, 255, 255, 255), 1);
|
|
230
243
|
color: var(--secondary-color);
|
|
231
244
|
border-radius: 5px;
|
|
232
245
|
transition: background 0.25s cubic-bezier(0.25, 0.8, 0.25, 1);
|
|
@@ -257,13 +270,13 @@
|
|
|
257
270
|
flex: 0 1 80%;
|
|
258
271
|
background: var(--item-color);
|
|
259
272
|
border-radius: var(--br);
|
|
260
|
-
border: 1px solid rgba(var(--item-color-rgb), 1
|
|
273
|
+
border: 1px solid rgba(var(--item-color-rgb, 255, 255, 255), 1);
|
|
261
274
|
box-sizing: border-box;
|
|
262
275
|
padding: 2px;
|
|
263
276
|
margin: 8px 0;
|
|
264
277
|
height: auto;
|
|
265
278
|
position: relative;
|
|
266
|
-
box-shadow: 0 10px 50px rgba(var(--primary-rgb), 0.05);
|
|
279
|
+
box-shadow: 0 10px 50px rgba(var(--primary-rgb, 27, 57, 51), 0.05);
|
|
267
280
|
}
|
|
268
281
|
|
|
269
282
|
.grid__subcontent h2 {
|
|
@@ -1205,3 +1218,435 @@
|
|
|
1205
1218
|
width: 100%;
|
|
1206
1219
|
position: relative;
|
|
1207
1220
|
}
|
|
1221
|
+
|
|
1222
|
+
// ============================================================================
|
|
1223
|
+
// 2026 pass — the index page frame
|
|
1224
|
+
// ----------------------------------------------------------------------------
|
|
1225
|
+
// The page title bar and the filter rail around the grid. Appended for the
|
|
1226
|
+
// same reason as DataGrid's pass: these are targeted overrides of rules above
|
|
1227
|
+
// and the cascade order is load-bearing.
|
|
1228
|
+
// ============================================================================
|
|
1229
|
+
|
|
1230
|
+
.crmtitle,
|
|
1231
|
+
.crmtitleSimple {
|
|
1232
|
+
display: flex;
|
|
1233
|
+
align-items: center;
|
|
1234
|
+
justify-content: space-between;
|
|
1235
|
+
gap: 1rem;
|
|
1236
|
+
// The title sat in its own white slab with a hard edge, which made the page
|
|
1237
|
+
// read as two stacked boxes. It is type on the page ground now, and the
|
|
1238
|
+
// grid card below is the only container.
|
|
1239
|
+
padding: 0 0.25rem 0.85rem;
|
|
1240
|
+
background: none;
|
|
1241
|
+
border: 0;
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1244
|
+
.crmtitle h1,
|
|
1245
|
+
.crmtitleSimple h1,
|
|
1246
|
+
.crmtitle h2,
|
|
1247
|
+
.crmtitleSimple h2 {
|
|
1248
|
+
margin: 0;
|
|
1249
|
+
font-size: 1.375rem;
|
|
1250
|
+
font-weight: 700;
|
|
1251
|
+
letter-spacing: -0.01em;
|
|
1252
|
+
color: var(--heading-color, var(--primary-color, #1b3933));
|
|
1253
|
+
}
|
|
1254
|
+
|
|
1255
|
+
// -- the filter rail ---------------------------------------------------------
|
|
1256
|
+
// Tabs on the left rail were solid brand-green blocks with square corners, one
|
|
1257
|
+
// per filter — a column of buttons shouting at the same volume as the data.
|
|
1258
|
+
|
|
1259
|
+
.grid__subnav,
|
|
1260
|
+
.grid__subnav__alternate {
|
|
1261
|
+
display: flex;
|
|
1262
|
+
flex-direction: column;
|
|
1263
|
+
gap: 0.15rem;
|
|
1264
|
+
padding: 0.4rem;
|
|
1265
|
+
border: 1px solid color-mix(in srgb, var(--paragraph-color, #2b2b2b) 12%, transparent);
|
|
1266
|
+
border-radius: 12px;
|
|
1267
|
+
background: var(--background-color, #fff);
|
|
1268
|
+
box-shadow: 0 1px 2px color-mix(in srgb, var(--primary-color, #1b3933) 6%, transparent);
|
|
1269
|
+
}
|
|
1270
|
+
|
|
1271
|
+
.grid__subnav > *,
|
|
1272
|
+
.grid__subnav__alternate > * {
|
|
1273
|
+
display: flex;
|
|
1274
|
+
align-items: center;
|
|
1275
|
+
padding: 0.5rem 0.7rem;
|
|
1276
|
+
border: 0;
|
|
1277
|
+
border-radius: var(--radius-sm, 8px);
|
|
1278
|
+
background: none;
|
|
1279
|
+
color: var(--muted-color, #6b7688);
|
|
1280
|
+
font-size: 0.8125rem;
|
|
1281
|
+
font-weight: 500;
|
|
1282
|
+
text-align: left;
|
|
1283
|
+
text-decoration: none;
|
|
1284
|
+
cursor: pointer;
|
|
1285
|
+
transition:
|
|
1286
|
+
background var(--speed, 160ms) var(--ease, cubic-bezier(0.4, 0, 0.2, 1)),
|
|
1287
|
+
color var(--speed, 160ms) var(--ease, cubic-bezier(0.4, 0, 0.2, 1));
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1290
|
+
.grid__subnav > *:hover,
|
|
1291
|
+
.grid__subnav__alternate > *:hover {
|
|
1292
|
+
background: color-mix(in srgb, var(--primary-color, #1b3933) 5%, transparent);
|
|
1293
|
+
color: var(--primary-color, #1b3933);
|
|
1294
|
+
}
|
|
1295
|
+
|
|
1296
|
+
// NOTE: the filter tabs themselves are TableFilter's, wrapped in a container
|
|
1297
|
+
// inside this rail — so their selected state is styled in
|
|
1298
|
+
// TableFilter.module.scss (`.subactive`), not from here. A `.grid__subnav > *`
|
|
1299
|
+
// rule reaches the wrapper and nothing else.
|
|
1300
|
+
|
|
1301
|
+
// -- states ------------------------------------------------------------------
|
|
1302
|
+
|
|
1303
|
+
.noData,
|
|
1304
|
+
.loadingContainer {
|
|
1305
|
+
display: flex;
|
|
1306
|
+
align-items: center;
|
|
1307
|
+
justify-content: center;
|
|
1308
|
+
min-height: 8rem;
|
|
1309
|
+
color: var(--muted-color, #6b7688);
|
|
1310
|
+
font-size: 0.875rem;
|
|
1311
|
+
}
|
|
1312
|
+
|
|
1313
|
+
.loadingSpinner {
|
|
1314
|
+
width: 20px;
|
|
1315
|
+
height: 20px;
|
|
1316
|
+
border: 2px solid color-mix(in srgb, var(--paragraph-color, #2b2b2b) 14%, transparent);
|
|
1317
|
+
border-top-color: var(--primary-color, #1b3933);
|
|
1318
|
+
border-radius: 50%;
|
|
1319
|
+
animation: genericIndexSpin 0.7s linear infinite;
|
|
1320
|
+
}
|
|
1321
|
+
|
|
1322
|
+
@keyframes genericIndexSpin {
|
|
1323
|
+
to { transform: rotate(360deg); }
|
|
1324
|
+
}
|
|
1325
|
+
|
|
1326
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1327
|
+
.loadingSpinner { animation-duration: 2s; }
|
|
1328
|
+
}
|
|
1329
|
+
|
|
1330
|
+
/* ============================================================================
|
|
1331
|
+
* 2026 pass — the rail / content split
|
|
1332
|
+
* ----------------------------------------------------------------------------
|
|
1333
|
+
* Three measured faults, not a matter of taste. On /settings at 1440x1500:
|
|
1334
|
+
* the rail card was 241px tall next to a 1264px content pane, so ~1020px of
|
|
1335
|
+
* the left column was a dead L-shaped void; the content pane drew a bordered,
|
|
1336
|
+
* shadowed card around a grid that already draws its own, so every index page
|
|
1337
|
+
* wore two card edges; and the selected rail item was a 10%-opacity tint with
|
|
1338
|
+
* no accent, which at a glance did not read as selected at all.
|
|
1339
|
+
*
|
|
1340
|
+
* The pattern itself stays — a vertical rail beside content is still right in
|
|
1341
|
+
* 2026, and it is the only one of the three that scales as sections are added
|
|
1342
|
+
* (horizontal tabs stop working somewhere around seven). What changes is that
|
|
1343
|
+
* the rail becomes a COLUMN rather than a card: it has no edge of its own to
|
|
1344
|
+
* terminate, so there is no void under it, and it sticks while the content
|
|
1345
|
+
* scrolls past.
|
|
1346
|
+
*
|
|
1347
|
+
* Appended rather than folded in, so the cascade order is doing the
|
|
1348
|
+
* overriding and the original rules stay readable. Every token carries a
|
|
1349
|
+
* literal fallback — a bare var() for a token the host has not declared is
|
|
1350
|
+
* invalid at computed-value time and takes the whole declaration with it.
|
|
1351
|
+
* ==========================================================================*/
|
|
1352
|
+
|
|
1353
|
+
.grid__subrow {
|
|
1354
|
+
/* Grid, not flex: the rail column gets a real, stable width instead of
|
|
1355
|
+
`flex: 1` fighting `flex: 0 1 80%` for it, and `start` alignment stops
|
|
1356
|
+
the two columns forcing each other to equal height — which is what
|
|
1357
|
+
created the void in the first place. */
|
|
1358
|
+
display: grid;
|
|
1359
|
+
grid-template-columns:
|
|
1360
|
+
minmax(var(--index-rail-min, 190px), var(--index-rail-width, 224px))
|
|
1361
|
+
minmax(0, 1fr);
|
|
1362
|
+
align-items: start;
|
|
1363
|
+
gap: var(--index-rail-gap, 1.25rem);
|
|
1364
|
+
}
|
|
1365
|
+
|
|
1366
|
+
.grid__subnav,
|
|
1367
|
+
.grid__subnav__alternate {
|
|
1368
|
+
/* No card. The rail is part of the page ground, so it has no bottom edge
|
|
1369
|
+
to leave a thousand pixels of nothing beneath. */
|
|
1370
|
+
background: none;
|
|
1371
|
+
border: none;
|
|
1372
|
+
box-shadow: none;
|
|
1373
|
+
padding: 0;
|
|
1374
|
+
margin: 8px 0;
|
|
1375
|
+
|
|
1376
|
+
/* It follows the reader instead of scrolling away. The offset is the app
|
|
1377
|
+
chrome above it; a host with different chrome retunes one token. */
|
|
1378
|
+
position: sticky;
|
|
1379
|
+
top: var(--index-rail-top, 88px);
|
|
1380
|
+
|
|
1381
|
+
/* A rail longer than the window scrolls itself, never the page. */
|
|
1382
|
+
max-height: calc(100vh - var(--index-rail-offset, 120px));
|
|
1383
|
+
overflow-y: auto;
|
|
1384
|
+
overscroll-behavior: contain;
|
|
1385
|
+
scrollbar-width: thin;
|
|
1386
|
+
}
|
|
1387
|
+
|
|
1388
|
+
.grid__subnav > ul li a,
|
|
1389
|
+
.grid__subnav__alternate > ul li a {
|
|
1390
|
+
/* Room for the accent edge below, so selecting an item does not shift its
|
|
1391
|
+
label sideways by 3px. */
|
|
1392
|
+
position: relative;
|
|
1393
|
+
padding-left: calc(var(--spacing-md, 1rem) - 3px);
|
|
1394
|
+
border-left: 3px solid transparent;
|
|
1395
|
+
border-radius: var(--radius-sm, 6px);
|
|
1396
|
+
color: var(--paragraph-color, #52606d);
|
|
1397
|
+
}
|
|
1398
|
+
|
|
1399
|
+
.grid__subnav > ul li:hover a,
|
|
1400
|
+
.grid__subnav__alternate > ul li:hover a {
|
|
1401
|
+
background: color-mix(
|
|
1402
|
+
in srgb,
|
|
1403
|
+
var(--primary-color, #1b3933) 6%,
|
|
1404
|
+
transparent
|
|
1405
|
+
);
|
|
1406
|
+
color: var(--heading-color, #111827);
|
|
1407
|
+
}
|
|
1408
|
+
|
|
1409
|
+
/* The SELECTED item is not styled here, and cannot be: `.subactive` is
|
|
1410
|
+
declared in TableFilter.module.scss, so a `.subactive` written in this file
|
|
1411
|
+
compiles to a different hashed class name and matches nothing. The accent
|
|
1412
|
+
edge lives with the class it belongs to, in TableFilter. The transparent
|
|
1413
|
+
3px border above is what reserves the space for it, so selecting an item
|
|
1414
|
+
does not shift its label. */
|
|
1415
|
+
|
|
1416
|
+
.grid__subcontent {
|
|
1417
|
+
/* The grid inside already draws a bordered, shadowed, rounded card. This
|
|
1418
|
+
drew a second one around it. */
|
|
1419
|
+
background: none;
|
|
1420
|
+
border: none;
|
|
1421
|
+
box-shadow: none;
|
|
1422
|
+
padding: 0;
|
|
1423
|
+
margin: 8px 0;
|
|
1424
|
+
min-width: 0;
|
|
1425
|
+
}
|
|
1426
|
+
|
|
1427
|
+
/* Narrow viewports: one column. TableFilter already turns the rail into a
|
|
1428
|
+
horizontal underline strip below 760px, so the two only have to agree on
|
|
1429
|
+
where that happens. */
|
|
1430
|
+
@media (max-width: 759px) {
|
|
1431
|
+
.grid__subrow {
|
|
1432
|
+
grid-template-columns: minmax(0, 1fr);
|
|
1433
|
+
gap: var(--spacing-sm, 0.5rem);
|
|
1434
|
+
}
|
|
1435
|
+
|
|
1436
|
+
.grid__subnav,
|
|
1437
|
+
.grid__subnav__alternate {
|
|
1438
|
+
/* A strip that sticks would cover the rows it is filtering. */
|
|
1439
|
+
position: static;
|
|
1440
|
+
max-height: none;
|
|
1441
|
+
overflow: visible;
|
|
1442
|
+
}
|
|
1443
|
+
}
|
|
1444
|
+
|
|
1445
|
+
/* ============================================================================
|
|
1446
|
+
* Embedded mode — an index rendered inside another page's panel
|
|
1447
|
+
* ----------------------------------------------------------------------------
|
|
1448
|
+
* See the block comment on `GenericIndex` for what asks for this. Two shapes:
|
|
1449
|
+
*
|
|
1450
|
+
* - `tabLayout="underline"`: the filter menu becomes a horizontal strip
|
|
1451
|
+
* ABOVE the grid instead of a rail beside it. The strip itself is
|
|
1452
|
+
* TableFilter's (`variant="underline"`); everything here is the container
|
|
1453
|
+
* around it, which has to undo the rail's card, its sticky positioning and
|
|
1454
|
+
* its scroller — a strip is none of those things.
|
|
1455
|
+
* - `showTitle={false}`: no page-title bar, so the record count is rendered
|
|
1456
|
+
* against the grid instead. It sits at the right-hand end of the strip
|
|
1457
|
+
* when there is one, and in `.embeddedInfoRow` when there is not.
|
|
1458
|
+
*
|
|
1459
|
+
* Appended, like the passes above it: these are targeted overrides of rules
|
|
1460
|
+
* earlier in this file and the cascade order is what does the overriding.
|
|
1461
|
+
* ==========================================================================*/
|
|
1462
|
+
|
|
1463
|
+
/* The rail layout is a two-column grid (`.grid__subrow` above). Stacked, it is
|
|
1464
|
+
one column: `grid-template-columns: none` is what gives the reclaimed rail
|
|
1465
|
+
width back to the grid rather than leaving a 224px hole beside it. */
|
|
1466
|
+
.grid__subrow--stacked {
|
|
1467
|
+
display: flex;
|
|
1468
|
+
flex-direction: column;
|
|
1469
|
+
flex-wrap: nowrap;
|
|
1470
|
+
grid-template-columns: none;
|
|
1471
|
+
align-items: stretch;
|
|
1472
|
+
gap: 0;
|
|
1473
|
+
}
|
|
1474
|
+
|
|
1475
|
+
.grid__subrow--stacked > .grid__subnav,
|
|
1476
|
+
.grid__subrow--stacked > .grid__subcontent {
|
|
1477
|
+
flex: 0 0 auto;
|
|
1478
|
+
width: 100%;
|
|
1479
|
+
/* Without this the strip's min-content width floors the flex item, so a
|
|
1480
|
+
row of ten tabs widens the page instead of scrolling inside it. */
|
|
1481
|
+
min-width: 0;
|
|
1482
|
+
}
|
|
1483
|
+
|
|
1484
|
+
/* The strip is separated from the grid card by one gap, stated once here —
|
|
1485
|
+
`.grid__subnav--underline` zeroes its own margin. A tab row butted straight
|
|
1486
|
+
onto the card below reads as that card's header rather than as a control
|
|
1487
|
+
above it. */
|
|
1488
|
+
.grid__subrow--stacked > .grid__subcontent {
|
|
1489
|
+
margin: var(--spacing-md, 1rem) 0 0;
|
|
1490
|
+
}
|
|
1491
|
+
|
|
1492
|
+
.grid__subnav--underline {
|
|
1493
|
+
/* Not a card, not sticky, not a scroller. */
|
|
1494
|
+
position: static;
|
|
1495
|
+
max-height: none;
|
|
1496
|
+
overflow: visible;
|
|
1497
|
+
overscroll-behavior: auto;
|
|
1498
|
+
padding: 0;
|
|
1499
|
+
margin: 0;
|
|
1500
|
+
background: none;
|
|
1501
|
+
border: none;
|
|
1502
|
+
border-radius: 0;
|
|
1503
|
+
box-shadow: none;
|
|
1504
|
+
/* The one hairline under the whole strip; the selected tab's 3px accent
|
|
1505
|
+
edge sits on top of it. */
|
|
1506
|
+
border-bottom: 1px solid
|
|
1507
|
+
color-mix(in srgb, var(--paragraph-color, #2b2b2b) 12%, transparent);
|
|
1508
|
+
|
|
1509
|
+
/* A row, so the record count can sit at the far end of it rather than
|
|
1510
|
+
costing a line of its own. `flex-end` keeps the count on the strip's
|
|
1511
|
+
baseline instead of floating above the tabs. */
|
|
1512
|
+
display: flex;
|
|
1513
|
+
flex-direction: row;
|
|
1514
|
+
align-items: flex-end;
|
|
1515
|
+
gap: var(--spacing-md, 1rem);
|
|
1516
|
+
}
|
|
1517
|
+
|
|
1518
|
+
/* `.grid__subnav > *` above pads, tints and FLEXES the TableFilter wrapper for
|
|
1519
|
+
the rail. In a strip that padding indents the first tab off the page edge,
|
|
1520
|
+
the hover tint lights up the whole row, and the flex is the one that
|
|
1521
|
+
actually breaks it: as a flex container the tab list floors at its own
|
|
1522
|
+
min-content width, so a row wider than the panel widens the page instead of
|
|
1523
|
+
scrolling inside itself. Back to a block, which is what TableFilter's own
|
|
1524
|
+
stylesheet expects around the scroller. */
|
|
1525
|
+
.grid__subnav--underline > * {
|
|
1526
|
+
display: block;
|
|
1527
|
+
min-width: 0;
|
|
1528
|
+
padding: 0;
|
|
1529
|
+
background: none;
|
|
1530
|
+
}
|
|
1531
|
+
|
|
1532
|
+
.grid__subnav--underline > *:hover {
|
|
1533
|
+
background: none;
|
|
1534
|
+
}
|
|
1535
|
+
|
|
1536
|
+
/* The strip takes the room; the count takes what it needs. */
|
|
1537
|
+
.grid__subnav--underline > *:first-child {
|
|
1538
|
+
flex: 1 1 auto;
|
|
1539
|
+
min-width: 0;
|
|
1540
|
+
}
|
|
1541
|
+
|
|
1542
|
+
.grid__subnav--underline > .titleInfo {
|
|
1543
|
+
flex: 0 0 auto;
|
|
1544
|
+
/* Clear of the hairline, on the same optical line as the tab labels. */
|
|
1545
|
+
padding-bottom: 0.55rem;
|
|
1546
|
+
white-space: nowrap;
|
|
1547
|
+
}
|
|
1548
|
+
|
|
1549
|
+
/* No strip to sit in: the count gets its own row, right-aligned above the
|
|
1550
|
+
grid card and matched to the card's own horizontal inset. */
|
|
1551
|
+
.embeddedInfoRow {
|
|
1552
|
+
display: flex;
|
|
1553
|
+
justify-content: flex-end;
|
|
1554
|
+
padding: 0 0.25rem 0.5rem;
|
|
1555
|
+
}
|
|
1556
|
+
|
|
1557
|
+
.grid__subnav--underline > .titleInfo,
|
|
1558
|
+
.embeddedInfoRow > .titleInfo {
|
|
1559
|
+
/* The `.titleInfo` rule inside `.crmtitle` positions it for the title bar;
|
|
1560
|
+
neither of these is the title bar. */
|
|
1561
|
+
position: static;
|
|
1562
|
+
display: flex;
|
|
1563
|
+
align-items: baseline;
|
|
1564
|
+
gap: 0.75rem;
|
|
1565
|
+
width: max-content;
|
|
1566
|
+
}
|
|
1567
|
+
|
|
1568
|
+
.grid__subnav--underline > .titleInfo span,
|
|
1569
|
+
.embeddedInfoRow > .titleInfo span {
|
|
1570
|
+
font-size: 0.8125rem;
|
|
1571
|
+
color: var(--muted-color, #6b7688);
|
|
1572
|
+
}
|
|
1573
|
+
|
|
1574
|
+
.grid__subnav--underline > .titleInfo strong,
|
|
1575
|
+
.embeddedInfoRow > .titleInfo strong {
|
|
1576
|
+
color: var(--heading-color, var(--primary-color, #1b3933));
|
|
1577
|
+
font-weight: 600;
|
|
1578
|
+
}
|
|
1579
|
+
|
|
1580
|
+
/* Narrow viewports need nothing of their own here. The rail's phone rules sit
|
|
1581
|
+
above this block, so a stacked row's own `gap: 0` and single column already
|
|
1582
|
+
win on source order — and the strip inside is the same one TableFilter shows
|
|
1583
|
+
on a phone anyway. */
|
|
1584
|
+
|
|
1585
|
+
/* ============================================================================
|
|
1586
|
+
* The grid card — one card, not two
|
|
1587
|
+
* ----------------------------------------------------------------------------
|
|
1588
|
+
* `GenericIndex` renders the data grid as
|
|
1589
|
+
*
|
|
1590
|
+
* .grid__full <- a card: white, bordered, rounded, lifted
|
|
1591
|
+
* .dataGridTopContainer <- the search / actions toolbar (a SIBLING)
|
|
1592
|
+
* .dataGridContainer <- ANOTHER card: bordered, rounded 14px,
|
|
1593
|
+
* shadowed, overflow hidden
|
|
1594
|
+
*
|
|
1595
|
+
* so the page drew a card inside a card, three pixels apart, with two
|
|
1596
|
+
* different corner radii, and put the toolbar in the gap between them — which
|
|
1597
|
+
* is exactly the "rounded corners but the white background ruins it, doesn't
|
|
1598
|
+
* line up, has a bit of padding" the owner is looking at. On a near-white page
|
|
1599
|
+
* ground the two whites were indistinguishable, so all you saw was a rounded
|
|
1600
|
+
* outline that didn't follow anything.
|
|
1601
|
+
*
|
|
1602
|
+
* The outer element is the only one that wraps BOTH the toolbar and the table,
|
|
1603
|
+
* so it is the one that gets to be the card. The inner container gives up its
|
|
1604
|
+
* border, its radius and its shadow and becomes a plain surface flush inside
|
|
1605
|
+
* it: search row, column header, rows and pager all on one white card, one
|
|
1606
|
+
* hairline around the lot, corners that clip what is actually at them.
|
|
1607
|
+
*
|
|
1608
|
+
* Scoped by attribute rather than by `:has()` on a module class, because
|
|
1609
|
+
* `.dataGridContainer` is DataGrid.module.scss's local name and hashes to
|
|
1610
|
+
* something this file cannot spell. `[class*='dataGridContainer']` matches the
|
|
1611
|
+
* generated `_dataGridContainer_hwl8s_579` and nothing else on the page. The
|
|
1612
|
+
* same trick is used for the auth brand panel in the app's _tokens.scss.
|
|
1613
|
+
*
|
|
1614
|
+
* Grids rendered anywhere OTHER than inside a `.grid__full` — in a modal, on a
|
|
1615
|
+
* detail tab — are untouched by this and keep drawing their own card, which is
|
|
1616
|
+
* correct: there is nothing else around them to be the card.
|
|
1617
|
+
* ==========================================================================*/
|
|
1618
|
+
|
|
1619
|
+
.grid__full:has([class*='dataGridContainer']) {
|
|
1620
|
+
/* `overflow` stays visible: the column filter selects, the row-action
|
|
1621
|
+
popovers and the pager's per-page dropdown all open out of the card and
|
|
1622
|
+
are clipped to nothing the moment this is `hidden`. The clipping that
|
|
1623
|
+
the radius needs happens on the inner container instead, which contains
|
|
1624
|
+
only the table and has nothing that overflows. */
|
|
1625
|
+
overflow: visible;
|
|
1626
|
+
|
|
1627
|
+
/* Descendant, not `>`. Measured: `GenericIndex` wraps the toolbar and the
|
|
1628
|
+
grid container together in one unclassed `<div>`, so the card's only
|
|
1629
|
+
direct child is that wrapper and a child combinator matches nothing. */
|
|
1630
|
+
[class*='dataGridContainer'] {
|
|
1631
|
+
border: 0;
|
|
1632
|
+
box-shadow: none;
|
|
1633
|
+
/* NOT `inherit`: the parent element is that unclassed wrapper, whose
|
|
1634
|
+
radius is 0, so inheriting would square the corners off.
|
|
1635
|
+
The card's INNER curve is its radius less its own 1px border, and
|
|
1636
|
+
this element sits exactly on that padding box — so that is the
|
|
1637
|
+
radius that meets the card's edge without a sliver of white
|
|
1638
|
+
overshooting the curve, or a gap short of it. */
|
|
1639
|
+
border-radius: calc(var(--card-radius, 10px) - 1px);
|
|
1640
|
+
overflow: hidden;
|
|
1641
|
+
}
|
|
1642
|
+
|
|
1643
|
+
/* The toolbar is the card's top edge now rather than a strip floating on
|
|
1644
|
+
it, so it loses the horizontal inset it needed when the card had 2px of
|
|
1645
|
+
padding, and its hairline runs the full width to meet the card's own
|
|
1646
|
+
border on both sides. */
|
|
1647
|
+
[class*='dataGridTopContainer'] {
|
|
1648
|
+
border-top-left-radius: calc(var(--card-radius, 10px) - 1px);
|
|
1649
|
+
border-top-right-radius: calc(var(--card-radius, 10px) - 1px);
|
|
1650
|
+
border-bottom-color: var(--border-color, #e1e1e1);
|
|
1651
|
+
}
|
|
1652
|
+
}
|
|
@@ -52,8 +52,11 @@
|
|
|
52
52
|
========================================================================= */
|
|
53
53
|
|
|
54
54
|
.header {
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
/* `color` was also var(--primary-color) — the same value as the
|
|
56
|
+
background, so every piece of header text was invisible against it
|
|
57
|
+
wherever the token was defined. */
|
|
58
|
+
background: var(--primary-color, #1b3933);
|
|
59
|
+
color: var(--tertiary-color, #fff);
|
|
57
60
|
position: sticky;
|
|
58
61
|
top: 0;
|
|
59
62
|
width: 100%;
|
|
@@ -102,7 +105,7 @@
|
|
|
102
105
|
background: var(--bg);
|
|
103
106
|
|
|
104
107
|
.content-header {
|
|
105
|
-
background: rgba(var(--tertiary-color-rgb), 1
|
|
108
|
+
background: rgba(var(--tertiary-color-rgb, 255, 255, 255), 1);
|
|
106
109
|
border-bottom: 1px solid rgba(0, 0, 0, 0.14);
|
|
107
110
|
box-sizing: border-box;
|
|
108
111
|
padding: 1em;
|