@attrus-ds/core 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.
- package/LICENSE +27 -0
- package/README.md +123 -0
- package/dist/assets/flags/Brazil-rounded.svg +16 -0
- package/dist/assets/flags/Brazil-square.svg +17 -0
- package/dist/assets/flags/Chile-rounded.svg +11 -0
- package/dist/assets/flags/Chile-square.svg +11 -0
- package/dist/assets/flags/Colombia-rounded.svg +10 -0
- package/dist/assets/flags/Colombia-square.svg +10 -0
- package/dist/assets/flags/EUA-rounded.svg +11 -0
- package/dist/assets/flags/EUA-square.svg +11 -0
- package/dist/assets/flags/EUR-rounded.svg +9 -0
- package/dist/assets/flags/EUR-square.svg +9 -0
- package/dist/assets/flags/Mexico-rounded.svg +19 -0
- package/dist/assets/flags/Mexico-square.svg +19 -0
- package/dist/assets/icon-attrus-dark.svg +3 -0
- package/dist/assets/icon-attrus-light.svg +3 -0
- package/dist/assets/logo-attrus-dark.svg +8 -0
- package/dist/assets/logo-attrus-light.svg +8 -0
- package/dist/css/components/buttons.css +301 -0
- package/dist/css/components/callout.css +195 -0
- package/dist/css/components/cards.css +272 -0
- package/dist/css/components/combobox.css +303 -0
- package/dist/css/components/empty-states.css +61 -0
- package/dist/css/components/inputs.css +1027 -0
- package/dist/css/components/number-input.css +138 -0
- package/dist/css/components/overlays.css +405 -0
- package/dist/css/components/primitives.css +305 -0
- package/dist/css/components/sidebar.css +179 -0
- package/dist/css/components/status-pills.css +207 -0
- package/dist/css/components/stepper.css +309 -0
- package/dist/css/components/table.css +600 -0
- package/dist/css/components/tabs.css +319 -0
- package/dist/css/components/toast.css +239 -0
- package/dist/css/components/tooltip.css +226 -0
- package/dist/css/components/topbar.css +148 -0
- package/dist/css/fonts.css +91 -0
- package/dist/css/index.css +23 -0
- package/dist/css/tokens.css +691 -0
- package/dist/fonts/LICENSE-JetBrainsMono.txt +93 -0
- package/dist/fonts/LICENSE-Lato.txt +93 -0
- package/dist/fonts/jetbrains-mono-latin-400-normal.woff2 +0 -0
- package/dist/fonts/jetbrains-mono-latin-500-normal.woff2 +0 -0
- package/dist/fonts/jetbrains-mono-latin-600-normal.woff2 +0 -0
- package/dist/fonts/lato-latin-100-normal.woff2 +0 -0
- package/dist/fonts/lato-latin-300-italic.woff2 +0 -0
- package/dist/fonts/lato-latin-300-normal.woff2 +0 -0
- package/dist/fonts/lato-latin-400-italic.woff2 +0 -0
- package/dist/fonts/lato-latin-400-normal.woff2 +0 -0
- package/dist/fonts/lato-latin-700-italic.woff2 +0 -0
- package/dist/fonts/lato-latin-700-normal.woff2 +0 -0
- package/dist/fonts/lato-latin-900-normal.woff2 +0 -0
- package/dist/tokens/attrus-tokens.flat.json +1235 -0
- package/dist/tokens/attrus-tokens.json +1090 -0
- package/package.json +46 -0
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
/* ============================================================
|
|
2
|
+
BUTTONS — ATTRUS Design System
|
|
3
|
+
Component CSS — pure tokens, no hardcoded values.
|
|
4
|
+
|
|
5
|
+
Anatomy:
|
|
6
|
+
[leading icon?] [label] [trailing icon?]
|
|
7
|
+
|
|
8
|
+
Variants (semantic):
|
|
9
|
+
.btn-primary | brand fill — main action
|
|
10
|
+
.btn-secondary | neutral fill + hairline border — alternative actions
|
|
11
|
+
.btn-tertiary | soft neutral fill (borderless) — quiet affirmative
|
|
12
|
+
.btn-ghost | no chrome — toolbar / cancel / low priority
|
|
13
|
+
.btn-link | inline text-link styling
|
|
14
|
+
.btn-danger | destructive solid — irreversible
|
|
15
|
+
.btn-danger-outline | destructive secondary — contextual remove
|
|
16
|
+
.btn-success | strong positive — approve / confirm
|
|
17
|
+
.btn-inverse | white pill on dark/brand surfaces
|
|
18
|
+
|
|
19
|
+
Modifier:
|
|
20
|
+
.btn-icon | icon-only (square hit-area)
|
|
21
|
+
|
|
22
|
+
Sizes:
|
|
23
|
+
.btn-xs (24h) .btn-sm (32h) default (40h) .btn-lg (48h)
|
|
24
|
+
|
|
25
|
+
States: default | :hover | :active | :focus-visible | [disabled] | .is-loading
|
|
26
|
+
============================================================ */
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
/* ----------------------------------------------------------------
|
|
30
|
+
1. BASE
|
|
31
|
+
---------------------------------------------------------------- */
|
|
32
|
+
.btn {
|
|
33
|
+
/* Layout */
|
|
34
|
+
display: inline-flex;
|
|
35
|
+
align-items: center;
|
|
36
|
+
justify-content: center;
|
|
37
|
+
gap: var(--space-2);
|
|
38
|
+
white-space: nowrap;
|
|
39
|
+
flex-shrink: 0;
|
|
40
|
+
|
|
41
|
+
/* Box — default size = md (40px tall) */
|
|
42
|
+
height: 40px;
|
|
43
|
+
padding: 0 var(--space-5);
|
|
44
|
+
border: 1px solid transparent;
|
|
45
|
+
border-radius: var(--radius-pill);
|
|
46
|
+
|
|
47
|
+
/* Type */
|
|
48
|
+
font-family: var(--font-sans);
|
|
49
|
+
font-size: var(--fs-md);
|
|
50
|
+
font-weight: var(--w-semibold);
|
|
51
|
+
line-height: 1;
|
|
52
|
+
letter-spacing: var(--ls-body);
|
|
53
|
+
|
|
54
|
+
/* Behavior */
|
|
55
|
+
cursor: pointer;
|
|
56
|
+
user-select: none;
|
|
57
|
+
-webkit-tap-highlight-color: transparent;
|
|
58
|
+
background: transparent;
|
|
59
|
+
color: inherit;
|
|
60
|
+
|
|
61
|
+
/* Motion */
|
|
62
|
+
transition:
|
|
63
|
+
background var(--transition-fast),
|
|
64
|
+
border-color var(--transition-fast),
|
|
65
|
+
color var(--transition-fast),
|
|
66
|
+
box-shadow var(--transition-fast),
|
|
67
|
+
transform var(--transition-fast);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.btn:active { transform: translateY(0.5px); }
|
|
71
|
+
|
|
72
|
+
.btn:focus { outline: none; }
|
|
73
|
+
.btn:focus-visible { box-shadow: var(--shadow-focus); }
|
|
74
|
+
|
|
75
|
+
.btn[disabled],
|
|
76
|
+
.btn.is-disabled {
|
|
77
|
+
cursor: not-allowed;
|
|
78
|
+
opacity: 0.5;
|
|
79
|
+
pointer-events: none;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/* Icon sizing inside buttons (Lucide replaces <i> with <svg>) */
|
|
83
|
+
.btn > i, .btn > svg,
|
|
84
|
+
.btn > svg {
|
|
85
|
+
width: var(--icon-sm);
|
|
86
|
+
height: var(--icon-sm);
|
|
87
|
+
stroke-width: var(--icon-stroke);
|
|
88
|
+
flex-shrink: 0;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
/* ----------------------------------------------------------------
|
|
93
|
+
2. SIZES
|
|
94
|
+
---------------------------------------------------------------- */
|
|
95
|
+
.btn-xs {
|
|
96
|
+
height: 24px;
|
|
97
|
+
padding: 0 var(--space-3);
|
|
98
|
+
font-size: var(--fs-sm);
|
|
99
|
+
gap: var(--space-1);
|
|
100
|
+
}
|
|
101
|
+
.btn-xs > i, .btn-xs > svg, .btn-xs > svg { width: var(--icon-xs); height: var(--icon-xs); }
|
|
102
|
+
|
|
103
|
+
.btn-sm {
|
|
104
|
+
height: 32px;
|
|
105
|
+
padding: 0 var(--space-4);
|
|
106
|
+
font-size: var(--fs-md);
|
|
107
|
+
}
|
|
108
|
+
.btn-sm > i, .btn-sm > svg, .btn-sm > svg { width: var(--icon-xs); height: var(--icon-xs); }
|
|
109
|
+
|
|
110
|
+
/* default = md (40px) — defined in .btn */
|
|
111
|
+
|
|
112
|
+
.btn-lg {
|
|
113
|
+
height: 48px;
|
|
114
|
+
padding: 0 var(--space-6);
|
|
115
|
+
font-size: var(--fs-base);
|
|
116
|
+
gap: var(--space-3);
|
|
117
|
+
}
|
|
118
|
+
.btn-lg > i, .btn-lg > svg, .btn-lg > svg { width: var(--icon-md); height: var(--icon-md); }
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
/* ----------------------------------------------------------------
|
|
122
|
+
3. ICON-ONLY MODIFIER
|
|
123
|
+
---------------------------------------------------------------- */
|
|
124
|
+
.btn-icon { padding: 0; aspect-ratio: 1 / 1; }
|
|
125
|
+
.btn-icon.btn-xs { width: 24px; }
|
|
126
|
+
.btn-icon.btn-sm { width: 32px; }
|
|
127
|
+
.btn-icon { width: 40px; }
|
|
128
|
+
.btn-icon.btn-lg { width: 48px; }
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
/* ----------------------------------------------------------------
|
|
132
|
+
4. VARIANTS
|
|
133
|
+
---------------------------------------------------------------- */
|
|
134
|
+
|
|
135
|
+
/* PRIMARY — brand-blue solid */
|
|
136
|
+
.btn-primary {
|
|
137
|
+
background: var(--color-brand-secondary-500);
|
|
138
|
+
color: var(--color-foreground-on-solid);
|
|
139
|
+
}
|
|
140
|
+
.btn-primary:hover { background: var(--color-brand-secondary-600); }
|
|
141
|
+
.btn-primary:active { background: var(--color-brand-secondary-700); }
|
|
142
|
+
.btn-primary:focus-visible { box-shadow: var(--shadow-focus); }
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
/* SECONDARY — soft neutral fill + hairline border */
|
|
146
|
+
.btn-secondary {
|
|
147
|
+
background: var(--color-background-subtle);
|
|
148
|
+
color: var(--color-foreground-default);
|
|
149
|
+
border-color: var(--color-border-default);
|
|
150
|
+
}
|
|
151
|
+
.btn-secondary:hover { background: var(--color-background-hover); border-color: var(--color-border-strong); }
|
|
152
|
+
.btn-secondary:active { background: var(--color-background-press); }
|
|
153
|
+
.btn-secondary:focus-visible { box-shadow: var(--shadow-focus); }
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
/* TERTIARY — soft neutral fill, borderless (quieter than secondary) */
|
|
157
|
+
.btn-tertiary {
|
|
158
|
+
background: color-mix(in srgb, var(--color-foreground-default) 7%, transparent);
|
|
159
|
+
color: var(--color-foreground-default);
|
|
160
|
+
border-color: transparent;
|
|
161
|
+
}
|
|
162
|
+
.btn-tertiary:hover { background: color-mix(in srgb, var(--color-foreground-default) 12%, transparent); }
|
|
163
|
+
.btn-tertiary:active { background: color-mix(in srgb, var(--color-foreground-default) 16%, transparent); }
|
|
164
|
+
.btn-tertiary:focus-visible { box-shadow: var(--shadow-focus); }
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
/* GHOST — no chrome until hover */
|
|
168
|
+
.btn-ghost {
|
|
169
|
+
background: transparent;
|
|
170
|
+
color: var(--color-foreground-secondary);
|
|
171
|
+
}
|
|
172
|
+
.btn-ghost:hover { background: var(--color-background-hover); color: var(--color-foreground-default); }
|
|
173
|
+
.btn-ghost:active { background: var(--color-background-press); }
|
|
174
|
+
.btn-ghost:focus-visible { box-shadow: var(--shadow-focus); }
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
/* LINK — looks like inline text link */
|
|
178
|
+
.btn-link {
|
|
179
|
+
background: transparent;
|
|
180
|
+
color: var(--color-foreground-highlight);
|
|
181
|
+
height: auto;
|
|
182
|
+
padding: 0;
|
|
183
|
+
border: 0;
|
|
184
|
+
border-radius: var(--radius-2xs);
|
|
185
|
+
text-decoration: none;
|
|
186
|
+
}
|
|
187
|
+
.btn-link:hover { color: var(--color-brand-secondary-700); text-decoration: underline; text-underline-offset: 2px; }
|
|
188
|
+
.btn-link:active { color: var(--color-brand-secondary-800); }
|
|
189
|
+
.btn-link:focus-visible { box-shadow: var(--shadow-focus); }
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
/* DANGER — destructive solid */
|
|
193
|
+
.btn-danger {
|
|
194
|
+
background: var(--color-danger-500);
|
|
195
|
+
color: var(--color-foreground-on-solid);
|
|
196
|
+
}
|
|
197
|
+
.btn-danger:hover { background: var(--color-danger-700); }
|
|
198
|
+
.btn-danger:active { background: var(--color-danger-900); }
|
|
199
|
+
.btn-danger:focus-visible { box-shadow: var(--shadow-focus-danger); }
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
/* DANGER OUTLINE — destructive contextual */
|
|
203
|
+
.btn-danger-outline {
|
|
204
|
+
background: var(--color-background-surface);
|
|
205
|
+
color: var(--color-danger-500);
|
|
206
|
+
border-color: var(--color-feedback-danger-border);
|
|
207
|
+
}
|
|
208
|
+
.btn-danger-outline:hover { background: var(--color-feedback-danger-background); border-color: var(--color-danger-500); }
|
|
209
|
+
.btn-danger-outline:active { background: color-mix(in srgb, var(--color-feedback-danger-background) 60%, var(--color-danger-100)); }
|
|
210
|
+
.btn-danger-outline:focus-visible { box-shadow: var(--shadow-focus-danger); }
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
/* SUCCESS — strong positive (rare) */
|
|
214
|
+
.btn-success {
|
|
215
|
+
background: var(--color-success-500);
|
|
216
|
+
color: var(--color-foreground-on-solid);
|
|
217
|
+
}
|
|
218
|
+
.btn-success:hover { background: var(--color-success-700); }
|
|
219
|
+
.btn-success:active { background: var(--color-success-900); }
|
|
220
|
+
.btn-success:focus-visible { box-shadow: var(--shadow-focus-success); }
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
/* INVERSE — white pill on dark/brand surfaces */
|
|
224
|
+
.btn-inverse {
|
|
225
|
+
background: var(--color-pure-white);
|
|
226
|
+
color: var(--color-brand-secondary-700);
|
|
227
|
+
}
|
|
228
|
+
.btn-inverse:hover { background: var(--color-neutral-100); color: var(--color-brand-secondary-800); }
|
|
229
|
+
.btn-inverse:active { background: var(--color-neutral-150); }
|
|
230
|
+
.btn-inverse:focus-visible { box-shadow: var(--shadow-focus-sky); }
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
/* ----------------------------------------------------------------
|
|
234
|
+
5. ON-INVERSE GHOSTS — for use inside .inverse / dark surfaces
|
|
235
|
+
Apply BOTH .btn-ghost AND .on-inverse
|
|
236
|
+
---------------------------------------------------------------- */
|
|
237
|
+
.btn-ghost.on-inverse {
|
|
238
|
+
color: var(--color-foreground-inverse-secondary);
|
|
239
|
+
}
|
|
240
|
+
.btn-ghost.on-inverse:hover { background: var(--color-background-inverse-hover); color: var(--color-foreground-inverse-default); }
|
|
241
|
+
.btn-ghost.on-inverse:active { background: var(--color-background-inverse-press); }
|
|
242
|
+
|
|
243
|
+
/* Outline ghost on inverse — pairs with .btn-secondary semantics */
|
|
244
|
+
.btn-secondary.on-inverse {
|
|
245
|
+
background: transparent;
|
|
246
|
+
color: var(--color-foreground-inverse-default);
|
|
247
|
+
border-color: var(--color-border-inverse-strong);
|
|
248
|
+
}
|
|
249
|
+
.btn-secondary.on-inverse:hover { background: var(--color-background-inverse-hover); border-color: var(--color-foreground-inverse-secondary); }
|
|
250
|
+
.btn-secondary.on-inverse:active { background: var(--color-background-inverse-press); }
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
/* ----------------------------------------------------------------
|
|
254
|
+
6. LOADING STATE
|
|
255
|
+
Add .is-loading; keeps current width but hides label/icons,
|
|
256
|
+
shows a centered spinner.
|
|
257
|
+
---------------------------------------------------------------- */
|
|
258
|
+
.btn.is-loading {
|
|
259
|
+
position: relative;
|
|
260
|
+
color: transparent !important;
|
|
261
|
+
pointer-events: none;
|
|
262
|
+
}
|
|
263
|
+
.btn.is-loading > * { visibility: hidden; }
|
|
264
|
+
.btn.is-loading::after {
|
|
265
|
+
content: "";
|
|
266
|
+
position: absolute;
|
|
267
|
+
top: 50%; left: 50%;
|
|
268
|
+
width: var(--icon-sm);
|
|
269
|
+
height: var(--icon-sm);
|
|
270
|
+
margin: calc(var(--icon-sm) / -2) 0 0 calc(var(--icon-sm) / -2);
|
|
271
|
+
border: 2px solid currentColor;
|
|
272
|
+
border-top-color: transparent;
|
|
273
|
+
border-radius: var(--radius-pill);
|
|
274
|
+
animation: btn-spin var(--duration-slower) linear infinite;
|
|
275
|
+
/* Re-introduce currentColor where the variant set it; ::after inherits the parent's color BEFORE the !important override */
|
|
276
|
+
color: var(--color-foreground-default);
|
|
277
|
+
}
|
|
278
|
+
.btn-primary.is-loading::after,
|
|
279
|
+
.btn-danger.is-loading::after,
|
|
280
|
+
.btn-success.is-loading::after { color: var(--color-pure-white); }
|
|
281
|
+
.btn-tertiary.is-loading::after { color: var(--color-foreground-default); }
|
|
282
|
+
|
|
283
|
+
@keyframes btn-spin {
|
|
284
|
+
to { transform: rotate(360deg); }
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
/* ----------------------------------------------------------------
|
|
289
|
+
7. BUTTON GROUP — segmented / toolbar
|
|
290
|
+
---------------------------------------------------------------- */
|
|
291
|
+
.btn-group {
|
|
292
|
+
display: inline-flex;
|
|
293
|
+
}
|
|
294
|
+
.btn-group .btn {
|
|
295
|
+
border-radius: 0;
|
|
296
|
+
}
|
|
297
|
+
.btn-group .btn:first-child { border-top-left-radius: var(--radius-pill); border-bottom-left-radius: var(--radius-pill); }
|
|
298
|
+
.btn-group .btn:last-child { border-top-right-radius: var(--radius-pill); border-bottom-right-radius: var(--radius-pill); }
|
|
299
|
+
.btn-group .btn + .btn { margin-left: -1px; }
|
|
300
|
+
.btn-group .btn:focus-visible,
|
|
301
|
+
.btn-group .btn:hover { z-index: 1; }
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
/* ============================================================
|
|
2
|
+
CALLOUT — note / aside / alert-bar for documentation & UI
|
|
3
|
+
------------------------------------------------------------
|
|
4
|
+
An icon + message in a tinted, bordered box. Theme-aware: tint
|
|
5
|
+
is mixed against --color-background-surface so it adapts to
|
|
6
|
+
light & dark; the icon uses a theme-aware foreground token.
|
|
7
|
+
|
|
8
|
+
Scales from a one-line note up to a rich panel (title + body +
|
|
9
|
+
action buttons + dismiss) and a full-width alert bar.
|
|
10
|
+
|
|
11
|
+
Simple:
|
|
12
|
+
<div class="callout"> (info — default)
|
|
13
|
+
<i data-lucide="info"></i>
|
|
14
|
+
<div class="callout-body">…<code>x</code>…</div>
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
Rich (vertical: title + body + actions + dismiss):
|
|
18
|
+
<div class="callout callout-warn">
|
|
19
|
+
<i data-lucide="alert-triangle"></i>
|
|
20
|
+
<div class="callout-content">
|
|
21
|
+
<div class="callout-title">Heading</div>
|
|
22
|
+
<div class="callout-body">Longer message…</div>
|
|
23
|
+
<div class="callout-actions">
|
|
24
|
+
<button class="btn btn-primary btn-sm">Confirm</button>
|
|
25
|
+
<button class="btn btn-ghost btn-sm">Later</button>
|
|
26
|
+
</div>
|
|
27
|
+
</div>
|
|
28
|
+
<button class="callout-dismiss" aria-label="Dismiss"><i data-lucide="x"></i></button>
|
|
29
|
+
</div>
|
|
30
|
+
|
|
31
|
+
Alert bar (full-width banner; actions + dismiss inline-right):
|
|
32
|
+
<div class="callout callout-bar callout-danger"> … </div>
|
|
33
|
+
|
|
34
|
+
Tonal: .callout-warn .callout-success .callout-danger .callout-neutral
|
|
35
|
+
Size: .callout-sm (compact)
|
|
36
|
+
Two props drive every tone:
|
|
37
|
+
--callout-tint raw family color → background + border mix
|
|
38
|
+
--callout-fg theme-aware foreground → icon color
|
|
39
|
+
============================================================ */
|
|
40
|
+
.callout {
|
|
41
|
+
--callout-tint: var(--color-brand-secondary-500); /* info / royal */
|
|
42
|
+
--callout-fg: var(--color-foreground-accent); /* sky, theme-aware */
|
|
43
|
+
display: flex;
|
|
44
|
+
gap: var(--space-3);
|
|
45
|
+
padding: var(--space-4) var(--space-5);
|
|
46
|
+
border-radius: var(--radius-md);
|
|
47
|
+
background: color-mix(in srgb, var(--callout-tint) 8%, var(--color-background-surface));
|
|
48
|
+
border: 1px solid color-mix(in srgb, var(--callout-tint) 22%, transparent);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.callout > i,
|
|
52
|
+
.callout > svg,
|
|
53
|
+
.callout-icon {
|
|
54
|
+
width: 18px;
|
|
55
|
+
height: 18px;
|
|
56
|
+
flex-shrink: 0;
|
|
57
|
+
margin-top: 1px;
|
|
58
|
+
color: var(--callout-fg);
|
|
59
|
+
stroke-width: var(--icon-stroke);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/* content column — wrap title + body + actions for rich callouts */
|
|
63
|
+
.callout-content {
|
|
64
|
+
flex: 1;
|
|
65
|
+
min-width: 0;
|
|
66
|
+
display: flex;
|
|
67
|
+
flex-direction: column;
|
|
68
|
+
gap: var(--space-2);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.callout-title {
|
|
72
|
+
font-size: var(--fs-md);
|
|
73
|
+
font-weight: var(--w-semibold);
|
|
74
|
+
letter-spacing: var(--ls-title);
|
|
75
|
+
color: var(--color-foreground-default);
|
|
76
|
+
line-height: var(--lh-tight);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.callout-body {
|
|
80
|
+
font-size: var(--fs-sm);
|
|
81
|
+
color: var(--color-foreground-secondary);
|
|
82
|
+
line-height: var(--lh-snug);
|
|
83
|
+
}
|
|
84
|
+
.callout-body strong { color: var(--color-foreground-default); font-weight: var(--w-semibold); }
|
|
85
|
+
.callout-body code {
|
|
86
|
+
font-family: var(--font-mono);
|
|
87
|
+
font-size: var(--fs-xs);
|
|
88
|
+
color: var(--color-foreground-accent);
|
|
89
|
+
}
|
|
90
|
+
.callout-body a { color: var(--color-foreground-accent); text-decoration: none; font-weight: var(--w-semibold); }
|
|
91
|
+
.callout-body p { margin: 0 0 var(--space-2); }
|
|
92
|
+
.callout-body p:last-child { margin-bottom: 0; }
|
|
93
|
+
.callout-body ul { margin: var(--space-2) 0 0; padding-left: var(--space-5); }
|
|
94
|
+
.callout-body li { margin-bottom: var(--space-1); }
|
|
95
|
+
|
|
96
|
+
/* action row — buttons use the canonical .btn system.
|
|
97
|
+
Convention: keep callout actions SMALL (.btn-xs). Use .btn-secondary
|
|
98
|
+
for the action — its border stays legible on the tinted box, where
|
|
99
|
+
borderless ghost/tertiary read as plain text. .btn-ghost for the
|
|
100
|
+
soft/secondary option; .btn-danger for destructive actions. */
|
|
101
|
+
.callout-actions {
|
|
102
|
+
display: flex;
|
|
103
|
+
flex-wrap: wrap;
|
|
104
|
+
align-items: center;
|
|
105
|
+
gap: var(--space-2-5);
|
|
106
|
+
margin-top: var(--space-3);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/* Action buttons adopt the callout's TONE so they belong to the tinted box.
|
|
110
|
+
.btn-secondary → tonal soft button (tint fill + tint border + tint text);
|
|
111
|
+
.btn-ghost → picks up the tone for text/hover.
|
|
112
|
+
.btn-danger / .btn-primary stay canonical (solid) for strong/destructive. */
|
|
113
|
+
.callout-actions .btn-secondary {
|
|
114
|
+
background: color-mix(in srgb, var(--callout-tint) 14%, var(--color-background-surface));
|
|
115
|
+
border-color: color-mix(in srgb, var(--callout-tint) 34%, transparent);
|
|
116
|
+
color: var(--callout-fg);
|
|
117
|
+
}
|
|
118
|
+
.callout-actions .btn-secondary:hover {
|
|
119
|
+
background: color-mix(in srgb, var(--callout-tint) 22%, var(--color-background-surface));
|
|
120
|
+
border-color: color-mix(in srgb, var(--callout-tint) 50%, transparent);
|
|
121
|
+
}
|
|
122
|
+
.callout-actions .btn-ghost { color: var(--callout-fg); }
|
|
123
|
+
.callout-actions .btn-ghost:hover { background: color-mix(in srgb, var(--callout-tint) 12%, transparent); color: var(--callout-fg); }
|
|
124
|
+
|
|
125
|
+
/* dismiss — ghost icon button, top-aligned */
|
|
126
|
+
.callout-dismiss {
|
|
127
|
+
flex-shrink: 0;
|
|
128
|
+
align-self: flex-start;
|
|
129
|
+
display: inline-flex;
|
|
130
|
+
align-items: center;
|
|
131
|
+
justify-content: center;
|
|
132
|
+
width: 26px;
|
|
133
|
+
height: 26px;
|
|
134
|
+
margin: -2px -2px 0 var(--space-2);
|
|
135
|
+
padding: 0;
|
|
136
|
+
border: 0;
|
|
137
|
+
border-radius: var(--radius-sm);
|
|
138
|
+
background: transparent;
|
|
139
|
+
color: var(--color-foreground-muted);
|
|
140
|
+
cursor: pointer;
|
|
141
|
+
transition: var(--transition-fast);
|
|
142
|
+
}
|
|
143
|
+
.callout-dismiss:hover { background: color-mix(in srgb, var(--callout-tint) 14%, transparent); color: var(--color-foreground-default); }
|
|
144
|
+
.callout-dismiss > i, .callout-dismiss > svg { width: 16px; height: 16px; stroke-width: var(--icon-stroke); }
|
|
145
|
+
|
|
146
|
+
/* ---- tonal variants ---- */
|
|
147
|
+
.callout-warn { --callout-tint: var(--color-warning-500); --callout-fg: var(--color-feedback-warning-foreground); }
|
|
148
|
+
.callout-success { --callout-tint: var(--color-success-500); --callout-fg: var(--color-feedback-success-foreground); }
|
|
149
|
+
.callout-danger { --callout-tint: var(--color-danger-500); --callout-fg: var(--color-feedback-danger-foreground); }
|
|
150
|
+
.callout-neutral { --callout-tint: var(--color-neutral-500); --callout-fg: var(--color-foreground-muted); }
|
|
151
|
+
|
|
152
|
+
/* ---- compact size ---- */
|
|
153
|
+
.callout-sm { padding: var(--space-3) var(--space-4); gap: var(--space-2-5); }
|
|
154
|
+
.callout-sm > i, .callout-sm > svg, .callout-sm .callout-icon { width: 16px; height: 16px; }
|
|
155
|
+
.callout-sm .callout-body { font-size: var(--fs-xs); }
|
|
156
|
+
.callout-sm .callout-title { font-size: var(--fs-sm); }
|
|
157
|
+
|
|
158
|
+
/* ---- alert bar — full-width banner, items centered, actions right ---- */
|
|
159
|
+
.callout-bar {
|
|
160
|
+
align-items: center;
|
|
161
|
+
border-radius: 0;
|
|
162
|
+
border-left: 0;
|
|
163
|
+
border-right: 0;
|
|
164
|
+
padding: var(--space-3) var(--space-6);
|
|
165
|
+
border-left: 3px solid var(--callout-tint); /* accent rule for scannability */
|
|
166
|
+
}
|
|
167
|
+
.callout-bar > i, .callout-bar > svg, .callout-bar .callout-icon { margin-top: 0; }
|
|
168
|
+
.callout-bar .callout-content { flex-direction: row; align-items: center; gap: var(--space-3); flex-wrap: wrap; }
|
|
169
|
+
.callout-bar .callout-actions { margin-top: 0; margin-left: auto; }
|
|
170
|
+
.callout-bar .callout-dismiss { align-self: center; margin-top: 0; }
|
|
171
|
+
.callout-bar .callout-title { font-size: var(--fs-sm); }
|
|
172
|
+
|
|
173
|
+
/* rounded alert bar (when not edge-to-edge) */
|
|
174
|
+
.callout-bar.callout-rounded { border-radius: var(--radius-md); border-left-width: 3px; border-top: 1px solid color-mix(in srgb, var(--callout-tint) 22%, transparent); border-right: 1px solid color-mix(in srgb, var(--callout-tint) 22%, transparent); border-bottom: 1px solid color-mix(in srgb, var(--callout-tint) 22%, transparent); }
|
|
175
|
+
|
|
176
|
+
/* ---- Inline: content-sized, single-line (badges, hero notices) ---- */
|
|
177
|
+
.callout-inline { display: inline-flex; width: auto; align-items: center; }
|
|
178
|
+
|
|
179
|
+
/* ---- On inverse: glassy translucent tint + light text, for dark
|
|
180
|
+
surfaces (hero, photo). Mirrors .pill.on-inverse. ---- */
|
|
181
|
+
.callout.on-inverse {
|
|
182
|
+
background: color-mix(in srgb, var(--callout-tint) 20%, transparent);
|
|
183
|
+
border-color: color-mix(in srgb, var(--callout-tint) 38%, transparent);
|
|
184
|
+
color: var(--color-foreground-inverse-default);
|
|
185
|
+
-webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
|
|
186
|
+
}
|
|
187
|
+
.callout.on-inverse > i, .callout.on-inverse > svg, .callout.on-inverse .callout-icon { color: var(--callout-fg-inv, currentColor); }
|
|
188
|
+
.callout.on-inverse .callout-title { color: var(--color-foreground-inverse-default); }
|
|
189
|
+
.callout.on-inverse .callout-body { color: var(--color-foreground-inverse-secondary); }
|
|
190
|
+
.callout.on-inverse .callout-body strong { color: var(--color-foreground-inverse-default); }
|
|
191
|
+
.callout-warn.on-inverse { --callout-fg-inv: var(--color-warning-300); }
|
|
192
|
+
.callout-success.on-inverse { --callout-fg-inv: var(--color-success-300); }
|
|
193
|
+
.callout-danger.on-inverse { --callout-fg-inv: var(--color-danger-300); }
|
|
194
|
+
.callout-info.on-inverse { --callout-fg-inv: var(--color-brand-accent-300); }
|
|
195
|
+
.callout-neutral.on-inverse { --callout-fg-inv: var(--color-foreground-inverse-muted); }
|