minora 0.1.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.
@@ -0,0 +1,586 @@
1
+ /* ============================================================
2
+ ELEGANT MINIMALIST UI KIT — Toast & Notification Components
3
+ toast.css
4
+
5
+ ANATOMY — TOAST
6
+ ─────────────────────────────────────────────────────────────
7
+ Structure:
8
+ <div class="toast toast-success" role="alert" aria-live="assertive">
9
+ <svg class="toast-icon">...</svg>
10
+ <div class="toast-body">
11
+ <span class="toast-message">Changes saved successfully.</span>
12
+ <button class="toast-action">Undo</button>
13
+ </div>
14
+ <button class="toast-close" aria-label="Close">
15
+ <svg>×</svg>
16
+ </button>
17
+ <div class="toast-progress" style="--progress:1"></div>
18
+ </div>
19
+
20
+ Class layers:
21
+ 1. .toast → Base card, shadow, layout
22
+ 2. .toast-{type} → Color scheme (success/error/warning/info/loading/neutral)
23
+ 3. .toast-icon → Icon on left (type-appropriate)
24
+ 4. .toast-body → Message + optional action
25
+ 5. .toast-action → Optional action button (e.g., "Undo")
26
+ 6. .toast-close → Dismiss button
27
+ 7. .toast-progress → Auto-dismiss progress bar
28
+ ─────────────────────────────────────────────────────────────
29
+
30
+ ANATOMY — NOTIFICATION PANEL
31
+ ─────────────────────────────────────────────────────────────
32
+ <div class="notification-panel">
33
+ <div class="notification-panel-header">
34
+ <h3>Notifications</h3>
35
+ <button class="notification-mark-all">Mark all as read</button>
36
+ </div>
37
+ <div class="notification-group-label">Today</div>
38
+ <div class="notification-item notification-unread">
39
+ <span class="notification-unread-dot"></span>
40
+ <div class="notification-avatar">...</div>
41
+ <div class="notification-content">
42
+ <p class="notification-text">...</p>
43
+ <span class="notification-time">...</span>
44
+ </div>
45
+ </div>
46
+ <!-- more items -->
47
+ <div class="notification-empty">
48
+ <svg>...</svg>
49
+ <p>No notifications yet</p>
50
+ </div>
51
+ </div>
52
+ ─────────────────────────────────────────────────────────────
53
+ ============================================================ */
54
+
55
+ /* ═══════════════════════════════════════════════════════════
56
+ TOAST STACK — Container
57
+ ═══════════════════════════════════════════════════════════ */
58
+
59
+ .toast-stack {
60
+ display: flex;
61
+ flex-direction: column;
62
+ gap: var(--toast-stack-gap);
63
+ position: fixed;
64
+ z-index: var(--z-toast);
65
+ pointer-events: none;
66
+ }
67
+
68
+ .toast-stack-bottom-right {
69
+ bottom: var(--space-6);
70
+ right: var(--space-6);
71
+ }
72
+
73
+ .toast-stack-bottom-left {
74
+ bottom: var(--space-6);
75
+ left: var(--space-6);
76
+ }
77
+
78
+ .toast-stack-bottom-center {
79
+ bottom: var(--space-6);
80
+ left: 50%;
81
+ transform: translateX(-50%);
82
+ }
83
+
84
+ .toast-stack-top-right {
85
+ top: var(--space-6);
86
+ right: var(--space-6);
87
+ }
88
+
89
+ .toast-stack-top-left {
90
+ top: var(--space-6);
91
+ left: var(--space-6);
92
+ }
93
+
94
+ .toast-stack-top-center {
95
+ top: var(--space-6);
96
+ left: 50%;
97
+ transform: translateX(-50%);
98
+ }
99
+
100
+ /* ═══════════════════════════════════════════════════════════
101
+ TOAST — Base
102
+ ═══════════════════════════════════════════════════════════ */
103
+
104
+ .toast {
105
+ display: flex;
106
+ align-items: flex-start;
107
+ gap: var(--space-3);
108
+ padding: var(--space-4);
109
+ max-width: var(--toast-max-width);
110
+ min-width: var(--toast-min-width);
111
+ background-color: var(--toast-bg);
112
+ border-radius: var(--toast-border-radius);
113
+ box-shadow: var(--toast-shadow);
114
+ border: var(--border-width) solid var(--color-neutral-200);
115
+ font-size: var(--toast-font-size);
116
+ color: var(--color-neutral-800);
117
+ pointer-events: auto;
118
+ position: relative;
119
+ overflow: hidden;
120
+ opacity: 0;
121
+ transform: translateY(8px);
122
+ transition: opacity var(--toast-slide-duration) var(--ease-out),
123
+ transform var(--toast-slide-duration) var(--ease-out),
124
+ max-height var(--toast-slide-duration) var(--ease-out),
125
+ margin-bottom var(--toast-slide-duration) var(--ease-out),
126
+ padding-top var(--toast-slide-duration) var(--ease-out),
127
+ padding-bottom var(--toast-slide-duration) var(--ease-out);
128
+ }
129
+
130
+ /* Entrance animation */
131
+ .toast.toast-enter {
132
+ animation: toast-slide-in var(--toast-slide-duration) var(--ease-out) forwards;
133
+ }
134
+
135
+ @keyframes toast-slide-in {
136
+ from {
137
+ opacity: 0;
138
+ transform: translateY(16px);
139
+ }
140
+ to {
141
+ opacity: 1;
142
+ transform: translateY(0);
143
+ }
144
+ }
145
+
146
+ /* Exit animation */
147
+ .toast.toast-exit {
148
+ animation: toast-slide-out var(--toast-slide-duration) var(--ease-in-out) forwards;
149
+ }
150
+
151
+ @keyframes toast-slide-out {
152
+ to {
153
+ opacity: 0;
154
+ transform: translateY(8px) scale(0.96);
155
+ max-height: 0;
156
+ margin-bottom: 0;
157
+ padding-top: 0;
158
+ padding-bottom: 0;
159
+ }
160
+ }
161
+
162
+ /* ── Icon ─────────────────────────────────────────────────── */
163
+ .toast-icon {
164
+ flex-shrink: 0;
165
+ width: var(--toast-icon-size);
166
+ height: var(--toast-icon-size);
167
+ margin-top: var(--toast-icon-margin);
168
+ }
169
+
170
+ /* ── Body ─────────────────────────────────────────────────── */
171
+ .toast-body {
172
+ flex: 1;
173
+ min-width: 0;
174
+ display: flex;
175
+ flex-direction: column;
176
+ gap: var(--space-0-5);
177
+ }
178
+
179
+ .toast-message {
180
+ font-family: var(--font-sans);
181
+ font-size: var(--text-sm);
182
+ line-height: var(--leading-snug);
183
+ color: var(--color-neutral-800);
184
+ }
185
+
186
+ .toast-action {
187
+ display: inline-flex;
188
+ align-items: center;
189
+ font-family: var(--font-sans);
190
+ font-size: var(--text-xs);
191
+ font-weight: var(--font-semibold);
192
+ color: var(--color-accent-600);
193
+ background: transparent;
194
+ border: none;
195
+ cursor: pointer;
196
+ padding: var(--space-0-5) 0;
197
+ margin-top: var(--space-0-5);
198
+ text-decoration: underline;
199
+ text-underline-offset: var(--toast-action-underline-offset);
200
+ transition: color var(--duration-fast) var(--ease-in-out);
201
+ align-self: flex-start;
202
+ }
203
+
204
+ .toast-action:hover {
205
+ color: var(--color-accent-700);
206
+ }
207
+
208
+ /* ── Close button ─────────────────────────────────────────── */
209
+ .toast-close {
210
+ flex-shrink: 0;
211
+ display: inline-flex;
212
+ align-items: center;
213
+ justify-content: center;
214
+ width: var(--space-5);
215
+ height: var(--space-5);
216
+ border: none;
217
+ border-radius: var(--radius-sm);
218
+ background: transparent;
219
+ color: var(--color-neutral-400);
220
+ cursor: pointer;
221
+ padding: 0;
222
+ margin-top: -2px;
223
+ margin-right: -2px;
224
+ transition: color var(--duration-fast) var(--ease-in-out),
225
+ background-color var(--duration-fast) var(--ease-in-out);
226
+ }
227
+
228
+ .toast-close:hover {
229
+ color: var(--color-neutral-700);
230
+ background-color: var(--color-neutral-100);
231
+ }
232
+
233
+ .toast-close svg {
234
+ width: var(--space-3);
235
+ height: var(--space-3);
236
+ }
237
+
238
+ /* ── Progress bar ─────────────────────────────────────────── */
239
+ .toast-progress {
240
+ position: absolute;
241
+ bottom: 0;
242
+ left: 0;
243
+ right: 0;
244
+ height: var(--toast-progress-height);
245
+ background-color: transparent;
246
+ overflow: hidden;
247
+ }
248
+
249
+ .toast-progress::after {
250
+ content: '';
251
+ display: block;
252
+ height: 100%;
253
+ background-color: var(--color-neutral-300);
254
+ transform-origin: left;
255
+ transform: scaleX(var(--progress, 1));
256
+ transition: transform linear;
257
+ }
258
+
259
+ .toast-progress.running::after {
260
+ animation: toast-progress var(--toast-default-duration) linear forwards;
261
+ }
262
+
263
+ @keyframes toast-progress {
264
+ from { transform: scaleX(1); }
265
+ to { transform: scaleX(0); }
266
+ }
267
+
268
+ /* ═══════════════════════════════════════════════════════════
269
+ TOAST — Type: Success
270
+ ═══════════════════════════════════════════════════════════ */
271
+
272
+ .toast-success {
273
+ border-color: var(--color-success-border);
274
+ }
275
+
276
+ .toast-success .toast-icon {
277
+ color: var(--color-success);
278
+ }
279
+
280
+ .toast-success .toast-progress::after {
281
+ background-color: var(--color-success);
282
+ }
283
+
284
+ /* ═══════════════════════════════════════════════════════════
285
+ TOAST — Type: Error
286
+ ═══════════════════════════════════════════════════════════ */
287
+
288
+ .toast-error {
289
+ border-color: var(--color-error-border);
290
+ }
291
+
292
+ .toast-error .toast-icon {
293
+ color: var(--color-error);
294
+ }
295
+
296
+ .toast-error .toast-progress::after {
297
+ background-color: var(--color-error);
298
+ }
299
+
300
+ /* ═══════════════════════════════════════════════════════════
301
+ TOAST — Type: Warning
302
+ ═══════════════════════════════════════════════════════════ */
303
+
304
+ .toast-warning {
305
+ border-color: var(--color-warning-border);
306
+ }
307
+
308
+ .toast-warning .toast-icon {
309
+ color: var(--color-warning);
310
+ }
311
+
312
+ .toast-warning .toast-progress::after {
313
+ background-color: var(--color-warning);
314
+ }
315
+
316
+ /* ═══════════════════════════════════════════════════════════
317
+ TOAST — Type: Info
318
+ ═══════════════════════════════════════════════════════════ */
319
+
320
+ .toast-info {
321
+ border-color: var(--color-info-border);
322
+ }
323
+
324
+ .toast-info .toast-icon {
325
+ color: var(--color-info);
326
+ }
327
+
328
+ .toast-info .toast-progress::after {
329
+ background-color: var(--color-info);
330
+ }
331
+
332
+ /* ═══════════════════════════════════════════════════════════
333
+ TOAST — Type: Neutral
334
+ ═══════════════════════════════════════════════════════════ */
335
+
336
+ .toast-neutral .toast-icon {
337
+ color: var(--color-neutral-500);
338
+ }
339
+
340
+ .toast-neutral .toast-progress::after {
341
+ background-color: var(--color-neutral-400);
342
+ }
343
+
344
+ /* ═══════════════════════════════════════════════════════════
345
+ TOAST — Type: Loading (no auto-dismiss, spinner icon)
346
+ ═══════════════════════════════════════════════════════════ */
347
+
348
+ .toast-loading {
349
+ border-color: var(--color-neutral-200);
350
+ }
351
+
352
+ .toast-loading .toast-icon {
353
+ color: var(--color-neutral-500);
354
+ animation: toast-spinner-spin var(--anim-spin-duration) linear infinite;
355
+ }
356
+
357
+ .toast-loading .toast-progress {
358
+ display: none;
359
+ }
360
+
361
+ @keyframes toast-spinner-spin {
362
+ 0% { transform: rotate(0deg); }
363
+ 100% { transform: rotate(360deg); }
364
+ }
365
+
366
+ /* ═══════════════════════════════════════════════════════════
367
+ NOTIFICATION PANEL
368
+ ═══════════════════════════════════════════════════════════ */
369
+
370
+ .notification-panel {
371
+ width: var(--notif-panel-width);
372
+ max-height: var(--notif-panel-max-height);
373
+ background-color: var(--toast-bg);
374
+ border: var(--border-width) solid var(--color-neutral-200);
375
+ border-radius: var(--radius-md);
376
+ box-shadow: var(--shadow-md);
377
+ display: flex;
378
+ flex-direction: column;
379
+ overflow: hidden;
380
+ }
381
+
382
+ /* ── Header ───────────────────────────────────────────────── */
383
+ .notification-panel-header {
384
+ display: flex;
385
+ align-items: center;
386
+ justify-content: space-between;
387
+ padding: var(--space-4);
388
+ border-bottom: var(--border-width) solid var(--color-neutral-100);
389
+ flex-shrink: 0;
390
+ }
391
+
392
+ .notification-panel-header h3 {
393
+ font-family: var(--font-sans);
394
+ font-size: var(--text-base);
395
+ font-weight: var(--font-semibold);
396
+ color: var(--color-neutral-900);
397
+ margin: 0;
398
+ }
399
+
400
+ .notification-mark-all {
401
+ font-family: var(--font-sans);
402
+ font-size: var(--text-xs);
403
+ font-weight: var(--font-medium);
404
+ color: var(--color-accent-600);
405
+ background: transparent;
406
+ border: none;
407
+ cursor: pointer;
408
+ padding: var(--space-1) var(--space-2);
409
+ border-radius: var(--radius-sm);
410
+ transition: background-color var(--duration-fast) var(--ease-in-out),
411
+ color var(--duration-fast) var(--ease-in-out);
412
+ }
413
+
414
+ .notification-mark-all:hover {
415
+ background-color: var(--color-accent-50);
416
+ color: var(--color-accent-700);
417
+ }
418
+
419
+ /* ── List container ───────────────────────────────────────── */
420
+ .notification-list {
421
+ overflow-y: auto;
422
+ flex: 1;
423
+ }
424
+
425
+ /* ── Group label ──────────────────────────────────────────── */
426
+ .notification-group-label {
427
+ padding: var(--space-2) var(--space-4);
428
+ font-family: var(--font-sans);
429
+ font-size: var(--text-xs);
430
+ font-weight: var(--font-semibold);
431
+ color: var(--color-neutral-500);
432
+ text-transform: uppercase;
433
+ letter-spacing: var(--tracking-wider);
434
+ border-bottom: var(--border-width) solid var(--color-neutral-100);
435
+ background-color: var(--color-neutral-50);
436
+ position: sticky;
437
+ top: 0;
438
+ z-index: var(--z-raised);
439
+ }
440
+
441
+ /* ── Notification item ────────────────────────────────────── */
442
+ .notification-item {
443
+ display: flex;
444
+ align-items: flex-start;
445
+ gap: var(--space-3);
446
+ padding: var(--space-4);
447
+ cursor: pointer;
448
+ border-bottom: var(--border-width) solid var(--color-neutral-50);
449
+ transition: background-color var(--duration-fast) var(--ease-in-out);
450
+ position: relative;
451
+ }
452
+
453
+ .notification-item:last-child {
454
+ border-bottom: none;
455
+ }
456
+
457
+ .notification-item:hover {
458
+ background-color: var(--color-neutral-50);
459
+ }
460
+
461
+ /* Unread state */
462
+ .notification-unread {
463
+ background-color: var(--color-info-light);
464
+ }
465
+
466
+ .notification-unread:hover {
467
+ background-color: var(--color-info-light);
468
+ }
469
+
470
+ .notification-unread-dot {
471
+ position: absolute;
472
+ left: var(--space-2);
473
+ top: 50%;
474
+ transform: translateY(-50%);
475
+ width: var(--space-2);
476
+ height: var(--space-2);
477
+ border-radius: var(--radius-pill);
478
+ background-color: var(--color-info);
479
+ flex-shrink: 0;
480
+ }
481
+
482
+ /* When unread: shift content to make room for dot */
483
+ .notification-unread .notification-avatar,
484
+ .notification-unread .notification-content,
485
+ .notification-unread .notification-time-indicator {
486
+ margin-left: var(--space-2);
487
+ }
488
+
489
+ /* ── Avatar ───────────────────────────────────────────────── */
490
+ .notification-avatar {
491
+ flex-shrink: 0;
492
+ width: var(--notif-avatar-size);
493
+ height: var(--notif-avatar-size);
494
+ border-radius: var(--radius-pill);
495
+ background-color: var(--color-neutral-200);
496
+ display: inline-flex;
497
+ align-items: center;
498
+ justify-content: center;
499
+ font-family: var(--font-sans);
500
+ font-size: var(--text-xs);
501
+ font-weight: var(--font-medium);
502
+ color: var(--color-neutral-500);
503
+ overflow: hidden;
504
+ }
505
+
506
+ .notification-avatar img {
507
+ width: 100%;
508
+ height: 100%;
509
+ object-fit: cover;
510
+ }
511
+
512
+ /* ── Content ──────────────────────────────────────────────── */
513
+ .notification-content {
514
+ flex: 1;
515
+ min-width: 0;
516
+ }
517
+
518
+ .notification-text {
519
+ font-size: var(--text-sm);
520
+ color: var(--color-neutral-800);
521
+ line-height: var(--leading-snug);
522
+ margin: 0 0 var(--space-1) 0;
523
+ }
524
+
525
+ .notification-text strong {
526
+ font-weight: var(--font-semibold);
527
+ color: var(--color-neutral-900);
528
+ }
529
+
530
+ .notification-time {
531
+ font-size: var(--text-xs);
532
+ color: var(--color-neutral-400);
533
+ }
534
+
535
+ /* ── Time indicator (right side) ──────────────────────────── */
536
+ .notification-time-indicator {
537
+ flex-shrink: 0;
538
+ font-size: var(--text-xs);
539
+ color: var(--color-neutral-400);
540
+ margin-top: var(--space-0-5);
541
+ white-space: nowrap;
542
+ }
543
+
544
+ /* ── Empty state ──────────────────────────────────────────── */
545
+ .notification-empty {
546
+ display: flex;
547
+ flex-direction: column;
548
+ align-items: center;
549
+ justify-content: center;
550
+ padding: var(--space-12) var(--space-8);
551
+ text-align: center;
552
+ gap: var(--space-3);
553
+ }
554
+
555
+ .notification-empty svg {
556
+ width: var(--notif-avatar-size);
557
+ height: var(--notif-avatar-size);
558
+ color: var(--color-neutral-300);
559
+ }
560
+
561
+ .notification-empty p {
562
+ font-size: var(--text-sm);
563
+ color: var(--color-neutral-500);
564
+ margin: 0;
565
+ }
566
+
567
+ /* ── Footer ───────────────────────────────────────────────── */
568
+ .notification-panel-footer {
569
+ padding: var(--space-3) var(--space-4);
570
+ border-top: var(--border-width) solid var(--color-neutral-100);
571
+ text-align: center;
572
+ flex-shrink: 0;
573
+ }
574
+
575
+ .notification-panel-footer a {
576
+ font-size: var(--text-xs);
577
+ font-weight: var(--font-medium);
578
+ color: var(--color-accent-600);
579
+ text-decoration: none;
580
+ transition: color var(--duration-fast) var(--ease-in-out);
581
+ }
582
+
583
+ .notification-panel-footer a:hover {
584
+ color: var(--color-accent-700);
585
+ text-decoration: underline;
586
+ }