@fpkit/acss 3.1.1 → 3.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.
- package/libs/{chunk-2NRIP6RB.cjs → chunk-2C3YLBWP.cjs} +3 -3
- package/libs/{chunk-NWJDAHP6.cjs → chunk-2GJHKWEK.cjs} +3 -3
- package/libs/{chunk-FVROL3V5.js → chunk-2JCDEC32.js} +3 -3
- package/libs/{chunk-IRLFZ3OL.js → chunk-3XJC4XUG.js} +2 -2
- package/libs/{chunk-L6PRDL6F.cjs → chunk-5CJPTDK3.cjs} +3 -3
- package/libs/{chunk-E4OSROCA.cjs → chunk-5QSNJQVH.cjs} +3 -3
- package/libs/{chunk-O3JIHC5M.cjs → chunk-6BUJZ4DJ.cjs} +3 -3
- package/libs/{chunk-WXBFBWYF.cjs → chunk-AFINOD2L.cjs} +3 -3
- package/libs/{chunk-HRRHPLER.js → chunk-AWZLSWDO.js} +2 -2
- package/libs/chunk-DDSXKOUB.js +7 -0
- package/libs/chunk-DDSXKOUB.js.map +1 -0
- package/libs/{chunk-CWRNJA4P.js → chunk-DIJBIOFE.js} +3 -3
- package/libs/chunk-EJ6KYBFE.cjs +13 -0
- package/libs/chunk-EJ6KYBFE.cjs.map +1 -0
- package/libs/{chunk-GUJSMQ3V.cjs → chunk-EKJYOCLY.cjs} +3 -3
- package/libs/{chunk-X5RKCLDC.cjs → chunk-F64GE6RG.cjs} +4 -4
- package/libs/{chunk-5RAWNUVD.js → chunk-IBUTNPTQ.js} +2 -2
- package/libs/chunk-IWP4VJEP.cjs +18 -0
- package/libs/chunk-IWP4VJEP.cjs.map +1 -0
- package/libs/{chunk-ZFJ4U45S.js → chunk-KDMX3FAW.js} +2 -2
- package/libs/{chunk-DYFAUAB7.cjs → chunk-LXODKKA3.cjs} +4 -4
- package/libs/{chunk-MPTMPBFT.js → chunk-M7JLT62Q.js} +2 -2
- package/libs/{chunk-IQ76HGVP.js → chunk-MBWI67UT.js} +2 -2
- package/libs/{chunk-O5XAJ7BY.cjs → chunk-NCGVF2QS.cjs} +4 -4
- package/libs/{chunk-W2UIN7EV.cjs → chunk-NPWHQVYB.cjs} +3 -3
- package/libs/{chunk-43TK2ICH.js → chunk-PMWL5XZ4.js} +3 -3
- package/libs/{chunk-KVKQLRJG.js → chunk-TF3GQKOY.js} +2 -2
- package/libs/{chunk-IEB64SWY.js → chunk-U5VA34SU.js} +2 -2
- package/libs/chunk-UGMP72J2.js +8 -0
- package/libs/chunk-UGMP72J2.js.map +1 -0
- package/libs/{chunk-EE3ZWSBY.cjs → chunk-URBGDUFN.cjs} +6 -6
- package/libs/{chunk-TPIB3RQP.js → chunk-ZF6Y7W57.js} +5 -5
- package/libs/component-props-50e69975.d.ts +66 -0
- package/libs/components/box/box.css +1 -0
- package/libs/components/box/box.css.map +1 -0
- package/libs/components/box/box.min.css +3 -0
- package/libs/components/breadcrumbs/breadcrumb.cjs +6 -6
- package/libs/components/breadcrumbs/breadcrumb.js +3 -3
- package/libs/components/button.cjs +4 -4
- package/libs/components/button.d.cts +10 -3
- package/libs/components/button.d.ts +10 -3
- package/libs/components/button.js +2 -2
- package/libs/components/card.cjs +7 -7
- package/libs/components/card.d.cts +13 -85
- package/libs/components/card.d.ts +13 -85
- package/libs/components/card.js +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/cluster/cluster.css +1 -0
- package/libs/components/cluster/cluster.css.map +1 -0
- package/libs/components/cluster/cluster.min.css +3 -0
- package/libs/components/dialog/dialog.cjs +7 -7
- package/libs/components/dialog/dialog.js +5 -5
- package/libs/components/form/fields.cjs +4 -4
- package/libs/components/form/fields.js +2 -2
- package/libs/components/form/textarea.cjs +4 -4
- package/libs/components/form/textarea.js +2 -2
- package/libs/components/grid/grid.css +1 -0
- package/libs/components/grid/grid.css.map +1 -0
- package/libs/components/grid/grid.min.css +3 -0
- package/libs/components/heading/heading.cjs +3 -3
- package/libs/components/heading/heading.js +2 -2
- package/libs/components/icons/icon.cjs +4 -4
- package/libs/components/icons/icon.d.cts +2 -2
- package/libs/components/icons/icon.d.ts +2 -2
- package/libs/components/icons/icon.js +2 -2
- package/libs/components/link/link.cjs +6 -6
- package/libs/components/link/link.js +2 -2
- package/libs/components/list/list.cjs +5 -5
- package/libs/components/list/list.js +2 -2
- package/libs/components/modal.cjs +4 -4
- package/libs/components/modal.d.cts +1 -1
- package/libs/components/modal.d.ts +1 -1
- package/libs/components/modal.js +3 -3
- package/libs/components/nav/nav.cjs +7 -7
- package/libs/components/nav/nav.js +3 -3
- package/libs/components/stack/stack.css +1 -0
- package/libs/components/stack/stack.css.map +1 -0
- package/libs/components/stack/stack.min.css +3 -0
- package/libs/components/tables/table.d.cts +1 -1
- package/libs/components/tables/table.d.ts +1 -1
- package/libs/components/text/text.cjs +5 -5
- package/libs/components/text/text.js +2 -2
- package/libs/hooks.cjs +4 -4
- package/libs/hooks.js +3 -3
- package/libs/{icons-287fce3a.d.ts → icons-df8e744f.d.ts} +1 -1
- package/libs/icons.cjs +3 -3
- package/libs/icons.d.cts +2 -2
- package/libs/icons.d.ts +2 -2
- package/libs/icons.js +2 -2
- package/libs/index.cjs +64 -63
- package/libs/index.cjs.map +1 -1
- package/libs/index.css +1 -1
- package/libs/index.css.map +1 -1
- package/libs/index.d.cts +923 -4
- package/libs/index.d.ts +923 -4
- package/libs/index.js +28 -28
- package/libs/index.js.map +1 -1
- package/package.json +2 -2
- package/src/components/alert/STYLES.mdx +790 -0
- package/src/components/badge/STYLES.mdx +610 -0
- package/src/components/box/README.mdx +401 -0
- package/src/components/box/STYLES.mdx +360 -0
- package/src/components/box/box.scss +245 -0
- package/src/components/box/box.stories.tsx +395 -0
- package/src/components/box/box.test.tsx +425 -0
- package/src/components/box/box.tsx +170 -0
- package/src/components/box/box.types.ts +166 -0
- package/src/components/breadcrumbs/STYLES.mdx +99 -0
- package/src/components/buttons/STYLES.mdx +766 -0
- package/src/components/cards/STYLES.mdx +835 -0
- package/src/components/cards/card.scss +29 -21
- package/src/components/cards/card.tsx +13 -3
- package/src/components/cards/card.types.ts +13 -0
- package/src/components/cluster/README.mdx +595 -0
- package/src/components/cluster/STYLES.mdx +626 -0
- package/src/components/cluster/cluster.scss +86 -0
- package/src/components/cluster/cluster.stories.tsx +385 -0
- package/src/components/cluster/cluster.test.tsx +655 -0
- package/src/components/cluster/cluster.tsx +94 -0
- package/src/components/cluster/cluster.types.ts +75 -0
- package/src/components/details/STYLES.mdx +445 -0
- package/src/components/dialog/STYLES.mdx +888 -0
- package/src/components/flexbox/STYLES.mdx +1 -1
- package/src/components/form/STYLES.mdx +821 -0
- package/src/components/grid/README.mdx +709 -0
- package/src/components/grid/STYLES.mdx +785 -0
- package/src/components/grid/grid.scss +287 -0
- package/src/components/grid/grid.stories.tsx +486 -0
- package/src/components/grid/grid.test.tsx +981 -0
- package/src/components/grid/grid.tsx +222 -0
- package/src/components/grid/grid.types.ts +344 -0
- package/src/components/icons/STYLES.mdx +56 -0
- package/src/components/images/STYLES.mdx +75 -0
- package/src/components/layout/STYLES.mdx +556 -0
- package/src/components/link/STYLES.mdx +75 -0
- package/src/components/list/STYLES.mdx +631 -0
- package/src/components/nav/STYLES.mdx +460 -0
- package/src/components/progress/STYLES.mdx +64 -0
- package/src/components/stack/README.mdx +400 -0
- package/src/components/stack/STYLES.mdx +414 -0
- package/src/components/stack/stack.scss +109 -0
- package/src/components/stack/stack.stories.tsx +559 -0
- package/src/components/stack/stack.test.tsx +426 -0
- package/src/components/stack/stack.tsx +141 -0
- package/src/components/stack/stack.types.ts +133 -0
- package/src/components/tag/STYLES.mdx +105 -0
- package/src/components/text-to-speech/STYLES.mdx +80 -0
- package/src/components/ui.tsx +3 -3
- package/src/index.scss +5 -1
- package/src/index.ts +305 -12
- package/src/sass/GLOBALS-STYLES.md +631 -0
- package/src/sass/_globals.scss +45 -24
- package/src/styles/box/box.css +220 -0
- package/src/styles/box/box.css.map +1 -0
- package/src/styles/cards/card.css +22 -17
- package/src/styles/cards/card.css.map +1 -1
- package/src/styles/cluster/cluster.css +71 -0
- package/src/styles/cluster/cluster.css.map +1 -0
- package/src/styles/grid/grid.css +238 -0
- package/src/styles/grid/grid.css.map +1 -0
- package/src/styles/index.css +667 -49
- package/src/styles/index.css.map +1 -1
- package/src/styles/stack/stack.css +86 -0
- package/src/styles/stack/stack.css.map +1 -0
- package/src/types/component-props.ts +42 -14
- package/src/types/layout-primitives.ts +48 -0
- package/src/types/shared.ts +10 -26
- package/libs/chunk-ENTCUJ3A.cjs +0 -13
- package/libs/chunk-ENTCUJ3A.cjs.map +0 -1
- package/libs/chunk-HHLNOC5T.js +0 -7
- package/libs/chunk-HHLNOC5T.js.map +0 -1
- package/libs/chunk-KK47SYZI.js +0 -8
- package/libs/chunk-KK47SYZI.js.map +0 -1
- package/libs/chunk-W5TKWBFC.cjs +0 -18
- package/libs/chunk-W5TKWBFC.cjs.map +0 -1
- package/libs/component-props-67d978a2.d.ts +0 -38
- /package/libs/{chunk-2NRIP6RB.cjs.map → chunk-2C3YLBWP.cjs.map} +0 -0
- /package/libs/{chunk-NWJDAHP6.cjs.map → chunk-2GJHKWEK.cjs.map} +0 -0
- /package/libs/{chunk-FVROL3V5.js.map → chunk-2JCDEC32.js.map} +0 -0
- /package/libs/{chunk-IRLFZ3OL.js.map → chunk-3XJC4XUG.js.map} +0 -0
- /package/libs/{chunk-L6PRDL6F.cjs.map → chunk-5CJPTDK3.cjs.map} +0 -0
- /package/libs/{chunk-E4OSROCA.cjs.map → chunk-5QSNJQVH.cjs.map} +0 -0
- /package/libs/{chunk-O3JIHC5M.cjs.map → chunk-6BUJZ4DJ.cjs.map} +0 -0
- /package/libs/{chunk-WXBFBWYF.cjs.map → chunk-AFINOD2L.cjs.map} +0 -0
- /package/libs/{chunk-HRRHPLER.js.map → chunk-AWZLSWDO.js.map} +0 -0
- /package/libs/{chunk-CWRNJA4P.js.map → chunk-DIJBIOFE.js.map} +0 -0
- /package/libs/{chunk-GUJSMQ3V.cjs.map → chunk-EKJYOCLY.cjs.map} +0 -0
- /package/libs/{chunk-X5RKCLDC.cjs.map → chunk-F64GE6RG.cjs.map} +0 -0
- /package/libs/{chunk-5RAWNUVD.js.map → chunk-IBUTNPTQ.js.map} +0 -0
- /package/libs/{chunk-ZFJ4U45S.js.map → chunk-KDMX3FAW.js.map} +0 -0
- /package/libs/{chunk-DYFAUAB7.cjs.map → chunk-LXODKKA3.cjs.map} +0 -0
- /package/libs/{chunk-MPTMPBFT.js.map → chunk-M7JLT62Q.js.map} +0 -0
- /package/libs/{chunk-IQ76HGVP.js.map → chunk-MBWI67UT.js.map} +0 -0
- /package/libs/{chunk-O5XAJ7BY.cjs.map → chunk-NCGVF2QS.cjs.map} +0 -0
- /package/libs/{chunk-W2UIN7EV.cjs.map → chunk-NPWHQVYB.cjs.map} +0 -0
- /package/libs/{chunk-43TK2ICH.js.map → chunk-PMWL5XZ4.js.map} +0 -0
- /package/libs/{chunk-KVKQLRJG.js.map → chunk-TF3GQKOY.js.map} +0 -0
- /package/libs/{chunk-IEB64SWY.js.map → chunk-U5VA34SU.js.map} +0 -0
- /package/libs/{chunk-EE3ZWSBY.cjs.map → chunk-URBGDUFN.cjs.map} +0 -0
- /package/libs/{chunk-TPIB3RQP.js.map → chunk-ZF6Y7W57.js.map} +0 -0
|
@@ -0,0 +1,835 @@
|
|
|
1
|
+
import { Meta } from "@storybook/addon-docs/blocks";
|
|
2
|
+
|
|
3
|
+
<Meta title="FP.REACT Components/Cards/Styles" />
|
|
4
|
+
|
|
5
|
+
# Card Styles
|
|
6
|
+
|
|
7
|
+
Flexible card component styling system with CSS custom properties for building
|
|
8
|
+
content containers with headers, bodies, and footers.
|
|
9
|
+
|
|
10
|
+
## Overview
|
|
11
|
+
|
|
12
|
+
The fpkit card styling system provides a versatile foundation for creating card
|
|
13
|
+
layouts with semantic structure. Cards support headers, bodies, footers, images,
|
|
14
|
+
and interactive states, all customizable through CSS custom properties.
|
|
15
|
+
|
|
16
|
+
### Key Features
|
|
17
|
+
|
|
18
|
+
- **Flexible layout** - Flexbox-based column layout with customizable gap
|
|
19
|
+
- **Semantic structure** - Support for header, body, and footer elements
|
|
20
|
+
- **Element-specific styling** - Dedicated variables for each card section
|
|
21
|
+
- **Interactive variant** - Hover and focus states for clickable cards
|
|
22
|
+
- **Image support** - Smart padding handling for card images
|
|
23
|
+
- **CSS custom properties** - Extensive theming via CSS variables
|
|
24
|
+
- **Rem-based sizing** - All measurements use rem units (1rem = 16px)
|
|
25
|
+
- **WCAG compliant** - Accessible focus indicators with proper contrast
|
|
26
|
+
|
|
27
|
+
## CSS Custom Properties
|
|
28
|
+
|
|
29
|
+
### Base Card Properties
|
|
30
|
+
|
|
31
|
+
Root-level variables define the card's overall appearance:
|
|
32
|
+
|
|
33
|
+
```css
|
|
34
|
+
:root {
|
|
35
|
+
/* Semantic Color Tokens (Global) */
|
|
36
|
+
--color-surface: #ffffff;
|
|
37
|
+
--color-surface-secondary: #f8f9fa;
|
|
38
|
+
--color-border: #dee2e6;
|
|
39
|
+
--color-focus: #0066cc;
|
|
40
|
+
|
|
41
|
+
/* Layout */
|
|
42
|
+
--card-gap: 1rem; /* 16px */
|
|
43
|
+
|
|
44
|
+
/* Colors */
|
|
45
|
+
--card-bg: var(--color-surface, #ffffff);
|
|
46
|
+
|
|
47
|
+
/* Spacing */
|
|
48
|
+
--card-padding: 1.5rem; /* 24px */
|
|
49
|
+
|
|
50
|
+
/* Borders */
|
|
51
|
+
--card-radius: calc(var(--card-padding) / 4); /* 0.375rem */
|
|
52
|
+
|
|
53
|
+
/* Alignment */
|
|
54
|
+
--card-align: left; /* Text alignment */
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Header Properties
|
|
59
|
+
|
|
60
|
+
Variables specific to card headers (now with atomic border properties):
|
|
61
|
+
|
|
62
|
+
```css
|
|
63
|
+
:root {
|
|
64
|
+
--card-header-padding: 1rem 1.5rem; /* 16px 24px */
|
|
65
|
+
--card-header-bg: var(--color-surface-secondary, #f8f9fa);
|
|
66
|
+
|
|
67
|
+
/* Border properties (atomic for flexibility) */
|
|
68
|
+
--card-header-border-bottom-width: 0.0625rem; /* 1px */
|
|
69
|
+
--card-header-border-bottom-style: solid;
|
|
70
|
+
--card-header-border-bottom-color: var(--color-border, #dee2e6);
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Body Properties
|
|
75
|
+
|
|
76
|
+
Variables for card body content:
|
|
77
|
+
|
|
78
|
+
```css
|
|
79
|
+
:root {
|
|
80
|
+
--card-body-padding: 1.5rem; /* 24px */
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Footer Properties
|
|
85
|
+
|
|
86
|
+
Variables for card footers (atomic border properties):
|
|
87
|
+
|
|
88
|
+
```css
|
|
89
|
+
:root {
|
|
90
|
+
--card-footer-padding: 1rem 1.5rem; /* 16px 24px */
|
|
91
|
+
--card-footer-bg: var(--color-surface-secondary, #f8f9fa);
|
|
92
|
+
|
|
93
|
+
/* Border properties (atomic for flexibility) */
|
|
94
|
+
--card-footer-border-top-width: 0.0625rem; /* 1px */
|
|
95
|
+
--card-footer-border-top-style: solid;
|
|
96
|
+
--card-footer-border-top-color: var(--color-border, #dee2e6);
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Interactive Card Properties
|
|
101
|
+
|
|
102
|
+
For clickable/interactive cards (fully customizable):
|
|
103
|
+
|
|
104
|
+
```css
|
|
105
|
+
[data-card="interactive"] {
|
|
106
|
+
/* Transition timing (NEW - now customizable) */
|
|
107
|
+
--card-transition-duration: 0.2s;
|
|
108
|
+
--card-transition-timing: ease;
|
|
109
|
+
|
|
110
|
+
/* Hover effects (NEW - now customizable) */
|
|
111
|
+
--card-hover-lift: -0.125rem; /* -2px lift on hover */
|
|
112
|
+
--card-hover-shadow: 0 0.25rem 0.75rem rgba(0, 0, 0, 0.15);
|
|
113
|
+
|
|
114
|
+
/* Focus indicator */
|
|
115
|
+
--color-focus: var(--color-focus, #0066cc); /* Uses global focus color */
|
|
116
|
+
|
|
117
|
+
cursor: pointer;
|
|
118
|
+
transition:
|
|
119
|
+
box-shadow var(--card-transition-duration) var(--card-transition-timing),
|
|
120
|
+
transform var(--card-transition-duration) var(--card-transition-timing);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/* Customize animations per card */
|
|
124
|
+
[data-card="interactive"].slow {
|
|
125
|
+
--card-transition-duration: 0.6s;
|
|
126
|
+
--card-transition-timing: cubic-bezier(0.4, 0, 0.2, 1);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
[data-card="interactive"].dramatic {
|
|
130
|
+
--card-hover-lift: -0.5rem;
|
|
131
|
+
--card-hover-shadow: 0 1rem 2rem rgba(0, 0, 0, 0.3);
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Customizing Card Styles
|
|
136
|
+
|
|
137
|
+
Override CSS variables for specific cards:
|
|
138
|
+
|
|
139
|
+
```css
|
|
140
|
+
.custom-card {
|
|
141
|
+
--card-bg: #f0f0f0;
|
|
142
|
+
--card-padding: 1.5rem;
|
|
143
|
+
--card-radius: 1rem;
|
|
144
|
+
--card-gap: 0.75rem;
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Or inline:
|
|
149
|
+
|
|
150
|
+
```html
|
|
151
|
+
<div data-card style="--card-bg: #f9f9f9; --card-padding: 1.5rem">
|
|
152
|
+
<!-- Card content -->
|
|
153
|
+
</div>
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Base Card Structure
|
|
157
|
+
|
|
158
|
+
### Simple Card
|
|
159
|
+
|
|
160
|
+
Basic card with content:
|
|
161
|
+
|
|
162
|
+
```html
|
|
163
|
+
<div data-card>
|
|
164
|
+
<h2>Card Title</h2>
|
|
165
|
+
<p>Card content goes here.</p>
|
|
166
|
+
</div>
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Alternative selector:
|
|
170
|
+
|
|
171
|
+
```html
|
|
172
|
+
<div data-component="card">
|
|
173
|
+
<h2>Card Title</h2>
|
|
174
|
+
<p>Card content goes here.</p>
|
|
175
|
+
</div>
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
**CSS Applied:**
|
|
179
|
+
|
|
180
|
+
```css
|
|
181
|
+
[data-card] {
|
|
182
|
+
display: flex;
|
|
183
|
+
flex-direction: column;
|
|
184
|
+
gap: 1rem;
|
|
185
|
+
border-radius: 0.5rem;
|
|
186
|
+
background-color: #fff;
|
|
187
|
+
text-align: left;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/* Smart padding: applied to all children except images */
|
|
191
|
+
[data-card] > *:not(img) {
|
|
192
|
+
padding-inline: 2rem;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/* First child padding */
|
|
196
|
+
[data-card] > *:first-child:not(img) {
|
|
197
|
+
padding-block-start: 1.5rem; /* card-padding - 0.5rem */
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/* Last child padding */
|
|
201
|
+
[data-card] > *:last-child:not(img) {
|
|
202
|
+
padding-block-end: 2rem;
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Card with Image
|
|
207
|
+
|
|
208
|
+
Cards intelligently handle images without applying padding:
|
|
209
|
+
|
|
210
|
+
```html
|
|
211
|
+
<div data-card>
|
|
212
|
+
<img src="image.jpg" alt="Card image" />
|
|
213
|
+
<h2>Card Title</h2>
|
|
214
|
+
<p>Content below image.</p>
|
|
215
|
+
</div>
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
**Note:** Images receive no horizontal or vertical padding, allowing them to
|
|
219
|
+
extend to card edges while other content remains padded.
|
|
220
|
+
|
|
221
|
+
## Structured Cards
|
|
222
|
+
|
|
223
|
+
### Card with Header, Body, and Footer
|
|
224
|
+
|
|
225
|
+
Use semantic HTML or data attributes:
|
|
226
|
+
|
|
227
|
+
```html
|
|
228
|
+
<!-- Using semantic HTML -->
|
|
229
|
+
<div data-card>
|
|
230
|
+
<header>
|
|
231
|
+
<h2>Card Title</h2>
|
|
232
|
+
</header>
|
|
233
|
+
<div data-card-body>
|
|
234
|
+
<p>Main content goes here.</p>
|
|
235
|
+
</div>
|
|
236
|
+
<footer>
|
|
237
|
+
<button>Action</button>
|
|
238
|
+
</footer>
|
|
239
|
+
</div>
|
|
240
|
+
|
|
241
|
+
<!-- Using data attributes -->
|
|
242
|
+
<div data-card>
|
|
243
|
+
<div data-card-header>
|
|
244
|
+
<h2>Card Title</h2>
|
|
245
|
+
</div>
|
|
246
|
+
<div data-card-body>
|
|
247
|
+
<p>Main content goes here.</p>
|
|
248
|
+
</div>
|
|
249
|
+
<div data-card-footer>
|
|
250
|
+
<button>Action</button>
|
|
251
|
+
</div>
|
|
252
|
+
</div>
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
**CSS Applied:**
|
|
256
|
+
|
|
257
|
+
```css
|
|
258
|
+
/* Header styling */
|
|
259
|
+
[data-card] > header,
|
|
260
|
+
[data-card] > [data-card-header] {
|
|
261
|
+
padding: 1rem 1.5rem;
|
|
262
|
+
background-color: #f8f9fa;
|
|
263
|
+
border-bottom: 1px solid #dee2e6;
|
|
264
|
+
border-radius: 0.5rem 0.5rem 0 0; /* Rounded top corners only */
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/* Body styling */
|
|
268
|
+
[data-card] > [data-card-body] {
|
|
269
|
+
padding: 1.5rem;
|
|
270
|
+
flex: 1; /* Grows to fill available space */
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/* Footer styling */
|
|
274
|
+
[data-card] > footer,
|
|
275
|
+
[data-card] > [data-card-footer] {
|
|
276
|
+
padding: 1rem 1.5rem;
|
|
277
|
+
background-color: #f8f9fa;
|
|
278
|
+
border-top: 1px solid #dee2e6;
|
|
279
|
+
border-radius: 0 0 0.5rem 0.5rem; /* Rounded bottom corners only */
|
|
280
|
+
}
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
## Card Variants
|
|
284
|
+
|
|
285
|
+
### Interactive Card
|
|
286
|
+
|
|
287
|
+
Clickable card with hover and focus states:
|
|
288
|
+
|
|
289
|
+
```html
|
|
290
|
+
<div data-card="interactive" tabindex="0" role="button">
|
|
291
|
+
<h2>Clickable Card</h2>
|
|
292
|
+
<p>This card responds to hover and keyboard focus.</p>
|
|
293
|
+
</div>
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
**CSS Applied:**
|
|
297
|
+
|
|
298
|
+
```css
|
|
299
|
+
[data-card="interactive"] {
|
|
300
|
+
cursor: pointer;
|
|
301
|
+
transition:
|
|
302
|
+
box-shadow 0.2s ease,
|
|
303
|
+
transform 0.2s ease;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/* Hover state */
|
|
307
|
+
[data-card="interactive"]:hover {
|
|
308
|
+
transform: translateY(-2px); /* Lifts up slightly */
|
|
309
|
+
box-shadow: 0 0.25rem 0.75rem rgba(0, 0, 0, 0.15); /* Elevated shadow */
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/* Focus indicator (WCAG 2.4.7 compliant) */
|
|
313
|
+
[data-card="interactive"]:focus-visible {
|
|
314
|
+
outline: 0.125rem solid #0066cc; /* 2px solid outline */
|
|
315
|
+
outline-offset: 0.125rem; /* 2px offset */
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/* Remove outline for mouse users */
|
|
319
|
+
[data-card="interactive"]:focus:not(:focus-visible) {
|
|
320
|
+
outline: none;
|
|
321
|
+
}
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
**Accessibility Notes:**
|
|
325
|
+
|
|
326
|
+
- Add `tabindex="0"` to make card keyboard-focusable
|
|
327
|
+
- Add `role="button"` or `role="link"` for screen readers
|
|
328
|
+
- Use `aria-label` for cards without descriptive text
|
|
329
|
+
- Handle click and keyboard events (Enter/Space)
|
|
330
|
+
|
|
331
|
+
### Centered Card
|
|
332
|
+
|
|
333
|
+
Center-aligned card content:
|
|
334
|
+
|
|
335
|
+
```html
|
|
336
|
+
<div data-card style="--card-align: center">
|
|
337
|
+
<h2>Centered Content</h2>
|
|
338
|
+
<p>All text is centered.</p>
|
|
339
|
+
</div>
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
### Card with Custom Gap
|
|
343
|
+
|
|
344
|
+
Adjust spacing between card children:
|
|
345
|
+
|
|
346
|
+
```html
|
|
347
|
+
<div data-card style="--card-gap: 1.5rem">
|
|
348
|
+
<h2>Title</h2>
|
|
349
|
+
<p>Content with larger gap between elements.</p>
|
|
350
|
+
</div>
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
## Real-World Examples
|
|
354
|
+
|
|
355
|
+
### Product Card
|
|
356
|
+
|
|
357
|
+
```html
|
|
358
|
+
<div data-card>
|
|
359
|
+
<img src="product.jpg" alt="Product name" />
|
|
360
|
+
<div data-card-body>
|
|
361
|
+
<h3>Product Name</h3>
|
|
362
|
+
<p>$99.99</p>
|
|
363
|
+
<p>Product description goes here.</p>
|
|
364
|
+
</div>
|
|
365
|
+
<div data-card-footer>
|
|
366
|
+
<button type="button">Add to Cart</button>
|
|
367
|
+
</div>
|
|
368
|
+
</div>
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
### Profile Card
|
|
372
|
+
|
|
373
|
+
```html
|
|
374
|
+
<div data-card style="--card-align: center">
|
|
375
|
+
<img
|
|
376
|
+
src="avatar.jpg"
|
|
377
|
+
alt="User name"
|
|
378
|
+
style="border-radius: 50%; width: 5rem"
|
|
379
|
+
/>
|
|
380
|
+
<h2>John Doe</h2>
|
|
381
|
+
<p>Software Engineer</p>
|
|
382
|
+
<div data-card-footer>
|
|
383
|
+
<button data-btn="text">View Profile</button>
|
|
384
|
+
</div>
|
|
385
|
+
</div>
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
### Article Card
|
|
389
|
+
|
|
390
|
+
```html
|
|
391
|
+
<div data-card="interactive" tabindex="0" role="article">
|
|
392
|
+
<header>
|
|
393
|
+
<small>Technology • 5 min read</small>
|
|
394
|
+
<h2>Article Title</h2>
|
|
395
|
+
</header>
|
|
396
|
+
<div data-card-body>
|
|
397
|
+
<p>
|
|
398
|
+
Article excerpt or summary text goes here. This provides a preview of the
|
|
399
|
+
full article content.
|
|
400
|
+
</p>
|
|
401
|
+
</div>
|
|
402
|
+
<footer>
|
|
403
|
+
<small>Published on Jan 1, 2025</small>
|
|
404
|
+
</footer>
|
|
405
|
+
</div>
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
### Stats Card
|
|
409
|
+
|
|
410
|
+
```html
|
|
411
|
+
<div
|
|
412
|
+
data-card
|
|
413
|
+
style="--card-bg: linear-gradient(135deg, #667eea 0%, #764ba2 100%); --card-align: center"
|
|
414
|
+
>
|
|
415
|
+
<h3 style="color: white; font-size: 3rem; margin: 0">1,234</h3>
|
|
416
|
+
<p style="color: rgba(255, 255, 255, 0.9)">Total Users</p>
|
|
417
|
+
</div>
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
### Notification Card
|
|
421
|
+
|
|
422
|
+
```html
|
|
423
|
+
<div
|
|
424
|
+
data-card
|
|
425
|
+
style="--card-bg: #fff3cd; --card-header-bg: #ffc107; --card-padding: 1rem"
|
|
426
|
+
>
|
|
427
|
+
<header>
|
|
428
|
+
<strong>⚠️ Warning</strong>
|
|
429
|
+
</header>
|
|
430
|
+
<div data-card-body>
|
|
431
|
+
<p>Your subscription will expire in 3 days.</p>
|
|
432
|
+
</div>
|
|
433
|
+
<footer>
|
|
434
|
+
<button type="button">Renew Now</button>
|
|
435
|
+
</footer>
|
|
436
|
+
</div>
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
### Image Gallery Card
|
|
440
|
+
|
|
441
|
+
```html
|
|
442
|
+
<div data-card style="--card-gap: 0">
|
|
443
|
+
<img src="gallery-1.jpg" alt="Gallery image 1" />
|
|
444
|
+
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 0">
|
|
445
|
+
<img src="gallery-2.jpg" alt="Gallery image 2" />
|
|
446
|
+
<img src="gallery-3.jpg" alt="Gallery image 3" />
|
|
447
|
+
</div>
|
|
448
|
+
<div data-card-body>
|
|
449
|
+
<h3>Photo Gallery</h3>
|
|
450
|
+
<p>3 images</p>
|
|
451
|
+
</div>
|
|
452
|
+
</div>
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
### Card with Article Element
|
|
456
|
+
|
|
457
|
+
Cards can contain article elements with automatic flex styling:
|
|
458
|
+
|
|
459
|
+
```html
|
|
460
|
+
<div data-card>
|
|
461
|
+
<article>
|
|
462
|
+
<h2>Article Heading</h2>
|
|
463
|
+
<p>Article content that automatically flexes to fill space.</p>
|
|
464
|
+
</article>
|
|
465
|
+
</div>
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
**CSS Applied:**
|
|
469
|
+
|
|
470
|
+
```css
|
|
471
|
+
[data-card] > article {
|
|
472
|
+
display: flex;
|
|
473
|
+
flex-direction: column;
|
|
474
|
+
flex: 2; /* Takes twice the space of other flex children */
|
|
475
|
+
}
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
## Layout Patterns
|
|
479
|
+
|
|
480
|
+
### Card Grid
|
|
481
|
+
|
|
482
|
+
Create responsive card layouts:
|
|
483
|
+
|
|
484
|
+
```html
|
|
485
|
+
<div
|
|
486
|
+
style="display: grid; grid-template-columns: repeat(auto-fill, minmax(20rem, 1fr)); gap: 1.5rem"
|
|
487
|
+
>
|
|
488
|
+
<div data-card>
|
|
489
|
+
<h2>Card 1</h2>
|
|
490
|
+
<p>Content</p>
|
|
491
|
+
</div>
|
|
492
|
+
<div data-card>
|
|
493
|
+
<h2>Card 2</h2>
|
|
494
|
+
<p>Content</p>
|
|
495
|
+
</div>
|
|
496
|
+
<div data-card>
|
|
497
|
+
<h2>Card 3</h2>
|
|
498
|
+
<p>Content</p>
|
|
499
|
+
</div>
|
|
500
|
+
</div>
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
### Horizontal Card Layout
|
|
504
|
+
|
|
505
|
+
Change card direction to row:
|
|
506
|
+
|
|
507
|
+
```html
|
|
508
|
+
<div data-card style="--card-direction: row; --card-gap: 1.5rem">
|
|
509
|
+
<img
|
|
510
|
+
src="image.jpg"
|
|
511
|
+
alt="Card image"
|
|
512
|
+
style="width: 12rem; object-fit: cover"
|
|
513
|
+
/>
|
|
514
|
+
<div>
|
|
515
|
+
<h2>Horizontal Card</h2>
|
|
516
|
+
<p>Content appears beside the image.</p>
|
|
517
|
+
</div>
|
|
518
|
+
</div>
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
### Nested Cards
|
|
522
|
+
|
|
523
|
+
Cards can be nested for complex layouts:
|
|
524
|
+
|
|
525
|
+
```html
|
|
526
|
+
<div data-card style="--card-bg: #f5f5f5; --card-padding: 1.5rem">
|
|
527
|
+
<h2>Parent Card</h2>
|
|
528
|
+
<div data-card style="--card-padding: 1rem">
|
|
529
|
+
<h3>Nested Card</h3>
|
|
530
|
+
<p>Inner card content.</p>
|
|
531
|
+
</div>
|
|
532
|
+
</div>
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
## Heading Spacing
|
|
536
|
+
|
|
537
|
+
Cards automatically adjust heading margins:
|
|
538
|
+
|
|
539
|
+
```css
|
|
540
|
+
[data-card] h2,
|
|
541
|
+
[data-card] h3 {
|
|
542
|
+
margin-block-end: 0;
|
|
543
|
+
padding-block-end: 0;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
[data-card] + div {
|
|
547
|
+
margin-block-start: 0;
|
|
548
|
+
}
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
This prevents excessive spacing between card headings and following content.
|
|
552
|
+
|
|
553
|
+
## Accessibility Considerations
|
|
554
|
+
|
|
555
|
+
### Interactive Cards
|
|
556
|
+
|
|
557
|
+
When creating clickable cards:
|
|
558
|
+
|
|
559
|
+
1. **Keyboard Accessibility:**
|
|
560
|
+
|
|
561
|
+
```html
|
|
562
|
+
<div data-card="interactive" tabindex="0" role="button">
|
|
563
|
+
<!-- Card content -->
|
|
564
|
+
</div>
|
|
565
|
+
```
|
|
566
|
+
|
|
567
|
+
2. **Focus Indicators:**
|
|
568
|
+
|
|
569
|
+
- Automatic visible focus outline (2px solid, 3:1 contrast minimum)
|
|
570
|
+
- `:focus-visible` only shows for keyboard navigation
|
|
571
|
+
- Mouse clicks don't trigger outline
|
|
572
|
+
|
|
573
|
+
3. **Screen Reader Support:**
|
|
574
|
+
|
|
575
|
+
```html
|
|
576
|
+
<div
|
|
577
|
+
data-card="interactive"
|
|
578
|
+
tabindex="0"
|
|
579
|
+
role="button"
|
|
580
|
+
aria-label="View product details"
|
|
581
|
+
>
|
|
582
|
+
<!-- Card content -->
|
|
583
|
+
</div>
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
4. **Keyboard Interaction:**
|
|
587
|
+
- **Tab** - Focus the card
|
|
588
|
+
- **Enter** or **Space** - Activate the card
|
|
589
|
+
- Add JavaScript to handle keyboard events
|
|
590
|
+
|
|
591
|
+
### Semantic Structure
|
|
592
|
+
|
|
593
|
+
Use proper HTML semantics:
|
|
594
|
+
|
|
595
|
+
```html
|
|
596
|
+
<!-- Good: Semantic elements -->
|
|
597
|
+
<div data-card>
|
|
598
|
+
<header>
|
|
599
|
+
<h2>Title</h2>
|
|
600
|
+
</header>
|
|
601
|
+
<section data-card-body>
|
|
602
|
+
<p>Content</p>
|
|
603
|
+
</section>
|
|
604
|
+
<footer>
|
|
605
|
+
<button>Action</button>
|
|
606
|
+
</footer>
|
|
607
|
+
</div>
|
|
608
|
+
```
|
|
609
|
+
|
|
610
|
+
### Color Contrast
|
|
611
|
+
|
|
612
|
+
Ensure sufficient contrast for card backgrounds and text (WCAG AA: 4.5:1):
|
|
613
|
+
|
|
614
|
+
```html
|
|
615
|
+
<!-- Good contrast -->
|
|
616
|
+
<div data-card style="--card-bg: #333; color: white">
|
|
617
|
+
<p>High contrast text</p>
|
|
618
|
+
</div>
|
|
619
|
+
```
|
|
620
|
+
|
|
621
|
+
### Focus Color Customization
|
|
622
|
+
|
|
623
|
+
Customize focus color for better contrast:
|
|
624
|
+
|
|
625
|
+
```html
|
|
626
|
+
<div data-card="interactive" tabindex="0" style="--focus-color: #d32f2f">
|
|
627
|
+
<!-- Card with custom focus color -->
|
|
628
|
+
</div>
|
|
629
|
+
```
|
|
630
|
+
|
|
631
|
+
## CSS Variable Naming Convention
|
|
632
|
+
|
|
633
|
+
All card CSS variables follow the `--card-{property}` pattern:
|
|
634
|
+
|
|
635
|
+
### Property Mapping
|
|
636
|
+
|
|
637
|
+
| Category | Variable Pattern | Example |
|
|
638
|
+
| ----------------- | -------------------------------- | ------------------------------------ |
|
|
639
|
+
| **Layout** | `--card-{layout-property}` | `--card-display`, `--card-direction` |
|
|
640
|
+
| **Colors** | `--card-{element}-{property}` | `--card-bg`, `--card-header-bg` |
|
|
641
|
+
| **Spacing** | `--card-{element}-padding` | `--card-padding`, `--card-gap` |
|
|
642
|
+
| **Borders** | `--card-{element}-border-{side}` | `--card-header-border-bottom` |
|
|
643
|
+
| **Border Radius** | `--card-radius` | `--card-radius` |
|
|
644
|
+
| **Alignment** | `--card-align` | `--card-align` |
|
|
645
|
+
| **Focus** | `--focus-color` | `--focus-color` |
|
|
646
|
+
|
|
647
|
+
### Common Variables Quick Reference
|
|
648
|
+
|
|
649
|
+
```css
|
|
650
|
+
/* Base Styling */
|
|
651
|
+
--card-bg /* Background color */
|
|
652
|
+
--card-padding /* Padding for card content */
|
|
653
|
+
--card-radius /* Border radius */
|
|
654
|
+
--card-gap /* Gap between children */
|
|
655
|
+
|
|
656
|
+
/* Layout */
|
|
657
|
+
--card-display /* Display mode (flex) */
|
|
658
|
+
--card-direction /* Flex direction (column/row) */
|
|
659
|
+
--card-align /* Text alignment */
|
|
660
|
+
--card-position /* Position value */
|
|
661
|
+
|
|
662
|
+
/* Header */
|
|
663
|
+
--card-header-padding /* Header padding */
|
|
664
|
+
--card-header-bg /* Header background */
|
|
665
|
+
--card-header-border-bottom /* Header bottom border */
|
|
666
|
+
|
|
667
|
+
/* Body */
|
|
668
|
+
--card-body-padding /* Body padding */
|
|
669
|
+
|
|
670
|
+
/* Footer */
|
|
671
|
+
--card-footer-padding /* Footer padding */
|
|
672
|
+
--card-footer-bg /* Footer background */
|
|
673
|
+
--card-footer-border-top /* Footer top border */
|
|
674
|
+
|
|
675
|
+
/* Interactive */
|
|
676
|
+
--focus-color /* Focus outline color */
|
|
677
|
+
```
|
|
678
|
+
|
|
679
|
+
## Browser Support
|
|
680
|
+
|
|
681
|
+
The card styles use modern CSS features:
|
|
682
|
+
|
|
683
|
+
- **CSS Custom Properties:** All modern browsers (IE11 not supported)
|
|
684
|
+
- **Flexbox:** All modern browsers
|
|
685
|
+
- **`:focus-visible`:** Chrome 86+, Firefox 85+, Safari 15.4+
|
|
686
|
+
- **`:not()` selector:** All modern browsers
|
|
687
|
+
- **`rgba()`:** All modern browsers
|
|
688
|
+
- **Logical properties** (`padding-inline`, `padding-block`): Chrome 87+,
|
|
689
|
+
Firefox 66+, Safari 14.1+
|
|
690
|
+
|
|
691
|
+
### Fallbacks
|
|
692
|
+
|
|
693
|
+
For browsers without `:focus-visible` support:
|
|
694
|
+
|
|
695
|
+
```css
|
|
696
|
+
/* Fallback: Always show outline on focus */
|
|
697
|
+
[data-card="interactive"]:focus {
|
|
698
|
+
outline: 0.125rem solid #0066cc;
|
|
699
|
+
outline-offset: 0.125rem;
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
/* Modern browsers: Only show for keyboard */
|
|
703
|
+
[data-card="interactive"]:focus-visible {
|
|
704
|
+
outline: 0.125rem solid #0066cc;
|
|
705
|
+
outline-offset: 0.125rem;
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
[data-card="interactive"]:focus:not(:focus-visible) {
|
|
709
|
+
outline: none;
|
|
710
|
+
}
|
|
711
|
+
```
|
|
712
|
+
|
|
713
|
+
## Performance Tips
|
|
714
|
+
|
|
715
|
+
### Minimize Inline Styles
|
|
716
|
+
|
|
717
|
+
Create reusable card classes:
|
|
718
|
+
|
|
719
|
+
```css
|
|
720
|
+
.card-dark {
|
|
721
|
+
--card-bg: #333;
|
|
722
|
+
color: white;
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
.card-compact {
|
|
726
|
+
--card-padding: 1rem;
|
|
727
|
+
--card-gap: 0.5rem;
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
.card-large {
|
|
731
|
+
--card-padding: 3rem;
|
|
732
|
+
--card-gap: 2rem;
|
|
733
|
+
}
|
|
734
|
+
```
|
|
735
|
+
|
|
736
|
+
```html
|
|
737
|
+
<div data-card class="card-dark">Dark theme card</div>
|
|
738
|
+
<div data-card class="card-compact">Compact card</div>
|
|
739
|
+
```
|
|
740
|
+
|
|
741
|
+
### Avoid Nested Transitions
|
|
742
|
+
|
|
743
|
+
Don't add transitions to all card children:
|
|
744
|
+
|
|
745
|
+
```css
|
|
746
|
+
/* Avoid */
|
|
747
|
+
[data-card] * {
|
|
748
|
+
transition: all 0.3s;
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
/* Good: Only transition what changes */
|
|
752
|
+
[data-card="interactive"] {
|
|
753
|
+
transition:
|
|
754
|
+
box-shadow 0.2s ease,
|
|
755
|
+
transform 0.2s ease;
|
|
756
|
+
}
|
|
757
|
+
```
|
|
758
|
+
|
|
759
|
+
### Use Transform for Animations
|
|
760
|
+
|
|
761
|
+
Prefer `transform` over properties like `top` or `margin`:
|
|
762
|
+
|
|
763
|
+
```css
|
|
764
|
+
/* Good: Uses transform (hardware accelerated) */
|
|
765
|
+
[data-card="interactive"]:hover {
|
|
766
|
+
transform: translateY(-2px);
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
/* Avoid: Uses top (causes reflow) */
|
|
770
|
+
[data-card="interactive"]:hover {
|
|
771
|
+
top: -2px;
|
|
772
|
+
}
|
|
773
|
+
```
|
|
774
|
+
|
|
775
|
+
## Migration from Other Systems
|
|
776
|
+
|
|
777
|
+
### From Tailwind CSS
|
|
778
|
+
|
|
779
|
+
| Tailwind | fpkit Card |
|
|
780
|
+
| ---------------------------------------- | ---------------------------------------------------------- |
|
|
781
|
+
| `class="bg-white rounded-lg shadow p-6"` | `data-card` with `--card-bg: #fff; --card-padding: 1.5rem` |
|
|
782
|
+
| `class="card card-bordered"` | `data-card` with custom `--card-header-border-bottom` |
|
|
783
|
+
| `class="hover:shadow-lg transition"` | `data-card="interactive"` |
|
|
784
|
+
| `class="card-body"` | `data-card-body` |
|
|
785
|
+
|
|
786
|
+
### From Bootstrap
|
|
787
|
+
|
|
788
|
+
| Bootstrap | fpkit Card |
|
|
789
|
+
| ---------------------- | ------------------------------------------- |
|
|
790
|
+
| `class="card"` | `data-card` |
|
|
791
|
+
| `class="card-header"` | `<header>` or `data-card-header` |
|
|
792
|
+
| `class="card-body"` | `data-card-body` |
|
|
793
|
+
| `class="card-footer"` | `<footer>` or `data-card-footer` |
|
|
794
|
+
| `class="card-img-top"` | `<img>` as first child (automatic handling) |
|
|
795
|
+
|
|
796
|
+
## Additional Documentation
|
|
797
|
+
|
|
798
|
+
### Complete CSS Variables Reference
|
|
799
|
+
|
|
800
|
+
See [CSS-VARIABLES.md](../../../CSS-VARIABLES.md) for:
|
|
801
|
+
- Complete variable reference for all components
|
|
802
|
+
- Global theme token system
|
|
803
|
+
- Migration guide from px to rem
|
|
804
|
+
- Best practices for CSS variable naming
|
|
805
|
+
- Advanced theming patterns
|
|
806
|
+
|
|
807
|
+
### Pre-Built Themes
|
|
808
|
+
|
|
809
|
+
See [theme-examples.css](../../../theme-examples.css) for ready-to-use themes:
|
|
810
|
+
- **Dark Theme** - High contrast dark mode
|
|
811
|
+
- **Ocean Theme** - Cool blue tones
|
|
812
|
+
- **Sunset Theme** - Warm orange/purple
|
|
813
|
+
- **Forest Theme** - Natural greens
|
|
814
|
+
- **Monochrome** - Grayscale design
|
|
815
|
+
- **Midnight** - Deep blue dark mode
|
|
816
|
+
- Plus custom component examples
|
|
817
|
+
|
|
818
|
+
### Global Typography Styles
|
|
819
|
+
|
|
820
|
+
See `src/sass/_globals.scss` for:
|
|
821
|
+
- HR (horizontal rule) styling variables
|
|
822
|
+
- Blockquote styling variables
|
|
823
|
+
- Body layout variables
|
|
824
|
+
- Typography system
|
|
825
|
+
|
|
826
|
+
## Related Resources
|
|
827
|
+
|
|
828
|
+
- **React Component** - See [README.mdx](./README.mdx) for the React Card
|
|
829
|
+
component API
|
|
830
|
+
- **MDN: Flexbox** -
|
|
831
|
+
[https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout)
|
|
832
|
+
- **W3C ARIA: Article Role** -
|
|
833
|
+
[https://www.w3.org/WAI/ARIA/apg/patterns/article/](https://www.w3.org/WAI/ARIA/apg/patterns/article/)
|
|
834
|
+
- **CSS Custom Properties** -
|
|
835
|
+
[https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties)
|