activeadmin-tom_select 4.1.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 (196) hide show
  1. checksums.yaml +7 -0
  2. data/.actrc +20 -0
  3. data/.claude/commands/fix-tests.md +203 -0
  4. data/.github/workflows/ci.yml +174 -0
  5. data/.github/workflows/npm-publish.yml +50 -0
  6. data/.gitignore +35 -0
  7. data/.npmignore +58 -0
  8. data/.rspec +1 -0
  9. data/.rubocop.yml +75 -0
  10. data/.yardopts +2 -0
  11. data/AGENTS.md +39 -0
  12. data/Appraisals +9 -0
  13. data/CHANGELOG.md +64 -0
  14. data/CLAUDE.md +157 -0
  15. data/Gemfile +12 -0
  16. data/Gemfile.lock +368 -0
  17. data/LICENSE.txt +25 -0
  18. data/README.md +483 -0
  19. data/Rakefile +4 -0
  20. data/activeadmin-tom_select.gemspec +43 -0
  21. data/bin/rspec +17 -0
  22. data/config/database.yml +16 -0
  23. data/docs/activeadmin-4-detailed-reference.md +932 -0
  24. data/docs/activeadmin-4-gem-migration-guide.md +313 -0
  25. data/docs/combustion.md +213 -0
  26. data/docs/fail.png +0 -0
  27. data/docs/guide-update-your-app.md +283 -0
  28. data/docs/normal.png +0 -0
  29. data/docs/propshaft-readme.md +320 -0
  30. data/docs/propshaft-upgrade.md +484 -0
  31. data/docs/setup-activeadmin-app.md +552 -0
  32. data/docs/setup-activeadmin-gem.md +535 -0
  33. data/docs/tailwind/blog-page.md +341 -0
  34. data/docs/tailwind/upgrade-guide-enhanced.md +438 -0
  35. data/docs/tailwind/upgrade-guide.md +416 -0
  36. data/docs/tailwind-4/active_admin.rake +38 -0
  37. data/docs/tailwind-4/active_admin.tailwind.css +415 -0
  38. data/docs/tailwind-4/tailwind-active_admin.config.js +18 -0
  39. data/docs/test-app-change.md +154 -0
  40. data/docs/test-environment-fixes.md +58 -0
  41. data/docs/update-tom-select.md +184 -0
  42. data/docs/upload-system.md +225 -0
  43. data/gemfiles/rails_7.x_active_admin_4.x.gemfile +10 -0
  44. data/gemfiles/rails_7.x_active_admin_4.x.gemfile.lock +377 -0
  45. data/gemfiles/rails_8.x_active_admin_4.x.gemfile +10 -0
  46. data/gemfiles/rails_8.x_active_admin_4.x.gemfile.lock +372 -0
  47. data/lefthook.yml +17 -0
  48. data/lib/activeadmin/inputs/filters/searchable_select_input.rb +19 -0
  49. data/lib/activeadmin/inputs/searchable_select_input.rb +16 -0
  50. data/lib/activeadmin/tom_select/engine.rb +17 -0
  51. data/lib/activeadmin/tom_select/option_collection.rb +128 -0
  52. data/lib/activeadmin/tom_select/resource_dsl_extension.rb +56 -0
  53. data/lib/activeadmin/tom_select/resource_extension.rb +10 -0
  54. data/lib/activeadmin/tom_select/select_input_extension.rb +168 -0
  55. data/lib/activeadmin/tom_select/version.rb +5 -0
  56. data/lib/activeadmin/tom_select.rb +20 -0
  57. data/lib/activeadmin-tom_select.rb +5 -0
  58. data/lib/generators/active_admin/tom_select/install/install_generator.rb +180 -0
  59. data/npm-package/package-lock.json +51 -0
  60. data/npm-package/package.json +43 -0
  61. data/npm-package/src/index.js +153 -0
  62. data/npm-package/src/tom-select-tailwind.css +392 -0
  63. data/sonar-project.properties +25 -0
  64. data/spec/features/ajax_params_spec.rb +31 -0
  65. data/spec/features/asset_pipeline_diagnostic_spec.rb +155 -0
  66. data/spec/features/end_to_end_spec.rb +273 -0
  67. data/spec/features/filter_input_spec.rb +144 -0
  68. data/spec/features/form_input_spec.rb +122 -0
  69. data/spec/features/inline_ajax_setting_spec.rb +26 -0
  70. data/spec/features/input_errors_spec.rb +76 -0
  71. data/spec/features/input_html_options_spec.rb +30 -0
  72. data/spec/features/options_dsl_spec.rb +230 -0
  73. data/spec/features/production_build_spec.rb +108 -0
  74. data/spec/internal/.node-version +1 -0
  75. data/spec/internal/Gemfile +43 -0
  76. data/spec/internal/Gemfile.lock +333 -0
  77. data/spec/internal/Procfile.dev +3 -0
  78. data/spec/internal/README.md +24 -0
  79. data/spec/internal/Rakefile +6 -0
  80. data/spec/internal/app/admin/categories.rb +26 -0
  81. data/spec/internal/app/admin/dashboard.rb +29 -0
  82. data/spec/internal/app/admin/option_types.rb +19 -0
  83. data/spec/internal/app/admin/option_values.rb +30 -0
  84. data/spec/internal/app/admin/posts.rb +27 -0
  85. data/spec/internal/app/admin/products.rb +22 -0
  86. data/spec/internal/app/admin/rgb_colors.rb +25 -0
  87. data/spec/internal/app/admin/tag_names.rb +21 -0
  88. data/spec/internal/app/admin/test_ajax_params_category.rb +10 -0
  89. data/spec/internal/app/admin/test_ajax_params_post.rb +20 -0
  90. data/spec/internal/app/admin/test_form_post_class.rb +7 -0
  91. data/spec/internal/app/admin/test_form_post_custom.rb +11 -0
  92. data/spec/internal/app/admin/test_form_post_resource.rb +11 -0
  93. data/spec/internal/app/admin/test_form_post_resource_custom.rb +12 -0
  94. data/spec/internal/app/admin/test_inline_ajax_post.rb +9 -0
  95. data/spec/internal/app/admin/test_input_html_post.rb +11 -0
  96. data/spec/internal/app/admin/test_posts_display_text.rb +9 -0
  97. data/spec/internal/app/admin/test_posts_filter.rb +9 -0
  98. data/spec/internal/app/admin/test_posts_named.rb +9 -0
  99. data/spec/internal/app/admin/test_posts_pagination.rb +9 -0
  100. data/spec/internal/app/admin/test_posts_payload_lambda.rb +11 -0
  101. data/spec/internal/app/admin/test_posts_payload_proc.rb +9 -0
  102. data/spec/internal/app/admin/test_posts_scope_lambda.rb +8 -0
  103. data/spec/internal/app/admin/test_posts_scope_params.rb +8 -0
  104. data/spec/internal/app/admin/test_posts_scope_user.rb +8 -0
  105. data/spec/internal/app/admin/test_posts_text_attr.rb +5 -0
  106. data/spec/internal/app/admin/users.rb +23 -0
  107. data/spec/internal/app/admin/variants.rb +31 -0
  108. data/spec/internal/app/assets/config/manifest.js +2 -0
  109. data/spec/internal/app/assets/images/.keep +0 -0
  110. data/spec/internal/app/assets/stylesheets/active_admin.tailwind.css +16 -0
  111. data/spec/internal/app/assets/stylesheets/application.tailwind.css +15 -0
  112. data/spec/internal/app/controllers/application_controller.rb +9 -0
  113. data/spec/internal/app/controllers/concerns/.keep +0 -0
  114. data/spec/internal/app/helpers/application_helper.rb +2 -0
  115. data/spec/internal/app/javascript/active_admin.js +19 -0
  116. data/spec/internal/app/javascript/application.js +2 -0
  117. data/spec/internal/app/jobs/application_job.rb +7 -0
  118. data/spec/internal/app/mailers/application_mailer.rb +4 -0
  119. data/spec/internal/app/models/admin_user.rb +9 -0
  120. data/spec/internal/app/models/application_record.rb +3 -0
  121. data/spec/internal/app/models/article.rb +12 -0
  122. data/spec/internal/app/models/category.rb +12 -0
  123. data/spec/internal/app/models/color.rb +9 -0
  124. data/spec/internal/app/models/concerns/.keep +0 -0
  125. data/spec/internal/app/models/internal/tag_name.rb +14 -0
  126. data/spec/internal/app/models/internal_tag_name.rb +11 -0
  127. data/spec/internal/app/models/option_type.rb +12 -0
  128. data/spec/internal/app/models/option_value.rb +4 -0
  129. data/spec/internal/app/models/post.rb +15 -0
  130. data/spec/internal/app/models/product.rb +12 -0
  131. data/spec/internal/app/models/rgb_color.rb +16 -0
  132. data/spec/internal/app/models/tag.rb +12 -0
  133. data/spec/internal/app/models/tagging.rb +12 -0
  134. data/spec/internal/app/models/user.rb +12 -0
  135. data/spec/internal/app/models/variant.rb +12 -0
  136. data/spec/internal/app/views/layouts/application.html.erb +28 -0
  137. data/spec/internal/app/views/layouts/mailer.html.erb +13 -0
  138. data/spec/internal/app/views/layouts/mailer.text.erb +1 -0
  139. data/spec/internal/app/views/pwa/manifest.json.erb +22 -0
  140. data/spec/internal/app/views/pwa/service-worker.js +26 -0
  141. data/spec/internal/bin/bundle +117 -0
  142. data/spec/internal/bin/dev +11 -0
  143. data/spec/internal/bin/rackup +27 -0
  144. data/spec/internal/bin/rails +4 -0
  145. data/spec/internal/bin/rake +4 -0
  146. data/spec/internal/bin/setup +37 -0
  147. data/spec/internal/config/application.rb +50 -0
  148. data/spec/internal/config/boot.rb +3 -0
  149. data/spec/internal/config/credentials.yml.enc +1 -0
  150. data/spec/internal/config/database.yml +32 -0
  151. data/spec/internal/config/environment.rb +5 -0
  152. data/spec/internal/config/environments/development.rb +63 -0
  153. data/spec/internal/config/environments/production.rb +86 -0
  154. data/spec/internal/config/environments/test.rb +50 -0
  155. data/spec/internal/config/initializers/active_admin.rb +54 -0
  156. data/spec/internal/config/initializers/assets.rb +8 -0
  157. data/spec/internal/config/initializers/content_security_policy.rb +25 -0
  158. data/spec/internal/config/initializers/devise.rb +315 -0
  159. data/spec/internal/config/initializers/filter_parameter_logging.rb +8 -0
  160. data/spec/internal/config/initializers/inflections.rb +16 -0
  161. data/spec/internal/config/initializers/searchable_select.rb +6 -0
  162. data/spec/internal/config/locales/devise.en.yml +65 -0
  163. data/spec/internal/config/locales/en.yml +31 -0
  164. data/spec/internal/config/master.key +1 -0
  165. data/spec/internal/config/puma.rb +38 -0
  166. data/spec/internal/config/routes.rb +17 -0
  167. data/spec/internal/config.ru +6 -0
  168. data/spec/internal/db/schema.rb +174 -0
  169. data/spec/internal/db/seeds.rb +167 -0
  170. data/spec/internal/esbuild.config.js +34 -0
  171. data/spec/internal/lib/tasks/.keep +0 -0
  172. data/spec/internal/lib/tasks/active_admin.rake +55 -0
  173. data/spec/internal/log/.keep +0 -0
  174. data/spec/internal/package-lock.json +1954 -0
  175. data/spec/internal/package.json +21 -0
  176. data/spec/internal/public/400.html +114 -0
  177. data/spec/internal/public/404.html +114 -0
  178. data/spec/internal/public/406-unsupported-browser.html +114 -0
  179. data/spec/internal/public/422.html +114 -0
  180. data/spec/internal/public/500.html +114 -0
  181. data/spec/internal/public/icon.png +0 -0
  182. data/spec/internal/public/icon.svg +3 -0
  183. data/spec/internal/public/robots.txt +1 -0
  184. data/spec/internal/script/.keep +0 -0
  185. data/spec/internal/storage/.keep +0 -0
  186. data/spec/internal/tailwind.config.js +23 -0
  187. data/spec/internal/vendor/.keep +0 -0
  188. data/spec/internal/yarn.lock +824 -0
  189. data/spec/rails_helper.rb +62 -0
  190. data/spec/spec_helper.rb +138 -0
  191. data/spec/support/active_admin_helpers.rb +17 -0
  192. data/spec/support/capybara.rb +8 -0
  193. data/spec/support/models.rb +11 -0
  194. data/spec/support/pluck_polyfill.rb +12 -0
  195. data/spec/support/reset_settings.rb +5 -0
  196. metadata +497 -0
@@ -0,0 +1,438 @@
1
+ # Tailwind CSS v3 to v4 Upgrade Guide - Enhanced Edition
2
+
3
+ This enhanced guide focuses on migrating from Tailwind CSS v3 to v4, with special attention to form controls, select elements, and component styling.
4
+
5
+ ## Table of Contents
6
+ 1. [Quick Start](#quick-start)
7
+ 2. [Core Breaking Changes](#core-breaking-changes)
8
+ 3. [Form and Input Styling Changes](#form-and-input-styling-changes)
9
+ 4. [Select Element Changes](#select-element-changes)
10
+ 5. [Component Migration Guide](#component-migration-guide)
11
+ 6. [Tom Select & Custom Selects](#tom-select--custom-selects)
12
+ 7. [Migration Checklist](#migration-checklist)
13
+
14
+ ## Quick Start
15
+
16
+ ### Automated Upgrade
17
+ ```bash
18
+ # Use the official upgrade tool (requires Node.js 20+)
19
+ $ npx @tailwindcss/upgrade
20
+ ```
21
+
22
+ ### Manual Installation
23
+
24
+ #### PostCSS Setup
25
+ ```js
26
+ // postcss.config.mjs
27
+ export default {
28
+ plugins: {
29
+ // Remove these v3 plugins
30
+ // "postcss-import": {},
31
+ // tailwindcss: {},
32
+ // autoprefixer: {},
33
+
34
+ // Add v4 plugin
35
+ "@tailwindcss/postcss": {},
36
+ },
37
+ };
38
+ ```
39
+
40
+ #### Vite Setup (Recommended)
41
+ ```ts
42
+ // vite.config.ts
43
+ import { defineConfig } from "vite";
44
+ import tailwindcss from "@tailwindcss/vite";
45
+
46
+ export default defineConfig({
47
+ plugins: [tailwindcss()],
48
+ });
49
+ ```
50
+
51
+ #### CSS Import Change
52
+ ```css
53
+ /* v3 */
54
+ @tailwind base;
55
+ @tailwind components;
56
+ @tailwind utilities;
57
+
58
+ /* v4 */
59
+ @import "tailwindcss";
60
+ ```
61
+
62
+ ## Core Breaking Changes
63
+
64
+ ### Browser Requirements
65
+ - **Minimum versions**: Safari 16.4+, Chrome 111+, Firefox 128+
66
+ - Uses modern CSS features: `@property`, `color-mix()`, cascade layers
67
+ - No fallback for older browsers
68
+
69
+ ### Configuration Migration
70
+
71
+ #### v3: JavaScript Config
72
+ ```js
73
+ // tailwind.config.js (v3)
74
+ module.exports = {
75
+ content: ['./src/**/*.{html,js}'],
76
+ theme: {
77
+ extend: {
78
+ colors: {
79
+ brand: '#1a73e8',
80
+ },
81
+ },
82
+ },
83
+ plugins: [require('@tailwindcss/forms')],
84
+ }
85
+ ```
86
+
87
+ #### v4: CSS-First Config
88
+ ```css
89
+ /* app.css (v4) */
90
+ @import "tailwindcss";
91
+
92
+ @theme {
93
+ --color-brand: #1a73e8;
94
+ --font-display: "Inter", "sans-serif";
95
+ --breakpoint-3xl: 120rem;
96
+ }
97
+
98
+ /* Automatic content detection - no config needed! */
99
+ ```
100
+
101
+ ### Renamed Utilities
102
+
103
+ | v3 | v4 | Notes |
104
+ |---|---|-------|
105
+ | `shadow-sm` | `shadow-xs` | |
106
+ | `shadow` | `shadow-sm` | |
107
+ | `rounded-sm` | `rounded-xs` | |
108
+ | `rounded` | `rounded-sm` | |
109
+ | `outline-none` | `outline-hidden` | Invisible outline for a11y |
110
+ | `ring` | `ring-3` | Default width changed |
111
+
112
+ ## Form and Input Styling Changes
113
+
114
+ ### Default Border Colors
115
+ ```css
116
+ /* v3: gray-200 by default */
117
+ .border { border-color: rgb(229 231 235); }
118
+
119
+ /* v4: currentColor by default */
120
+ .border { border-color: currentColor; }
121
+
122
+ /* Fix: Always specify border color */
123
+ <input class="border border-gray-200" />
124
+
125
+ /* Or add global override */
126
+ @layer base {
127
+ *,
128
+ ::after,
129
+ ::before,
130
+ ::backdrop,
131
+ ::file-selector-button {
132
+ border-color: var(--color-gray-200, currentColor);
133
+ }
134
+ }
135
+ ```
136
+
137
+ ### Placeholder Colors
138
+ ```css
139
+ /* v3: gray-400 by default */
140
+ input::placeholder { color: rgb(156 163 175); }
141
+
142
+ /* v4: 50% opacity of text color */
143
+ input::placeholder { color: color-mix(in srgb, currentColor 50%, transparent); }
144
+
145
+ /* Restore v3 behavior if needed */
146
+ @layer base {
147
+ input::placeholder,
148
+ textarea::placeholder {
149
+ color: var(--color-gray-400);
150
+ }
151
+ }
152
+ ```
153
+
154
+ ### Button Cursor Changes
155
+ ```css
156
+ /* v3: pointer cursor */
157
+ button { cursor: pointer; }
158
+
159
+ /* v4: default cursor (browser default) */
160
+ button { cursor: default; }
161
+
162
+ /* Restore pointer cursor */
163
+ @layer base {
164
+ button:not(:disabled),
165
+ [role="button"]:not(:disabled) {
166
+ cursor: pointer;
167
+ }
168
+ }
169
+ ```
170
+
171
+ ### New Form Utilities in v4
172
+
173
+ #### Field Sizing
174
+ ```html
175
+ <!-- Auto-resize textareas without JavaScript -->
176
+ <textarea class="field-sizing-content">
177
+ Content grows with text
178
+ </textarea>
179
+
180
+ <!-- Fixed size (default behavior) -->
181
+ <textarea class="field-sizing-fixed w-full">
182
+ Fixed width textarea
183
+ </textarea>
184
+ ```
185
+
186
+ #### Accent Color
187
+ ```html
188
+ <!-- Custom checkbox/radio colors -->
189
+ <input type="checkbox" class="accent-blue-500" />
190
+ <input type="radio" class="accent-purple-500" />
191
+
192
+ <!-- With opacity modifier -->
193
+ <input type="checkbox" class="accent-green-500/75" />
194
+ ```
195
+
196
+ ## Select Element Changes
197
+
198
+ ### Native Select Styling
199
+
200
+ #### v3 Approach
201
+ ```html
202
+ <!-- v3: Required forms plugin or custom styles -->
203
+ <select class="form-select rounded-md border-gray-300">
204
+ <option>Option 1</option>
205
+ </select>
206
+ ```
207
+
208
+ #### v4 Approach
209
+ ```html
210
+ <!-- v4: Style with utilities directly -->
211
+ <select class="rounded-sm border border-gray-300 bg-white px-3 py-2">
212
+ <option>Option 1</option>
213
+ </select>
214
+
215
+ <!-- Remove default appearance for custom styling -->
216
+ <div class="relative">
217
+ <select class="appearance-none rounded-sm border border-gray-300 bg-white pl-3 pr-10 py-2">
218
+ <option>Option 1</option>
219
+ </select>
220
+ <div class="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2">
221
+ <svg class="h-5 w-5 text-gray-400"><!-- chevron icon --></svg>
222
+ </div>
223
+ </div>
224
+ ```
225
+
226
+ ### Forms Plugin Changes
227
+
228
+ The `@tailwindcss/forms` plugin approach has changed in v4:
229
+
230
+ ```css
231
+ /* v3: Auto-applied with plugin */
232
+ /* @tailwindcss/forms would style all inputs automatically */
233
+
234
+ /* v4: Explicit utility classes */
235
+ /* More control, less magic */
236
+ ```
237
+
238
+ ## Component Migration Guide
239
+
240
+ ### Card/Panel Component
241
+
242
+ #### v3
243
+ ```html
244
+ <div class="shadow rounded bg-white p-4">
245
+ <h3 class="text-lg font-semibold">Card Title</h3>
246
+ <p class="text-gray-600">Card content</p>
247
+ </div>
248
+ ```
249
+
250
+ #### v4
251
+ ```html
252
+ <div class="shadow-sm rounded-sm bg-white p-4">
253
+ <h3 class="text-lg font-semibold">Card Title</h3>
254
+ <p class="text-gray-600">Card content</p>
255
+ </div>
256
+ ```
257
+
258
+ ### Form Component
259
+
260
+ #### v3
261
+ ```html
262
+ <form class="space-y-4">
263
+ <div>
264
+ <label class="block text-sm font-medium text-gray-700">
265
+ Name
266
+ </label>
267
+ <input type="text"
268
+ class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500">
269
+ </div>
270
+ <button class="rounded bg-blue-500 px-4 py-2 text-white hover:bg-blue-600">
271
+ Submit
272
+ </button>
273
+ </form>
274
+ ```
275
+
276
+ #### v4
277
+ ```html
278
+ <form class="flex flex-col gap-4">
279
+ <div>
280
+ <label class="block text-sm font-medium text-gray-700">
281
+ Name
282
+ </label>
283
+ <input type="text"
284
+ class="mt-1 block w-full rounded-sm border border-gray-300 shadow-xs focus:border-indigo-500 focus:ring-3 focus:ring-indigo-500">
285
+ </div>
286
+ <button class="rounded-sm bg-blue-500 px-4 py-2 text-white hover:bg-blue-600 cursor-pointer">
287
+ Submit
288
+ </button>
289
+ </form>
290
+ ```
291
+
292
+ ## Tom Select & Custom Selects
293
+
294
+ ### Tom Select with Tailwind v4
295
+
296
+ ```css
297
+ /* tom-select-tailwind.css for v4 */
298
+ @layer components {
299
+ .ts-wrapper {
300
+ @apply relative;
301
+ }
302
+
303
+ .ts-control {
304
+ @apply flex flex-wrap items-center rounded-sm border border-gray-300 bg-white px-3 py-2;
305
+ @apply focus-within:border-blue-500 focus-within:ring-3 focus-within:ring-blue-500;
306
+ }
307
+
308
+ .ts-control input {
309
+ @apply flex-1 border-0 bg-transparent p-0 outline-hidden;
310
+ }
311
+
312
+ .ts-dropdown {
313
+ @apply absolute z-50 mt-1 w-full rounded-sm border border-gray-200 bg-white shadow-sm;
314
+ }
315
+
316
+ .ts-dropdown .option {
317
+ @apply cursor-pointer px-3 py-2 hover:bg-gray-100;
318
+ }
319
+
320
+ .ts-dropdown .option.active {
321
+ @apply bg-blue-50 text-blue-700;
322
+ }
323
+ }
324
+ ```
325
+
326
+ ### Select2 to Tom Select Migration
327
+
328
+ | Select2 Class | Tom Select Class | Purpose |
329
+ |--------------|------------------|---------|
330
+ | `.select2-container` | `.ts-wrapper` | Main container |
331
+ | `.select2-selection` | `.ts-control` | Selected items display |
332
+ | `.select2-dropdown` | `.ts-dropdown` | Dropdown container |
333
+ | `.select2-results__option` | `.ts-dropdown .option` | Dropdown options |
334
+ | `.select2-search__field` | `.ts-control input` | Search input |
335
+
336
+ ## Migration Checklist
337
+
338
+ ### Pre-Migration
339
+ - [ ] Verify Node.js 20+ is installed
340
+ - [ ] Check browser support requirements
341
+ - [ ] Backup current configuration
342
+ - [ ] Review custom components for breaking changes
343
+
344
+ ### Core Changes
345
+ - [ ] Run upgrade tool or manually update dependencies
346
+ - [ ] Convert `@tailwind` directives to `@import "tailwindcss"`
347
+ - [ ] Migrate JavaScript config to CSS `@theme` block
348
+ - [ ] Update PostCSS or switch to Vite plugin
349
+
350
+ ### Utility Updates
351
+ - [ ] Replace `shadow` → `shadow-sm`, `shadow-sm` → `shadow-xs`
352
+ - [ ] Replace `rounded` → `rounded-sm`, `rounded-sm` → `rounded-xs`
353
+ - [ ] Replace `outline-none` → `outline-hidden`
354
+ - [ ] Replace `ring` → `ring-3`
355
+ - [ ] Update `space-y-*` to `flex flex-col gap-*` where needed
356
+
357
+ ### Form Styling
358
+ - [ ] Add explicit border colors to all border utilities
359
+ - [ ] Review placeholder text colors
360
+ - [ ] Add `cursor-pointer` to buttons if needed
361
+ - [ ] Update select elements with explicit styles
362
+ - [ ] Test form components with new utilities
363
+
364
+ ### Component Libraries
365
+ - [ ] Update Tom Select styles for v4 utilities
366
+ - [ ] Migrate Select2 to Tom Select if applicable
367
+ - [ ] Test all custom dropdowns and selects
368
+ - [ ] Verify third-party component compatibility
369
+
370
+ ### Testing
371
+ - [ ] Test in all target browsers
372
+ - [ ] Verify responsive designs work correctly
373
+ - [ ] Check dark mode if implemented
374
+ - [ ] Validate accessibility features
375
+ - [ ] Run visual regression tests
376
+
377
+ ### Post-Migration
378
+ - [ ] Update documentation
379
+ - [ ] Train team on new v4 patterns
380
+ - [ ] Monitor for issues in production
381
+ - [ ] Document any custom workarounds
382
+
383
+ ## Additional Resources
384
+
385
+ - [Official Tailwind CSS v4.0 Blog Post](https://tailwindcss.com/blog/tailwindcss-v4)
386
+ - [Official Upgrade Guide](https://tailwindcss.com/docs/upgrade-guide)
387
+ - [v4.0 Release Notes](https://github.com/tailwindlabs/tailwindcss/releases/tag/v4.0.0)
388
+ - [Tom Select Documentation](https://tom-select.js.org/)
389
+ - [Modern CSS Features Used in v4](https://developer.mozilla.org/en-US/docs/Web/CSS)
390
+
391
+ ## Common Gotchas
392
+
393
+ 1. **CSS Variables in Media Queries**: The `theme()` function now uses CSS variable names
394
+ ```css
395
+ /* v3 */
396
+ @media (min-width: theme(screens.lg)) { }
397
+
398
+ /* v4 */
399
+ @media (min-width: theme(--breakpoint-lg)) { }
400
+ ```
401
+
402
+ 2. **Gradient Preservation**: Gradients now preserve all stops when overridden
403
+ ```html
404
+ <!-- v3: to-yellow-400 becomes transparent in dark mode -->
405
+ <div class="bg-gradient-to-r from-red-500 to-yellow-400 dark:from-blue-500"></div>
406
+
407
+ <!-- v4: Explicitly reset with via-none -->
408
+ <div class="bg-linear-to-r from-red-500 via-orange-400 to-yellow-400 dark:via-none dark:from-blue-500 dark:to-teal-400"></div>
409
+ ```
410
+
411
+ 3. **Hover on Touch Devices**: `hover:` now only applies when device supports hover
412
+ ```css
413
+ /* v4: Add custom variant for old behavior */
414
+ @custom-variant hover (&:hover);
415
+ ```
416
+
417
+ 4. **Dynamic Values**: Many utilities now accept any value without configuration
418
+ ```html
419
+ <!-- v3: Required extending config -->
420
+ <div class="grid-cols-[arbitrary]">
421
+
422
+ <!-- v4: Works out of the box -->
423
+ <div class="grid-cols-15">
424
+ <div class="mt-17">
425
+ <div class="w-29">
426
+ ```
427
+
428
+ ## Summary
429
+
430
+ Tailwind CSS v4 brings significant improvements in performance, developer experience, and modern CSS support. While there are breaking changes, the upgrade tool handles most migrations automatically. The key changes for forms and selects are:
431
+
432
+ 1. More explicit styling requirements (no magic defaults)
433
+ 2. Better performance with native CSS features
434
+ 3. Improved customization through CSS variables
435
+ 4. Enhanced form utilities like `field-sizing` and `accent-color`
436
+ 5. Simpler configuration without JavaScript
437
+
438
+ The migration effort is worth it for the performance gains (5x faster builds, 100x faster incremental builds) and the improved developer experience with automatic content detection and CSS-first configuration.