@fpkit/acss 0.6.2 → 1.0.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/README.md +32 -0
- package/docs/README.md +325 -0
- package/docs/guides/accessibility.md +764 -0
- package/docs/guides/architecture.md +705 -0
- package/docs/guides/composition.md +688 -0
- package/docs/guides/css-variables.md +522 -0
- package/docs/guides/storybook.md +828 -0
- package/docs/guides/testing.md +817 -0
- package/docs/testing/focus-indicator-testing.md +437 -0
- package/libs/components/alert/alert.css +1 -1
- package/libs/components/alert/alert.css.map +1 -1
- package/libs/components/alert/alert.min.css +2 -2
- package/libs/components/badge/badge.css +1 -1
- package/libs/components/badge/badge.css.map +1 -1
- package/libs/components/badge/badge.min.css +2 -2
- package/libs/components/breadcrumbs/breadcrumb.css +1 -1
- package/libs/components/breadcrumbs/breadcrumb.css.map +1 -1
- package/libs/components/breadcrumbs/breadcrumb.min.css +2 -2
- package/libs/components/buttons/button.css +1 -1
- package/libs/components/buttons/button.css.map +1 -1
- package/libs/components/buttons/button.min.css +2 -2
- package/libs/components/cards/card.css +1 -1
- package/libs/components/cards/card.css.map +1 -1
- package/libs/components/cards/card.min.css +2 -2
- package/libs/components/details/details.css +1 -1
- package/libs/components/details/details.css.map +1 -1
- package/libs/components/details/details.min.css +2 -2
- package/libs/components/dialog/dialog.css +1 -1
- package/libs/components/dialog/dialog.css.map +1 -1
- package/libs/components/dialog/dialog.min.css +2 -2
- package/libs/components/form/form.css +1 -1
- package/libs/components/form/form.css.map +1 -1
- package/libs/components/form/form.min.css +2 -2
- package/libs/components/images/img.css +1 -1
- package/libs/components/images/img.css.map +1 -1
- package/libs/components/images/img.min.css +2 -2
- package/libs/components/layout/landmarks.css +1 -1
- package/libs/components/layout/landmarks.css.map +1 -1
- package/libs/components/layout/landmarks.min.css +2 -2
- package/libs/components/link/link.css +1 -1
- package/libs/components/link/link.css.map +1 -1
- package/libs/components/link/link.min.css +2 -2
- package/libs/components/list/list.css +1 -1
- package/libs/components/list/list.min.css +1 -1
- package/libs/components/nav/nav.css +1 -1
- package/libs/components/nav/nav.css.map +1 -1
- package/libs/components/nav/nav.min.css +2 -2
- package/libs/components/progress/progress.css +1 -1
- package/libs/components/progress/progress.css.map +1 -1
- package/libs/components/progress/progress.min.css +2 -2
- package/libs/components/tag/tag.css +1 -1
- package/libs/components/tag/tag.css.map +1 -1
- package/libs/components/tag/tag.min.css +2 -2
- package/libs/index.css +1 -1
- package/libs/index.css.map +1 -1
- package/package.json +4 -3
- package/src/components/README.mdx +1 -1
- package/src/components/alert/alert.scss +4 -4
- package/src/components/alert/alert.scss.backup +184 -0
- package/src/components/alert/alert.stories.tsx +53 -2
- package/src/components/badge/badge.scss +2 -2
- package/src/components/badge/badge.scss.backup +39 -0
- package/src/components/badge/badge.stories.tsx +40 -0
- package/src/components/breadcrumbs/breadcrumb.scss +5 -5
- package/src/components/breadcrumbs/breadcrumb.scss.backup +35 -0
- package/src/components/breadcrumbs/breadcrumb.stories.tsx +17 -1
- package/src/components/buttons/button.scss +32 -27
- package/src/components/buttons/button.scss.backup +145 -0
- package/src/components/buttons/button.stories.tsx +196 -7
- package/src/components/cards/card.scss +39 -5
- package/src/components/cards/card.scss.backup +67 -0
- package/src/components/cards/card.stories.tsx +184 -1
- package/src/components/details/details.scss +14 -14
- package/src/components/details/details.scss.backup +126 -0
- package/src/components/details/details.stories.tsx +41 -1
- package/src/components/dialog/dialog.scss +3 -3
- package/src/components/dialog/dialog.scss.backup +126 -0
- package/src/components/form/form.scss +25 -9
- package/src/components/form/form.scss.backup +87 -0
- package/src/components/form/form.stories.tsx +272 -1
- package/src/components/form/input.stories.tsx +159 -1
- package/src/components/form/select.stories.tsx +1 -1
- package/src/components/heading/README.mdx +292 -0
- package/src/components/icons/icon.stories.tsx +1 -1
- package/src/components/images/figure.stories.tsx +41 -1
- package/src/components/images/img.scss +8 -8
- package/src/components/images/img.scss.backup +59 -0
- package/src/components/layout/_header.scss +14 -14
- package/src/components/layout/_header.scss.backup +72 -0
- package/src/components/layout/landmarks.scss +7 -7
- package/src/components/layout/landmarks.scss.backup +51 -0
- package/src/components/layout/landmarks.stories.tsx +42 -0
- package/src/components/link/link.scss +5 -5
- package/src/components/link/link.scss.backup +145 -0
- package/src/components/link/link.stories.tsx +38 -2
- package/src/components/list/list.scss +1 -1
- package/src/components/nav/nav.scss +17 -17
- package/src/components/nav/nav.scss.backup +123 -0
- package/src/components/nav/nav.stories.tsx +36 -2
- package/src/components/progress/progress.scss +7 -7
- package/src/components/progress/progress.scss.backup +70 -0
- package/src/components/tag/tag.scss +10 -10
- package/src/components/tag/tag.scss.backup +130 -0
- package/src/components/tag/tag.stories.tsx +23 -2
- package/src/components/ui.stories.tsx +53 -19
- package/src/docs/accessibility.mdx +484 -0
- package/src/docs/composition.mdx +549 -0
- package/src/docs/css-variables.mdx +380 -0
- package/src/docs/fpkit-developer.mdx +545 -0
- package/src/introduction.mdx +356 -0
- package/src/styles/alert/alert.css +4 -4
- package/src/styles/badge/badge.css +2 -2
- package/src/styles/breadcrumbs/breadcrumb.css +5 -5
- package/src/styles/buttons/button.css +30 -27
- package/src/styles/buttons/button.css.map +1 -1
- package/src/styles/cards/card.css +35 -5
- package/src/styles/cards/card.css.map +1 -1
- package/src/styles/details/details.css +14 -14
- package/src/styles/dialog/dialog.css +3 -3
- package/src/styles/form/form.css +20 -10
- package/src/styles/form/form.css.map +1 -1
- package/src/styles/images/img.css +8 -8
- package/src/styles/index.css +179 -134
- package/src/styles/index.css.map +1 -1
- package/src/styles/layout/landmarks.css +21 -21
- package/src/styles/link/link.css +5 -5
- package/src/styles/list/list.css +1 -1
- package/src/styles/nav/nav.css +17 -17
- package/src/styles/progress/progress.css +6 -6
- package/src/styles/tag/tag.css +4 -4
- package/src/styles/utilities/_disabled.scss +5 -4
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
--card-p: 2rem;
|
|
3
|
+
--card-bg: #fff;
|
|
4
|
+
--card-radius: calc(var(--card-p) / 4);
|
|
5
|
+
--card-position: relative;
|
|
6
|
+
--card-display: flex;
|
|
7
|
+
--card-direction: column;
|
|
8
|
+
--card-gap: 1rem;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
[data-card],
|
|
12
|
+
[data-component~='card'] {
|
|
13
|
+
display: var(--card-display);
|
|
14
|
+
flex-direction: var(--card-direction);
|
|
15
|
+
gap: var(--card-gap);
|
|
16
|
+
border-radius: var(--card-radius);
|
|
17
|
+
background-color: var(--card-bg);
|
|
18
|
+
text-align: var(--card-align, left);
|
|
19
|
+
|
|
20
|
+
h3,
|
|
21
|
+
h2 {
|
|
22
|
+
margin-block-end: 0;
|
|
23
|
+
padding-block-end: 0;
|
|
24
|
+
}
|
|
25
|
+
+ div {
|
|
26
|
+
margin-block-start: 0;
|
|
27
|
+
}
|
|
28
|
+
> article {
|
|
29
|
+
display: flex;
|
|
30
|
+
flex-direction: column;
|
|
31
|
+
flex: 2;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
> *:not(img) {
|
|
35
|
+
padding-inline: var(--card-p);
|
|
36
|
+
}
|
|
37
|
+
> *:last-child:not(img) {
|
|
38
|
+
// margin-block-end: 0;
|
|
39
|
+
padding-block-end: var(--card-p);
|
|
40
|
+
}
|
|
41
|
+
> *:first-child:not(img) {
|
|
42
|
+
padding-block-start: calc(var(--card-p) - 0.5rem);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Interactive card styles - WCAG 2.4.7 compliant focus indicators
|
|
47
|
+
[data-card="interactive"] {
|
|
48
|
+
cursor: pointer;
|
|
49
|
+
transition: box-shadow 0.2s ease, transform 0.2s ease;
|
|
50
|
+
|
|
51
|
+
&:hover {
|
|
52
|
+
transform: translateY(-2px);
|
|
53
|
+
box-shadow: 0 0.25rem 0.75rem rgba(0, 0, 0, 0.15);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Visible focus indicator with 3:1 minimum contrast (WCAG 2.4.7)
|
|
57
|
+
&:focus-visible {
|
|
58
|
+
outline: 0.125rem solid var(--focus-color, #0066CC);
|
|
59
|
+
outline-offset: 0.125rem;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Hide outline for mouse users (modern browsers)
|
|
63
|
+
&:focus:not(:focus-visible) {
|
|
64
|
+
outline: none;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
@@ -6,7 +6,7 @@ const content =
|
|
|
6
6
|
|
|
7
7
|
const meta: Meta<typeof Card> = {
|
|
8
8
|
title: "FP.REACT Components/Card",
|
|
9
|
-
tags: ["
|
|
9
|
+
tags: ["stable", "autodocs"],
|
|
10
10
|
component: Card,
|
|
11
11
|
args: {
|
|
12
12
|
children: <p>{content}</p>,
|
|
@@ -307,3 +307,186 @@ export const CustomHeadingLevels: Story = {
|
|
|
307
307
|
},
|
|
308
308
|
},
|
|
309
309
|
} as Story;
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* CSS Variable Customization
|
|
313
|
+
*
|
|
314
|
+
* Demonstrates how to customize card appearance using the new standardized
|
|
315
|
+
* CSS custom property naming convention.
|
|
316
|
+
*
|
|
317
|
+
* New variable naming patterns:
|
|
318
|
+
* - Base properties: `--card-padding`, `--card-radius`, `--card-bg`, `--card-gap`
|
|
319
|
+
* - Element-specific: `--card-header-*`, `--card-body-*`, `--card-footer-*`
|
|
320
|
+
* - Full property names (no single-letter abbreviations)
|
|
321
|
+
*/
|
|
322
|
+
export const Customization: Story = {
|
|
323
|
+
render: () => (
|
|
324
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '2rem' }}>
|
|
325
|
+
{/* Custom padding and spacing */}
|
|
326
|
+
<div>
|
|
327
|
+
<h4>Custom Padding & Spacing</h4>
|
|
328
|
+
<Card styles={{
|
|
329
|
+
"--card-padding": "3rem",
|
|
330
|
+
"--card-radius": "1rem",
|
|
331
|
+
"--card-gap": "1.5rem",
|
|
332
|
+
}}>
|
|
333
|
+
<Card.Title>Spacious Card</Card.Title>
|
|
334
|
+
<Card.Content>
|
|
335
|
+
<p>This card uses custom padding (3rem) and larger border radius (1rem).</p>
|
|
336
|
+
</Card.Content>
|
|
337
|
+
</Card>
|
|
338
|
+
</div>
|
|
339
|
+
|
|
340
|
+
{/* Compact card */}
|
|
341
|
+
<div>
|
|
342
|
+
<h4>Compact Card</h4>
|
|
343
|
+
<Card styles={{
|
|
344
|
+
"--card-padding": "1rem",
|
|
345
|
+
"--card-radius": "0.25rem",
|
|
346
|
+
"--card-gap": "0.5rem",
|
|
347
|
+
}}>
|
|
348
|
+
<Card.Title>Compact Card</Card.Title>
|
|
349
|
+
<Card.Content>
|
|
350
|
+
<p>This card uses minimal padding and smaller gaps for a compact layout.</p>
|
|
351
|
+
</Card.Content>
|
|
352
|
+
</Card>
|
|
353
|
+
</div>
|
|
354
|
+
|
|
355
|
+
{/* Custom header/footer styling */}
|
|
356
|
+
<div>
|
|
357
|
+
<h4>Element-Specific Customization (Header, Body, Footer)</h4>
|
|
358
|
+
<div style={{ display: 'flex', gap: '1rem', flexWrap: 'wrap' }}>
|
|
359
|
+
<Card styles={{
|
|
360
|
+
"--card-header-padding": "1.5rem 2rem",
|
|
361
|
+
"--card-header-bg": "#0066cc",
|
|
362
|
+
"--card-header-border-bottom": "none",
|
|
363
|
+
"--card-body-padding": "2rem",
|
|
364
|
+
"--card-footer-padding": "1rem 2rem",
|
|
365
|
+
"--card-footer-bg": "#f0f0f0",
|
|
366
|
+
"--card-footer-border-top": "2px solid #ddd",
|
|
367
|
+
}}>
|
|
368
|
+
<header data-card-header style={{ color: 'white' }}>
|
|
369
|
+
<h3 style={{ margin: 0 }}>Custom Header</h3>
|
|
370
|
+
</header>
|
|
371
|
+
<div data-card-body>
|
|
372
|
+
<p>This card demonstrates element-specific customization using the new scoped variables.</p>
|
|
373
|
+
<p>Header has custom blue background, body has custom padding, footer has custom gray background.</p>
|
|
374
|
+
</div>
|
|
375
|
+
<footer data-card-footer>
|
|
376
|
+
<small>Custom Footer Content</small>
|
|
377
|
+
</footer>
|
|
378
|
+
</Card>
|
|
379
|
+
|
|
380
|
+
<Card styles={{
|
|
381
|
+
"--card-header-padding": "0.75rem 1.25rem",
|
|
382
|
+
"--card-header-bg": "#28a745",
|
|
383
|
+
"--card-header-border-bottom": "3px solid #1e7e34",
|
|
384
|
+
"--card-body-padding": "1.25rem",
|
|
385
|
+
"--card-footer-padding": "0.75rem 1.25rem",
|
|
386
|
+
"--card-footer-bg": "#e7f5ea",
|
|
387
|
+
}}>
|
|
388
|
+
<header data-card-header style={{ color: 'white' }}>
|
|
389
|
+
<h3 style={{ margin: 0 }}>Green Theme</h3>
|
|
390
|
+
</header>
|
|
391
|
+
<div data-card-body>
|
|
392
|
+
<p>Another example with green theme and custom element spacing.</p>
|
|
393
|
+
</div>
|
|
394
|
+
<footer data-card-footer>
|
|
395
|
+
<small>Footer with light green background</small>
|
|
396
|
+
</footer>
|
|
397
|
+
</Card>
|
|
398
|
+
</div>
|
|
399
|
+
</div>
|
|
400
|
+
|
|
401
|
+
{/* Dark theme card */}
|
|
402
|
+
<div
|
|
403
|
+
style={{
|
|
404
|
+
background: "#1a1a1a",
|
|
405
|
+
padding: "1.5rem",
|
|
406
|
+
borderRadius: "0.5rem",
|
|
407
|
+
}}
|
|
408
|
+
>
|
|
409
|
+
<h4 style={{ color: "white", marginTop: 0 }}>Dark Theme Example</h4>
|
|
410
|
+
<Card styles={{
|
|
411
|
+
"--card-bg": "#2a2a2a",
|
|
412
|
+
"--card-padding": "2rem",
|
|
413
|
+
"--card-radius": "0.75rem",
|
|
414
|
+
"--card-header-bg": "#3a3a3a",
|
|
415
|
+
"--card-header-border-bottom": "1px solid #4a4a4a",
|
|
416
|
+
"--card-footer-bg": "#3a3a3a",
|
|
417
|
+
"--card-footer-border-top": "1px solid #4a4a4a",
|
|
418
|
+
}}>
|
|
419
|
+
<header data-card-header>
|
|
420
|
+
<h3 style={{ margin: 0, color: 'white' }}>Dark Mode Card</h3>
|
|
421
|
+
</header>
|
|
422
|
+
<div data-card-body style={{ color: '#e5e7eb' }}>
|
|
423
|
+
<p>This card demonstrates dark theme customization with all element-specific variables.</p>
|
|
424
|
+
</div>
|
|
425
|
+
<footer data-card-footer style={{ color: '#9ca3af' }}>
|
|
426
|
+
<small>Styled with CSS custom properties</small>
|
|
427
|
+
</footer>
|
|
428
|
+
</Card>
|
|
429
|
+
</div>
|
|
430
|
+
|
|
431
|
+
{/* Brand card */}
|
|
432
|
+
<div>
|
|
433
|
+
<h4>Brand Card (No Radius, Custom Colors)</h4>
|
|
434
|
+
<Card styles={{
|
|
435
|
+
"--card-bg": "#fff5e6",
|
|
436
|
+
"--card-radius": "0",
|
|
437
|
+
"--card-padding": "2.5rem",
|
|
438
|
+
"--card-gap": "2rem",
|
|
439
|
+
"--card-header-bg": "#ff9800",
|
|
440
|
+
"--card-header-border-bottom": "4px solid #f57c00",
|
|
441
|
+
}}>
|
|
442
|
+
<header data-card-header>
|
|
443
|
+
<h3 style={{ margin: 0, color: 'white' }}>Brand Card</h3>
|
|
444
|
+
</header>
|
|
445
|
+
<div data-card-body>
|
|
446
|
+
<p>This card uses brand colors and no border radius for a distinct look.</p>
|
|
447
|
+
</div>
|
|
448
|
+
</Card>
|
|
449
|
+
</div>
|
|
450
|
+
</div>
|
|
451
|
+
),
|
|
452
|
+
parameters: {
|
|
453
|
+
docs: {
|
|
454
|
+
description: {
|
|
455
|
+
story: `
|
|
456
|
+
## Available CSS Variables
|
|
457
|
+
|
|
458
|
+
### Base Properties
|
|
459
|
+
- \`--card-padding\`: Main card padding (default: 2rem)
|
|
460
|
+
- \`--card-bg\`: Background color (default: #fff)
|
|
461
|
+
- \`--card-radius\`: Border radius (default: calc(var(--card-padding) / 4))
|
|
462
|
+
- \`--card-display\`: Display property (default: flex)
|
|
463
|
+
- \`--card-direction\`: Flex direction (default: column)
|
|
464
|
+
- \`--card-gap\`: Gap between child elements (default: 1rem)
|
|
465
|
+
|
|
466
|
+
### Element-Specific Variables (NEW)
|
|
467
|
+
#### Header
|
|
468
|
+
- \`--card-header-padding\`: Header padding (default: 1rem 1.5rem)
|
|
469
|
+
- \`--card-header-bg\`: Header background color (default: #f8f9fa)
|
|
470
|
+
- \`--card-header-border-bottom\`: Header bottom border (default: 1px solid #dee2e6)
|
|
471
|
+
|
|
472
|
+
#### Body
|
|
473
|
+
- \`--card-body-padding\`: Body content padding (default: 1.5rem)
|
|
474
|
+
|
|
475
|
+
#### Footer
|
|
476
|
+
- \`--card-footer-padding\`: Footer padding (default: 1rem 1.5rem)
|
|
477
|
+
- \`--card-footer-bg\`: Footer background color (default: #f8f9fa)
|
|
478
|
+
- \`--card-footer-border-top\`: Footer top border (default: 1px solid #dee2e6)
|
|
479
|
+
|
|
480
|
+
### Migration from Old Names
|
|
481
|
+
- ❌ \`--card-p\` → ✅ \`--card-padding\`
|
|
482
|
+
|
|
483
|
+
### Usage with Element Selectors
|
|
484
|
+
Element-specific variables work with:
|
|
485
|
+
- \`<header>\` or \`[data-card-header]\`
|
|
486
|
+
- \`[data-card-body]\`
|
|
487
|
+
- \`<footer>\` or \`[data-card-footer]\`
|
|
488
|
+
`,
|
|
489
|
+
},
|
|
490
|
+
},
|
|
491
|
+
},
|
|
492
|
+
} as Story;
|
|
@@ -3,14 +3,14 @@ details {
|
|
|
3
3
|
--details-direction: column;
|
|
4
4
|
--details-display: flex;
|
|
5
5
|
--details-gap: 0rem;
|
|
6
|
-
--details-
|
|
6
|
+
--details-height: max-content;
|
|
7
7
|
--details-justify: flex-start;
|
|
8
|
-
--details-
|
|
9
|
-
--details-
|
|
8
|
+
--details-padding-inline: 1.5rem;
|
|
9
|
+
--details-padding-block: 1rem;
|
|
10
10
|
--details-radius: 0;
|
|
11
|
-
--details-
|
|
12
|
-
--max-
|
|
13
|
-
--max-
|
|
11
|
+
--details-width: 100%;
|
|
12
|
+
--details-max-height-closed: 6.25rem;
|
|
13
|
+
--details-max-height-open: 50rem;
|
|
14
14
|
--summary-align: center;
|
|
15
15
|
--summary-cursor: pointer;
|
|
16
16
|
--summary-display: flex;
|
|
@@ -23,12 +23,12 @@ details {
|
|
|
23
23
|
flex-direction: var(--details-direction);
|
|
24
24
|
justify-content: var(--details-justify);
|
|
25
25
|
gap: var(--details-gap);
|
|
26
|
-
width: var(--details-
|
|
26
|
+
width: var(--details-width);
|
|
27
27
|
border: var(--details-border);
|
|
28
28
|
border-left: none;
|
|
29
29
|
border-right: none;
|
|
30
30
|
transition: var(--summary-transitions);
|
|
31
|
-
max-height: var(--max-
|
|
31
|
+
max-height: var(--details-max-height-closed);
|
|
32
32
|
overflow: clip;
|
|
33
33
|
|
|
34
34
|
@starting-style {
|
|
@@ -62,8 +62,8 @@ details {
|
|
|
62
62
|
display: var(--summary-display);
|
|
63
63
|
justify-content: var(--summary-justify);
|
|
64
64
|
align-items: var(--summary-align);
|
|
65
|
-
padding-inline: var(--summary-
|
|
66
|
-
padding-block: var(--summary-
|
|
65
|
+
padding-inline: var(--summary-padding-inline, var(--details-padding-inline));
|
|
66
|
+
padding-block: var(--summary-padding-block, var(--details-padding-block));
|
|
67
67
|
gap: var(--summary-gap);
|
|
68
68
|
list-style: none;
|
|
69
69
|
border-top-left-radius: var(--details-radius);
|
|
@@ -85,7 +85,7 @@ details {
|
|
|
85
85
|
cursor: var(--summary-cursor);
|
|
86
86
|
}
|
|
87
87
|
> section {
|
|
88
|
-
width: var(--details-
|
|
88
|
+
width: var(--details-width);
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
91
|
|
|
@@ -97,8 +97,8 @@ details {
|
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
> section {
|
|
100
|
-
padding-inline: var(--details-
|
|
101
|
-
padding-block: var(--details-
|
|
100
|
+
padding-inline: var(--details-padding-inline);
|
|
101
|
+
padding-block: var(--details-padding-block);
|
|
102
102
|
margin-block-start: 0;
|
|
103
103
|
border: 1px transparent solid;
|
|
104
104
|
}
|
|
@@ -110,7 +110,7 @@ details {
|
|
|
110
110
|
border-bottom: var(--details-border);
|
|
111
111
|
}
|
|
112
112
|
> section {
|
|
113
|
-
max-height: var(--max-
|
|
113
|
+
max-height: var(--details-max-height-open);
|
|
114
114
|
@starting-style {
|
|
115
115
|
max-height: 0;
|
|
116
116
|
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
details {
|
|
2
|
+
--details-border: 0.0625rem solid #dfdfdf;
|
|
3
|
+
--details-direction: column;
|
|
4
|
+
--details-display: flex;
|
|
5
|
+
--details-gap: 0rem;
|
|
6
|
+
--details-h: max-content;
|
|
7
|
+
--details-justify: flex-start;
|
|
8
|
+
--details-px: 1.5rem;
|
|
9
|
+
--details-py: 1rem;
|
|
10
|
+
--details-radius: 0;
|
|
11
|
+
--details-w: 100%;
|
|
12
|
+
--max-h-closed: 6.25rem;
|
|
13
|
+
--max-h-open: 50rem;
|
|
14
|
+
--summary-align: center;
|
|
15
|
+
--summary-cursor: pointer;
|
|
16
|
+
--summary-display: flex;
|
|
17
|
+
--summary-gap: 0.5rem;
|
|
18
|
+
--summary-justify: flex-start;
|
|
19
|
+
--summary-transitions: all 0.75s ease-in-out;
|
|
20
|
+
|
|
21
|
+
interpolate-size: allow-keywords;
|
|
22
|
+
display: var(--details-display);
|
|
23
|
+
flex-direction: var(--details-direction);
|
|
24
|
+
justify-content: var(--details-justify);
|
|
25
|
+
gap: var(--details-gap);
|
|
26
|
+
width: var(--details-w);
|
|
27
|
+
border: var(--details-border);
|
|
28
|
+
border-left: none;
|
|
29
|
+
border-right: none;
|
|
30
|
+
transition: var(--summary-transitions);
|
|
31
|
+
max-height: var(--max-h-closed);
|
|
32
|
+
overflow: clip;
|
|
33
|
+
|
|
34
|
+
@starting-style {
|
|
35
|
+
transition: var(--summary-transitions);
|
|
36
|
+
color: red;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
& + details {
|
|
40
|
+
border-radius: 0; // remove radius from middle elements
|
|
41
|
+
border-top: none; // optional: remove double borders
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
&:first-of-type {
|
|
45
|
+
border-radius: var(--details-radius) var(--details-radius) 0 0;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
&:last-of-type {
|
|
49
|
+
border-radius: 0 0 var(--details-radius) var(--details-radius);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// If it's the only details element, keep original radius
|
|
53
|
+
&:only-of-type {
|
|
54
|
+
border-radius: var(--details-radius);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
&::marker {
|
|
58
|
+
content: none;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
summary {
|
|
62
|
+
display: var(--summary-display);
|
|
63
|
+
justify-content: var(--summary-justify);
|
|
64
|
+
align-items: var(--summary-align);
|
|
65
|
+
padding-inline: var(--summary-px, var(--details-px));
|
|
66
|
+
padding-block: var(--summary-py, var(--details-py));
|
|
67
|
+
gap: var(--summary-gap);
|
|
68
|
+
list-style: none;
|
|
69
|
+
border-top-left-radius: var(--details-radius);
|
|
70
|
+
border-top-right-radius: var(--details-radius);
|
|
71
|
+
transition: var(--summary-transitions);
|
|
72
|
+
|
|
73
|
+
&::-webkit-details-marker {
|
|
74
|
+
display: none;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
&:focus-within {
|
|
78
|
+
outline: none;
|
|
79
|
+
border-bottom: solid 2px currentColor;
|
|
80
|
+
background-color: whitesmoke;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/* This ensures no bullet points are shown */
|
|
84
|
+
&:hover {
|
|
85
|
+
cursor: var(--summary-cursor);
|
|
86
|
+
}
|
|
87
|
+
> section {
|
|
88
|
+
width: var(--details-w);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.list-styles {
|
|
93
|
+
summary {
|
|
94
|
+
border-left: none;
|
|
95
|
+
border-right: none;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
> section {
|
|
100
|
+
padding-inline: var(--details-px);
|
|
101
|
+
padding-block: var(--details-py);
|
|
102
|
+
margin-block-start: 0;
|
|
103
|
+
border: 1px transparent solid;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
&[open] {
|
|
107
|
+
max-height: max-content;
|
|
108
|
+
transition: var(--summary-transitions);
|
|
109
|
+
> summary {
|
|
110
|
+
border-bottom: var(--details-border);
|
|
111
|
+
}
|
|
112
|
+
> section {
|
|
113
|
+
max-height: var(--max-h-open);
|
|
114
|
+
@starting-style {
|
|
115
|
+
max-height: 0;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
@supports (transition-behavior: allow-discrete) {
|
|
121
|
+
@starting-style {
|
|
122
|
+
max-height: 0;
|
|
123
|
+
transition: var(--summary-transitions);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
@@ -31,7 +31,47 @@ const icon = <Icons.Add />;
|
|
|
31
31
|
const meta: Meta<typeof Details> = {
|
|
32
32
|
title: "FP.REACT Components/Details",
|
|
33
33
|
component: Details,
|
|
34
|
-
tags: ["
|
|
34
|
+
tags: ["stable"],
|
|
35
|
+
parameters: {
|
|
36
|
+
docs: {
|
|
37
|
+
description: {
|
|
38
|
+
component: `Expandable/collapsible details component with smooth transitions and accessible markup.
|
|
39
|
+
|
|
40
|
+
## CSS Variables
|
|
41
|
+
|
|
42
|
+
### Layout & Display
|
|
43
|
+
- \`--details-display\`: Display mode (default: flex)
|
|
44
|
+
- \`--details-direction\`: Flex direction (default: column)
|
|
45
|
+
- \`--details-justify\`: Content justification (default: flex-start)
|
|
46
|
+
- \`--details-width\`: Details width (default: 100%)
|
|
47
|
+
- \`--details-height\`: Details height (default: max-content)
|
|
48
|
+
- \`--details-gap\`: Gap between elements (default: 0rem)
|
|
49
|
+
|
|
50
|
+
### Sizing & Constraints
|
|
51
|
+
- \`--details-max-height-closed\`: Max height when closed (default: 6.25rem)
|
|
52
|
+
- \`--details-max-height-open\`: Max height when open (default: 50rem)
|
|
53
|
+
|
|
54
|
+
### Spacing
|
|
55
|
+
- \`--details-padding-inline\`: Horizontal padding (default: 1.5rem)
|
|
56
|
+
- \`--details-padding-block\`: Vertical padding (default: 1rem)
|
|
57
|
+
|
|
58
|
+
### Borders & Radius
|
|
59
|
+
- \`--details-border\`: Border style (default: 0.0625rem solid #dfdfdf)
|
|
60
|
+
- \`--details-radius\`: Border radius (default: 0)
|
|
61
|
+
|
|
62
|
+
### Summary Element
|
|
63
|
+
- \`--summary-display\`: Summary display mode (default: flex)
|
|
64
|
+
- \`--summary-justify\`: Summary content justification (default: flex-start)
|
|
65
|
+
- \`--summary-align\`: Summary vertical alignment (default: center)
|
|
66
|
+
- \`--summary-gap\`: Gap within summary (default: 0.5rem)
|
|
67
|
+
- \`--summary-padding-inline\`: Summary horizontal padding (fallback: \`--details-padding-inline\`)
|
|
68
|
+
- \`--summary-padding-block\`: Summary vertical padding (fallback: \`--details-padding-block\`)
|
|
69
|
+
- \`--summary-cursor\`: Summary cursor style (default: pointer)
|
|
70
|
+
- \`--summary-transitions\`: Transition timing (default: all 0.75s ease-in-out)
|
|
71
|
+
`,
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
},
|
|
35
75
|
args: {
|
|
36
76
|
children: content,
|
|
37
77
|
icon: icon,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
:root {
|
|
2
|
-
--dialog-min-
|
|
2
|
+
--dialog-min-width: max(20rem, 80%);
|
|
3
3
|
--dialog-gap: 0.625rem;
|
|
4
4
|
--dialog-border-color: lightgray;
|
|
5
5
|
--dialog-border-width: thin;
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
dialog {
|
|
36
|
-
width: var(--dialog-min-
|
|
37
|
-
min-width: var(--min-
|
|
36
|
+
width: var(--dialog-min-width);
|
|
37
|
+
min-width: var(--dialog-min-width);
|
|
38
38
|
gap: var(--dialog-gap);
|
|
39
39
|
border: var(--dialog-border-color) var(--dialog-border-width) solid;
|
|
40
40
|
border-radius: var(--dialog-border-radius);
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
--dialog-min-w: max(20rem, 80%);
|
|
3
|
+
--dialog-gap: 0.625rem;
|
|
4
|
+
--dialog-border-color: lightgray;
|
|
5
|
+
--dialog-border-width: thin;
|
|
6
|
+
--dialog-border-style: solid;
|
|
7
|
+
--dialog-border-radius: var(--border-radius);
|
|
8
|
+
--dialog-padding: 1.5rem;
|
|
9
|
+
--dialog-padding-inline: 1rem;
|
|
10
|
+
--dialog-close-color: gray;
|
|
11
|
+
--dialog-button-bg: transparent;
|
|
12
|
+
--dialog-button-border: transparent thin solid;
|
|
13
|
+
--dialog-button-hover-bg: whitesmoke;
|
|
14
|
+
--dialog-display: flex;
|
|
15
|
+
--dialog-flex-direction: column;
|
|
16
|
+
|
|
17
|
+
/* Focus and accessibility */
|
|
18
|
+
--dialog-focus-color: #0066cc;
|
|
19
|
+
--dialog-focus-width: 0.125rem;
|
|
20
|
+
--dialog-focus-offset: 0.125rem;
|
|
21
|
+
--dialog-focus-outline: var(--dialog-focus-width) solid var(--dialog-focus-color);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/* High contrast mode support */
|
|
25
|
+
@media (prefers-contrast: high) {
|
|
26
|
+
:root {
|
|
27
|
+
--dialog-border-color: currentColor;
|
|
28
|
+
--dialog-border-width: 0.125rem;
|
|
29
|
+
--dialog-close-color: currentColor;
|
|
30
|
+
--dialog-button-border: currentColor 0.125rem solid;
|
|
31
|
+
--dialog-focus-width: 0.1875rem;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
dialog {
|
|
36
|
+
width: var(--dialog-min-w);
|
|
37
|
+
min-width: var(--min-w);
|
|
38
|
+
gap: var(--dialog-gap);
|
|
39
|
+
border: var(--dialog-border-color) var(--dialog-border-width) solid;
|
|
40
|
+
border-radius: var(--dialog-border-radius);
|
|
41
|
+
padding: var(--dialog-padding);
|
|
42
|
+
padding-block-start: var(--dialog-padding);
|
|
43
|
+
|
|
44
|
+
/* Focus visible for keyboard navigation */
|
|
45
|
+
&:focus-visible {
|
|
46
|
+
outline: var(--dialog-focus-outline);
|
|
47
|
+
outline-offset: var(--dialog-focus-offset);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
&[open] {
|
|
51
|
+
display: var(--dialog-display);
|
|
52
|
+
flex-direction: var(--dialog-flex-direction);
|
|
53
|
+
gap: var(--dialog-gap);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
section {
|
|
57
|
+
width: 100%;
|
|
58
|
+
display: flex;
|
|
59
|
+
justify-content: start;
|
|
60
|
+
gap: var(--dialog-gap);
|
|
61
|
+
flex-direction: var(--dialog-flex-direction);
|
|
62
|
+
margin-block-start: 0;
|
|
63
|
+
--sect-y: 0;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.dialog-header {
|
|
68
|
+
display: flex;
|
|
69
|
+
justify-content: space-between;
|
|
70
|
+
align-items: center;
|
|
71
|
+
width: 100%;
|
|
72
|
+
min-width: 100%;
|
|
73
|
+
|
|
74
|
+
h3 {
|
|
75
|
+
margin-block-start: 0;
|
|
76
|
+
margin-block-end: 0;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.dialog-close {
|
|
80
|
+
margin-block-end: 0;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
button[type="button"] {
|
|
84
|
+
background-color: var(--dialog-button-bg);
|
|
85
|
+
border: var(--dialog-button-border);
|
|
86
|
+
cursor: pointer;
|
|
87
|
+
|
|
88
|
+
&:hover {
|
|
89
|
+
border-color: var(--dialog-close-color);
|
|
90
|
+
background-color: var(--dialog-button-hover-bg);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/* Keyboard focus indicator */
|
|
94
|
+
&:focus-visible {
|
|
95
|
+
outline: var(--dialog-focus-outline);
|
|
96
|
+
outline-offset: var(--dialog-focus-offset);
|
|
97
|
+
border-color: var(--dialog-focus-color);
|
|
98
|
+
background-color: var(--dialog-button-hover-bg);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/* Remove default focus for mouse users */
|
|
102
|
+
&:focus:not(:focus-visible) {
|
|
103
|
+
outline: none;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.alert-dialog-actions,
|
|
109
|
+
.dialog-footer {
|
|
110
|
+
display: flex;
|
|
111
|
+
flex-direction: row;
|
|
112
|
+
flex-wrap: wrap;
|
|
113
|
+
justify-content: var(--dialog-footer-justify, flex-end);
|
|
114
|
+
gap: var(--dialog-gap);
|
|
115
|
+
width: 100%;
|
|
116
|
+
|
|
117
|
+
/* Focus styles for footer buttons */
|
|
118
|
+
button:focus-visible {
|
|
119
|
+
outline: var(--dialog-focus-outline);
|
|
120
|
+
outline-offset: var(--dialog-focus-offset);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
button:focus:not(:focus-visible) {
|
|
124
|
+
outline: none;
|
|
125
|
+
}
|
|
126
|
+
}
|