@fluid-theme/core 0.4.3

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.
Files changed (48) hide show
  1. package/AGENTS.md +32 -0
  2. package/CHANGELOG.md +159 -0
  3. package/CLAUDE.md +104 -0
  4. package/GEMINI.md +48 -0
  5. package/LICENSE +21 -0
  6. package/README.md +253 -0
  7. package/dist/fluid.min.css +2 -0
  8. package/fluid-agent-kit/README.md +57 -0
  9. package/fluid-agent-kit/skills/accessibility.md +41 -0
  10. package/fluid-agent-kit/skills/css-conventions.md +51 -0
  11. package/fluid-agent-kit/skills/image-optimization.md +115 -0
  12. package/fluid-agent-kit/skills/ux-rules.md +43 -0
  13. package/package.json +68 -0
  14. package/src/animations/scroll-reveal.css +224 -0
  15. package/src/components/accordion.css +250 -0
  16. package/src/components/alert.css +453 -0
  17. package/src/components/avatar.css +192 -0
  18. package/src/components/badge.css +182 -0
  19. package/src/components/button.css +387 -0
  20. package/src/components/card.css +650 -0
  21. package/src/components/chip.css +143 -0
  22. package/src/components/dropdown.css +335 -0
  23. package/src/components/empty-state.css +105 -0
  24. package/src/components/form.css +508 -0
  25. package/src/components/hero.css +293 -0
  26. package/src/components/indicator.css +455 -0
  27. package/src/components/loading.css +274 -0
  28. package/src/components/modal.css +364 -0
  29. package/src/components/nav.css +726 -0
  30. package/src/components/scroll-progress.css +104 -0
  31. package/src/components/search-input.css +125 -0
  32. package/src/components/settings-panel.css +603 -0
  33. package/src/components/step-indicator.css +188 -0
  34. package/src/components/table.css +350 -0
  35. package/src/components/themed-images.css +229 -0
  36. package/src/components/tooltip.css +247 -0
  37. package/src/components/version-badge.css +70 -0
  38. package/src/core/base.css +884 -0
  39. package/src/core/reset.css +159 -0
  40. package/src/core/tokens.css +2416 -0
  41. package/src/fluid.css +242 -0
  42. package/src/layouts/positioning.css +626 -0
  43. package/src/sections/cta.css +210 -0
  44. package/src/sections/features.css +356 -0
  45. package/src/sections/footer.css +283 -0
  46. package/src/sections/stats.css +234 -0
  47. package/src/sections/team.css +181 -0
  48. package/src/sections/testimonials.css +251 -0
@@ -0,0 +1,188 @@
1
+ /**
2
+ * Fluid Framework - Step Indicator Component
3
+ * @layer components
4
+ *
5
+ * Discrete labeled steps for multi-step forms and onboarding flows.
6
+ *
7
+ * Usage:
8
+ * <nav class="steps" aria-label="Progress">
9
+ * <ol class="steps__list">
10
+ * <li class="steps__item" data-status="complete">
11
+ * <span class="steps__marker">1</span>
12
+ * <span class="steps__label">Account</span>
13
+ * </li>
14
+ * <li class="steps__item" data-status="current" aria-current="step">
15
+ * <span class="steps__marker">2</span>
16
+ * <span class="steps__label">Details</span>
17
+ * </li>
18
+ * <li class="steps__item">
19
+ * <span class="steps__marker">3</span>
20
+ * <span class="steps__label">Review</span>
21
+ * </li>
22
+ * </ol>
23
+ * </nav>
24
+ *
25
+ * Statuses: data-status="complete|current" (default: upcoming)
26
+ * Variants: data-size="sm"
27
+ */
28
+
29
+ @layer components {
30
+ .steps__list {
31
+ display: flex;
32
+ align-items: flex-start;
33
+ gap: 0;
34
+ list-style: none;
35
+ padding: 0;
36
+ margin: 0;
37
+ counter-reset: step;
38
+ }
39
+
40
+ .steps__item {
41
+ flex: 1;
42
+ display: flex;
43
+ flex-direction: column;
44
+ align-items: center;
45
+ gap: var(--space-2);
46
+ position: relative;
47
+ text-align: center;
48
+ margin: 0;
49
+ }
50
+
51
+ /* Connector line between steps */
52
+ .steps__item:not(:last-child)::after {
53
+ content: "";
54
+ position: absolute;
55
+ inset-block-start: calc(1.25rem / 2);
56
+ inset-inline-start: calc(50% + 1rem);
57
+ inline-size: calc(100% - 2rem);
58
+ block-size: 2px;
59
+ background: var(--color-border);
60
+ z-index: 0;
61
+ }
62
+
63
+ .steps__item[data-status="complete"]:not(:last-child)::after {
64
+ background: var(--accent);
65
+ }
66
+
67
+ /* Step marker (circle) */
68
+ .steps__marker {
69
+ display: flex;
70
+ align-items: center;
71
+ justify-content: center;
72
+ inline-size: 2.5rem;
73
+ block-size: 2.5rem;
74
+ border-radius: var(--radius-full);
75
+ border: 2px solid var(--color-border);
76
+ background: var(--color-background);
77
+ font-size: var(--font-size-sm);
78
+ font-weight: var(--weight-semibold);
79
+ color: var(--color-text-muted);
80
+ position: relative;
81
+ z-index: var(--z-raised);
82
+ transition:
83
+ background-color var(--duration-normal) var(--ease-fluid),
84
+ border-color var(--duration-normal) var(--ease-fluid),
85
+ color var(--duration-normal) var(--ease-fluid);
86
+ }
87
+
88
+ /* Current step */
89
+ .steps__item[data-status="current"] .steps__marker {
90
+ border-color: var(--accent);
91
+ background: var(--accent);
92
+ color: var(--white);
93
+ box-shadow: 0 0 0 3px var(--accent-subtle);
94
+ }
95
+
96
+ /* Completed step */
97
+ .steps__item[data-status="complete"] .steps__marker {
98
+ border-color: var(--accent);
99
+ background: var(--accent);
100
+ color: var(--white);
101
+ }
102
+
103
+ /* Checkmark for completed steps */
104
+ .steps__item[data-status="complete"] .steps__marker::after {
105
+ content: "✓";
106
+ font-size: var(--font-size-base);
107
+ }
108
+
109
+ /* Hide the number text when showing checkmark */
110
+ .steps__item[data-status="complete"] .steps__marker {
111
+ font-size: 0;
112
+ }
113
+
114
+ .steps__item[data-status="complete"] .steps__marker::after {
115
+ font-size: var(--font-size-base);
116
+ }
117
+
118
+ /* Step label */
119
+ .steps__label {
120
+ font-size: var(--font-size-sm);
121
+ color: var(--color-text-muted);
122
+ font-weight: var(--weight-medium);
123
+ }
124
+
125
+ .steps__item[data-status="current"] .steps__label {
126
+ color: var(--color-text);
127
+ font-weight: var(--weight-semibold);
128
+ }
129
+
130
+ .steps__item[data-status="complete"] .steps__label {
131
+ color: var(--color-text);
132
+ }
133
+
134
+
135
+ /* ========================================
136
+ SMALL VARIANT
137
+ ======================================== */
138
+
139
+ .steps[data-size="sm"] .steps__marker {
140
+ inline-size: 1.75rem;
141
+ block-size: 1.75rem;
142
+ font-size: var(--font-size-xs);
143
+ }
144
+
145
+ .steps[data-size="sm"] .steps__item:not(:last-child)::after {
146
+ inset-block-start: calc(1.75rem / 2 - 1px);
147
+ inset-inline-start: calc(50% + 0.75rem);
148
+ inline-size: calc(100% - 1.5rem);
149
+ }
150
+
151
+ .steps[data-size="sm"] .steps__label {
152
+ font-size: var(--font-size-xs);
153
+ }
154
+
155
+
156
+ /* ========================================
157
+ RESPONSIVE
158
+ ======================================== */
159
+
160
+ @media (max-width: 40rem) {
161
+ .steps__label {
162
+ font-size: var(--font-size-xs);
163
+ }
164
+
165
+ .steps__marker {
166
+ inline-size: 2rem;
167
+ block-size: 2rem;
168
+ font-size: var(--font-size-xs);
169
+ }
170
+
171
+ .steps__item:not(:last-child)::after {
172
+ inset-block-start: calc(1rem - 1px);
173
+ inset-inline-start: calc(50% + 0.75rem);
174
+ inline-size: calc(100% - 1.5rem);
175
+ }
176
+ }
177
+
178
+
179
+ /* ========================================
180
+ REDUCED MOTION
181
+ ======================================== */
182
+
183
+ @media (prefers-reduced-motion: reduce) {
184
+ .steps__marker {
185
+ transition: none;
186
+ }
187
+ }
188
+ }
@@ -0,0 +1,350 @@
1
+ /**
2
+ * Fluid Framework - Responsive Table Component
3
+ * @layer components
4
+ *
5
+ * Tables that adapt to their container.
6
+ * Responsive strategies: horizontal scroll, stacked on mobile.
7
+ *
8
+ * Usage:
9
+ * <div class="table-wrap">
10
+ * <table class="table">
11
+ * <thead>
12
+ * <tr>
13
+ * <th>Name</th>
14
+ * <th>Status</th>
15
+ * <th data-align="end">Amount</th>
16
+ * </tr>
17
+ * </thead>
18
+ * <tbody>
19
+ * <tr>
20
+ * <td>Item</td>
21
+ * <td><span class="badge" data-status="good">Active</span></td>
22
+ * <td data-align="end">$99.00</td>
23
+ * </tr>
24
+ * </tbody>
25
+ * </table>
26
+ * </div>
27
+ *
28
+ * Variants:
29
+ * data-variant="striped" — alternating row backgrounds
30
+ * data-variant="bordered" — all cell borders
31
+ * data-variant="compact" — reduced padding
32
+ *
33
+ * Features:
34
+ * data-hover — highlight rows on hover
35
+ * data-sticky-col — sticky first column
36
+ */
37
+
38
+ @layer components {
39
+ /* ========================================
40
+ TABLE WRAPPER
41
+ Provides horizontal scroll overflow
42
+ ======================================== */
43
+
44
+ .table-wrap {
45
+ overflow-x: auto;
46
+ overscroll-behavior-x: contain;
47
+ border: var(--border-width) solid var(--color-border-subtle);
48
+ border-radius: var(--radius-lg);
49
+
50
+ /* Scrollbar styling */
51
+ scrollbar-width: thin;
52
+ scrollbar-color: var(--color-border) transparent;
53
+ }
54
+
55
+ .table-wrap::-webkit-scrollbar {
56
+ block-size: 6px;
57
+ }
58
+
59
+ .table-wrap::-webkit-scrollbar-track {
60
+ background: transparent;
61
+ }
62
+
63
+ .table-wrap::-webkit-scrollbar-thumb {
64
+ background: var(--color-border);
65
+ border-radius: var(--radius-full);
66
+ }
67
+
68
+
69
+ /* ========================================
70
+ BASE TABLE
71
+ ======================================== */
72
+
73
+ .table {
74
+ inline-size: 100%;
75
+ border-collapse: collapse;
76
+ font-size: var(--font-size-sm);
77
+ line-height: var(--leading-normal);
78
+ text-align: start;
79
+ }
80
+
81
+ /* Header cells */
82
+ .table th {
83
+ padding: var(--space-3) var(--space-4);
84
+ font-weight: var(--weight-semibold);
85
+ font-size: var(--font-size-xs);
86
+ text-transform: uppercase;
87
+ letter-spacing: var(--tracking-wider);
88
+ color: var(--color-text-muted);
89
+ background: var(--color-surface);
90
+ border-block-end: var(--border-width-thick) solid var(--color-border-subtle);
91
+ white-space: nowrap;
92
+ position: relative;
93
+ }
94
+
95
+ /* Body cells */
96
+ .table td {
97
+ padding: var(--space-3) var(--space-4);
98
+ border-block-end: var(--border-width) solid var(--color-border-subtle);
99
+ vertical-align: middle;
100
+ }
101
+
102
+ /* Last row: no bottom border */
103
+ .table tbody tr:last-child td {
104
+ border-block-end: none;
105
+ }
106
+
107
+ /* Alignment via data attribute */
108
+ .table [data-align="end"],
109
+ .table [data-align="right"] {
110
+ text-align: end;
111
+ }
112
+
113
+ .table [data-align="center"] {
114
+ text-align: center;
115
+ }
116
+
117
+ /* Numeric data: tabular-nums for alignment */
118
+ .table [data-type="numeric"] {
119
+ font-variant-numeric: tabular-nums;
120
+ text-align: end;
121
+ }
122
+
123
+
124
+ /* ========================================
125
+ TABLE VARIANTS
126
+ ======================================== */
127
+
128
+ /* Striped: alternating row backgrounds */
129
+ .table[data-variant="striped"] tbody tr:nth-child(even) {
130
+ background: var(--color-surface);
131
+ }
132
+
133
+ /* Bordered: all cell borders */
134
+ .table[data-variant="bordered"] th,
135
+ .table[data-variant="bordered"] td {
136
+ border: var(--border-width) solid var(--color-border-subtle);
137
+ }
138
+
139
+ /* Compact: tighter spacing */
140
+ .table[data-variant="compact"] th,
141
+ .table[data-variant="compact"] td {
142
+ padding: var(--space-2) var(--space-3);
143
+ }
144
+
145
+
146
+ /* ========================================
147
+ INTERACTIVE FEATURES
148
+ ======================================== */
149
+
150
+ /* Hover highlight */
151
+ .table[data-hover] tbody tr {
152
+ transition: background-color var(--duration-fast) var(--ease-fluid);
153
+ }
154
+
155
+ .table[data-hover] tbody tr:hover {
156
+ background: color-mix(in oklch, var(--accent) 5%, var(--color-background));
157
+ }
158
+
159
+ /* Selectable rows */
160
+ .table[data-selectable] tbody tr {
161
+ cursor: pointer;
162
+ }
163
+
164
+ .table[data-selectable] tbody tr[aria-selected="true"] {
165
+ background: color-mix(in oklch, var(--accent) 10%, var(--color-background));
166
+ }
167
+
168
+ /* Sticky first column */
169
+ .table[data-sticky-col] th:first-child,
170
+ .table[data-sticky-col] td:first-child {
171
+ position: sticky;
172
+ inset-inline-start: 0;
173
+ z-index: var(--z-raised);
174
+ background: var(--color-surface-raised);
175
+ box-shadow: 2px 0 4px oklch(from var(--shadow-color) l c h / 0.06);
176
+ }
177
+
178
+ .table[data-sticky-col] th:first-child {
179
+ background: var(--color-surface);
180
+ z-index: calc(var(--z-raised) + 1);
181
+ }
182
+
183
+ /* Sticky header */
184
+ .table[data-sticky-header] thead th {
185
+ position: sticky;
186
+ inset-block-start: 0;
187
+ z-index: var(--z-raised);
188
+ }
189
+
190
+
191
+ /* ========================================
192
+ SORTABLE HEADERS
193
+ ======================================== */
194
+
195
+ .table th[data-sortable] {
196
+ cursor: pointer;
197
+ user-select: none;
198
+ padding-inline-end: var(--space-6);
199
+ }
200
+
201
+ .table th[data-sortable]:hover {
202
+ background: color-mix(in oklch, var(--accent) 8%, var(--color-surface));
203
+ }
204
+
205
+ .table th[data-sortable]::after {
206
+ content: "";
207
+ position: absolute;
208
+ inset-inline-end: var(--space-3);
209
+ inset-block-start: 50%;
210
+ translate: 0 -50%;
211
+ inline-size: 0.75rem;
212
+ block-size: 0.75rem;
213
+ background: var(--color-text-subtle);
214
+ mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2.5'%3E%3Cpath d='M8 9l4-4 4 4M8 15l4 4 4-4'/%3E%3C/svg%3E");
215
+ mask-size: contain;
216
+ mask-repeat: no-repeat;
217
+ opacity: 0.4;
218
+ }
219
+
220
+ .table th[data-sort="asc"]::after {
221
+ mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2.5'%3E%3Cpath d='M8 14l4-4 4 4'/%3E%3C/svg%3E");
222
+ opacity: 1;
223
+ background: var(--accent);
224
+ }
225
+
226
+ .table th[data-sort="desc"]::after {
227
+ mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2.5'%3E%3Cpath d='M8 10l4 4 4-4'/%3E%3C/svg%3E");
228
+ opacity: 1;
229
+ background: var(--accent);
230
+ }
231
+
232
+
233
+ /* ========================================
234
+ EMPTY STATE
235
+ ======================================== */
236
+
237
+ .table__empty {
238
+ text-align: center;
239
+ padding: var(--space-10) var(--space-5);
240
+ color: var(--color-text-subtle);
241
+ }
242
+
243
+ .table__empty td {
244
+ border: none;
245
+ }
246
+
247
+
248
+ /* ========================================
249
+ TABLE CAPTION & FOOTER
250
+ ======================================== */
251
+
252
+ .table caption {
253
+ padding: var(--space-3) var(--space-4);
254
+ font-size: var(--font-size-sm);
255
+ color: var(--color-text-muted);
256
+ text-align: start;
257
+ caption-side: bottom;
258
+ }
259
+
260
+ .table tfoot td {
261
+ font-weight: var(--weight-semibold);
262
+ background: var(--color-surface);
263
+ border-block-start: var(--border-width-thick) solid var(--color-border-subtle);
264
+ }
265
+
266
+
267
+ /* ========================================
268
+ THEME-SPECIFIC STYLES
269
+ ======================================== */
270
+
271
+ /* Still: crisp borders */
272
+ [data-motion="still"] .table-wrap {
273
+ border-radius: 0;
274
+ }
275
+
276
+ /* Serene: soft rounded */
277
+ [data-motion="serene"] .table-wrap {
278
+ border-radius: var(--radius-xl);
279
+ }
280
+
281
+ /* Rapids: hard offset shadow */
282
+ [data-motion="rapids"] .table-wrap {
283
+ box-shadow: var(--shadow-offset);
284
+ }
285
+
286
+ /* Tsunami: asymmetric corners */
287
+ [data-motion="tsunami"] .table-wrap {
288
+ border-radius: var(--radius-asymmetric, 0 24px 0 0);
289
+ }
290
+
291
+
292
+ /* ========================================
293
+ RESPONSIVE: Stacked layout on mobile
294
+ Apply data-responsive to enable
295
+ ======================================== */
296
+
297
+ @media (max-width: 40rem) {
298
+ .table[data-responsive] thead {
299
+ /* Visually hide header but keep accessible */
300
+ position: absolute;
301
+ inline-size: 1px;
302
+ block-size: 1px;
303
+ overflow: hidden;
304
+ clip: rect(0, 0, 0, 0);
305
+ }
306
+
307
+ .table[data-responsive] tbody tr {
308
+ display: block;
309
+ padding: var(--space-4);
310
+ border-block-end: var(--border-width) solid var(--color-border-subtle);
311
+ }
312
+
313
+ .table[data-responsive] tbody tr:last-child {
314
+ border-block-end: none;
315
+ }
316
+
317
+ .table[data-responsive] td {
318
+ display: flex;
319
+ justify-content: space-between;
320
+ align-items: center;
321
+ gap: var(--space-3);
322
+ padding: var(--space-2) 0;
323
+ border: none;
324
+ text-align: end;
325
+ }
326
+
327
+ /* Use data-label for row headers on mobile */
328
+ .table[data-responsive] td::before {
329
+ content: attr(data-label);
330
+ font-weight: var(--weight-semibold);
331
+ color: var(--color-text);
332
+ text-align: start;
333
+ }
334
+
335
+ .table[data-responsive] td[data-align] {
336
+ text-align: end;
337
+ }
338
+ }
339
+
340
+
341
+ /* ========================================
342
+ REDUCED MOTION
343
+ ======================================== */
344
+
345
+ @media (prefers-reduced-motion: reduce) {
346
+ .table[data-hover] tbody tr {
347
+ transition: none;
348
+ }
349
+ }
350
+ }