@crewlethq/ui 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.
@@ -0,0 +1,264 @@
1
+ /*
2
+ * Toaster + Toast styles: a 380px max width, a 12px radius, a 240ms
3
+ * slide-in, and a scaleX progress drain whose animationend event is the
4
+ * onDismiss handshake, so the visible countdown and the dismissal can
5
+ * never drift apart.
6
+ *
7
+ * Variant accents:
8
+ * .crewlet-toast--info neutral, no accent strip
9
+ * .crewlet-toast--success matt moss-green icon
10
+ * .crewlet-toast--warn amber icon
11
+ * .crewlet-toast--error soft rose icon, never red flood
12
+ * .crewlet-toast--quota brand accent on a caller-supplied icon, for
13
+ * a usage limit notice (announced as an alert)
14
+ * quota and any other custom variant render with no default icon or
15
+ * title; consumers paint their own by passing the `icon` prop or by
16
+ * overriding the body via `renderBody`.
17
+ */
18
+
19
+ .crewlet-toaster {
20
+ position: fixed;
21
+ z-index: var(--z-index-toast, 10001);
22
+ display: flex;
23
+ flex-direction: column;
24
+ gap: 10px;
25
+ width: min(380px, calc(100vw - 48px));
26
+ pointer-events: none;
27
+ }
28
+
29
+ .crewlet-toaster--bottom-right { bottom: 24px; right: 24px; }
30
+ .crewlet-toaster--top-right { top: 24px; right: 24px; }
31
+ .crewlet-toaster--bottom-left { bottom: 24px; left: 24px; }
32
+ .crewlet-toaster--top-left { top: 24px; left: 24px; }
33
+
34
+ .crewlet-toast {
35
+ pointer-events: auto;
36
+ position: relative;
37
+ display: flex;
38
+ align-items: flex-start;
39
+ gap: 12px;
40
+ padding: 14px 38px 14px 14px;
41
+ background: color-mix(in srgb, var(--color-surface-subtle) 60%, #000);
42
+ border: 1px solid var(--color-border-default);
43
+ border-radius: 12px;
44
+ color: var(--color-text-primary);
45
+ font-family: var(--font-family-sans);
46
+ font-size: 13px;
47
+ line-height: 1.45;
48
+ letter-spacing: -0.005em;
49
+ box-shadow:
50
+ 0 16px 32px rgba(0, 0, 0, 0.42),
51
+ inset 0 1px 0 rgba(255, 255, 255, 0.04);
52
+ animation: crewlet-toast-in 240ms cubic-bezier(0.16, 1, 0.3, 1);
53
+ overflow: hidden;
54
+ }
55
+
56
+ @keyframes crewlet-toast-in {
57
+ from { opacity: 0; transform: translateX(16px); }
58
+ to { opacity: 1; transform: translateX(0); }
59
+ }
60
+
61
+ /* Children sit above the drain fill. */
62
+ .crewlet-toast > * {
63
+ position: relative;
64
+ z-index: 1;
65
+ }
66
+
67
+ .crewlet-toast__icon {
68
+ flex-shrink: 0;
69
+ font-size: 20px;
70
+ color: var(--color-text-secondary);
71
+ line-height: 1;
72
+ margin-top: 1px;
73
+ }
74
+
75
+ .crewlet-toast__icon .material-symbols-outlined {
76
+ font-size: 20px;
77
+ }
78
+
79
+ .crewlet-toast--success .crewlet-toast__icon,
80
+ .crewlet-toast--success .crewlet-toast__icon .material-symbols-outlined {
81
+ color: #8fbf9f;
82
+ font-variation-settings: 'FILL' 1;
83
+ }
84
+
85
+ .crewlet-toast--warn .crewlet-toast__icon,
86
+ .crewlet-toast--warn .crewlet-toast__icon .material-symbols-outlined {
87
+ color: #e4c97c;
88
+ font-variation-settings: 'FILL' 1;
89
+ }
90
+
91
+ .crewlet-toast--error .crewlet-toast__icon,
92
+ .crewlet-toast--error .crewlet-toast__icon .material-symbols-outlined {
93
+ color: #f87171;
94
+ font-variation-settings: 'FILL' 1;
95
+ }
96
+
97
+ /*
98
+ * The `quota` variant (a usage limit notice) paints the icon the caller
99
+ * supplies with the brand accent and a filled glyph. Its styling lives
100
+ * here so an app can render `<Toaster>` directly without shipping a
101
+ * stylesheet of its own.
102
+ */
103
+ .crewlet-toast--quota .crewlet-toast__icon,
104
+ .crewlet-toast--quota .crewlet-toast__icon .material-symbols-outlined {
105
+ color: var(--color-brand-accent, #5469d4);
106
+ font-variation-settings: 'FILL' 1;
107
+ }
108
+
109
+ .crewlet-toast__body {
110
+ flex: 1;
111
+ min-width: 0;
112
+ display: flex;
113
+ flex-direction: column;
114
+ gap: 2px;
115
+ }
116
+
117
+ .crewlet-toast__title {
118
+ font-size: 13px;
119
+ font-weight: 600;
120
+ color: var(--color-text-primary);
121
+ letter-spacing: -0.01em;
122
+ }
123
+
124
+ .crewlet-toast__message {
125
+ font-size: 13px;
126
+ color: var(--color-text-secondary);
127
+ word-wrap: break-word;
128
+ }
129
+
130
+ .crewlet-toast__actions {
131
+ margin-top: 10px;
132
+ display: flex;
133
+ gap: 8px;
134
+ }
135
+
136
+ .crewlet-toast__action-btn,
137
+ .crewlet-toast__action-link {
138
+ display: inline-flex;
139
+ align-items: center;
140
+ justify-content: center;
141
+ padding: 6px 12px;
142
+ border-radius: 8px;
143
+ background: var(--color-brand-accent, #5469d4);
144
+ color: var(--color-text-on-brand, #fff);
145
+ border: 1px solid var(--color-brand-accent, #5469d4);
146
+ font-size: 12px;
147
+ font-weight: 600;
148
+ text-decoration: none;
149
+ cursor: pointer;
150
+ transition: background 120ms ease, border-color 120ms ease;
151
+ }
152
+
153
+ .crewlet-toast__action-btn:hover,
154
+ .crewlet-toast__action-link:hover {
155
+ background: var(--color-brand-accent-hover, #6478e0);
156
+ border-color: var(--color-brand-accent-hover, #6478e0);
157
+ }
158
+
159
+ .crewlet-toast--error .crewlet-toast__action-btn,
160
+ .crewlet-toast--error .crewlet-toast__action-link {
161
+ background: #f43f5e;
162
+ border-color: #f43f5e;
163
+ }
164
+
165
+ .crewlet-toast--error .crewlet-toast__action-btn:hover,
166
+ .crewlet-toast--error .crewlet-toast__action-link:hover {
167
+ background: #e11d48;
168
+ border-color: #e11d48;
169
+ }
170
+
171
+ /* Dismiss "X" sits absolute in the top-right so multi-line content
172
+ flows naturally underneath it. */
173
+ .crewlet-toast__dismiss {
174
+ position: absolute;
175
+ top: 8px;
176
+ right: 8px;
177
+ width: 24px;
178
+ height: 24px;
179
+ display: inline-flex;
180
+ align-items: center;
181
+ justify-content: center;
182
+ background: transparent;
183
+ border: none;
184
+ border-radius: 6px;
185
+ color: var(--color-text-tertiary);
186
+ cursor: pointer;
187
+ padding: 0;
188
+ transition: background 120ms ease, color 120ms ease;
189
+ z-index: 2;
190
+ }
191
+
192
+ .crewlet-toast__dismiss:hover {
193
+ background: var(--color-surface-elevated, var(--color-surface-subtle));
194
+ color: var(--color-text-primary);
195
+ }
196
+
197
+ .crewlet-toast__dismiss:focus-visible {
198
+ outline: none;
199
+ box-shadow: var(--shadow-focus, 0 0 0 3px rgba(84, 105, 212, 0.32));
200
+ }
201
+
202
+ .crewlet-toast__dismiss .material-symbols-outlined {
203
+ font-size: 16px;
204
+ }
205
+
206
+ /*
207
+ * Progress fill drives auto-dismissal: animationend → onDismiss.
208
+ * Hover/focus pauses the keyframe (and the implicit timer with it).
209
+ * Variant wash: slate for calm informational variants, rose for error,
210
+ * moss-green for success.
211
+ */
212
+ .crewlet-toast__progress {
213
+ position: absolute;
214
+ inset: 0;
215
+ z-index: 0;
216
+ transform-origin: left center;
217
+ transform: scaleX(1);
218
+ background: var(--color-brand-slate, #3c4052);
219
+ opacity: 0.3;
220
+ pointer-events: none;
221
+ animation-name: crewlet-toast-drain;
222
+ animation-timing-function: linear;
223
+ animation-fill-mode: forwards;
224
+ }
225
+
226
+ .crewlet-toast--error .crewlet-toast__progress {
227
+ background: #ae4a4a;
228
+ opacity: 0.18;
229
+ }
230
+
231
+ .crewlet-toast--success .crewlet-toast__progress {
232
+ background: rgba(78, 134, 90, 0.6);
233
+ opacity: 0.28;
234
+ }
235
+
236
+ .crewlet-toast--warn .crewlet-toast__progress {
237
+ background: rgba(180, 140, 50, 0.5);
238
+ opacity: 0.22;
239
+ }
240
+
241
+ .crewlet-toast:hover .crewlet-toast__progress,
242
+ .crewlet-toast:focus-within .crewlet-toast__progress {
243
+ animation-play-state: paused;
244
+ }
245
+
246
+ @keyframes crewlet-toast-drain {
247
+ from { transform: scaleX(1); }
248
+ to { transform: scaleX(0); }
249
+ }
250
+
251
+ @media (max-width: 480px) {
252
+ .crewlet-toaster--bottom-right,
253
+ .crewlet-toaster--top-right,
254
+ .crewlet-toaster--bottom-left,
255
+ .crewlet-toaster--top-left {
256
+ left: 12px;
257
+ right: 12px;
258
+ width: auto;
259
+ }
260
+ .crewlet-toaster--bottom-right,
261
+ .crewlet-toaster--bottom-left { bottom: 12px; }
262
+ .crewlet-toaster--top-right,
263
+ .crewlet-toaster--top-left { top: 12px; }
264
+ }