@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.
Files changed (202) 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-IWP4VJEP.cjs +18 -0
  19. package/libs/chunk-IWP4VJEP.cjs.map +1 -0
  20. package/libs/{chunk-ZFJ4U45S.js → chunk-KDMX3FAW.js} +2 -2
  21. package/libs/{chunk-DYFAUAB7.cjs → chunk-LXODKKA3.cjs} +4 -4
  22. package/libs/{chunk-MPTMPBFT.js → chunk-M7JLT62Q.js} +2 -2
  23. package/libs/{chunk-IQ76HGVP.js → chunk-MBWI67UT.js} +2 -2
  24. package/libs/{chunk-O5XAJ7BY.cjs → chunk-NCGVF2QS.cjs} +4 -4
  25. package/libs/{chunk-W2UIN7EV.cjs → chunk-NPWHQVYB.cjs} +3 -3
  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-UGMP72J2.js +8 -0
  30. package/libs/chunk-UGMP72J2.js.map +1 -0
  31. package/libs/{chunk-EE3ZWSBY.cjs → chunk-URBGDUFN.cjs} +6 -6
  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 +29 -21
  114. package/src/components/cards/card.tsx +13 -3
  115. package/src/components/cards/card.types.ts +13 -0
  116. package/src/components/cluster/README.mdx +595 -0
  117. package/src/components/cluster/STYLES.mdx +626 -0
  118. package/src/components/cluster/cluster.scss +86 -0
  119. package/src/components/cluster/cluster.stories.tsx +385 -0
  120. package/src/components/cluster/cluster.test.tsx +655 -0
  121. package/src/components/cluster/cluster.tsx +94 -0
  122. package/src/components/cluster/cluster.types.ts +75 -0
  123. package/src/components/details/STYLES.mdx +445 -0
  124. package/src/components/dialog/STYLES.mdx +888 -0
  125. package/src/components/flexbox/STYLES.mdx +1 -1
  126. package/src/components/form/STYLES.mdx +821 -0
  127. package/src/components/grid/README.mdx +709 -0
  128. package/src/components/grid/STYLES.mdx +785 -0
  129. package/src/components/grid/grid.scss +287 -0
  130. package/src/components/grid/grid.stories.tsx +486 -0
  131. package/src/components/grid/grid.test.tsx +981 -0
  132. package/src/components/grid/grid.tsx +222 -0
  133. package/src/components/grid/grid.types.ts +344 -0
  134. package/src/components/icons/STYLES.mdx +56 -0
  135. package/src/components/images/STYLES.mdx +75 -0
  136. package/src/components/layout/STYLES.mdx +556 -0
  137. package/src/components/link/STYLES.mdx +75 -0
  138. package/src/components/list/STYLES.mdx +631 -0
  139. package/src/components/nav/STYLES.mdx +460 -0
  140. package/src/components/progress/STYLES.mdx +64 -0
  141. package/src/components/stack/README.mdx +400 -0
  142. package/src/components/stack/STYLES.mdx +414 -0
  143. package/src/components/stack/stack.scss +109 -0
  144. package/src/components/stack/stack.stories.tsx +559 -0
  145. package/src/components/stack/stack.test.tsx +426 -0
  146. package/src/components/stack/stack.tsx +141 -0
  147. package/src/components/stack/stack.types.ts +133 -0
  148. package/src/components/tag/STYLES.mdx +105 -0
  149. package/src/components/text-to-speech/STYLES.mdx +80 -0
  150. package/src/components/ui.tsx +3 -3
  151. package/src/index.scss +5 -1
  152. package/src/index.ts +305 -12
  153. package/src/sass/GLOBALS-STYLES.md +631 -0
  154. package/src/sass/_globals.scss +45 -24
  155. package/src/styles/box/box.css +220 -0
  156. package/src/styles/box/box.css.map +1 -0
  157. package/src/styles/cards/card.css +22 -17
  158. package/src/styles/cards/card.css.map +1 -1
  159. package/src/styles/cluster/cluster.css +71 -0
  160. package/src/styles/cluster/cluster.css.map +1 -0
  161. package/src/styles/grid/grid.css +238 -0
  162. package/src/styles/grid/grid.css.map +1 -0
  163. package/src/styles/index.css +667 -49
  164. package/src/styles/index.css.map +1 -1
  165. package/src/styles/stack/stack.css +86 -0
  166. package/src/styles/stack/stack.css.map +1 -0
  167. package/src/types/component-props.ts +42 -14
  168. package/src/types/layout-primitives.ts +48 -0
  169. package/src/types/shared.ts +10 -26
  170. package/libs/chunk-ENTCUJ3A.cjs +0 -13
  171. package/libs/chunk-ENTCUJ3A.cjs.map +0 -1
  172. package/libs/chunk-HHLNOC5T.js +0 -7
  173. package/libs/chunk-HHLNOC5T.js.map +0 -1
  174. package/libs/chunk-KK47SYZI.js +0 -8
  175. package/libs/chunk-KK47SYZI.js.map +0 -1
  176. package/libs/chunk-W5TKWBFC.cjs +0 -18
  177. package/libs/chunk-W5TKWBFC.cjs.map +0 -1
  178. package/libs/component-props-67d978a2.d.ts +0 -38
  179. /package/libs/{chunk-2NRIP6RB.cjs.map → chunk-2C3YLBWP.cjs.map} +0 -0
  180. /package/libs/{chunk-NWJDAHP6.cjs.map → chunk-2GJHKWEK.cjs.map} +0 -0
  181. /package/libs/{chunk-FVROL3V5.js.map → chunk-2JCDEC32.js.map} +0 -0
  182. /package/libs/{chunk-IRLFZ3OL.js.map → chunk-3XJC4XUG.js.map} +0 -0
  183. /package/libs/{chunk-L6PRDL6F.cjs.map → chunk-5CJPTDK3.cjs.map} +0 -0
  184. /package/libs/{chunk-E4OSROCA.cjs.map → chunk-5QSNJQVH.cjs.map} +0 -0
  185. /package/libs/{chunk-O3JIHC5M.cjs.map → chunk-6BUJZ4DJ.cjs.map} +0 -0
  186. /package/libs/{chunk-WXBFBWYF.cjs.map → chunk-AFINOD2L.cjs.map} +0 -0
  187. /package/libs/{chunk-HRRHPLER.js.map → chunk-AWZLSWDO.js.map} +0 -0
  188. /package/libs/{chunk-CWRNJA4P.js.map → chunk-DIJBIOFE.js.map} +0 -0
  189. /package/libs/{chunk-GUJSMQ3V.cjs.map → chunk-EKJYOCLY.cjs.map} +0 -0
  190. /package/libs/{chunk-X5RKCLDC.cjs.map → chunk-F64GE6RG.cjs.map} +0 -0
  191. /package/libs/{chunk-5RAWNUVD.js.map → chunk-IBUTNPTQ.js.map} +0 -0
  192. /package/libs/{chunk-ZFJ4U45S.js.map → chunk-KDMX3FAW.js.map} +0 -0
  193. /package/libs/{chunk-DYFAUAB7.cjs.map → chunk-LXODKKA3.cjs.map} +0 -0
  194. /package/libs/{chunk-MPTMPBFT.js.map → chunk-M7JLT62Q.js.map} +0 -0
  195. /package/libs/{chunk-IQ76HGVP.js.map → chunk-MBWI67UT.js.map} +0 -0
  196. /package/libs/{chunk-O5XAJ7BY.cjs.map → chunk-NCGVF2QS.cjs.map} +0 -0
  197. /package/libs/{chunk-W2UIN7EV.cjs.map → chunk-NPWHQVYB.cjs.map} +0 -0
  198. /package/libs/{chunk-43TK2ICH.js.map → chunk-PMWL5XZ4.js.map} +0 -0
  199. /package/libs/{chunk-KVKQLRJG.js.map → chunk-TF3GQKOY.js.map} +0 -0
  200. /package/libs/{chunk-IEB64SWY.js.map → chunk-U5VA34SU.js.map} +0 -0
  201. /package/libs/{chunk-EE3ZWSBY.cjs.map → chunk-URBGDUFN.cjs.map} +0 -0
  202. /package/libs/{chunk-TPIB3RQP.js.map → chunk-ZF6Y7W57.js.map} +0 -0
@@ -0,0 +1,821 @@
1
+ import { Meta } from "@storybook/addon-docs/blocks";
2
+
3
+ <Meta title="FP.REACT Components/Forms/Styles" />
4
+
5
+ # Form Styles
6
+
7
+ Comprehensive form control styling system with CSS custom properties for inputs,
8
+ textareas, selects, and form layouts.
9
+
10
+ ## Overview
11
+
12
+ The fpkit form styling system provides consistent, accessible form controls with
13
+ extensive customization through CSS variables. All form elements support focus
14
+ states, disabled states, placeholder styling, and validation indicators.
15
+
16
+ ### Key Features
17
+
18
+ - **Universal input styling** - Text inputs, textareas, and selects with
19
+ consistent appearance
20
+ - **Custom select arrows** - SVG-based dropdown indicator
21
+ - **Accessible focus indicators** - Visible focus states for keyboard navigation
22
+ - **Disabled state styling** - Visual feedback for disabled form controls
23
+ - **Required field indicators** - ARIA-based required field styling
24
+ - **Placeholder customization** - Full control over placeholder appearance
25
+ - **Flexible layouts** - Column or row-based form layouts
26
+ - **CSS custom properties** - Extensive theming via CSS variables
27
+ - **Rem-based sizing** - All measurements use rem units (1rem = 16px)
28
+
29
+ ## CSS Custom Properties
30
+
31
+ ### Input Properties
32
+
33
+ Core styling variables for inputs, textareas, and selects:
34
+
35
+ ```css
36
+ :root {
37
+ /* Appearance */
38
+ --input-appearance: none; /* Remove browser defaults */
39
+ --input-bg: inherit; /* Background color */
40
+ --input-border-color: gray; /* Border/outline color */
41
+
42
+ /* Borders & Outlines */
43
+ --input-border: none; /* Inner border */
44
+ --input-outline: thin solid var(--input-border-color); /* Outer outline */
45
+ --input-radius: var(--radius); /* Border radius */
46
+
47
+ /* Spacing */
48
+ --input-padding-inline: 0.6rem; /* Horizontal padding (9.6px) */
49
+ --input-padding-block: 0.4rem; /* Vertical padding (6.4px) */
50
+
51
+ /* Typography */
52
+ --input-fs: var(--fs); /* Font size */
53
+
54
+ /* Dimensions */
55
+ --input-width: clamp(200px, 100%, 500px); /* Responsive width */
56
+ }
57
+ ```
58
+
59
+ ### Focus State Properties
60
+
61
+ ```css
62
+ :root {
63
+ /* Focus indicators */
64
+ --input-focus-outline: medium solid var(--input-border-color);
65
+ --input-focus-outline-offset: 0;
66
+ }
67
+ ```
68
+
69
+ ### Disabled State Properties
70
+
71
+ ```css
72
+ :root {
73
+ /* Disabled styling */
74
+ --input-disabled-bg: #f5f5f5;
75
+ --input-disabled-opacity: 0.6;
76
+ --input-disabled-cursor: not-allowed;
77
+ }
78
+ ```
79
+
80
+ ### Placeholder Properties
81
+
82
+ ```css
83
+ :root {
84
+ /* Placeholder styling */
85
+ --placeholder-color: gray;
86
+ --placeholder-style: italic;
87
+ --placeholder-fs: smaller;
88
+ }
89
+ ```
90
+
91
+ ### Form Layout Properties
92
+
93
+ ```css
94
+ :root {
95
+ /* Form layout */
96
+ --form-direction: column; /* Form flex direction */
97
+ }
98
+ ```
99
+
100
+ ### Select Properties
101
+
102
+ ```css
103
+ :root {
104
+ /* Custom select arrow */
105
+ --select-arrow: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='20' height='20'><polyline points='6,9 10,13 14,9' stroke='%23000000' stroke-width='1.5' fill='none' /></svg>");
106
+ }
107
+ ```
108
+
109
+ ### Customizing Form Styles
110
+
111
+ Override CSS variables globally or per-element:
112
+
113
+ ```css
114
+ /* Global customization */
115
+ :root {
116
+ --input-border-color: #0066cc;
117
+ --input-padding-inline: 1rem;
118
+ --input-radius: 0.5rem;
119
+ }
120
+
121
+ /* Per-element customization */
122
+ .custom-input {
123
+ --input-bg: #f9f9f9;
124
+ --input-border-color: #333;
125
+ }
126
+ ```
127
+
128
+ Or inline:
129
+
130
+ ```html
131
+ <input type="text" style="--input-bg: #f0f0f0; --input-border-color: blue" />
132
+ ```
133
+
134
+ ## Form Structure
135
+
136
+ ### Basic Form
137
+
138
+ Standard vertical form layout:
139
+
140
+ ```html
141
+ <form>
142
+ <div>
143
+ <label for="name">Name</label>
144
+ <input type="text" id="name" name="name" />
145
+ </div>
146
+ <div>
147
+ <label for="email">Email</label>
148
+ <input type="email" id="email" name="email" />
149
+ </div>
150
+ <button type="submit">Submit</button>
151
+ </form>
152
+ ```
153
+
154
+ **CSS Applied:**
155
+
156
+ ```css
157
+ form {
158
+ display: flex;
159
+ flex-direction: column; /* Vertical layout */
160
+ gap: 1rem; /* 16px spacing between fields */
161
+ }
162
+
163
+ form > div {
164
+ display: flex;
165
+ gap: 1rem;
166
+ flex-direction: column; /* Vertical label/input pairing */
167
+ }
168
+
169
+ form label {
170
+ display: block;
171
+ }
172
+ ```
173
+
174
+ ### Horizontal Form Layout
175
+
176
+ Change form direction to row:
177
+
178
+ ```html
179
+ <form style="--form-direction: row">
180
+ <div>
181
+ <label for="search">Search</label>
182
+ <input type="text" id="search" name="search" />
183
+ </div>
184
+ <button type="submit">Go</button>
185
+ </form>
186
+ ```
187
+
188
+ ## Input Types
189
+
190
+ ### Text Input
191
+
192
+ Standard text input with outline:
193
+
194
+ ```html
195
+ <input type="text" placeholder="Enter text" />
196
+ ```
197
+
198
+ **CSS Applied:**
199
+
200
+ ```css
201
+ input[type]:not([type="checkbox"], [type="radio"]) {
202
+ -webkit-appearance: none;
203
+ -moz-appearance: none;
204
+ appearance: none;
205
+ width: clamp(200px, 100%, 500px);
206
+ border: none;
207
+ outline: thin solid gray;
208
+ padding-inline: 0.6rem;
209
+ padding-block: 0.4rem;
210
+ border-radius: var(--radius);
211
+ background-color: #fff;
212
+ }
213
+ ```
214
+
215
+ **Note:** Checkboxes and radios are excluded from these styles to preserve their
216
+ native appearance.
217
+
218
+ ### Textarea
219
+
220
+ Multi-line text input:
221
+
222
+ ```html
223
+ <textarea placeholder="Enter message" rows="4"></textarea>
224
+ ```
225
+
226
+ **CSS:** Same as text input, with resizable height.
227
+
228
+ ### Select Dropdown
229
+
230
+ Dropdown with custom arrow:
231
+
232
+ ```html
233
+ <select>
234
+ <option value="">Choose an option</option>
235
+ <option value="1">Option 1</option>
236
+ <option value="2">Option 2</option>
237
+ <option value="3">Option 3</option>
238
+ </select>
239
+ ```
240
+
241
+ **CSS Applied:**
242
+
243
+ ```css
244
+ select {
245
+ border: thin solid gray; /* Border instead of outline */
246
+ outline: none;
247
+ -webkit-appearance: none;
248
+ -moz-appearance: none;
249
+ appearance: none;
250
+ background: var(--select-arrow) no-repeat;
251
+ background-position: right 0.5rem top 50%;
252
+ padding-inline-end: 0; /* Remove right padding for arrow space */
253
+ }
254
+ ```
255
+
256
+ **Custom Arrow:** The select uses an SVG data URL for the dropdown arrow,
257
+ positioned on the right side.
258
+
259
+ ## Input States
260
+
261
+ ### Default State
262
+
263
+ Standard input appearance:
264
+
265
+ ```html
266
+ <input type="text" value="Default value" />
267
+ ```
268
+
269
+ ### Focus State
270
+
271
+ Enhanced outline on focus:
272
+
273
+ ```html
274
+ <input type="text" placeholder="Focus me" />
275
+ ```
276
+
277
+ **CSS:**
278
+
279
+ ```css
280
+ input:focus-visible,
281
+ input:focus {
282
+ outline: medium solid var(--input-border-color);
283
+ outline-offset: 0;
284
+ }
285
+ ```
286
+
287
+ **Customization:**
288
+
289
+ ```html
290
+ <input
291
+ type="text"
292
+ style="--input-focus-outline: 3px solid blue; --input-focus-outline-offset: 2px"
293
+ />
294
+ ```
295
+
296
+ ### Disabled State
297
+
298
+ Grayed-out appearance with strikethrough text:
299
+
300
+ ```html
301
+ <input type="text" value="Disabled" disabled />
302
+ <input type="text" value="Disabled" aria-disabled="true" />
303
+ ```
304
+
305
+ **CSS:**
306
+
307
+ ```css
308
+ input[aria-disabled="true"],
309
+ input:disabled {
310
+ --input-border-color: lightgray;
311
+ background-color: #f5f5f5;
312
+ opacity: 0.6;
313
+ cursor: not-allowed;
314
+ text-transform: capitalize;
315
+ text-decoration: line-through;
316
+ }
317
+ ```
318
+
319
+ ### Required Fields
320
+
321
+ Visual indicator for required fields:
322
+
323
+ ```html
324
+ <input type="text" aria-required="true" placeholder="Required field" />
325
+ ```
326
+
327
+ **CSS:**
328
+
329
+ ```css
330
+ input[aria-required="true"]::placeholder {
331
+ color: var(--color-required, gray);
332
+ font-weight: 600;
333
+ }
334
+
335
+ input[aria-required="true"]::placeholder::after {
336
+ content: "* ";
337
+ }
338
+ ```
339
+
340
+ **Note:** The asterisk (\*) is automatically appended to the placeholder text
341
+ for required fields.
342
+
343
+ ## Placeholder Styling
344
+
345
+ ### Default Placeholder
346
+
347
+ Italic, gray, smaller text:
348
+
349
+ ```html
350
+ <input type="text" placeholder="Enter your name" />
351
+ ```
352
+
353
+ **CSS:**
354
+
355
+ ```css
356
+ input::placeholder {
357
+ color: gray;
358
+ font-style: italic;
359
+ font-size: smaller;
360
+ text-transform: capitalize;
361
+ }
362
+ ```
363
+
364
+ ### Custom Placeholder
365
+
366
+ ```html
367
+ <input
368
+ type="text"
369
+ placeholder="Custom placeholder"
370
+ style="--placeholder-color: blue; --placeholder-style: normal; --placeholder-fs: 1rem"
371
+ />
372
+ ```
373
+
374
+ ## Real-World Examples
375
+
376
+ ### Login Form
377
+
378
+ ```html
379
+ <form>
380
+ <div>
381
+ <label for="username">Username</label>
382
+ <input type="text" id="username" name="username" aria-required="true" />
383
+ </div>
384
+ <div>
385
+ <label for="password">Password</label>
386
+ <input type="password" id="password" name="password" aria-required="true" />
387
+ </div>
388
+ <div>
389
+ <label>
390
+ <input type="checkbox" name="remember" />
391
+ Remember me
392
+ </label>
393
+ </div>
394
+ <button type="submit">Log In</button>
395
+ </form>
396
+ ```
397
+
398
+ ### Contact Form
399
+
400
+ ```html
401
+ <form style="--input-border-color: #0066cc">
402
+ <div>
403
+ <label for="name">Name *</label>
404
+ <input type="text" id="name" name="name" aria-required="true" />
405
+ </div>
406
+ <div>
407
+ <label for="email">Email *</label>
408
+ <input type="email" id="email" name="email" aria-required="true" />
409
+ </div>
410
+ <div>
411
+ <label for="subject">Subject</label>
412
+ <select id="subject" name="subject">
413
+ <option value="">Choose a subject</option>
414
+ <option value="support">Support</option>
415
+ <option value="sales">Sales</option>
416
+ <option value="feedback">Feedback</option>
417
+ </select>
418
+ </div>
419
+ <div>
420
+ <label for="message">Message *</label>
421
+ <textarea
422
+ id="message"
423
+ name="message"
424
+ rows="5"
425
+ aria-required="true"
426
+ ></textarea>
427
+ </div>
428
+ <button type="submit">Send Message</button>
429
+ </form>
430
+ ```
431
+
432
+ ### Search Form (Horizontal)
433
+
434
+ ```html
435
+ <form style="--form-direction: row; align-items: flex-end">
436
+ <div style="flex: 1">
437
+ <label for="search">Search</label>
438
+ <input
439
+ type="search"
440
+ id="search"
441
+ name="q"
442
+ placeholder="Search..."
443
+ style="--input-width: 100%"
444
+ />
445
+ </div>
446
+ <button type="submit">Search</button>
447
+ </form>
448
+ ```
449
+
450
+ ### Inline Label Form
451
+
452
+ ```html
453
+ <form>
454
+ <div style="--form-direction: row; align-items: center">
455
+ <label for="email" style="width: 8rem">Email Address</label>
456
+ <input type="email" id="email" name="email" style="flex: 1" />
457
+ </div>
458
+ <div style="--form-direction: row; align-items: center">
459
+ <label for="phone" style="width: 8rem">Phone Number</label>
460
+ <input type="tel" id="phone" name="phone" style="flex: 1" />
461
+ </div>
462
+ <button type="submit">Submit</button>
463
+ </form>
464
+ ```
465
+
466
+ ### Form with Fieldset
467
+
468
+ ```html
469
+ <form>
470
+ <fieldset
471
+ style="border: 1px solid gray; padding: 1rem; border-radius: 0.5rem"
472
+ >
473
+ <legend>Personal Information</legend>
474
+ <div>
475
+ <label for="firstName">First Name</label>
476
+ <input type="text" id="firstName" name="firstName" />
477
+ </div>
478
+ <div>
479
+ <label for="lastName">Last Name</label>
480
+ <input type="text" id="lastName" name="lastName" />
481
+ </div>
482
+ </fieldset>
483
+ <button type="submit">Continue</button>
484
+ </form>
485
+ ```
486
+
487
+ ### Multi-Column Form
488
+
489
+ ```html
490
+ <form>
491
+ <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 1rem">
492
+ <div>
493
+ <label for="firstName">First Name</label>
494
+ <input type="text" id="firstName" name="firstName" />
495
+ </div>
496
+ <div>
497
+ <label for="lastName">Last Name</label>
498
+ <input type="text" id="lastName" name="lastName" />
499
+ </div>
500
+ </div>
501
+ <div>
502
+ <label for="address">Address</label>
503
+ <input type="text" id="address" name="address" />
504
+ </div>
505
+ <button type="submit">Submit</button>
506
+ </form>
507
+ ```
508
+
509
+ ### Form with Validation States
510
+
511
+ ```html
512
+ <form>
513
+ <div>
514
+ <label for="valid">Valid Input</label>
515
+ <input
516
+ type="text"
517
+ id="valid"
518
+ value="Valid value"
519
+ style="--input-border-color: green"
520
+ />
521
+ </div>
522
+ <div>
523
+ <label for="invalid">Invalid Input</label>
524
+ <input
525
+ type="text"
526
+ id="invalid"
527
+ value="Invalid value"
528
+ style="--input-border-color: red"
529
+ aria-invalid="true"
530
+ />
531
+ <small style="color: red">This field has an error.</small>
532
+ </div>
533
+ <button type="submit">Submit</button>
534
+ </form>
535
+ ```
536
+
537
+ ## Accessibility Considerations
538
+
539
+ ### Labels
540
+
541
+ Always associate labels with inputs:
542
+
543
+ ```html
544
+ <!-- Good: Explicit association -->
545
+ <label for="email">Email</label>
546
+ <input type="email" id="email" name="email" />
547
+
548
+ <!-- Good: Implicit association -->
549
+ <label>
550
+ Email
551
+ <input type="email" name="email" />
552
+ </label>
553
+
554
+ <!-- Bad: No association -->
555
+ <label>Email</label>
556
+ <input type="email" name="email" />
557
+ ```
558
+
559
+ ### Required Fields
560
+
561
+ Use `aria-required` for screen reader support:
562
+
563
+ ```html
564
+ <label for="name">Name *</label>
565
+ <input type="text" id="name" name="name" aria-required="true" required />
566
+ ```
567
+
568
+ **Note:** Include both `aria-required="true"` (for styling) and `required` (for
569
+ HTML5 validation).
570
+
571
+ ### Error Messages
572
+
573
+ Associate error messages with inputs:
574
+
575
+ ```html
576
+ <label for="email">Email</label>
577
+ <input
578
+ type="email"
579
+ id="email"
580
+ name="email"
581
+ aria-invalid="true"
582
+ aria-describedby="email-error"
583
+ />
584
+ <span id="email-error" role="alert">Please enter a valid email address.</span>
585
+ ```
586
+
587
+ ### Focus Indicators
588
+
589
+ Ensure visible focus indicators (automatic with `:focus-visible`):
590
+
591
+ ```css
592
+ input:focus-visible {
593
+ outline: medium solid var(--input-border-color);
594
+ }
595
+ ```
596
+
597
+ **Never remove focus outlines** without providing alternatives.
598
+
599
+ ### Disabled Fields
600
+
601
+ Use proper disabled attributes:
602
+
603
+ ```html
604
+ <!-- Native disabled (recommended) -->
605
+ <input type="text" disabled />
606
+
607
+ <!-- ARIA disabled (for custom behavior) -->
608
+ <input type="text" aria-disabled="true" />
609
+ ```
610
+
611
+ ### Keyboard Navigation
612
+
613
+ All form controls are keyboard-accessible by default:
614
+
615
+ - **Tab** - Move to next field
616
+ - **Shift+Tab** - Move to previous field
617
+ - **Enter** - Submit form
618
+ - **Space** - Toggle checkbox/radio
619
+
620
+ ## Form Validation Styling
621
+
622
+ ### Valid State
623
+
624
+ ```html
625
+ <input
626
+ type="email"
627
+ value="user@example.com"
628
+ style="--input-border-color: #28a745"
629
+ />
630
+ ```
631
+
632
+ ### Invalid State
633
+
634
+ ```html
635
+ <input
636
+ type="email"
637
+ value="invalid-email"
638
+ aria-invalid="true"
639
+ style="--input-border-color: #dc3545"
640
+ />
641
+ ```
642
+
643
+ ### Custom Validation Colors
644
+
645
+ ```css
646
+ :root {
647
+ --input-valid-color: #28a745;
648
+ --input-invalid-color: #dc3545;
649
+ }
650
+ ```
651
+
652
+ ```html
653
+ <input type="text" style="--input-border-color: var(--input-valid-color)" />
654
+ <input
655
+ type="text"
656
+ aria-invalid="true"
657
+ style="--input-border-color: var(--input-invalid-color)"
658
+ />
659
+ ```
660
+
661
+ ## CSS Variable Naming Convention
662
+
663
+ All form CSS variables follow specific patterns:
664
+
665
+ ### Property Mapping
666
+
667
+ | Category | Variable Pattern | Example |
668
+ | ---------------- | ---------------------------- | ---------------------------------------------- |
669
+ | **Input Core** | `--input-{property}` | `--input-bg`, `--input-border` |
670
+ | **Input States** | `--input-{state}-{property}` | `--input-focus-outline`, `--input-disabled-bg` |
671
+ | **Placeholder** | `--placeholder-{property}` | `--placeholder-color`, `--placeholder-fs` |
672
+ | **Form Layout** | `--form-{property}` | `--form-direction` |
673
+ | **Select** | `--select-{property}` | `--select-arrow` |
674
+
675
+ ### Common Variables Quick Reference
676
+
677
+ ```css
678
+ /* Input Appearance */
679
+ --input-bg /* Background color */
680
+ --input-border /* Inner border */
681
+ --input-outline /* Outer outline */
682
+ --input-border-color /* Border/outline color */
683
+ --input-radius /* Border radius */
684
+ --input-appearance /* Browser appearance reset */
685
+
686
+ /* Input Spacing */
687
+ --input-padding-inline /* Horizontal padding */
688
+ --input-padding-block /* Vertical padding */
689
+ --input-width /* Input width */
690
+
691
+ /* Input Typography */
692
+ --input-fs /* Font size */
693
+
694
+ /* Focus State */
695
+ --input-focus-outline /* Focus outline style */
696
+ --input-focus-outline-offset /* Focus outline offset */
697
+
698
+ /* Disabled State */
699
+ --input-disabled-bg /* Disabled background */
700
+ --input-disabled-opacity /* Disabled opacity */
701
+ --input-disabled-cursor /* Disabled cursor */
702
+
703
+ /* Placeholder */
704
+ --placeholder-color /* Placeholder text color */
705
+ --placeholder-style /* Placeholder font style */
706
+ --placeholder-fs /* Placeholder font size */
707
+
708
+ /* Form Layout */
709
+ --form-direction /* Form flex direction */
710
+
711
+ /* Select */
712
+ --select-arrow /* Custom dropdown arrow */
713
+ ```
714
+
715
+ ## Browser Support
716
+
717
+ The form styles use modern CSS features:
718
+
719
+ - **CSS Custom Properties:** All modern browsers (IE11 not supported)
720
+ - **`:focus-visible`:** Chrome 86+, Firefox 85+, Safari 15.4+
721
+ - **`appearance: none`:** All modern browsers
722
+ - **`clamp()`:** Chrome 79+, Firefox 75+, Safari 13.1+
723
+ - **Logical properties** (`padding-inline`, `padding-block`): Chrome 87+,
724
+ Firefox 66+, Safari 14.1+
725
+ - **`::placeholder`:** All modern browsers
726
+ - **SVG data URLs:** All modern browsers
727
+
728
+ ### Fallbacks
729
+
730
+ For older browsers without `clamp()`:
731
+
732
+ ```css
733
+ /* Fallback */
734
+ --input-width: 100%;
735
+ max-width: 500px;
736
+ min-width: 200px;
737
+
738
+ /* Modern */
739
+ --input-width: clamp(200px, 100%, 500px);
740
+ ```
741
+
742
+ ## Performance Tips
743
+
744
+ ### Avoid Over-Styling
745
+
746
+ Style only what's necessary:
747
+
748
+ ```html
749
+ <!-- Good: Uses defaults -->
750
+ <input type="text" />
751
+
752
+ <!-- Avoid: Unnecessary customization -->
753
+ <input
754
+ type="text"
755
+ style="--input-bg: white; --input-outline: thin solid gray"
756
+ />
757
+ ```
758
+
759
+ ### Use CSS Classes
760
+
761
+ Create reusable form classes:
762
+
763
+ ```css
764
+ .form-control-lg {
765
+ --input-padding-inline: 1rem;
766
+ --input-padding-block: 0.75rem;
767
+ --input-fs: 1.125rem;
768
+ }
769
+
770
+ .form-control-sm {
771
+ --input-padding-inline: 0.5rem;
772
+ --input-padding-block: 0.25rem;
773
+ --input-fs: 0.875rem;
774
+ }
775
+ ```
776
+
777
+ ```html
778
+ <input type="text" class="form-control-lg" />
779
+ <input type="text" class="form-control-sm" />
780
+ ```
781
+
782
+ ### Minimize Select Arrow Customization
783
+
784
+ The default select arrow works well for most cases. Only customize when
785
+ necessary:
786
+
787
+ ```css
788
+ /* Custom arrow color (if needed) */
789
+ --select-arrow: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='20' height='20'><polyline points='6,9 10,13 14,9' stroke='%230066cc' stroke-width='1.5' fill='none' /></svg>");
790
+ ```
791
+
792
+ ## Migration from Other Systems
793
+
794
+ ### From Tailwind CSS
795
+
796
+ | Tailwind | fpkit Form |
797
+ | -------------------------------------------------- | ------------------------------------ |
798
+ | `class="border border-gray-300 rounded px-3 py-2"` | Default `<input>` styles |
799
+ | `class="focus:ring focus:border-blue-500"` | `--input-focus-outline` |
800
+ | `class="disabled:bg-gray-100"` | `disabled` or `aria-disabled="true"` |
801
+ | `class="placeholder-gray-400"` | `--placeholder-color` |
802
+ | `class="w-full"` | `style="--input-width: 100%"` |
803
+
804
+ ### From Bootstrap
805
+
806
+ | Bootstrap | fpkit Form |
807
+ | ------------------------------- | ------------------------------------ |
808
+ | `class="form-control"` | Default `<input>` styles |
809
+ | `class="form-control:focus"` | Automatic focus styles |
810
+ | `class="form-control:disabled"` | `disabled` or `aria-disabled="true"` |
811
+ | `class="form-select"` | Default `<select>` styles |
812
+
813
+ ## Related Resources
814
+
815
+ - **React Component** - See form component README for React API
816
+ - **MDN: Forms** -
817
+ [https://developer.mozilla.org/en-US/docs/Learn/Forms](https://developer.mozilla.org/en-US/docs/Learn/Forms)
818
+ - **W3C: Form Accessibility** -
819
+ [https://www.w3.org/WAI/tutorials/forms/](https://www.w3.org/WAI/tutorials/forms/)
820
+ - **CSS Custom Properties** -
821
+ [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)