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.
- package/.claude/settings.local.json +2 -1
- package/CHANGELOG.md +40 -0
- package/index.html +6 -0
- package/maverick-wave.min.css +5 -1
- package/maverick-wave.min.js +1 -1
- package/package.json +2 -2
- package/src/js/main.js +216 -0
- package/src/partials/documentation-container.html +3 -0
- package/src/partials/kanban-container.html +771 -0
- package/src/scss/abstracts/_variables.scss +1 -1
- package/src/scss/components/_buttons.scss +2 -1
- package/src/scss/components/_cards.scss +2 -1
- package/src/scss/components/_index.scss +1 -0
- package/src/scss/components/_kanban.scss +368 -0
- package/maverick-wave.css +0 -8241
- package/maverick-wave.js +0 -587
|
@@ -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: #
|
|
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
|
|
@@ -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
|
+
}
|