@fpkit/acss 3.1.1 → 3.2.1

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 (204) hide show
  1. package/libs/{chunk-2NRIP6RB.cjs → chunk-2C3YLBWP.cjs} +3 -3
  2. package/libs/{chunk-NWJDAHP6.cjs → chunk-2GJHKWEK.cjs} +3 -3
  3. package/libs/{chunk-FVROL3V5.js → chunk-2JCDEC32.js} +3 -3
  4. package/libs/{chunk-IRLFZ3OL.js → chunk-3XJC4XUG.js} +2 -2
  5. package/libs/{chunk-L6PRDL6F.cjs → chunk-5CJPTDK3.cjs} +3 -3
  6. package/libs/{chunk-E4OSROCA.cjs → chunk-5QSNJQVH.cjs} +3 -3
  7. package/libs/{chunk-O3JIHC5M.cjs → chunk-6BUJZ4DJ.cjs} +3 -3
  8. package/libs/{chunk-WXBFBWYF.cjs → chunk-AFINOD2L.cjs} +3 -3
  9. package/libs/{chunk-HRRHPLER.js → chunk-AWZLSWDO.js} +2 -2
  10. package/libs/chunk-DDSXKOUB.js +7 -0
  11. package/libs/chunk-DDSXKOUB.js.map +1 -0
  12. package/libs/{chunk-CWRNJA4P.js → chunk-DIJBIOFE.js} +3 -3
  13. package/libs/chunk-EJ6KYBFE.cjs +13 -0
  14. package/libs/chunk-EJ6KYBFE.cjs.map +1 -0
  15. package/libs/{chunk-GUJSMQ3V.cjs → chunk-EKJYOCLY.cjs} +3 -3
  16. package/libs/{chunk-X5RKCLDC.cjs → chunk-F64GE6RG.cjs} +4 -4
  17. package/libs/{chunk-5RAWNUVD.js → chunk-IBUTNPTQ.js} +2 -2
  18. package/libs/{chunk-ZFJ4U45S.js → chunk-KDMX3FAW.js} +2 -2
  19. package/libs/{chunk-DYFAUAB7.cjs → chunk-LXODKKA3.cjs} +4 -4
  20. package/libs/{chunk-MPTMPBFT.js → chunk-M7JLT62Q.js} +2 -2
  21. package/libs/{chunk-IQ76HGVP.js → chunk-MBWI67UT.js} +2 -2
  22. package/libs/{chunk-O5XAJ7BY.cjs → chunk-NCGVF2QS.cjs} +4 -4
  23. package/libs/{chunk-W2UIN7EV.cjs → chunk-NPWHQVYB.cjs} +3 -3
  24. package/libs/chunk-OU52NIKA.js +8 -0
  25. package/libs/chunk-OU52NIKA.js.map +1 -0
  26. package/libs/{chunk-43TK2ICH.js → chunk-PMWL5XZ4.js} +3 -3
  27. package/libs/{chunk-KVKQLRJG.js → chunk-TF3GQKOY.js} +2 -2
  28. package/libs/{chunk-IEB64SWY.js → chunk-U5VA34SU.js} +2 -2
  29. package/libs/{chunk-EE3ZWSBY.cjs → chunk-URBGDUFN.cjs} +6 -6
  30. package/libs/chunk-WWPLBWCQ.cjs +18 -0
  31. package/libs/chunk-WWPLBWCQ.cjs.map +1 -0
  32. package/libs/{chunk-TPIB3RQP.js → chunk-ZF6Y7W57.js} +5 -5
  33. package/libs/component-props-50e69975.d.ts +66 -0
  34. package/libs/components/box/box.css +1 -0
  35. package/libs/components/box/box.css.map +1 -0
  36. package/libs/components/box/box.min.css +3 -0
  37. package/libs/components/breadcrumbs/breadcrumb.cjs +6 -6
  38. package/libs/components/breadcrumbs/breadcrumb.js +3 -3
  39. package/libs/components/button.cjs +4 -4
  40. package/libs/components/button.d.cts +10 -3
  41. package/libs/components/button.d.ts +10 -3
  42. package/libs/components/button.js +2 -2
  43. package/libs/components/card.cjs +7 -7
  44. package/libs/components/card.d.cts +13 -85
  45. package/libs/components/card.d.ts +13 -85
  46. package/libs/components/card.js +2 -2
  47. package/libs/components/cards/card.css +1 -1
  48. package/libs/components/cards/card.css.map +1 -1
  49. package/libs/components/cards/card.min.css +2 -2
  50. package/libs/components/cluster/cluster.css +1 -0
  51. package/libs/components/cluster/cluster.css.map +1 -0
  52. package/libs/components/cluster/cluster.min.css +3 -0
  53. package/libs/components/dialog/dialog.cjs +7 -7
  54. package/libs/components/dialog/dialog.js +5 -5
  55. package/libs/components/form/fields.cjs +4 -4
  56. package/libs/components/form/fields.js +2 -2
  57. package/libs/components/form/textarea.cjs +4 -4
  58. package/libs/components/form/textarea.js +2 -2
  59. package/libs/components/grid/grid.css +1 -0
  60. package/libs/components/grid/grid.css.map +1 -0
  61. package/libs/components/grid/grid.min.css +3 -0
  62. package/libs/components/heading/heading.cjs +3 -3
  63. package/libs/components/heading/heading.js +2 -2
  64. package/libs/components/icons/icon.cjs +4 -4
  65. package/libs/components/icons/icon.d.cts +2 -2
  66. package/libs/components/icons/icon.d.ts +2 -2
  67. package/libs/components/icons/icon.js +2 -2
  68. package/libs/components/link/link.cjs +6 -6
  69. package/libs/components/link/link.js +2 -2
  70. package/libs/components/list/list.cjs +5 -5
  71. package/libs/components/list/list.js +2 -2
  72. package/libs/components/modal.cjs +4 -4
  73. package/libs/components/modal.d.cts +1 -1
  74. package/libs/components/modal.d.ts +1 -1
  75. package/libs/components/modal.js +3 -3
  76. package/libs/components/nav/nav.cjs +7 -7
  77. package/libs/components/nav/nav.js +3 -3
  78. package/libs/components/stack/stack.css +1 -0
  79. package/libs/components/stack/stack.css.map +1 -0
  80. package/libs/components/stack/stack.min.css +3 -0
  81. package/libs/components/tables/table.d.cts +1 -1
  82. package/libs/components/tables/table.d.ts +1 -1
  83. package/libs/components/text/text.cjs +5 -5
  84. package/libs/components/text/text.js +2 -2
  85. package/libs/hooks.cjs +4 -4
  86. package/libs/hooks.js +3 -3
  87. package/libs/{icons-287fce3a.d.ts → icons-df8e744f.d.ts} +1 -1
  88. package/libs/icons.cjs +3 -3
  89. package/libs/icons.d.cts +2 -2
  90. package/libs/icons.d.ts +2 -2
  91. package/libs/icons.js +2 -2
  92. package/libs/index.cjs +64 -63
  93. package/libs/index.cjs.map +1 -1
  94. package/libs/index.css +1 -1
  95. package/libs/index.css.map +1 -1
  96. package/libs/index.d.cts +923 -4
  97. package/libs/index.d.ts +923 -4
  98. package/libs/index.js +28 -28
  99. package/libs/index.js.map +1 -1
  100. package/package.json +2 -2
  101. package/src/components/alert/STYLES.mdx +790 -0
  102. package/src/components/badge/STYLES.mdx +610 -0
  103. package/src/components/box/README.mdx +401 -0
  104. package/src/components/box/STYLES.mdx +360 -0
  105. package/src/components/box/box.scss +245 -0
  106. package/src/components/box/box.stories.tsx +395 -0
  107. package/src/components/box/box.test.tsx +425 -0
  108. package/src/components/box/box.tsx +170 -0
  109. package/src/components/box/box.types.ts +166 -0
  110. package/src/components/breadcrumbs/STYLES.mdx +99 -0
  111. package/src/components/buttons/STYLES.mdx +766 -0
  112. package/src/components/cards/STYLES.mdx +835 -0
  113. package/src/components/cards/card.scss +30 -21
  114. package/src/components/cards/card.stories.tsx +120 -80
  115. package/src/components/cards/card.tsx +14 -4
  116. package/src/components/cards/card.types.ts +13 -0
  117. package/src/components/cluster/README.mdx +595 -0
  118. package/src/components/cluster/STYLES.mdx +626 -0
  119. package/src/components/cluster/cluster.scss +86 -0
  120. package/src/components/cluster/cluster.stories.tsx +385 -0
  121. package/src/components/cluster/cluster.test.tsx +655 -0
  122. package/src/components/cluster/cluster.tsx +94 -0
  123. package/src/components/cluster/cluster.types.ts +75 -0
  124. package/src/components/details/STYLES.mdx +445 -0
  125. package/src/components/dialog/STYLES.mdx +888 -0
  126. package/src/components/flexbox/STYLES.mdx +1 -1
  127. package/src/components/form/STYLES.mdx +821 -0
  128. package/src/components/grid/README.mdx +709 -0
  129. package/src/components/grid/STYLES.mdx +785 -0
  130. package/src/components/grid/grid.scss +287 -0
  131. package/src/components/grid/grid.stories.tsx +486 -0
  132. package/src/components/grid/grid.test.tsx +981 -0
  133. package/src/components/grid/grid.tsx +222 -0
  134. package/src/components/grid/grid.types.ts +344 -0
  135. package/src/components/icons/STYLES.mdx +56 -0
  136. package/src/components/images/STYLES.mdx +75 -0
  137. package/src/components/layout/STYLES.mdx +556 -0
  138. package/src/components/link/STYLES.mdx +75 -0
  139. package/src/components/list/STYLES.mdx +631 -0
  140. package/src/components/nav/STYLES.mdx +460 -0
  141. package/src/components/progress/STYLES.mdx +64 -0
  142. package/src/components/stack/README.mdx +400 -0
  143. package/src/components/stack/STYLES.mdx +414 -0
  144. package/src/components/stack/stack.scss +109 -0
  145. package/src/components/stack/stack.stories.tsx +559 -0
  146. package/src/components/stack/stack.test.tsx +426 -0
  147. package/src/components/stack/stack.tsx +141 -0
  148. package/src/components/stack/stack.types.ts +133 -0
  149. package/src/components/tag/STYLES.mdx +105 -0
  150. package/src/components/text-to-speech/STYLES.mdx +80 -0
  151. package/src/components/ui.tsx +3 -3
  152. package/src/index.scss +7 -2
  153. package/src/index.ts +305 -12
  154. package/src/sass/GLOBALS-STYLES.md +631 -0
  155. package/src/sass/_globals.scss +45 -24
  156. package/src/sass/_styles.scss +2 -2
  157. package/src/styles/box/box.css +220 -0
  158. package/src/styles/box/box.css.map +1 -0
  159. package/src/styles/cards/card.css +23 -17
  160. package/src/styles/cards/card.css.map +1 -1
  161. package/src/styles/cluster/cluster.css +71 -0
  162. package/src/styles/cluster/cluster.css.map +1 -0
  163. package/src/styles/grid/grid.css +238 -0
  164. package/src/styles/grid/grid.css.map +1 -0
  165. package/src/styles/index.css +668 -49
  166. package/src/styles/index.css.map +1 -1
  167. package/src/styles/stack/stack.css +86 -0
  168. package/src/styles/stack/stack.css.map +1 -0
  169. package/src/types/component-props.ts +42 -14
  170. package/src/types/layout-primitives.ts +48 -0
  171. package/src/types/shared.ts +10 -26
  172. package/libs/chunk-ENTCUJ3A.cjs +0 -13
  173. package/libs/chunk-ENTCUJ3A.cjs.map +0 -1
  174. package/libs/chunk-HHLNOC5T.js +0 -7
  175. package/libs/chunk-HHLNOC5T.js.map +0 -1
  176. package/libs/chunk-KK47SYZI.js +0 -8
  177. package/libs/chunk-KK47SYZI.js.map +0 -1
  178. package/libs/chunk-W5TKWBFC.cjs +0 -18
  179. package/libs/chunk-W5TKWBFC.cjs.map +0 -1
  180. package/libs/component-props-67d978a2.d.ts +0 -38
  181. /package/libs/{chunk-2NRIP6RB.cjs.map → chunk-2C3YLBWP.cjs.map} +0 -0
  182. /package/libs/{chunk-NWJDAHP6.cjs.map → chunk-2GJHKWEK.cjs.map} +0 -0
  183. /package/libs/{chunk-FVROL3V5.js.map → chunk-2JCDEC32.js.map} +0 -0
  184. /package/libs/{chunk-IRLFZ3OL.js.map → chunk-3XJC4XUG.js.map} +0 -0
  185. /package/libs/{chunk-L6PRDL6F.cjs.map → chunk-5CJPTDK3.cjs.map} +0 -0
  186. /package/libs/{chunk-E4OSROCA.cjs.map → chunk-5QSNJQVH.cjs.map} +0 -0
  187. /package/libs/{chunk-O3JIHC5M.cjs.map → chunk-6BUJZ4DJ.cjs.map} +0 -0
  188. /package/libs/{chunk-WXBFBWYF.cjs.map → chunk-AFINOD2L.cjs.map} +0 -0
  189. /package/libs/{chunk-HRRHPLER.js.map → chunk-AWZLSWDO.js.map} +0 -0
  190. /package/libs/{chunk-CWRNJA4P.js.map → chunk-DIJBIOFE.js.map} +0 -0
  191. /package/libs/{chunk-GUJSMQ3V.cjs.map → chunk-EKJYOCLY.cjs.map} +0 -0
  192. /package/libs/{chunk-X5RKCLDC.cjs.map → chunk-F64GE6RG.cjs.map} +0 -0
  193. /package/libs/{chunk-5RAWNUVD.js.map → chunk-IBUTNPTQ.js.map} +0 -0
  194. /package/libs/{chunk-ZFJ4U45S.js.map → chunk-KDMX3FAW.js.map} +0 -0
  195. /package/libs/{chunk-DYFAUAB7.cjs.map → chunk-LXODKKA3.cjs.map} +0 -0
  196. /package/libs/{chunk-MPTMPBFT.js.map → chunk-M7JLT62Q.js.map} +0 -0
  197. /package/libs/{chunk-IQ76HGVP.js.map → chunk-MBWI67UT.js.map} +0 -0
  198. /package/libs/{chunk-O5XAJ7BY.cjs.map → chunk-NCGVF2QS.cjs.map} +0 -0
  199. /package/libs/{chunk-W2UIN7EV.cjs.map → chunk-NPWHQVYB.cjs.map} +0 -0
  200. /package/libs/{chunk-43TK2ICH.js.map → chunk-PMWL5XZ4.js.map} +0 -0
  201. /package/libs/{chunk-KVKQLRJG.js.map → chunk-TF3GQKOY.js.map} +0 -0
  202. /package/libs/{chunk-IEB64SWY.js.map → chunk-U5VA34SU.js.map} +0 -0
  203. /package/libs/{chunk-EE3ZWSBY.cjs.map → chunk-URBGDUFN.cjs.map} +0 -0
  204. /package/libs/{chunk-TPIB3RQP.js.map → chunk-ZF6Y7W57.js.map} +0 -0
@@ -1,34 +1,36 @@
1
1
  :root {
2
2
  // Base card properties
3
- --card-padding: 2rem;
4
- --card-bg: #fff;
3
+ --card-padding: 1.5rem;
4
+ --card-bg: var(--color-surface, #ffffff);
5
5
  --card-radius: calc(var(--card-padding) / 4);
6
- --card-position: relative;
7
- --card-display: flex;
8
- --card-direction: column;
9
6
  --card-gap: 1rem;
10
7
 
11
8
  // Element-specific variables (NEW - for complex card layouts)
12
9
  --card-header-padding: 1rem 1.5rem;
13
- --card-header-bg: #f8f9fa;
14
- --card-header-border-bottom: 1px solid #dee2e6;
10
+ --card-header-bg: var(--color-surface-secondary, #f8f9fa);
11
+ --card-header-border-bottom-width: 0.0625rem;
12
+ --card-header-border-bottom-style: solid;
13
+ --card-header-border-bottom-color: var(--color-border, #dee2e6);
15
14
 
16
15
  --card-body-padding: 1.5rem;
17
16
 
18
17
  --card-footer-padding: 1rem 1.5rem;
19
- --card-footer-bg: #f8f9fa;
20
- --card-footer-border-top: 1px solid #dee2e6;
18
+ --card-footer-bg: var(--color-surface-secondary, #f8f9fa);
19
+ --card-footer-border-top-width: 0.0625rem;
20
+ --card-footer-border-top-style: solid;
21
+ --card-footer-border-top-color: var(--color-border, #dee2e6);
21
22
  }
22
23
 
23
24
  [data-card],
24
- [data-component~='card'] {
25
- display: var(--card-display);
26
- flex-direction: var(--card-direction);
25
+ [data-component~="card"] {
26
+ display: flex;
27
+ flex-direction: column;
27
28
  gap: var(--card-gap);
28
29
  border-radius: var(--card-radius);
30
+ border: var(--card-border, 0.0625rem solid rgba(0, 0, 0, 0.08));
29
31
  background-color: var(--card-bg);
30
32
  text-align: var(--card-align, left);
31
-
33
+
32
34
  h3,
33
35
  h2 {
34
36
  margin-block-end: 0;
@@ -47,10 +49,11 @@
47
49
  padding-inline: var(--card-padding);
48
50
  }
49
51
  > *:last-child:not(img) {
50
- // margin-block-end: 0;
51
52
  padding-block-end: var(--card-padding);
52
53
  }
53
54
  > *:first-child:not(img) {
55
+ // Reduced top padding to account for heading's inherent spacing
56
+ // Prevents excessive whitespace above titles
54
57
  padding-block-start: calc(var(--card-padding) - 0.5rem);
55
58
  }
56
59
 
@@ -59,7 +62,7 @@
59
62
  > [data-card-header] {
60
63
  padding: var(--card-header-padding);
61
64
  background-color: var(--card-header-bg);
62
- border-bottom: var(--card-header-border-bottom);
65
+ border-bottom: var(--card-header-border-bottom-width) var(--card-header-border-bottom-style) var(--card-header-border-bottom-color);
63
66
  border-radius: var(--card-radius) var(--card-radius) 0 0;
64
67
  }
65
68
 
@@ -72,24 +75,31 @@
72
75
  > [data-card-footer] {
73
76
  padding: var(--card-footer-padding);
74
77
  background-color: var(--card-footer-bg);
75
- border-top: var(--card-footer-border-top);
78
+ border-top: var(--card-footer-border-top-width) var(--card-footer-border-top-style) var(--card-footer-border-top-color);
76
79
  border-radius: 0 0 var(--card-radius) var(--card-radius);
77
80
  }
78
81
  }
79
82
 
80
83
  // Interactive card styles - WCAG 2.4.7 compliant focus indicators
81
84
  [data-card="interactive"] {
85
+ --card-transition-duration: 0.2s;
86
+ --card-transition-timing: ease;
87
+ --card-hover-lift: -0.125rem;
88
+ --card-hover-shadow: 0 0.25rem 0.75rem rgba(0, 0, 0, 0.15);
89
+
82
90
  cursor: pointer;
83
- transition: box-shadow 0.2s ease, transform 0.2s ease;
91
+ transition:
92
+ box-shadow var(--card-transition-duration) var(--card-transition-timing),
93
+ transform var(--card-transition-duration) var(--card-transition-timing);
84
94
 
85
95
  &:hover {
86
- transform: translateY(-2px);
87
- box-shadow: 0 0.25rem 0.75rem rgba(0, 0, 0, 0.15);
96
+ transform: translateY(var(--card-hover-lift));
97
+ box-shadow: var(--card-hover-shadow);
88
98
  }
89
99
 
90
100
  // Visible focus indicator with 3:1 minimum contrast (WCAG 2.4.7)
91
101
  &:focus-visible {
92
- outline: 0.125rem solid var(--focus-color, #0066CC);
102
+ outline: 0.125rem solid var(--color-focus, #0066cc);
93
103
  outline-offset: 0.125rem;
94
104
  }
95
105
 
@@ -98,4 +108,3 @@
98
108
  outline: none;
99
109
  }
100
110
  }
101
-
@@ -10,26 +10,28 @@ const meta: Meta<typeof Card> = {
10
10
  component: Card,
11
11
  args: {
12
12
  children: <p>{content}</p>,
13
+ classes: "shadow-md",
13
14
  },
14
15
  argTypes: {
15
16
  as: {
16
- control: 'select',
17
- options: ['div', 'article', 'section', 'aside'],
18
- description: 'HTML element to render',
17
+ control: "select",
18
+ options: ["div", "article", "section", "aside"],
19
+ description: "HTML element to render",
19
20
  },
20
21
  interactive: {
21
- control: 'boolean',
22
- description: 'Enable keyboard navigation and button semantics',
22
+ control: "boolean",
23
+ description: "Enable keyboard navigation and button semantics",
23
24
  },
24
25
  role: {
25
- control: 'text',
26
- description: 'ARIA role attribute',
26
+ control: "text",
27
+ description: "ARIA role attribute",
27
28
  },
28
29
  },
29
30
  parameters: {
30
31
  docs: {
31
32
  description: {
32
- component: 'A flexible, accessible card component with compound component pattern. Supports polymorphic rendering, interactive variants, and WCAG 2.1 AA compliance.',
33
+ component:
34
+ "A flexible, accessible card component with compound component pattern. Supports polymorphic rendering, interactive variants, and WCAG 2.1 AA compliance.",
33
35
  },
34
36
  },
35
37
  },
@@ -171,13 +173,13 @@ export const FlexibleContent: Story = {
171
173
  export const InteractiveCard: Story = {
172
174
  args: {
173
175
  interactive: true,
174
- 'aria-label': 'View product details',
176
+ "aria-label": "View product details",
175
177
  },
176
178
  render: (args) => (
177
179
  <Card
178
180
  {...args}
179
- onClick={() => alert('Card clicked!')}
180
- style={{ cursor: 'pointer' }}
181
+ onClick={() => alert("Card clicked!")}
182
+ style={{ cursor: "pointer" }}
181
183
  >
182
184
  <Card.Title>Interactive Product Card</Card.Title>
183
185
  <Card.Content>
@@ -185,12 +187,12 @@ export const InteractiveCard: Story = {
185
187
  This card is fully interactive! Click anywhere or use your keyboard
186
188
  (Tab to focus, Enter or Space to activate) to trigger the action.
187
189
  </p>
188
- <p style={{ fontSize: '0.875rem', color: '#666', marginTop: '0.5rem' }}>
190
+ <p style={{ fontSize: "0.875rem", color: "#666", marginTop: "0.5rem" }}>
189
191
  Try it: Tab to focus this card, then press Enter or Space.
190
192
  </p>
191
193
  </Card.Content>
192
194
  <Card.Footer>
193
- <span style={{ color: '#007bff', fontWeight: 'bold' }}>
195
+ <span style={{ color: "#007bff", fontWeight: "bold" }}>
194
196
  Click to learn more →
195
197
  </span>
196
198
  </Card.Footer>
@@ -199,7 +201,8 @@ export const InteractiveCard: Story = {
199
201
  parameters: {
200
202
  docs: {
201
203
  description: {
202
- story: 'Interactive cards support full keyboard navigation (Enter/Space keys) and automatically receive proper ARIA attributes for accessibility.',
204
+ story:
205
+ "Interactive cards support full keyboard navigation (Enter/Space keys) and automatically receive proper ARIA attributes for accessibility.",
203
206
  },
204
207
  },
205
208
  },
@@ -217,7 +220,7 @@ export const AccessibleCard: Story = {
217
220
  This card uses <code>aria-labelledby</code> to connect the title with
218
221
  the card container, providing an accessible name for screen readers.
219
222
  </p>
220
- <p style={{ fontSize: '0.875rem', color: '#666', marginTop: '0.5rem' }}>
223
+ <p style={{ fontSize: "0.875rem", color: "#666", marginTop: "0.5rem" }}>
221
224
  Screen readers will announce: "Featured Product, article"
222
225
  </p>
223
226
  </Card.Content>
@@ -229,7 +232,8 @@ export const AccessibleCard: Story = {
229
232
  parameters: {
230
233
  docs: {
231
234
  description: {
232
- story: 'Demonstrates best practices for accessible cards using aria-labelledby to provide context to assistive technologies.',
235
+ story:
236
+ "Demonstrates best practices for accessible cards using aria-labelledby to provide context to assistive technologies.",
233
237
  },
234
238
  },
235
239
  },
@@ -240,7 +244,7 @@ export const AccessibleCard: Story = {
240
244
  */
241
245
  export const PolymorphicElements: Story = {
242
246
  render: () => (
243
- <div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
247
+ <div style={{ display: "flex", flexDirection: "column", gap: "1rem" }}>
244
248
  <Card as="article">
245
249
  <Card.Title as="h2">Article Card</Card.Title>
246
250
  <Card.Content>
@@ -266,7 +270,8 @@ export const PolymorphicElements: Story = {
266
270
  parameters: {
267
271
  docs: {
268
272
  description: {
269
- story: 'The Card component supports polymorphic rendering via the `as` prop, allowing you to use semantic HTML elements while maintaining consistent styling.',
273
+ story:
274
+ "The Card component supports polymorphic rendering via the `as` prop, allowing you to use semantic HTML elements while maintaining consistent styling.",
270
275
  },
271
276
  },
272
277
  },
@@ -277,7 +282,7 @@ export const PolymorphicElements: Story = {
277
282
  */
278
283
  export const CustomHeadingLevels: Story = {
279
284
  render: () => (
280
- <div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
285
+ <div style={{ display: "flex", flexDirection: "column", gap: "1rem" }}>
281
286
  <Card>
282
287
  <Card.Title as="h1">Level 1 Heading</Card.Title>
283
288
  <Card.Content>Main page title level</Card.Content>
@@ -290,7 +295,9 @@ export const CustomHeadingLevels: Story = {
290
295
 
291
296
  <Card>
292
297
  <Card.Title as="h3">Level 3 Heading (Default)</Card.Title>
293
- <Card.Content>Subsection title level - this is the default</Card.Content>
298
+ <Card.Content>
299
+ Subsection title level - this is the default
300
+ </Card.Content>
294
301
  </Card>
295
302
 
296
303
  <Card>
@@ -302,7 +309,8 @@ export const CustomHeadingLevels: Story = {
302
309
  parameters: {
303
310
  docs: {
304
311
  description: {
305
- story: 'Card.Title supports all heading levels (h1-h6) to maintain proper document outline and heading hierarchy.',
312
+ story:
313
+ "Card.Title supports all heading levels (h1-h6) to maintain proper document outline and heading hierarchy.",
306
314
  },
307
315
  },
308
316
  },
@@ -321,18 +329,23 @@ export const CustomHeadingLevels: Story = {
321
329
  */
322
330
  export const Customization: Story = {
323
331
  render: () => (
324
- <div style={{ display: 'flex', flexDirection: 'column', gap: '2rem' }}>
332
+ <div style={{ display: "flex", flexDirection: "column", gap: "2rem" }}>
325
333
  {/* Custom padding and spacing */}
326
334
  <div>
327
335
  <h4>Custom Padding & Spacing</h4>
328
- <Card styles={{
329
- "--card-padding": "3rem",
330
- "--card-radius": "1rem",
331
- "--card-gap": "1.5rem",
332
- }}>
336
+ <Card
337
+ styles={{
338
+ "--card-padding": "3rem",
339
+ "--card-radius": "1rem",
340
+ "--card-gap": "1.5rem",
341
+ }}
342
+ >
333
343
  <Card.Title>Spacious Card</Card.Title>
334
344
  <Card.Content>
335
- <p>This card uses custom padding (3rem) and larger border radius (1rem).</p>
345
+ <p>
346
+ This card uses custom padding (3rem) and larger border radius
347
+ (1rem).
348
+ </p>
336
349
  </Card.Content>
337
350
  </Card>
338
351
  </div>
@@ -340,14 +353,19 @@ export const Customization: Story = {
340
353
  {/* Compact card */}
341
354
  <div>
342
355
  <h4>Compact Card</h4>
343
- <Card styles={{
344
- "--card-padding": "1rem",
345
- "--card-radius": "0.25rem",
346
- "--card-gap": "0.5rem",
347
- }}>
356
+ <Card
357
+ styles={{
358
+ "--card-padding": "1rem",
359
+ "--card-radius": "0.25rem",
360
+ "--card-gap": "0.5rem",
361
+ }}
362
+ >
348
363
  <Card.Title>Compact Card</Card.Title>
349
364
  <Card.Content>
350
- <p>This card uses minimal padding and smaller gaps for a compact layout.</p>
365
+ <p>
366
+ This card uses minimal padding and smaller gaps for a compact
367
+ layout.
368
+ </p>
351
369
  </Card.Content>
352
370
  </Card>
353
371
  </div>
@@ -355,41 +373,53 @@ export const Customization: Story = {
355
373
  {/* Custom header/footer styling */}
356
374
  <div>
357
375
  <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' }}>
376
+ <div style={{ display: "flex", gap: "1rem", flexWrap: "wrap" }}>
377
+ <Card
378
+ styles={{
379
+ "--card-header-padding": "1.5rem 2rem",
380
+ "--card-header-bg": "#0066cc",
381
+ "--card-header-border-bottom": "none",
382
+ "--card-body-padding": "2rem",
383
+ "--card-footer-padding": "1rem 2rem",
384
+ "--card-footer-bg": "#f0f0f0",
385
+ "--card-footer-border-top": "2px solid #ddd",
386
+ }}
387
+ >
388
+ <header data-card-header style={{ color: "white" }}>
369
389
  <h3 style={{ margin: 0 }}>Custom Header</h3>
370
390
  </header>
371
391
  <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>
392
+ <p>
393
+ This card demonstrates element-specific customization using the
394
+ new scoped variables.
395
+ </p>
396
+ <p>
397
+ Header has custom blue background, body has custom padding,
398
+ footer has custom gray background.
399
+ </p>
374
400
  </div>
375
401
  <footer data-card-footer>
376
402
  <small>Custom Footer Content</small>
377
403
  </footer>
378
404
  </Card>
379
405
 
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' }}>
406
+ <Card
407
+ styles={{
408
+ "--card-header-padding": "0.75rem 1.25rem",
409
+ "--card-header-bg": "#28a745",
410
+ "--card-header-border-bottom": "3px solid #1e7e34",
411
+ "--card-body-padding": "1.25rem",
412
+ "--card-footer-padding": "0.75rem 1.25rem",
413
+ "--card-footer-bg": "#e7f5ea",
414
+ }}
415
+ >
416
+ <header data-card-header style={{ color: "white" }}>
389
417
  <h3 style={{ margin: 0 }}>Green Theme</h3>
390
418
  </header>
391
419
  <div data-card-body>
392
- <p>Another example with green theme and custom element spacing.</p>
420
+ <p>
421
+ Another example with green theme and custom element spacing.
422
+ </p>
393
423
  </div>
394
424
  <footer data-card-footer>
395
425
  <small>Footer with light green background</small>
@@ -407,22 +437,27 @@ export const Customization: Story = {
407
437
  }}
408
438
  >
409
439
  <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
- }}>
440
+ <Card
441
+ styles={{
442
+ "--card-bg": "#2a2a2a",
443
+ "--card-padding": "2rem",
444
+ "--card-radius": "0.75rem",
445
+ "--card-header-bg": "#3a3a3a",
446
+ "--card-header-border-bottom": "1px solid #4a4a4a",
447
+ "--card-footer-bg": "#3a3a3a",
448
+ "--card-footer-border-top": "1px solid #4a4a4a",
449
+ }}
450
+ >
419
451
  <header data-card-header>
420
- <h3 style={{ margin: 0, color: 'white' }}>Dark Mode Card</h3>
452
+ <h3 style={{ margin: 0, color: "white" }}>Dark Mode Card</h3>
421
453
  </header>
422
- <div data-card-body style={{ color: '#e5e7eb' }}>
423
- <p>This card demonstrates dark theme customization with all element-specific variables.</p>
454
+ <div data-card-body style={{ color: "#e5e7eb" }}>
455
+ <p>
456
+ This card demonstrates dark theme customization with all
457
+ element-specific variables.
458
+ </p>
424
459
  </div>
425
- <footer data-card-footer style={{ color: '#9ca3af' }}>
460
+ <footer data-card-footer style={{ color: "#9ca3af" }}>
426
461
  <small>Styled with CSS custom properties</small>
427
462
  </footer>
428
463
  </Card>
@@ -431,19 +466,24 @@ export const Customization: Story = {
431
466
  {/* Brand card */}
432
467
  <div>
433
468
  <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
- }}>
469
+ <Card
470
+ styles={{
471
+ "--card-bg": "#fff5e6",
472
+ "--card-radius": "0",
473
+ "--card-padding": "2.5rem",
474
+ "--card-gap": "2rem",
475
+ "--card-header-bg": "#ff9800",
476
+ "--card-header-border-bottom": "4px solid #f57c00",
477
+ }}
478
+ >
442
479
  <header data-card-header>
443
- <h3 style={{ margin: 0, color: 'white' }}>Brand Card</h3>
480
+ <h3 style={{ margin: 0, color: "white" }}>Brand Card</h3>
444
481
  </header>
445
482
  <div data-card-body>
446
- <p>This card uses brand colors and no border radius for a distinct look.</p>
483
+ <p>
484
+ This card uses brand colors and no border radius for a distinct
485
+ look.
486
+ </p>
447
487
  </div>
448
488
  </Card>
449
489
  </div>
@@ -5,6 +5,7 @@ import type {
5
5
  CardTitleProps,
6
6
  CardContentProps,
7
7
  CardFooterProps,
8
+ CardComponent,
8
9
  } from './card.types'
9
10
  import { cn, CARD_CLASSES, handleCardKeyDown, warnInteractiveUsage } from './card.utils'
10
11
 
@@ -218,11 +219,11 @@ Footer.displayName = 'Card.Footer'
218
219
  * </Card>
219
220
  * ```
220
221
  */
221
- export const Card = ({
222
+ const CardRoot = ({
222
223
  as = 'div',
223
224
  styles,
224
225
  children,
225
- classes = 'shadow',
226
+ classes = 'shadow-sm',
226
227
  id,
227
228
  interactive = false,
228
229
  onClick,
@@ -275,11 +276,20 @@ export const Card = ({
275
276
  )
276
277
  }
277
278
 
278
- export default Card
279
+ // Create compound component with proper TypeScript typing
280
+ export const Card = CardRoot as CardComponent
279
281
  Card.displayName = 'Card'
280
282
  Card.Title = Title
281
283
  Card.Content = Content
282
284
  Card.Footer = Footer
283
285
 
286
+ export default Card
287
+
284
288
  // Export types for external consumption
285
- export type { CardProps, CardTitleProps, CardContentProps, CardFooterProps } from './card.types'
289
+ export type {
290
+ CardProps,
291
+ CardTitleProps,
292
+ CardContentProps,
293
+ CardFooterProps,
294
+ CardComponent,
295
+ } from './card.types'
@@ -61,6 +61,19 @@ export interface CardFooterProps extends CardSubComponentProps {
61
61
  as?: 'div' | 'footer'
62
62
  }
63
63
 
64
+ /**
65
+ * Type for Card component with attached sub-components.
66
+ *
67
+ * This type ensures TypeScript recognizes Card.Title, Card.Content, and Card.Footer
68
+ * as valid properties on the Card component.
69
+ */
70
+ export interface CardComponent extends React.FC<CardProps> {
71
+ Title: React.FC<CardTitleProps>
72
+ Content: React.FC<CardContentProps>
73
+ Footer: React.FC<CardFooterProps>
74
+ displayName: string
75
+ }
76
+
64
77
  /**
65
78
  * Props for the main Card component.
66
79
  *