@webority/theme 0.27.1 → 0.27.3

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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webority/theme",
3
- "version": "0.27.1",
3
+ "version": "0.27.3",
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": {
@@ -1,4 +1,5 @@
1
1
  // Signal: an opt-in brand layer, a violet-primary palette with ink headings and a serif display face.
2
+ // Its dark mode is pure black with neutral grey surfaces; violet is kept for accents only.
2
3
  //
3
4
  // Loaded AFTER webority-theme.css; the default theme never contains these values. It re-points the
4
5
  // --wui-* tokens, then overrides the few Bootstrap values the theme compiles as literals (button
@@ -74,16 +75,17 @@
74
75
  --wui-shadow-overlay: 0 8px 28px -6px rgba(22, 9, 58, 0.16);
75
76
  --wui-shadow-overlay-lg: 0 24px 60px -16px rgba(22, 9, 58, 0.30);
76
77
 
77
- --wui-dark-bg-page: #120830;
78
- --wui-dark-bg-elevated: #0E0626;
79
- --wui-dark-bg-surface: #1A0F40;
80
- --wui-dark-bg-muted: #261853;
81
- --wui-dark-border: #35266B;
82
- --wui-dark-border-strong: #4B3A8A;
83
- --wui-dark-progress-track: #35266B;
84
- --wui-dark-text: #EDE9F8;
85
- --wui-dark-text-muted: #C2BADB;
86
- --wui-dark-text-subtle: #A59BC6;
78
+ // Dark mode is pure black and neutral grey; violet appears only on accents (fills, links, focus, selection marks).
79
+ --wui-dark-bg-page: #000000;
80
+ --wui-dark-bg-elevated: #0F0F0F;
81
+ --wui-dark-bg-surface: #161616;
82
+ --wui-dark-bg-muted: #1E1E1E;
83
+ --wui-dark-border: #2A2A2A;
84
+ --wui-dark-border-strong: #333333;
85
+ --wui-dark-progress-track: #333333;
86
+ --wui-dark-text: #EDEDED;
87
+ --wui-dark-text-muted: #C0C0C0;
88
+ --wui-dark-text-subtle: #A0A0A0;
87
89
  --wui-dark-primary: #A98BFF;
88
90
  --wui-dark-primary-hover: #BFA6FF;
89
91
 
@@ -135,7 +137,8 @@
135
137
  .page-title,
136
138
  .card-title,
137
139
  .wui-modal-title,
138
- .empty-state-title {
140
+ .empty-state-title,
141
+ .result-title {
139
142
  font-family: var(--wui-font-display);
140
143
  font-weight: 600;
141
144
  font-style: normal;
@@ -145,18 +148,20 @@
145
148
 
146
149
  @mixin wui-signal-dark {
147
150
  --wui-signal-heading: #C4AEFF;
148
- --color-primary-soft: color-mix(in srgb, #A98BFF 20%, transparent);
151
+ // Selected, hover and highlight fills are a neutral lift; the violet stays on the text, border
152
+ // or edge that marks the state. check-contrast.mjs mirrors the 8%; change them together.
153
+ --color-primary-soft: color-mix(in srgb, #FFFFFF 8%, transparent);
149
154
  // Ink on the lilac fill (--color-primary): 8:1 or better.
150
155
  --color-primary-text: #16093A;
151
156
  --color-progress-label: #16093A;
152
- --bs-body-bg-rgb: 18, 8, 48;
153
- --bs-body-color-rgb: 237, 233, 248;
154
- --bs-emphasis-color-rgb: 237, 233, 248;
155
- --bs-secondary-color-rgb: 194, 186, 219;
156
- --bs-tertiary-color-rgb: 165, 155, 198;
157
- --bs-secondary-bg-rgb: 26, 15, 64;
158
- --bs-tertiary-bg-rgb: 38, 24, 83;
159
- --bs-border-color-rgb: 53, 38, 107;
157
+ --bs-body-bg-rgb: 0, 0, 0;
158
+ --bs-body-color-rgb: 237, 237, 237;
159
+ --bs-emphasis-color-rgb: 237, 237, 237;
160
+ --bs-secondary-color-rgb: 192, 192, 192;
161
+ --bs-tertiary-color-rgb: 160, 160, 160;
162
+ --bs-secondary-bg-rgb: 22, 22, 22;
163
+ --bs-tertiary-bg-rgb: 30, 30, 30;
164
+ --bs-border-color-rgb: 42, 42, 42;
160
165
  --bs-link-color: #A98BFF;
161
166
  --bs-link-color-rgb: 169, 139, 255;
162
167
  --bs-link-hover-color: #BFA6FF;
@@ -188,6 +193,35 @@
188
193
  :where(.stepper:not(.wizard-stepper)) {
189
194
  --wui-step-accent-fg: #16093A;
190
195
  }
196
+
197
+ // Components that mix their violet fill inline rather than through --color-primary-soft.
198
+ // :where(&) keeps each rule at the component's own specificity, so a tone variant still wins.
199
+ :where(&) .struct-card.checked,
200
+ :where(&) .tpg-arrow:hover:not(:disabled),
201
+ :where(&) .tpg-page:hover:not(.is-active),
202
+ :where(&) .u-action:hover:not(:disabled),
203
+ :where(&) .tbl-empty-icon,
204
+ :where(&) .u-avatar,
205
+ :where(&) .wui-file-viewer-audio-art {
206
+ background: var(--color-primary-soft);
207
+ }
208
+ :where(&) .wui-calendar-view-btn[aria-pressed="true"],
209
+ :where(&) .compare-table td.is-highlight {
210
+ background: color-mix(in srgb, #FFFFFF 8%, var(--color-surface));
211
+ }
212
+ :where(&) .segmented {
213
+ --segmented-selected-bg: color-mix(in srgb, #FFFFFF 8%, var(--color-surface));
214
+ }
215
+ :where(&) .table-ledger tbody tr.is-selected:hover {
216
+ --bs-table-bg-state: color-mix(in srgb, #FFFFFF 12%, transparent);
217
+ }
218
+ // A grey row alone reads as disabled; the violet edge says chosen. One step below the row status
219
+ // bar's specificity, so a status row keeps its own colour bar.
220
+ :where(&) .table-ledger tbody tr.is-selected > :first-child {
221
+ box-shadow:
222
+ inset 3px 0 0 0 var(--color-primary),
223
+ inset 0 0 0 9999px var(--bs-table-bg-state, var(--bs-table-bg-type, var(--bs-table-accent-bg)));
224
+ }
191
225
  }
192
226
 
193
227
  :root[data-theme="dark"],
@@ -351,7 +351,10 @@ a.info-row:hover .info-value {
351
351
  padding: 0;
352
352
  }
353
353
  .descs-item {
354
- display: contents;
354
+ display: flex;
355
+ flex-direction: column;
356
+ min-width: 0;
357
+ border-bottom: 1px solid var(--color-border);
355
358
  grid-column: span var(--descs-span, 1);
356
359
  }
357
360
  .descs-label {
@@ -360,16 +363,14 @@ a.info-row:hover .info-value {
360
363
  text-transform: uppercase;
361
364
  letter-spacing: 0.04em;
362
365
  color: var(--color-text-subtle);
363
- padding: 12px 16px;
364
- border-bottom: 1px solid var(--color-border);
366
+ padding: 12px 16px 0;
365
367
  margin: 0;
366
368
  }
367
369
  .descs-value {
368
370
  font-size: 14px;
369
371
  font-weight: 500;
370
372
  color: var(--color-text);
371
- padding: 12px 16px;
372
- border-bottom: 1px solid var(--color-border);
373
+ padding: 4px 16px 12px;
373
374
  margin: 0;
374
375
  word-break: break-word;
375
376
  }
@@ -379,24 +380,22 @@ a.info-row:hover .info-value {
379
380
  color: var(--color-text-subtle);
380
381
  }
381
382
  // Small size variant.
382
- .descs-sm .descs-label,
383
+ .descs-sm .descs-label {
384
+ font-size: 12px;
385
+ padding: 8px 12px 0;
386
+ }
383
387
  .descs-sm .descs-value {
384
388
  font-size: 12px;
385
- padding: 8px 12px;
389
+ padding: 4px 12px 8px;
386
390
  }
387
- // Bordered variant removes inner dividers (only outer border on cells).
388
- .descs-bordered .descs-label,
389
- .descs-bordered .descs-value {
391
+ // Bordered variant draws dividers between neighbouring items instead of under each row.
392
+ .descs-bordered .descs-item {
390
393
  border-bottom: none;
391
394
  border-right: 1px solid var(--color-border);
392
395
  }
393
- .descs-bordered .descs-item:last-child .descs-label,
394
- .descs-bordered .descs-item:last-child .descs-value {
396
+ .descs-bordered .descs-item:last-child {
395
397
  border-right: none;
396
398
  }
397
- .descs-bordered .descs-list > :nth-child(2n-1) {
398
- border-bottom: 1px solid var(--color-border);
399
- }
400
399
  // Column variants — set the grid-template-columns.
401
400
  .descs-col-1 .descs-list {
402
401
  --descs-cols: 1;
@@ -263,8 +263,8 @@
263
263
  flex-direction: column;
264
264
  gap: 2px;
265
265
  overflow-y: auto;
266
- // The rail is chrome, not content: a scrollbar here reads as clutter and, at
267
- // 88px collapsed, would eat a meaningful share of the width.
266
+ // A native scrollbar always takes layout width, and its width differs by browser and OS, so
267
+ // it stays hidden; the thumb below is drawn over the links instead.
268
268
  scrollbar-width: none;
269
269
  }
270
270
  .app-sidebar-scroll::-webkit-scrollbar {
@@ -272,6 +272,47 @@
272
272
  width: 0;
273
273
  height: 0;
274
274
  }
275
+ // Scroll thumb for a long menu, shown on hover or keyboard focus and only when the links
276
+ // overflow. It is a sticky pseudo-element over the nav's right edge, moved by the nav's own
277
+ // scroll timeline, so it takes no width. The negative bottom margin cancels its height and the
278
+ // flex gap, so no link moves. Browsers without scroll timelines keep the hidden scrollbar.
279
+ @supports (animation-timeline: scroll()) {
280
+ .app-sidebar-scroll {
281
+ container-type: scroll-state;
282
+ }
283
+ .app-sidebar-scroll::before {
284
+ content: "";
285
+ position: sticky;
286
+ top: 0;
287
+ flex: none;
288
+ align-self: flex-end;
289
+ width: 6px;
290
+ height: 48px;
291
+ margin-bottom: -50px;
292
+ border-radius: 9999px;
293
+ background: var(--wui-scrollbar);
294
+ visibility: hidden;
295
+ opacity: 0;
296
+ pointer-events: none;
297
+ transition: opacity 0.2s var(--wui-ease-ui);
298
+ animation: wui-sidebar-thumb linear both;
299
+ animation-timeline: scroll(nearest);
300
+ }
301
+ @container scroll-state(scrollable: y) {
302
+ .app-sidebar-scroll::before {
303
+ visibility: visible;
304
+ }
305
+ }
306
+ .app-sidebar-scroll:hover::before,
307
+ .app-sidebar-scroll:focus-within::before {
308
+ opacity: 1;
309
+ }
310
+ }
311
+ @keyframes wui-sidebar-thumb {
312
+ to {
313
+ top: calc(100% - 48px);
314
+ }
315
+ }
275
316
  // Between the brand row and the nav — a workspace/tenant switcher, an environment
276
317
  // badge. It must not shrink when the nav overflows. The full card has no place on
277
318
  // the 88px rail, so the collapsed state hides it (the mobile drawer restores it).