sid-ui 0.1.2 → 0.2.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.
@@ -27,100 +27,200 @@
27
27
  }
28
28
 
29
29
  .os-note {
30
+ position: relative;
30
31
  display: flex;
31
- align-items: stretch;
32
+ align-items: flex-start;
32
33
  border-bottom: 1px solid var(--color-border);
34
+ transition: background-color var(--duration-fast) var(--ease-standard);
33
35
  }
34
36
 
35
37
  .os-note:last-child {
36
38
  border-bottom: 0;
37
39
  }
38
40
 
41
+ .os-note-interactive:hover {
42
+ background: color-mix(in srgb, var(--color-text-primary) 5%, transparent);
43
+ }
44
+
45
+ .os-note-unread {
46
+ background: color-mix(in srgb, var(--color-accent) 4%, transparent);
47
+ }
48
+
39
49
  .os-note-main {
40
50
  flex: 1;
41
51
  min-width: 0;
42
- display: grid;
43
- grid-template-columns: 10px auto minmax(0, 1fr) auto;
44
- column-gap: var(--spacing-3);
45
- align-items: center;
52
+ display: flex;
53
+ align-items: flex-start;
54
+ gap: var(--spacing-3);
46
55
  padding: var(--spacing-3) var(--spacing-2);
47
- color: inherit;
48
- text-decoration: none;
49
56
  text-align: start;
50
- background: transparent;
57
+ }
58
+
59
+ /* The title's link or button stretches over the whole row; the row's own
60
+ buttons (actions, action, dismiss) sit above it and stay clickable. */
61
+ .os-note-hit {
62
+ padding: 0;
51
63
  border: 0;
64
+ background: none;
65
+ color: inherit;
52
66
  font: inherit;
53
- cursor: default;
67
+ text-align: inherit;
68
+ text-decoration: none;
69
+ cursor: pointer;
54
70
  }
55
71
 
56
- a.os-note-main,
57
- button.os-note-main {
58
- cursor: pointer;
72
+ .os-note-hit::after {
73
+ content: "";
74
+ position: absolute;
75
+ inset: 0;
59
76
  }
60
77
 
61
- a.os-note-main:hover,
62
- button.os-note-main:hover {
63
- background: var(--surface-hover);
78
+ .os-note-hit:focus-visible {
79
+ outline: none;
64
80
  }
65
81
 
66
- .os-note-main:focus-visible {
82
+ .os-note-hit:focus-visible::after {
67
83
  outline: 2px solid var(--color-accent);
68
84
  outline-offset: -2px;
69
85
  }
70
86
 
87
+ .os-note-actions,
88
+ .os-note-action,
89
+ .os-note-dismiss {
90
+ position: relative;
91
+ z-index: 1;
92
+ }
93
+
71
94
  .os-note-unread .os-note-title {
72
95
  font-weight: var(--font-weight-semibold);
73
96
  }
74
97
 
98
+ /* Centered on the title's first line. */
75
99
  .os-note-mark {
100
+ flex-shrink: 0;
76
101
  width: 8px;
77
102
  height: 8px;
103
+ margin-top: calc((1.3em - 8px) / 2 + 1px);
104
+ margin-inline: 1px;
78
105
  border-radius: var(--radius-full);
79
- justify-self: center;
80
106
  background: transparent;
81
107
  }
82
108
 
83
109
  .os-note-unread .os-note-mark {
84
110
  background: var(--color-accent);
111
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-accent) 18%, transparent);
85
112
  }
86
113
 
87
114
  .os-note-tone-success.os-note-mark {
88
- background: var(--color-success);
115
+ background: var(--color-data-categorical-green);
116
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-data-categorical-green) 18%, transparent);
89
117
  }
90
118
  .os-note-tone-warning.os-note-mark {
91
- background: var(--color-warning);
119
+ background: var(--color-data-categorical-orange);
120
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-data-categorical-orange) 22%, transparent);
92
121
  }
93
122
  .os-note-tone-danger.os-note-mark {
94
- background: var(--color-error);
123
+ background: var(--color-data-categorical-red);
124
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-data-categorical-red) 18%, transparent);
95
125
  }
96
126
  .os-note-tone-neutral.os-note-mark {
97
127
  background: var(--color-text-secondary);
128
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-text-secondary) 18%, transparent);
98
129
  }
99
130
 
100
131
  .os-note:not(.os-note-unread) .os-note-mark {
101
132
  background: transparent;
133
+ box-shadow: none;
102
134
  }
103
135
 
104
136
  .os-note-start {
137
+ position: relative;
138
+ flex-shrink: 0;
105
139
  display: flex;
106
140
  align-items: center;
107
141
  }
108
142
 
109
- .os-note-main:has(.os-note-start-empty) {
110
- grid-template-columns: 10px minmax(0, 1fr) auto;
143
+ /* The event-type chip on the avatar's corner. */
144
+ .os-note-badge {
145
+ position: absolute;
146
+ inset-inline-end: -5px;
147
+ bottom: -4px;
148
+ display: grid;
149
+ place-items: center;
150
+ width: 18px;
151
+ height: 18px;
152
+ border-radius: var(--radius-full);
153
+ background: var(--color-accent);
154
+ color: #fff;
155
+ font-size: 11px;
156
+ box-shadow: 0 0 0 2px var(--color-background-surface);
111
157
  }
112
158
 
113
- .os-note-start-empty {
114
- display: none;
159
+ .os-note-badge > * {
160
+ width: 11px;
161
+ height: 11px;
162
+ }
163
+
164
+ .os-note-badge-success {
165
+ background: var(--color-data-categorical-green);
166
+ }
167
+ .os-note-badge-warning {
168
+ background: var(--color-data-categorical-orange);
169
+ }
170
+ .os-note-badge-danger {
171
+ background: var(--color-data-categorical-red);
172
+ }
173
+ .os-note-badge-neutral {
174
+ background: var(--color-text-secondary);
175
+ }
176
+
177
+ /* System events: a tinted round icon in place of an avatar. Tag token pairs
178
+ keep the glyph readable on its tint in both themes. */
179
+ .os-note-icon,
180
+ .os-note-card-icon {
181
+ --os-note-tile-bg: var(--color-accent-muted);
182
+ --os-note-tile-fg: var(--color-accent);
183
+ flex-shrink: 0;
184
+ display: grid;
185
+ place-items: center;
186
+ width: 2rem;
187
+ height: 2rem;
188
+ border-radius: var(--radius-full);
189
+ background: var(--os-note-tile-bg);
190
+ color: var(--os-note-tile-fg);
191
+ font-size: 1rem;
192
+ }
193
+
194
+ .os-note-icon-success,
195
+ .os-note-card-success .os-note-card-icon {
196
+ --os-note-tile-bg: var(--color-background-green);
197
+ --os-note-tile-fg: var(--color-icon-green);
198
+ }
199
+ .os-note-icon-warning,
200
+ .os-note-card-warning .os-note-card-icon {
201
+ --os-note-tile-bg: var(--color-background-yellow);
202
+ --os-note-tile-fg: var(--color-icon-yellow);
203
+ }
204
+ .os-note-icon-danger,
205
+ .os-note-card-danger .os-note-card-icon {
206
+ --os-note-tile-bg: var(--color-background-red);
207
+ --os-note-tile-fg: var(--color-icon-red);
208
+ }
209
+ .os-note-icon-neutral,
210
+ .os-note-card-neutral .os-note-card-icon {
211
+ --os-note-tile-bg: var(--color-background-gray);
212
+ --os-note-tile-fg: var(--color-icon-gray);
115
213
  }
116
214
 
117
215
  .os-note-action {
118
216
  display: flex;
119
217
  align-items: center;
218
+ align-self: center;
120
219
  padding-inline-end: var(--spacing-2);
121
220
  }
122
221
 
123
222
  .os-note-body {
223
+ flex: 1;
124
224
  display: flex;
125
225
  flex-direction: column;
126
226
  gap: var(--spacing-0-5);
@@ -147,16 +247,70 @@ button.os-note-main:hover {
147
247
  }
148
248
 
149
249
  .os-note-time {
250
+ flex-shrink: 0;
150
251
  white-space: nowrap;
151
252
  font-variant-numeric: tabular-nums;
152
- padding-inline-start: var(--spacing-3);
253
+ padding-inline-start: var(--spacing-2);
254
+ line-height: calc(var(--font-size-base) * 1.3);
255
+ }
256
+
257
+ /* Rich detail: a quoted comment, a file, an amount. */
258
+ .os-note-preview {
259
+ display: block;
260
+ margin-top: var(--spacing-1-5);
261
+ padding: var(--spacing-2) var(--spacing-3);
262
+ border-radius: var(--radius-element);
263
+ background: var(--color-background-body);
264
+ border: 1px solid var(--color-border);
265
+ font-size: var(--font-size-sm);
266
+ line-height: 1.45;
267
+ color: var(--color-text-primary);
268
+ }
269
+
270
+ .os-note-actions {
271
+ display: flex;
272
+ flex-wrap: wrap;
273
+ gap: var(--spacing-2);
274
+ margin-top: var(--spacing-2);
275
+ }
276
+
277
+ /* Day sections. */
278
+ .os-note-group {
279
+ border-bottom: 1px solid var(--color-border);
280
+ }
281
+
282
+ .os-note-group:last-child {
283
+ border-bottom: 0;
284
+ }
285
+
286
+ .os-note-group > .os-notes-list > .os-note {
287
+ border-bottom: 0;
288
+ }
289
+
290
+ .os-note-group-label {
291
+ padding: var(--spacing-3) var(--spacing-2) var(--spacing-1);
292
+ font-size: var(--font-size-sm);
293
+ font-weight: var(--font-weight-semibold);
294
+ letter-spacing: 0.02em;
295
+ color: var(--color-text-secondary);
296
+ }
297
+
298
+ .os-notes-empty {
299
+ display: flex;
300
+ flex-direction: column;
301
+ align-items: center;
302
+ gap: var(--spacing-2);
303
+ padding: var(--spacing-8) var(--spacing-4);
304
+ color: var(--color-text-secondary);
305
+ text-align: center;
153
306
  }
154
307
 
155
308
  .os-note-dismiss {
156
309
  display: flex;
157
310
  align-items: center;
158
311
  justify-content: center;
159
- align-self: center;
312
+ align-self: flex-start;
313
+ margin-top: var(--spacing-2);
160
314
  width: var(--control-height);
161
315
  height: var(--control-height);
162
316
  margin-inline-end: var(--spacing-1);
@@ -169,7 +323,7 @@ button.os-note-main:hover {
169
323
  }
170
324
 
171
325
  .os-note-dismiss:hover {
172
- background: var(--surface-hover);
326
+ background: color-mix(in srgb, var(--color-text-primary) 5%, transparent);
173
327
  color: var(--color-icon-primary);
174
328
  }
175
329
 
@@ -295,26 +449,67 @@ button.os-note-main:hover {
295
449
  }
296
450
  }
297
451
 
298
- .os-note-card-mark {
299
- width: var(--spacing-2);
300
- height: var(--spacing-2);
301
- margin-top: var(--spacing-1);
302
- border-radius: var(--radius-full);
303
- background: var(--color-accent);
452
+ .os-note-card {
453
+ --os-note-tone: var(--color-accent);
454
+ position: relative;
455
+ }
456
+
457
+ .os-note-card-success {
458
+ --os-note-tone: var(--color-data-categorical-green);
459
+ }
460
+ .os-note-card-warning {
461
+ --os-note-tone: var(--color-data-categorical-orange);
462
+ }
463
+ .os-note-card-danger {
464
+ --os-note-tone: var(--color-data-categorical-red);
465
+ }
466
+ .os-note-card-neutral {
467
+ --os-note-tone: var(--color-text-secondary);
468
+ }
469
+
470
+ .os-note-card-start {
304
471
  flex-shrink: 0;
472
+ display: flex;
305
473
  }
306
474
 
307
- .os-note-card-success .os-note-card-mark {
308
- background: var(--color-success);
475
+ .os-note-card-actions {
476
+ display: flex;
477
+ flex-wrap: wrap;
478
+ gap: var(--spacing-2);
479
+ margin-top: var(--spacing-2);
309
480
  }
310
- .os-note-card-warning .os-note-card-mark {
311
- background: var(--color-warning);
481
+
482
+ /* Time left. Paused while the card is hovered or holds focus. */
483
+ .os-note-card-progress {
484
+ position: absolute;
485
+ inset-inline: 0;
486
+ bottom: 0;
487
+ height: 3px;
488
+ background: var(--os-note-tone);
489
+ opacity: 0.55;
490
+ transform-origin: left;
491
+ animation-name: os-note-countdown;
492
+ animation-timing-function: linear;
493
+ animation-fill-mode: forwards;
312
494
  }
313
- .os-note-card-danger .os-note-card-mark {
314
- background: var(--color-error);
495
+
496
+ [dir="rtl"] .os-note-card-progress {
497
+ transform-origin: right;
315
498
  }
316
- .os-note-card-neutral .os-note-card-mark {
317
- background: var(--color-text-secondary);
499
+
500
+ .os-note-card:hover .os-note-card-progress,
501
+ .os-note-card:focus-within .os-note-card-progress {
502
+ animation-play-state: paused;
503
+ }
504
+
505
+ .os-note-card-progress-hidden {
506
+ visibility: hidden;
507
+ }
508
+
509
+ @keyframes os-note-countdown {
510
+ to {
511
+ transform: scaleX(0);
512
+ }
318
513
  }
319
514
 
320
515
  .os-note-card-copy {
@@ -0,0 +1,117 @@
1
+ /* StatusIndicator — a dot with its words, plain or in a pill. */
2
+
3
+ .os-status {
4
+ --os-status-color: var(--color-accent);
5
+ --os-status-dot: 8px;
6
+ display: inline-flex;
7
+ align-items: center;
8
+ gap: var(--spacing-2);
9
+ max-width: 100%;
10
+ font-size: var(--font-size-base);
11
+ line-height: 1.3;
12
+ color: var(--color-text-primary);
13
+ white-space: nowrap;
14
+ }
15
+
16
+ .os-status-success {
17
+ --os-status-color: var(--color-data-categorical-green);
18
+ }
19
+ .os-status-warning {
20
+ --os-status-color: var(--color-data-categorical-orange);
21
+ }
22
+ .os-status-error {
23
+ --os-status-color: var(--color-data-categorical-red);
24
+ }
25
+ .os-status-neutral {
26
+ --os-status-color: var(--color-data-neutral);
27
+ }
28
+
29
+ .os-status-sm {
30
+ --os-status-dot: 6px;
31
+ gap: var(--spacing-1-5);
32
+ font-size: var(--font-size-sm);
33
+ }
34
+
35
+ .os-status-lg {
36
+ --os-status-dot: 10px;
37
+ gap: var(--spacing-2-5, var(--spacing-2));
38
+ font-size: var(--font-size-lg);
39
+ }
40
+
41
+ .os-status-dot {
42
+ position: relative;
43
+ flex-shrink: 0;
44
+ width: var(--os-status-dot);
45
+ height: var(--os-status-dot);
46
+ border-radius: var(--radius-full);
47
+ background: var(--os-status-color);
48
+ }
49
+
50
+ .os-status-pulsing .os-status-dot::after {
51
+ content: "";
52
+ position: absolute;
53
+ inset: 0;
54
+ border-radius: inherit;
55
+ background: var(--os-status-color);
56
+ animation: os-status-ripple 1.8s cubic-bezier(0, 0, 0.2, 1) infinite;
57
+ }
58
+
59
+ @keyframes os-status-ripple {
60
+ from {
61
+ opacity: 0.6;
62
+ transform: scale(1);
63
+ }
64
+ to {
65
+ opacity: 0;
66
+ transform: scale(2.8);
67
+ }
68
+ }
69
+
70
+ @media (prefers-reduced-motion: reduce) {
71
+ .os-status-pulsing .os-status-dot::after {
72
+ animation: none;
73
+ opacity: 0.25;
74
+ transform: scale(2);
75
+ }
76
+ }
77
+
78
+ .os-status-label {
79
+ overflow: hidden;
80
+ text-overflow: ellipsis;
81
+ }
82
+
83
+ .os-status-detail {
84
+ color: var(--color-text-secondary);
85
+ font-variant-numeric: tabular-nums;
86
+ }
87
+
88
+ .os-status-detail::before {
89
+ content: "·";
90
+ margin-inline-end: var(--spacing-2);
91
+ opacity: 0.6;
92
+ }
93
+
94
+ /* Pills */
95
+ .os-status-soft,
96
+ .os-status-outline {
97
+ padding: var(--spacing-1) var(--spacing-3) var(--spacing-1) var(--spacing-2-5, var(--spacing-2));
98
+ border-radius: var(--radius-full);
99
+ }
100
+
101
+ .os-status-soft.os-status-sm,
102
+ .os-status-outline.os-status-sm {
103
+ padding: 2px var(--spacing-2) 2px var(--spacing-1-5);
104
+ }
105
+
106
+ .os-status-soft.os-status-lg,
107
+ .os-status-outline.os-status-lg {
108
+ padding: var(--spacing-1-5) var(--spacing-4) var(--spacing-1-5) var(--spacing-3);
109
+ }
110
+
111
+ .os-status-soft {
112
+ background: color-mix(in srgb, var(--os-status-color) 13%, transparent);
113
+ }
114
+
115
+ .os-status-outline {
116
+ box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--os-status-color) 45%, var(--color-border));
117
+ }
@@ -11,6 +11,9 @@
11
11
  @import "./components/calendar.css";
12
12
  @import "./components/responsive.css";
13
13
  @import "./components/notification.css";
14
+ @import "./components/status.css";
15
+ @import "./components/chip.css";
16
+ @import "./components/card-effects.css";
14
17
  @import "./components/sticky.css";
15
18
  @import "./components/charts.css";
16
19
  @import "./components/message-list.css";
@@ -201,35 +204,117 @@
201
204
  }
202
205
 
203
206
  /* Rating */
207
+ /* Rating — gold stars or rose hearts. Each mark is an outline with a clipped fill on top, so
208
+ fractional scores fill part of a mark. Hover previews, a pick pops. */
204
209
  .os-rating {
210
+ --_mark: 22px;
211
+ --_on: #f5a524;
212
+ --_off: color-mix(in srgb, var(--color-text-primary) 14%, transparent);
205
213
  display: inline-flex;
206
214
  align-items: center;
207
215
  gap: var(--spacing-2);
208
216
  }
209
- .os-rating-stars {
217
+ .os-rating-heart {
218
+ --_on: #f43f5e;
219
+ }
220
+ .os-rating-sm {
221
+ --_mark: 16px;
222
+ }
223
+ .os-rating-lg {
224
+ --_mark: 32px;
225
+ }
226
+ .os-rating-marks {
210
227
  display: inline-flex;
211
- gap: 2px;
228
+ gap: calc(var(--_mark) * 0.12);
212
229
  }
213
- .os-star {
230
+ .os-rating-mark {
231
+ position: relative;
232
+ display: inline-grid;
233
+ width: var(--_mark);
234
+ height: var(--_mark);
235
+ padding: 0;
214
236
  border: 0;
237
+ border-radius: 4px;
215
238
  background: transparent;
216
- color: var(--color-border-emphasized, var(--color-border));
217
- font-size: 20px;
218
- line-height: 1;
219
- padding: 0;
220
239
  cursor: default;
240
+ transition: transform 0.18s cubic-bezier(0.34, 1.56, 0.64, 1);
221
241
  }
222
- button.os-star {
242
+ button.os-rating-mark {
223
243
  cursor: pointer;
224
244
  }
225
- .os-star-on {
226
- color: var(--color-warning);
245
+ button.os-rating-mark:focus-visible {
246
+ outline: 2px solid var(--color-accent);
247
+ outline-offset: 2px;
227
248
  }
228
- .os-rating-sm .os-star {
229
- font-size: 14px;
249
+ .os-rating-mark svg {
250
+ display: block;
251
+ width: var(--_mark);
252
+ height: var(--_mark);
253
+ }
254
+ .os-rating-mark-base {
255
+ fill: var(--_off);
256
+ }
257
+ .os-rating-mark-fill {
258
+ position: absolute;
259
+ inset: 0 auto 0 0;
260
+ overflow: hidden;
261
+ transition: width 0.2s var(--ease-standard);
262
+ }
263
+ [dir="rtl"] .os-rating-mark-fill {
264
+ inset: 0 0 0 auto;
265
+ direction: rtl;
266
+ }
267
+ .os-rating-mark-fill svg {
268
+ fill: var(--_on);
269
+ filter: drop-shadow(0 1px 1px color-mix(in srgb, var(--_on) 35%, transparent));
230
270
  }
231
- .os-rating-lg .os-star {
232
- font-size: 28px;
271
+ /* Hovered marks grow a touch; the picked one pops. */
272
+ .os-rating-mark-preview {
273
+ transform: scale(1.12);
274
+ }
275
+ .os-rating-mark-inner {
276
+ position: relative;
277
+ display: inline-grid;
278
+ }
279
+ .os-rating-mark-pop .os-rating-mark-inner {
280
+ animation: os-rating-pop 0.45s cubic-bezier(0.34, 1.56, 0.64, 1);
281
+ }
282
+ .os-rating-heart .os-rating-mark-pop .os-rating-mark-inner {
283
+ animation-name: os-rating-beat;
284
+ }
285
+ @keyframes os-rating-pop {
286
+ 0% {
287
+ transform: scale(1);
288
+ }
289
+ 40% {
290
+ transform: scale(1.35) rotate(-8deg);
291
+ }
292
+ 100% {
293
+ transform: scale(1);
294
+ }
295
+ }
296
+ @keyframes os-rating-beat {
297
+ 0%,
298
+ 100% {
299
+ transform: scale(1);
300
+ }
301
+ 25% {
302
+ transform: scale(1.35);
303
+ }
304
+ 50% {
305
+ transform: scale(0.92);
306
+ }
307
+ 70% {
308
+ transform: scale(1.12);
309
+ }
310
+ }
311
+ @media (prefers-reduced-motion: reduce) {
312
+ .os-rating-mark,
313
+ .os-rating-mark-inner,
314
+ .os-rating-mark-fill {
315
+ transition: none;
316
+ animation: none !important;
317
+ }
233
318
  }
234
319
  .os-rating-value {
235
320
  font-size: var(--font-size-sm, 0.75rem);