@webority/theme 0.53.1 → 0.54.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.
Files changed (62) hide show
  1. package/dist/purge-safelist.json +339 -3
  2. package/dist/webority-theme.css +1 -1
  3. package/package.json +1 -1
  4. package/scss/_components.scss +27 -4
  5. package/scss/_marketing.scss +5 -0
  6. package/scss/_variables.scss +5 -4
  7. package/scss/_wui-aliases.scss +14 -0
  8. package/scss/_wui-components.scss +29 -0
  9. package/scss/wui/_avatar-picker.scss +1 -1
  10. package/scss/wui/_calendar.scss +5 -5
  11. package/scss/wui/_card.scss +2 -2
  12. package/scss/wui/_carousel.scss +182 -0
  13. package/scss/wui/_chart.scss +2 -2
  14. package/scss/wui/_choice.scss +88 -8
  15. package/scss/wui/_code-block.scss +138 -0
  16. package/scss/wui/_command-palette.scss +99 -1
  17. package/scss/wui/_comment-thread.scss +268 -0
  18. package/scss/wui/_context-menu.scss +2 -2
  19. package/scss/wui/_controls.scss +14 -12
  20. package/scss/wui/_data.scss +407 -14
  21. package/scss/wui/_disclosure.scss +2 -2
  22. package/scss/wui/_display.scss +13 -9
  23. package/scss/wui/_dock.scss +2 -2
  24. package/scss/wui/_drawer.scss +198 -0
  25. package/scss/wui/_file-viewer.scss +6 -6
  26. package/scss/wui/_groups.scss +111 -0
  27. package/scss/wui/_hover-card.scss +55 -0
  28. package/scss/wui/_illustration.scss +76 -0
  29. package/scss/wui/_image-crop.scss +6 -6
  30. package/scss/wui/_inline-edit.scss +131 -0
  31. package/scss/wui/_interaction.scss +286 -0
  32. package/scss/wui/_kanban.scss +6 -6
  33. package/scss/wui/_lightbox.scss +169 -0
  34. package/scss/wui/_media.scss +8 -5
  35. package/scss/wui/_mention-input.scss +88 -0
  36. package/scss/wui/_menubar.scss +110 -0
  37. package/scss/wui/_navigation-menu.scss +172 -0
  38. package/scss/wui/_navigation.scss +109 -6
  39. package/scss/wui/_notification-center.scss +251 -0
  40. package/scss/wui/_onboarding-checklist.scss +199 -0
  41. package/scss/wui/_overlays.scss +7 -11
  42. package/scss/wui/_rating.scss +87 -0
  43. package/scss/wui/_record-pager.scss +27 -0
  44. package/scss/wui/_relative-time.scss +10 -0
  45. package/scss/wui/_resizable.scss +98 -0
  46. package/scss/wui/_rich-text.scss +2 -2
  47. package/scss/wui/_rolling-number.scss +60 -0
  48. package/scss/wui/_sections.scss +315 -0
  49. package/scss/wui/_shell-parts.scss +12 -3
  50. package/scss/wui/_shell.scss +6 -6
  51. package/scss/wui/_shortcuts.scss +143 -0
  52. package/scss/wui/_show-more.scss +30 -0
  53. package/scss/wui/_sortable.scss +2 -2
  54. package/scss/wui/_split-view.scss +321 -0
  55. package/scss/wui/_toolbar.scss +4 -4
  56. package/scss/wui/_tour.scss +2 -2
  57. package/scss/wui/_tree.scss +2 -2
  58. package/scss/wui/_truncate.scss +32 -0
  59. package/scss/wui/_typography.scss +14 -0
  60. package/scss/wui/_utilities.scss +8 -8
  61. package/scss/wui/_whats-new.scss +147 -0
  62. package/scss/wui/_workspace.scss +2 -2
@@ -0,0 +1,286 @@
1
+ // ── Focus ring and pressed state ──
2
+ // The one keyboard focus ring and the one pressed wash, for every control the library draws.
3
+ // The recipe is tokens in _wui-aliases.scss: an outline of --wui-focus-ring-width in
4
+ // --color-focus-ring at --wui-focus-ring-offset (--wui-focus-ring-inset inside a scroller), and
5
+ // --color-pressed-overlay laid over the control's own fill. A component partial keeps its own
6
+ // :focus-visible rule only to place the ring (offset, radius, which box carries it).
7
+ //
8
+ // Part of the wui-components layer, imported last so its pressed rules settle ties with the
9
+ // hover rules of the partials above.
10
+
11
+ // ---- Default ring -----------------------------------------------------------
12
+ // Anything focusable that no partial styles gets the shared ring instead of the browser's.
13
+ // Zero specificity, so every component rule (including a panel's deliberate `outline: none`)
14
+ // still wins. Text fields are left out: they get the field edge below.
15
+ :where(
16
+ a[href],
17
+ area[href],
18
+ button,
19
+ summary,
20
+ input[type="checkbox"],
21
+ input[type="radio"],
22
+ input[type="range"],
23
+ [role="button"],
24
+ [role="link"],
25
+ [role="tab"],
26
+ [role="menuitem"],
27
+ [role="menuitemcheckbox"],
28
+ [role="menuitemradio"],
29
+ [role="option"],
30
+ [role="treeitem"],
31
+ [role="switch"],
32
+ [role="checkbox"],
33
+ [role="radio"],
34
+ [role="slider"],
35
+ [tabindex]:not([tabindex="-1"])
36
+ ):where(:focus-visible) {
37
+ outline: var(--wui-focus-ring-width) solid var(--color-focus-ring);
38
+ outline-offset: var(--wui-focus-ring-offset);
39
+ }
40
+
41
+ // ---- Bootstrap controls -----------------------------------------------------
42
+ // Bootstrap rings a button with a 50% primary box-shadow, under 3:1 on white, and repaints it
43
+ // on toggled and checked buttons. The shared outline replaces it; its offset leaves a real gap,
44
+ // so the ring reads beside a solid fill and on whatever surface is behind the button.
45
+ .btn {
46
+ --bs-btn-focus-box-shadow: 0 0 #0000;
47
+ }
48
+ .btn:focus-visible,
49
+ .btn-check:focus-visible + .btn {
50
+ outline: var(--wui-focus-ring-width) solid var(--color-focus-ring);
51
+ outline-offset: var(--wui-focus-ring-offset);
52
+ }
53
+
54
+ // Bootstrap rings the close button on any :focus, a mouse click included.
55
+ .btn-close {
56
+ --bs-btn-close-focus-shadow: 0 0 #0000;
57
+ }
58
+ .btn-close:focus-visible {
59
+ outline: var(--wui-focus-ring-width) solid var(--color-focus-ring);
60
+ outline-offset: var(--wui-focus-ring-offset);
61
+ }
62
+
63
+ .pagination {
64
+ --bs-pagination-focus-box-shadow: 0 0 #0000;
65
+ }
66
+ .page-link:focus-visible {
67
+ outline: var(--wui-focus-ring-width) solid var(--color-focus-ring);
68
+ outline-offset: var(--wui-focus-ring-offset);
69
+ }
70
+
71
+ // A menu row showed focus only as the soft hover tint (about 1.2:1). Inset, because the menu
72
+ // scrolls and would clip an outer ring.
73
+ .dropdown-item:focus-visible {
74
+ outline: var(--wui-focus-ring-width) solid var(--color-focus-ring);
75
+ outline-offset: var(--wui-focus-ring-inset);
76
+ }
77
+
78
+ // ---- Not obscured (WCAG 2.4.11) ---------------------------------------------
79
+ // A control focused by Tab scrolls clear of the sticky shell topbar (72px) and a sticky form
80
+ // footer (AppFormActions sticky, about 78px), not under them.
81
+ html:has(.app-shell .app-topbar) {
82
+ scroll-padding-top: 88px;
83
+ }
84
+ html:has(.form-actions-sticky) {
85
+ scroll-padding-bottom: 96px;
86
+ }
87
+ // A modal or drawer body scrolls on its own, so the document's padding does not reach a sticky
88
+ // footer inside it.
89
+ :is(.wui-modal-body, .modal-body, .wui-drawer-body):has(.form-actions-sticky) {
90
+ scroll-padding-bottom: 96px;
91
+ }
92
+
93
+ // ---- Text fields --------------------------------------------------------------
94
+ // A field's focus cue is its edge: the 1px border plus an outline of the rest of
95
+ // --wui-focus-ring-width right outside it, so the edge reads 2px and nothing shifts. Each
96
+ // selector repeats its partial's focus rule at the same specificity, so an invalid field's own
97
+ // border colour still wins and only the outer edge is added. The open state of a picker counts:
98
+ // focus has moved into its pop-up, but the field still reads as the one being edited.
99
+ .form-control:focus,
100
+ .form-select:focus,
101
+ .input:focus,
102
+ .select:focus,
103
+ .textarea:focus,
104
+ .search-select-control:focus-within,
105
+ .search-select-control.open,
106
+ .search-select-search:focus-within,
107
+ .datepicker.open .datepicker-trigger,
108
+ .daterange.open .daterange-trigger,
109
+ .timepicker.open .timepicker-trigger,
110
+ .input-affixed:focus-within,
111
+ .input-with-unit:focus-within,
112
+ .num-wrap:focus-within,
113
+ .app-phone-number-input .phone-input-wrap:focus-within,
114
+ .wui-input-group:focus-within,
115
+ .otp-slot.active,
116
+ .dropdown-search-input:focus,
117
+ .file-input:not(.has-files):focus-within,
118
+ .wui-rich-text-shell:focus-within,
119
+ .wui-rich-text-link-input:focus,
120
+ .workspace-switcher-trigger:focus-visible,
121
+ .workspace-switcher-trigger[aria-expanded="true"] {
122
+ outline: calc(var(--wui-focus-ring-width) - 1px) solid var(--color-focus-ring);
123
+ outline-offset: 0;
124
+ }
125
+ // A control inside a wrapper that draws the border leaves the edge to the wrapper, and a bare
126
+ // input has no edge.
127
+ .input-bare:focus,
128
+ :is(.input-affixed, .input-with-unit, .num-wrap, .phone-input-wrap, .wui-input-group) :is(.form-control, .input, .textarea, .num-input):focus {
129
+ outline: none;
130
+ }
131
+
132
+ // ---- Active option in a pop-up list --------------------------------------------
133
+ // Search results, the country list, select and autocomplete options, mentions and the command
134
+ // palette keep focus in their input and mark the keyboard's row (aria-activedescendant) with
135
+ // the hover tint alone, about 1.2:1. The inset ring makes that row plain; inset, because the
136
+ // list scrolls and would clip an outer ring.
137
+ .wui-topsearch-hit.is-active,
138
+ .country-dropdown-item.is-active,
139
+ .search-select-option.is-active,
140
+ .wui-mention-option.is-active,
141
+ .wui-cmd-item[aria-selected="true"] {
142
+ outline: var(--wui-focus-ring-width) solid var(--color-focus-ring);
143
+ outline-offset: var(--wui-focus-ring-inset);
144
+ }
145
+
146
+ // ---- Pressed ----------------------------------------------------------------
147
+ // One step deeper than hover: the control's own ink at 12% over whatever fill it has, on a
148
+ // solid fill and a transparent one, in both themes. It is a colour change, so it needs no
149
+ // reduced-motion variant. !important because pressing always happens under the pointer, so a
150
+ // more specific hover rule's `background` shorthand would otherwise reset the wash.
151
+ // Buttons (.btn) keep Bootstrap's active fill. Controls drawn by a background image (checkbox,
152
+ // switch, Bootstrap's close glyph) are not in this list.
153
+ :is(
154
+ .u-action,
155
+ .pw-toggle,
156
+ .input-clear,
157
+ .num-btn,
158
+ .num-stepper-btns button,
159
+ .search-clear,
160
+ .search-select-clear,
161
+ .search-select-reset,
162
+ button.wui-input-leading,
163
+ button.wui-input-trailing,
164
+ .country-toggle,
165
+ .wui-timepicker-toggle,
166
+ .datepicker-nav-btn,
167
+ button.datepicker-month,
168
+ .datepicker-day,
169
+ .datepicker-cell,
170
+ .wui-daterange-preset,
171
+ .timepicker-option,
172
+ .wui-calendar-nav-btn,
173
+ .wui-calendar-today-btn,
174
+ .wui-calendar-view-btn,
175
+ .app-tabs-scroll-btn,
176
+ .wui-overflow-more,
177
+ .wui-overflow-item,
178
+ .app-sidebar-toggle,
179
+ .topbar-icon-btn,
180
+ .infotip-btn,
181
+ .wui-dropdown-trigger,
182
+ .wui-banner-dismiss,
183
+ .alert-dismissible .btn-close,
184
+ .wui-modal-close,
185
+ .wui-drawer-close,
186
+ .wui-toast-action,
187
+ .wui-shortcut-close,
188
+ .wui-shortcut-toggle,
189
+ .wui-sortable-handle,
190
+ .wui-crop-toolbtn,
191
+ .wui-crop-zoombtn,
192
+ .wui-file-viewer-zoom,
193
+ .wui-rich-text-button,
194
+ .wui-rich-text-link-apply,
195
+ .wui-rich-text-link-cancel,
196
+ .wui-rich-text-link-remove,
197
+ .wui-kanban-action,
198
+ .wui-kanban-collapse,
199
+ .wui-kanban-more,
200
+ .wui-comment-action,
201
+ .wui-reaction-add,
202
+ .wui-reaction-choice,
203
+ button.wui-reaction,
204
+ .wui-cmd-back,
205
+ button.wui-cmd-crumb,
206
+ .wui-code-copy,
207
+ .wui-notification-center-markall,
208
+ .wui-notification-center-foot,
209
+ .wui-bell-markall,
210
+ .wui-bell-foot,
211
+ .wui-onboarding-toggle,
212
+ .wui-onboarding-restore,
213
+ .attach-remove,
214
+ .attach-item-remove,
215
+ .file-preview-remove,
216
+ .set-uploader-remove,
217
+ .chip-remove,
218
+ .repeater-remove,
219
+ .wui-usermenu-trigger,
220
+ .workspace-switcher-trigger,
221
+ .workspace-switcher-create,
222
+ .workspace-switcher-footer-action,
223
+ .wui-carousel-arrow,
224
+ .wui-carousel-pause,
225
+ .wui-menubar-trigger,
226
+ .wui-nav-menu-trigger,
227
+ .wui-expand-toggle,
228
+ .wui-group-toggle,
229
+ .tpg-arrow,
230
+ .tpg-page,
231
+ .page-link,
232
+ .dropdown-item,
233
+ .country-dropdown-item,
234
+ .search-select-option,
235
+ .wui-tree-row,
236
+ .wui-split-link,
237
+ .wui-topsearch-hit,
238
+ a.wui-bell-item,
239
+ .wui-notification-center-item,
240
+ .workspace-switcher-option,
241
+ .app-nav-item,
242
+ .wui-tabbar-item,
243
+ .dock-item,
244
+ .toolbar-item,
245
+ .toolbar-action,
246
+ .app-tab,
247
+ .segmented-option,
248
+ .choice-chip,
249
+ .chip-clickable,
250
+ .faq-q,
251
+ .wui-chart-legend-item,
252
+ .wui-column-menu-item,
253
+ .wui-nav-menu-link,
254
+ .wui-nav-menu-toplink,
255
+ .wui-whats-new-link,
256
+ a.wui-onboarding-label,
257
+ .wui-inline-edit-display,
258
+ .table th.sortable,
259
+ .wui-lightbox-item,
260
+ .card-clickable,
261
+ .res-card,
262
+ a.kpi,
263
+ a.info-row,
264
+ .struct-card,
265
+ .avatar-clickable,
266
+ .attach-drop,
267
+ .logo-dropzone,
268
+ .wui-rating-input .wui-rating-star
269
+ ):active:not(:disabled, [aria-disabled="true"]) {
270
+ background-image: linear-gradient(var(--color-pressed-overlay), var(--color-pressed-overlay)) !important;
271
+ }
272
+
273
+ // Glyph-only controls have little fill for the wash to show on: the glyph itself answers.
274
+ // No transform on the close button: an alert positions its close with one.
275
+ .btn-close:active:not(:disabled) {
276
+ opacity: 1;
277
+ }
278
+ .wui-carousel-dot:active::before {
279
+ background: var(--color-text);
280
+ }
281
+ @media (prefers-reduced-motion: no-preference) {
282
+ .wui-rating-input:not([disabled]) .wui-rating-star:active {
283
+ transform: scale(var(--wui-press-scale));
284
+ transition: transform var(--wui-press-duration) ease-out;
285
+ }
286
+ }
@@ -196,8 +196,8 @@
196
196
  .wui-kanban-collapse:focus-visible,
197
197
  .wui-kanban-action:focus-visible,
198
198
  .wui-kanban-switch:focus-visible {
199
- outline: 2px solid var(--color-primary);
200
- outline-offset: 2px;
199
+ outline: var(--wui-focus-ring-width) solid var(--color-focus-ring);
200
+ outline-offset: var(--wui-focus-ring-offset);
201
201
  }
202
202
  @media (pointer: coarse) {
203
203
  .wui-kanban-collapse,
@@ -257,8 +257,8 @@
257
257
  border-color: var(--color-border-strong);
258
258
  }
259
259
  .wui-kanban-card:focus-visible {
260
- outline: 2px solid var(--color-primary);
261
- outline-offset: 2px;
260
+ outline: var(--wui-focus-ring-width) solid var(--color-focus-ring);
261
+ outline-offset: var(--wui-focus-ring-offset);
262
262
  }
263
263
  .wui-kanban-card[hidden],
264
264
  .wui-kanban-card[data-wui-overflow] {
@@ -301,8 +301,8 @@
301
301
  color: var(--color-text);
302
302
  }
303
303
  .wui-kanban-more:focus-visible {
304
- outline: 2px solid var(--color-primary);
305
- outline-offset: 2px;
304
+ outline: var(--wui-focus-ring-width) solid var(--color-focus-ring);
305
+ outline-offset: var(--wui-focus-ring-offset);
306
306
  }
307
307
  @media (pointer: coarse) {
308
308
  .wui-kanban-more {
@@ -0,0 +1,169 @@
1
+ // ── Lightbox ──
2
+ // AppLightbox / <app-lightbox> (a <wui-lightbox> element): a gallery of thumbnails that open
3
+ // full screen with zoom, previous and next, a caption and a download. The element builds the
4
+ // dialog inside itself, so a lightbox opened from a modal stays inside that modal's focus trap.
5
+ //
6
+ // Part of the wui-components layer, see _wui-components.scss for load order.
7
+
8
+ .wui-lightbox {
9
+ display: flex;
10
+ flex-wrap: wrap;
11
+ gap: 8px;
12
+ }
13
+ .wui-lightbox-item {
14
+ display: block;
15
+ flex: 0 0 auto;
16
+ width: 112px;
17
+ aspect-ratio: 4 / 3;
18
+ overflow: hidden;
19
+ border: 1px solid var(--color-border);
20
+ border-radius: var(--wui-radius);
21
+ background: var(--color-bg-muted);
22
+ cursor: zoom-in;
23
+ img {
24
+ display: block;
25
+ width: 100%;
26
+ height: 100%;
27
+ object-fit: cover;
28
+ }
29
+ &:hover {
30
+ border-color: var(--color-border-strong);
31
+ }
32
+ &:focus-visible {
33
+ outline: var(--wui-focus-ring-width) solid var(--color-focus-ring);
34
+ outline-offset: var(--wui-focus-ring-offset);
35
+ }
36
+ }
37
+
38
+ // Above a modal (so a gallery in a dialog opens over it), below menus and tooltips.
39
+ .wui-lightbox-overlay {
40
+ position: fixed;
41
+ inset: 0;
42
+ z-index: var(--wui-z-tour);
43
+ display: flex;
44
+ flex-direction: column;
45
+ background: var(--color-scrim-strong);
46
+ color: var(--color-on-scrim);
47
+ backdrop-filter: blur(12px);
48
+ -webkit-backdrop-filter: blur(12px);
49
+ &:focus {
50
+ outline: none;
51
+ }
52
+ }
53
+ @media (prefers-reduced-motion: no-preference) {
54
+ .wui-lightbox-overlay {
55
+ animation: wui-lightbox-in 160ms var(--wui-ease-out-quart);
56
+ }
57
+ .wui-lightbox-image {
58
+ transition: transform 120ms var(--wui-ease-out-quart);
59
+ }
60
+ .wui-lightbox-stage.is-dragging .wui-lightbox-image {
61
+ transition: none;
62
+ }
63
+ }
64
+ @keyframes wui-lightbox-in {
65
+ from {
66
+ opacity: 0;
67
+ }
68
+ }
69
+
70
+ .wui-lightbox-bar {
71
+ flex: 0 0 auto;
72
+ display: flex;
73
+ align-items: center;
74
+ justify-content: space-between;
75
+ gap: 12px;
76
+ padding: 8px 12px;
77
+ }
78
+ .wui-lightbox-count {
79
+ font-size: 14px;
80
+ font-variant-numeric: tabular-nums;
81
+ }
82
+ .wui-lightbox-tools {
83
+ display: flex;
84
+ align-items: center;
85
+ gap: 4px;
86
+ }
87
+ .wui-lightbox-btn.u-action {
88
+ color: var(--color-on-scrim);
89
+ &:hover:not(:disabled) {
90
+ background: color-mix(in srgb, var(--color-on-scrim) 16%, transparent);
91
+ color: var(--color-on-scrim);
92
+ }
93
+ &:focus-visible {
94
+ outline: var(--wui-focus-ring-width) solid var(--color-on-scrim);
95
+ outline-offset: var(--wui-focus-ring-offset);
96
+ }
97
+ &:disabled {
98
+ opacity: 0.4;
99
+ }
100
+ }
101
+
102
+ .wui-lightbox-stage {
103
+ position: relative;
104
+ flex: 1 1 auto;
105
+ min-height: 0;
106
+ display: flex;
107
+ align-items: center;
108
+ justify-content: center;
109
+ overflow: hidden;
110
+ // The element handles every gesture itself (swipe, pinch, pan); the browser must not scroll or zoom the page.
111
+ touch-action: none;
112
+ user-select: none;
113
+ -webkit-user-select: none;
114
+ &.wui-lightbox-zoomed {
115
+ cursor: grab;
116
+ }
117
+ }
118
+ .wui-lightbox-image {
119
+ max-width: 100%;
120
+ max-height: 100%;
121
+ object-fit: contain;
122
+ transform-origin: center;
123
+ &[hidden] {
124
+ display: none;
125
+ }
126
+ }
127
+ .wui-lightbox-status {
128
+ margin: 0;
129
+ padding: 0 24px;
130
+ text-align: center;
131
+ &:empty {
132
+ display: none;
133
+ }
134
+ }
135
+ .wui-lightbox-nav.u-action {
136
+ position: absolute;
137
+ top: 50%;
138
+ transform: translateY(-50%);
139
+ background: color-mix(in srgb, var(--color-scrim-strong) 70%, transparent);
140
+ &[hidden] {
141
+ display: none;
142
+ }
143
+ }
144
+ .wui-lightbox-prev {
145
+ left: 12px;
146
+ }
147
+ .wui-lightbox-next {
148
+ right: 12px;
149
+ }
150
+ .wui-lightbox-caption {
151
+ flex: 0 0 auto;
152
+ margin: 0;
153
+ padding: 12px 64px 20px;
154
+ text-align: center;
155
+ font-size: 14px;
156
+ &[hidden] {
157
+ display: none;
158
+ }
159
+ }
160
+
161
+ // A phone swipes between images and has little width to spare.
162
+ @media (max-width: 575.98px) {
163
+ .wui-lightbox-item {
164
+ width: calc(33.333% - 6px);
165
+ }
166
+ .wui-lightbox-caption {
167
+ padding-inline: 16px;
168
+ }
169
+ }
@@ -151,8 +151,8 @@
151
151
  transform: scale(1.06);
152
152
  }
153
153
  .avatar-clickable:focus-visible {
154
- outline: 2px solid var(--color-primary);
155
- outline-offset: 2px;
154
+ outline: var(--wui-focus-ring-width) solid var(--color-focus-ring);
155
+ outline-offset: var(--wui-focus-ring-offset);
156
156
  }
157
157
 
158
158
  // ── Presence status ── (`status`): a dot at the lower-right, ringed in the surface
@@ -317,8 +317,8 @@
317
317
  .attach-drop:has(+ input:focus-visible) {
318
318
  border-color: var(--color-primary);
319
319
  background: var(--color-primary-soft);
320
- outline: 2px solid var(--color-primary);
321
- outline-offset: 2px;
320
+ outline: var(--wui-focus-ring-width) solid var(--color-focus-ring);
321
+ outline-offset: var(--wui-focus-ring-offset);
322
322
  }
323
323
  .attach-drop-icon {
324
324
  flex: 0 0 auto;
@@ -1210,7 +1210,10 @@
1210
1210
  .logo-dropzone:focus-visible {
1211
1211
  border-color: var(--color-primary);
1212
1212
  background: var(--color-primary-soft);
1213
- outline: none;
1213
+ }
1214
+ .logo-dropzone:focus-visible {
1215
+ outline: var(--wui-focus-ring-width) solid var(--color-focus-ring);
1216
+ outline-offset: var(--wui-focus-ring-offset);
1214
1217
  }
1215
1218
  .logo-dropzone.has-image {
1216
1219
  border-style: solid;
@@ -0,0 +1,88 @@
1
+ // ── Mention input ──
2
+ // AppMentionInput / <app-mention-input> / <wui-mention-input>, also the boxes of a comment thread.
3
+ // A textarea where "@" opens a fixed list of people under the box, placed by the element
4
+ // (anchorOverlay) so it escapes a scrolling card or dialog.
5
+ //
6
+ // Part of the wui-components layer, see _wui-components.scss for load order.
7
+
8
+ .wui-mention-input {
9
+ display: block;
10
+ min-width: 0;
11
+ }
12
+ .wui-mention-input-text {
13
+ width: 100%;
14
+ resize: vertical;
15
+ }
16
+
17
+ .wui-mention-menu {
18
+ position: fixed;
19
+ z-index: var(--wui-z-menu);
20
+ display: flex;
21
+ flex-direction: column;
22
+ gap: 2px;
23
+ min-width: 240px;
24
+ max-width: min(360px, calc(100vw - 8px));
25
+ max-height: 300px;
26
+ overflow-y: auto;
27
+ padding: 4px;
28
+ background: var(--color-surface);
29
+ border: 1px solid var(--color-border);
30
+ border-radius: var(--radius-lg);
31
+ corner-shape: squircle;
32
+ box-shadow: var(--shadow-overlay);
33
+ }
34
+ .wui-mention-menu[hidden] {
35
+ display: none;
36
+ }
37
+
38
+ .wui-mention-option {
39
+ display: flex;
40
+ align-items: center;
41
+ gap: 10px;
42
+ padding: 8px 12px;
43
+ border-radius: var(--radius);
44
+ corner-shape: squircle;
45
+ color: var(--color-text);
46
+ cursor: pointer;
47
+ }
48
+ // The active row is the element's, not :hover, so keys and pointer agree on one row.
49
+ .wui-mention-option.is-active {
50
+ background: var(--color-primary-soft);
51
+ color: var(--color-primary-ink);
52
+ }
53
+ .wui-mention-option-photo {
54
+ flex: none;
55
+ width: 24px;
56
+ height: 24px;
57
+ border-radius: 50%;
58
+ object-fit: cover;
59
+ }
60
+ .wui-mention-option-text {
61
+ display: flex;
62
+ flex-direction: column;
63
+ min-width: 0;
64
+ }
65
+ .wui-mention-option-label,
66
+ .wui-mention-option-description {
67
+ overflow: hidden;
68
+ text-overflow: ellipsis;
69
+ white-space: nowrap;
70
+ }
71
+ .wui-mention-option-description {
72
+ font-size: 12px;
73
+ color: var(--color-text-muted);
74
+ }
75
+ .wui-mention-option.is-active .wui-mention-option-description {
76
+ color: inherit;
77
+ }
78
+ .wui-mention-empty {
79
+ padding: 8px 12px;
80
+ font-size: 13px;
81
+ color: var(--color-text-muted);
82
+ }
83
+
84
+ @media (pointer: coarse) {
85
+ .wui-mention-option {
86
+ min-height: 44px;
87
+ }
88
+ }