maverick-wave 3.7.0 → 3.10.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.
@@ -21,7 +21,7 @@ $danger-color: #db182f !default;
21
21
  $info-color: #17a2b8 !default;
22
22
  $gray-color: #565656 !default;
23
23
  $dark-background: #0b111a !default;
24
- $dark-text-color: #dd2222 !default;
24
+ $dark-text-color: #d6dbdf !default;
25
25
  $light-background: #d2d1e1 !default;
26
26
  $light-text-color: #1a1a1d !default;
27
27
  // Form controls stay light in both themes, so they get their own root value
@@ -123,7 +123,8 @@
123
123
  .mw-modal-footer,
124
124
  .mw-form-actions,
125
125
  .mw-panel-footer,
126
- .mw-button-bar {
126
+ .mw-button-bar,
127
+ .mw-kanban-composer-actions {
127
128
  .mw-btn {
128
129
  min-width: 80px;
129
130
  }
@@ -38,7 +38,8 @@ $_mw-card-addon-colors: (
38
38
  // really needs the card to clip.
39
39
  overflow: visible;
40
40
 
41
- &:has(.mw-card-ribbon) {
41
+ // Direct child only - a card nested inside another one must not clip its host
42
+ &:has(> .mw-card-ribbon) {
42
43
  overflow: hidden;
43
44
  }
44
45
 
@@ -13,6 +13,7 @@
13
13
  @forward 'empty-state';
14
14
  @forward 'gallery';
15
15
  @forward 'info';
16
+ @forward 'kanban';
16
17
  @forward 'lists';
17
18
  @forward 'localhost-indicator';
18
19
  @forward 'meta-info';
@@ -0,0 +1,368 @@
1
+ @use '../abstracts' as *;
2
+
3
+ // Pixel-precise shape values — no fractional keys in the spacing map
4
+ $_mw-kanban-action-size: 26px;
5
+ $_mw-kanban-action-size-touch: 32px;
6
+ // Room the ribbon needs in the top right corner of a ticket
7
+ $_mw-kanban-ribbon-clearance: 66px;
8
+ $_mw-kanban-ribbon-clearance-compact: 58px;
9
+
10
+ @keyframes mw-kanban-card-in {
11
+ from {
12
+ opacity: 0;
13
+ transform: translateY(-6px);
14
+ }
15
+ to {
16
+ opacity: 1;
17
+ transform: translateY(0);
18
+ }
19
+ }
20
+
21
+ // ---------------------------------------------------------------------------
22
+ // Board
23
+ // ---------------------------------------------------------------------------
24
+ .mw-kanban {
25
+ // Board surface — drop it with .mw-kanban-plain or override per board.
26
+ --mw-kanban-background: color-mix(
27
+ in srgb,
28
+ var(--mw-gray-color) 40%,
29
+ transparent
30
+ );
31
+ --mw-kanban-lane-border: 1px dashed
32
+ color-mix(in srgb, var(--mw-text-muted-color) 40%, transparent);
33
+ // Keeps an empty lane from collapsing onto its header — raise it per board
34
+ // to give a board that starts out empty some presence
35
+ --mw-kanban-column-min-height: 120px;
36
+
37
+ display: grid;
38
+ grid-auto-flow: column;
39
+ grid-auto-columns: minmax(0, 1fr);
40
+ gap: spacing('4');
41
+ padding: spacing('4');
42
+ background: var(--mw-kanban-background);
43
+ border-radius: radius('md');
44
+
45
+ // Two lanes side by side stay readable, four do not
46
+ @include media-down('lg') {
47
+ grid-auto-flow: row;
48
+ grid-template-columns: repeat(2, minmax(0, 1fr));
49
+ }
50
+
51
+ @include media-down('sm') {
52
+ grid-template-columns: minmax(0, 1fr);
53
+ gap: spacing('3');
54
+ padding: spacing('3');
55
+ }
56
+ }
57
+
58
+ // Board without its own surface — for pages that already sit on a panel
59
+ .mw-kanban-plain {
60
+ --mw-kanban-background: transparent;
61
+ padding: spacing('0');
62
+ }
63
+
64
+ // Lane
65
+ .mw-kanban-column {
66
+ display: flex;
67
+ flex-direction: column;
68
+ min-width: 0;
69
+ padding: spacing('4') spacing('3');
70
+ border: var(--mw-kanban-lane-border);
71
+ border-radius: radius('sm');
72
+ }
73
+
74
+ .mw-kanban-column-header {
75
+ display: flex;
76
+ align-items: center;
77
+ gap: spacing('3');
78
+ margin-bottom: spacing('4');
79
+ }
80
+
81
+ .mw-kanban-title {
82
+ flex: 1;
83
+ min-width: 0;
84
+ margin: spacing('0');
85
+ font-size: font-size('sm');
86
+ font-weight: font-weight('bold');
87
+ color: var(--mw-text-color);
88
+ text-transform: uppercase;
89
+ letter-spacing: 0.05em;
90
+ white-space: nowrap;
91
+ overflow: hidden;
92
+ text-overflow: ellipsis;
93
+ }
94
+
95
+ .mw-kanban-count {
96
+ display: inline-flex;
97
+ align-items: center;
98
+ justify-content: center;
99
+ min-width: 22px;
100
+ padding: spacing('0') spacing('2');
101
+ border-radius: radius('xl');
102
+ background: var(--mw-gray-background);
103
+ border: 1px solid var(--mw-border);
104
+ color: var(--mw-text-muted-color);
105
+ font-size: font-size('xs');
106
+ font-weight: font-weight('medium');
107
+ font-variant-numeric: tabular-nums;
108
+ flex-shrink: 0;
109
+ }
110
+
111
+ // Sits on .mw-btn — this only trims it down to the header's line height
112
+ .mw-kanban-add {
113
+ padding: spacing('1') spacing('3');
114
+ line-height: 1;
115
+ flex-shrink: 0;
116
+ }
117
+
118
+ .mw-kanban-column-body {
119
+ display: flex;
120
+ flex-direction: column;
121
+ gap: spacing('3');
122
+ // Fills the lane the grid stretched, so the empty state stays centred in it
123
+ flex: 1;
124
+ min-height: var(--mw-kanban-column-min-height);
125
+ }
126
+
127
+ // Ticket — a plain .mw-card, only smaller
128
+ .mw-kanban-card {
129
+ padding: spacing('4');
130
+
131
+ &.mw-kanban-card-in {
132
+ animation: mw-kanban-card-in 0.25s ease;
133
+ }
134
+ }
135
+
136
+ // The card ribbon carries the priority, including its color
137
+ .mw-kanban-card .mw-card-ribbon {
138
+ top: 10px;
139
+ right: -34px;
140
+ width: 120px;
141
+ padding: spacing('0') spacing('3');
142
+ font-size: font-size('2xs');
143
+ opacity: 1;
144
+ }
145
+
146
+ // Keeps the first lines clear of the ribbon - only where there is one
147
+ .mw-kanban-card:has(> .mw-card-ribbon) .mw-kanban-card-title {
148
+ padding-right: $_mw-kanban-ribbon-clearance;
149
+ }
150
+
151
+ .mw-kanban-card-title {
152
+ margin: spacing('0') spacing('0') spacing('2');
153
+ font-size: font-size('base');
154
+ font-weight: font-weight('medium');
155
+ color: var(--mw-text-color);
156
+ line-height: 1.35;
157
+ }
158
+
159
+ // Caps the description so a wordy ticket cannot dwarf the ones next to it
160
+ .mw-kanban-card-text {
161
+ display: -webkit-box;
162
+ -webkit-line-clamp: 4;
163
+ line-clamp: 4;
164
+ -webkit-box-orient: vertical;
165
+ overflow: hidden;
166
+ margin: spacing('0');
167
+ font-size: font-size('sm');
168
+ color: var(--mw-text-muted-color);
169
+ line-height: 1.45;
170
+ }
171
+
172
+ // Footer — ticket key on the left, assignee and the action buttons on the right
173
+ .mw-kanban-card-footer {
174
+ display: flex;
175
+ align-items: center;
176
+ flex-wrap: wrap;
177
+ gap: spacing('2');
178
+ margin-top: spacing('4');
179
+ padding-top: spacing('3');
180
+ border-top: 1px solid var(--mw-border);
181
+ }
182
+
183
+ // Monospaced so keys of equal length line up across cards
184
+ .mw-kanban-card-id {
185
+ font-family: 'Fira Code', 'Consolas', 'Monaco', monospace;
186
+ font-size: font-size('xs');
187
+ color: var(--mw-text-muted-color);
188
+ letter-spacing: 0.03em;
189
+ flex-shrink: 0;
190
+ }
191
+
192
+ .mw-kanban-card-actions {
193
+ display: flex;
194
+ align-items: center;
195
+ gap: spacing('2');
196
+ margin-left: auto;
197
+ flex-shrink: 0;
198
+
199
+ // The global avatar margin would push the buttons off the card
200
+ .mw-avatar {
201
+ margin: spacing('0');
202
+ }
203
+ }
204
+
205
+ // Move, edit and delete all share one button shape
206
+ .mw-kanban-action {
207
+ display: inline-flex;
208
+ align-items: center;
209
+ justify-content: center;
210
+ width: $_mw-kanban-action-size;
211
+ height: $_mw-kanban-action-size;
212
+ padding: spacing('0');
213
+ border: 1px solid var(--mw-border);
214
+ border-radius: radius('sm');
215
+ background: transparent;
216
+ color: var(--mw-text-muted-color);
217
+ font-size: font-size('xs');
218
+ line-height: 1;
219
+ cursor: pointer;
220
+ transition: var(--mw-transition);
221
+
222
+ &:hover:not(:disabled) {
223
+ background: var(--mw-primary-color);
224
+ border-color: var(--mw-primary-color);
225
+ color: var(--mw-accent-text-color);
226
+ }
227
+
228
+ &:focus-visible {
229
+ outline: 2px solid var(--mw-primary-color);
230
+ outline-offset: 2px;
231
+ }
232
+
233
+ &:disabled {
234
+ opacity: 0.35;
235
+ cursor: not-allowed;
236
+ }
237
+
238
+ // Comfortable tap target where there is no mouse
239
+ @include media-down('md') {
240
+ width: $_mw-kanban-action-size-touch;
241
+ height: $_mw-kanban-action-size-touch;
242
+ }
243
+ }
244
+
245
+ .mw-kanban-action-danger:hover:not(:disabled) {
246
+ background: var(--mw-danger-color);
247
+ border-color: var(--mw-danger-color);
248
+ }
249
+
250
+ // Composer — one per board, moved into whichever lane it is needed in
251
+ .mw-kanban-composer {
252
+ display: none;
253
+ flex-direction: column;
254
+ gap: spacing('3');
255
+ padding: spacing('4');
256
+ background: var(--mw-card-background);
257
+ border: 1px dashed var(--mw-primary-color);
258
+ // Same silhouette as a ticket, so it reads as one being written
259
+ border-radius: radius('sm') radius('xl') radius('sm') radius('xl');
260
+
261
+ &.mw-active {
262
+ display: flex;
263
+ animation: mw-kanban-card-in 0.2s ease;
264
+ }
265
+
266
+ // Three lines of description without a scrollbar
267
+ .mw-textarea {
268
+ min-height: 66px;
269
+ }
270
+ }
271
+
272
+ // Priority and assignee side by side, stacked once the lane gets too narrow
273
+ .mw-kanban-composer-row {
274
+ display: flex;
275
+ flex-wrap: wrap;
276
+ gap: spacing('3');
277
+
278
+ > * {
279
+ flex: 1 1 104px;
280
+ }
281
+ }
282
+
283
+ .mw-kanban-composer-actions {
284
+ display: flex;
285
+ align-items: center;
286
+ justify-content: flex-end;
287
+ flex-wrap: wrap;
288
+ gap: spacing('3');
289
+ }
290
+
291
+ // The ticket being edited steps aside for the composer that replaces it
292
+ .mw-kanban-editing {
293
+ display: none;
294
+ }
295
+
296
+ // Empty lane placeholder
297
+ .mw-kanban-empty {
298
+ display: flex;
299
+ align-items: center;
300
+ justify-content: center;
301
+ flex: 1;
302
+ padding: spacing('5') spacing('3');
303
+ color: var(--mw-text-muted-color);
304
+ font-size: font-size('sm');
305
+ text-align: center;
306
+ }
307
+
308
+ .mw-kanban-column-body:has(.mw-kanban-card, .mw-kanban-composer.mw-active)
309
+ .mw-kanban-empty {
310
+ display: none;
311
+ }
312
+
313
+ // Compact board — for many lanes or a board next to a sidebar
314
+ .mw-kanban-compact {
315
+ --mw-kanban-column-min-height: 90px;
316
+
317
+ .mw-kanban-column {
318
+ padding: spacing('3');
319
+ }
320
+
321
+ .mw-kanban-column-header {
322
+ margin-bottom: spacing('3');
323
+ }
324
+
325
+ .mw-kanban-column-body {
326
+ gap: spacing('2');
327
+ }
328
+
329
+ .mw-kanban-card {
330
+ padding: spacing('3');
331
+ }
332
+
333
+ .mw-kanban-card .mw-card-ribbon {
334
+ top: 8px;
335
+ right: -36px;
336
+ width: 110px;
337
+ }
338
+
339
+ .mw-kanban-card:has(> .mw-card-ribbon) .mw-kanban-card-title {
340
+ padding-right: $_mw-kanban-ribbon-clearance-compact;
341
+ }
342
+
343
+ .mw-kanban-card-title {
344
+ font-size: font-size('sm');
345
+ }
346
+
347
+ // Tighter than the four lines a regular board allows
348
+ .mw-kanban-card-text {
349
+ -webkit-line-clamp: 2;
350
+ line-clamp: 2;
351
+ }
352
+
353
+ .mw-kanban-card-footer {
354
+ margin-top: spacing('3');
355
+ padding-top: spacing('2');
356
+ }
357
+ }
358
+
359
+ @media (prefers-reduced-motion: reduce) {
360
+ .mw-kanban-card,
361
+ .mw-kanban-move {
362
+ transition: none;
363
+ }
364
+
365
+ .mw-kanban-card.mw-kanban-card-in {
366
+ animation: none;
367
+ }
368
+ }