Initial commit

This commit is contained in:
Zhongwei Li
2025-11-29 18:22:33 +08:00
commit 735ed8d1d7
19 changed files with 5548 additions and 0 deletions

View File

@@ -0,0 +1,495 @@
---
name: migrating-from-v3
description: Migrate from Tailwind CSS v3 to v4 including configuration migration (JS to CSS), utility renames, opacity changes, and color system updates. Use when upgrading existing projects to v4.
allowed-tools: Read, Write, Edit, Grep, Glob, Bash
---
# Migrating from v3 to v4
## Purpose
Migrate existing Tailwind CSS v3 projects to v4's CSS-first configuration, updated utilities, and modern color system.
## Automated Migration Tool
Tailwind provides an automated upgrade tool:
```bash
npx @tailwindcss/upgrade@next
```
**Requirements:**
- Node.js 20 or higher
- Run in a new git branch
- Review all changes manually
- Test thoroughly
**What it handles:**
- Updates dependencies
- Migrates configuration to CSS
- Updates template files
- Converts utility class names
**What it doesn't handle:**
- Custom plugins (manual migration needed)
- Complex configuration logic
- Dynamic class generation
## Configuration Migration
### JavaScript Config → CSS Theme
**v3 (tailwind.config.js):**
```javascript
module.exports = {
content: ['./src/**/*.{html,js}'],
theme: {
extend: {
colors: {
brand: '#3b82f6',
accent: '#a855f7',
},
fontFamily: {
sans: ['Inter', 'sans-serif'],
display: ['Satoshi', 'sans-serif'],
},
spacing: {
18: '4.5rem',
72: '18rem',
},
borderRadius: {
'4xl': '2rem',
},
},
},
plugins: [],
};
```
**v4 (CSS @theme):**
```css
@import 'tailwindcss';
@theme {
--font-sans: 'Inter', sans-serif;
--font-display: 'Satoshi', sans-serif;
--color-brand: oklch(0.65 0.25 270);
--color-accent: oklch(0.65 0.25 320);
--spacing-18: 4.5rem;
--spacing-72: 18rem;
--radius-4xl: 2rem;
}
```
### Content Detection
**v3:**
```javascript
content: ['./src/**/*.{html,js,jsx,ts,tsx}']
```
**v4:**
Automatic detection. No configuration needed.
**Manual control (if needed):**
```css
@import 'tailwindcss';
@source "../packages/ui";
@source not "./legacy";
```
### Import Syntax Changes
**v3:**
```css
@tailwind base;
@tailwind components;
@tailwind utilities;
```
**v4:**
```css
@import 'tailwindcss';
```
## Utility Class Renames
### Opacity Modifiers
**v3:**
```html
<div class="bg-black bg-opacity-50"></div>
<div class="text-gray-900 text-opacity-75"></div>
<div class="border-blue-500 border-opacity-60"></div>
```
**v4:**
```html
<div class="bg-black/50"></div>
<div class="text-gray-900/75"></div>
<div class="border-blue-500/60"></div>
```
**Migration pattern:**
- `bg-opacity-{value}``bg-{color}/{value}`
- `text-opacity-{value}``text-{color}/{value}`
- `border-opacity-{value}``border-{color}/{value}`
### Flex Utilities
**v3:**
```html
<div class="flex-shrink-0"></div>
<div class="flex-shrink"></div>
<div class="flex-grow-0"></div>
<div class="flex-grow"></div>
```
**v4:**
```html
<div class="shrink-0"></div>
<div class="shrink"></div>
<div class="grow-0"></div>
<div class="grow"></div>
```
**Migration pattern:**
- `flex-shrink-*``shrink-*`
- `flex-grow-*``grow-*`
### Shadow Utilities
**v3:**
```html
<div class="shadow-sm"></div>
```
**v4:**
```html
<div class="shadow-xs"></div>
```
**Migration:**
- `shadow-sm``shadow-xs`
- All other shadow utilities remain the same
### Ring Width
**v3 default:**
```html
<input class="ring" />
```
Ring width: 3px
**v4 default:**
```html
<input class="ring" />
```
Ring width: 1px
**To keep v3 behavior:**
```html
<input class="ring-3" />
```
## Color System Changes
### Default Border and Ring Colors
**v3:**
```html
<div class="border"></div>
```
Border color: gray-200
**v4:**
```html
<div class="border"></div>
```
Border color: currentColor
**To keep v3 behavior:**
```html
<div class="border border-gray-200"></div>
```
### OkLCh Color Space
**v3 (RGB):**
```javascript
colors: {
brand: '#3b82f6',
}
```
**v4 (OkLCh):**
```css
@theme {
--color-brand: oklch(0.65 0.25 270);
}
```
Use conversion tool: https://oklch.com/
## PostCSS Configuration
### Plugin Changes
**v3:**
```javascript
module.exports = {
plugins: {
'tailwindcss': {},
'autoprefixer': {},
},
};
```
**v4:**
```javascript
export default {
plugins: {
'@tailwindcss/postcss': {},
},
};
```
No longer need `autoprefixer` or `postcss-import`.
### Vite Plugin
**v3:**
```javascript
import tailwindcss from 'tailwindcss';
import autoprefixer from 'autoprefixer';
export default defineConfig({
css: {
postcss: {
plugins: [tailwindcss(), autoprefixer()],
},
},
});
```
**v4:**
```javascript
import tailwindcss from '@tailwindcss/vite';
export default defineConfig({
plugins: [tailwindcss()],
});
```
## Preflight Changes
### Placeholder Colors
**v3:**
Placeholder text: gray-400
**v4:**
Placeholder text: currentColor at 50% opacity
**To keep v3 behavior:**
```css
@layer base {
::placeholder {
color: theme('colors.gray.400');
}
}
```
### Button Cursor
**v3:**
```css
button {
cursor: pointer;
}
```
**v4:**
```css
button {
cursor: default;
}
```
**To restore v3 behavior:**
```css
@layer base {
button {
cursor: pointer;
}
}
```
## Feature Additions
### Built-in Container Queries
**v3 (plugin required):**
```javascript
plugins: [require('@tailwindcss/container-queries')]
```
**v4 (built-in):**
No plugin needed. Use `@container` and `@{breakpoint}:` syntax.
### 3D Transforms
**v3:**
Not available
**v4:**
```html
<div class="transform-3d rotate-x-45 rotate-y-30 translate-z-12"></div>
```
### Starting Variant for Animations
**v3:**
Not available
**v4:**
```html
<div class="opacity-100 starting:opacity-0 transition-opacity"></div>
```
## Breaking Changes Checklist
- [ ] Update dependencies to v4
- [ ] Migrate tailwind.config.js to @theme
- [ ] Replace @tailwind directives with @import
- [ ] Update PostCSS configuration
- [ ] Convert opacity utilities (bg-opacity → bg-{color}/{value})
- [ ] Rename flex utilities (flex-shrink → shrink)
- [ ] Update shadow-sm to shadow-xs
- [ ] Add explicit border colors if using bare `border`
- [ ] Update ring-3 if expecting 3px default
- [ ] Convert hex colors to oklch()
- [ ] Remove container-queries plugin (now built-in)
- [ ] Test placeholder colors
- [ ] Test button cursor behavior
- [ ] Update arbitrary value syntax (spaces → underscores)
## Migration Strategy
### Phase 1: Preparation
1. Create new git branch
2. Ensure all changes committed
3. Run automated migration tool
4. Review generated changes
### Phase 2: Configuration
1. Convert tailwind.config.js to CSS @theme
2. Update PostCSS/Vite configuration
3. Replace @tailwind directives
4. Add @source if needed
### Phase 3: Utilities
1. Search and replace opacity modifiers
2. Rename flex utilities
3. Update shadow utilities
4. Add explicit border colors
5. Convert hex colors to oklch()
### Phase 4: Testing
1. Test all pages/components
2. Verify responsive behavior
3. Check dark mode
4. Test interactive states
5. Validate production build
### Phase 5: Cleanup
1. Remove unused dependencies
2. Delete tailwind.config.js
3. Update documentation
4. Commit changes
## Common Issues
### Styles Not Applying
Check:
1. CSS import: `@import "tailwindcss";`
2. PostCSS plugin: `@tailwindcss/postcss`
3. Vite plugin: `@tailwindcss/vite`
4. Template files not in .gitignore
### Class Names Not Working
Ensure:
1. Class names are complete strings
2. Not using dynamic concatenation
3. Using underscores for spaces in arbitrary values
### Colors Look Different
OkLCh uses different color space. Convert hex to oklch using:
https://oklch.com/
### Build Errors
Check:
1. Node.js version (20+)
2. Dependencies updated
3. PostCSS config using correct plugin
## See Also
- references/breaking-changes.md - Complete breaking changes list
- references/migration-checklist.md - Step-by-step migration guide

View File

@@ -0,0 +1,516 @@
# Complete Breaking Changes List
## Configuration System
### JavaScript → CSS Configuration
**Breaking:** No more `tailwind.config.js` file.
**v3:**
```javascript
module.exports = {
theme: {
extend: {
colors: { brand: '#3b82f6' },
},
},
};
```
**v4:**
```css
@theme {
--color-brand: oklch(0.65 0.25 270);
}
```
**Impact:** All theme customization moves to CSS.
### Content Detection
**Breaking:** No manual content array needed.
**v3:**
```javascript
content: ['./src/**/*.{html,js}']
```
**v4:**
Automatic detection. Manual control via `@source` if needed.
**Impact:** Simplified setup, but less explicit control.
## Import Directives
### @tailwind → @import
**Breaking:** Different import syntax.
**v3:**
```css
@tailwind base;
@tailwind components;
@tailwind utilities;
```
**v4:**
```css
@import 'tailwindcss';
```
**Impact:** All templates need updating.
## Utility Class Changes
### Opacity Modifiers Removed
**Breaking:** Separate opacity utilities removed.
**v3:**
```html
<div class="bg-black bg-opacity-50"></div>
<div class="text-gray-900 text-opacity-75"></div>
<div class="border-blue-500 border-opacity-60"></div>
<div class="ring-blue-500 ring-opacity-30"></div>
```
**v4:**
```html
<div class="bg-black/50"></div>
<div class="text-gray-900/75"></div>
<div class="border-blue-500/60"></div>
<div class="ring-blue-500/30"></div>
```
**Impact:** Search and replace needed across entire codebase.
**Automated fix:**
```bash
find . -name "*.html" -o -name "*.jsx" -o -name "*.tsx" | xargs sed -i '' 's/bg-\([a-z-]*\) bg-opacity-\([0-9]*\)/bg-\1\/\2/g'
```
### Flex Utility Renames
**Breaking:** Utility names changed.
**v3:**
```html
<div class="flex-shrink-0"></div>
<div class="flex-shrink"></div>
<div class="flex-grow-0"></div>
<div class="flex-grow"></div>
```
**v4:**
```html
<div class="shrink-0"></div>
<div class="shrink"></div>
<div class="grow-0"></div>
<div class="grow"></div>
```
**Impact:** All flex utilities need renaming.
### Shadow Utility Rename
**Breaking:** Smallest shadow renamed.
**v3:**
```html
<div class="shadow-sm"></div>
```
**v4:**
```html
<div class="shadow-xs"></div>
```
**Impact:** Update all uses of `shadow-sm`.
### Ring Default Width
**Breaking:** Default ring width changed.
**v3:**
```html
<input class="ring" />
```
Ring width: 3px
**v4:**
```html
<input class="ring" />
```
Ring width: 1px
**Fix for v3 behavior:**
```html
<input class="ring-3" />
```
**Impact:** All bare `ring` utilities render thinner.
## Color System
### Default Border Color
**Breaking:** Border color changed from gray to currentColor.
**v3:**
```html
<div class="border"></div>
```
Border color: gray-200
**v4:**
```html
<div class="border"></div>
```
Border color: currentColor (inherits text color)
**Fix for v3 behavior:**
```html
<div class="border border-gray-200"></div>
```
**Impact:** Borders may appear different colors.
### Default Ring Color
**Breaking:** Ring color changed from blue to currentColor.
**v3:**
```html
<input class="ring" />
```
Ring color: blue-500
**v4:**
```html
<input class="ring" />
```
Ring color: currentColor
**Fix for v3 behavior:**
```html
<input class="ring ring-blue-500" />
```
**Impact:** Rings inherit text color.
### OkLCh Color Space
**Breaking:** Color values use OkLCh instead of RGB.
**v3:**
```javascript
colors: {
brand: '#3b82f6',
}
```
**v4:**
```css
@theme {
--color-brand: oklch(0.65 0.25 270);
}
```
**Impact:** Custom colors need conversion. Colors may look slightly different (more vivid on modern displays).
## PostCSS Changes
### Plugin Name
**Breaking:** Different PostCSS plugin.
**v3:**
```javascript
plugins: {
'tailwindcss': {},
'autoprefixer': {},
}
```
**v4:**
```javascript
plugins: {
'@tailwindcss/postcss': {},
}
```
**Impact:** PostCSS config needs updating. Remove `autoprefixer` and `postcss-import` (no longer needed).
## Preflight Changes
### Placeholder Color
**Breaking:** Placeholder text color changed.
**v3:**
```css
::placeholder {
color: theme('colors.gray.400');
}
```
**v4:**
```css
::placeholder {
color: currentColor;
opacity: 0.5;
}
```
**Impact:** Placeholders inherit text color at 50% opacity.
**Fix for v3 behavior:**
```css
@layer base {
::placeholder {
color: theme('colors.gray.400');
opacity: 1;
}
}
```
### Button Cursor
**Breaking:** Button cursor changed.
**v3:**
```css
button {
cursor: pointer;
}
```
**v4:**
```css
button {
cursor: default;
}
```
**Impact:** Buttons no longer show pointer cursor by default.
**Fix for v3 behavior:**
```css
@layer base {
button {
cursor: pointer;
}
}
```
Or add explicit classes:
```html
<button class="cursor-pointer">Click me</button>
```
## Arbitrary Values
### Space Handling
**Breaking:** Spaces in arbitrary values use underscores.
**v3:**
```html
<div class="grid-cols-[1fr,500px,2fr]"></div>
```
**v4:**
```html
<div class="grid-cols-[1fr_500px_2fr]"></div>
```
**Impact:** All arbitrary values with commas need updating.
## Browser Support
### Minimum Versions
**Breaking:** Dropped support for older browsers.
**v3:**
- IE 11+
- Safari 10+
- Chrome 60+
**v4:**
- Safari 16.4+
- Chrome 111+
- Firefox 128+
**Impact:** Projects requiring older browser support cannot upgrade.
## CSS Preprocessors
### No Sass/Less/Stylus Support
**Breaking:** Incompatible with CSS preprocessors.
**v3:**
Can use with Sass, Less, Stylus
**v4:**
Cannot use CSS preprocessors (Tailwind functions as preprocessing layer)
**Impact:** Remove CSS preprocessors from build pipeline.
## Plugin System
### Plugin API Changes
**Breaking:** Plugin API completely rewritten.
**v3 plugin:**
```javascript
const plugin = require('tailwindcss/plugin');
module.exports = plugin(function ({ addUtilities, theme }) {
addUtilities({
'.content-auto': {
'content-visibility': 'auto',
},
});
});
```
**v4 equivalent:**
```css
@utility content-auto {
content-visibility: auto;
}
```
**Impact:** All custom plugins need manual rewrite.
## @apply Restrictions
### Limited @apply Support
**Breaking:** @apply only works for small subset of utilities.
**v3:**
```css
.btn {
@apply px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700;
}
```
**v4:**
@apply has limited support. Use @utility instead:
```css
@utility btn {
padding: var(--spacing-2) var(--spacing-4);
background: var(--color-blue-600);
color: var(--color-white);
border-radius: var(--radius-md);
}
```
**Impact:** Many @apply patterns need refactoring.
## Mobile Hover Behavior
### Hover on Touch Devices
**Breaking:** Hover styles don't apply on touch devices.
**v3:**
Hover styles triggered on tap
**v4:**
Hover styles only on devices supporting hover
**Impact:** Touch devices won't show hover states (improves UX).
## Container Plugin
### Built-in Container Queries
**Breaking:** Container queries plugin no longer needed.
**v3:**
```javascript
plugins: [require('@tailwindcss/container-queries')]
```
**v4:**
Built-in. No plugin needed.
**Impact:** Remove plugin dependency. Syntax remains same.
## Summary Table
| Change | v3 | v4 | Impact |
|--------|----|----|--------|
| Config | tailwind.config.js | @theme | High |
| Import | @tailwind | @import | High |
| Opacity | bg-opacity-50 | bg-{color}/50 | High |
| Flex | flex-shrink | shrink | Medium |
| Shadow | shadow-sm | shadow-xs | Low |
| Ring width | 3px | 1px | Medium |
| Border color | gray-200 | currentColor | Medium |
| Color space | RGB | OkLCh | Medium |
| PostCSS | tailwindcss | @tailwindcss/postcss | High |
| Placeholder | gray-400 | currentColor/50 | Low |
| Button cursor | pointer | default | Low |
| Browsers | IE 11+ | Safari 16.4+ | High |
| Preprocessors | Supported | Not supported | High |
| Plugins | JS API | CSS @utility | High |

View File

@@ -0,0 +1,469 @@
# Step-by-Step Migration Checklist
## Pre-Migration
- [ ] Create new git branch: `git checkout -b upgrade-tailwind-v4`
- [ ] Commit all current changes
- [ ] Document current Tailwind version
- [ ] Backup tailwind.config.js
- [ ] Review custom plugins in use
- [ ] Check browser support requirements
- [ ] Note any CSS preprocessor usage
## Phase 1: Dependencies
### Update Package Dependencies
- [ ] Update Tailwind CSS to v4
```bash
npm install tailwindcss@next
```
- [ ] Install appropriate build tool plugin
**For Vite:**
```bash
npm install @tailwindcss/vite
```
**For PostCSS:**
```bash
npm install @tailwindcss/postcss
```
**For CLI:**
```bash
npm install @tailwindcss/cli
```
- [ ] Remove deprecated dependencies
```bash
npm uninstall autoprefixer postcss-import @tailwindcss/container-queries
```
- [ ] Update package.json
```json
{
"dependencies": {
"tailwindcss": "^4.0.0"
},
"devDependencies": {
"@tailwindcss/vite": "^4.0.0"
}
}
```
## Phase 2: Build Configuration
### Vite Configuration
- [ ] Update vite.config.js
```javascript
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import tailwindcss from '@tailwindcss/vite';
export default defineConfig({
plugins: [react(), tailwindcss()],
});
```
- [ ] Remove PostCSS config if using Vite plugin
- [ ] Test build: `npm run build`
### PostCSS Configuration
- [ ] Update postcss.config.js
```javascript
export default {
plugins: {
'@tailwindcss/postcss': {},
},
};
```
- [ ] Remove autoprefixer and postcss-import
- [ ] Test build: `npm run build`
### Next.js Configuration
- [ ] Ensure postcss.config.js exists
```javascript
export default {
plugins: {
'@tailwindcss/postcss': {},
},
};
```
- [ ] Test: `npm run dev`
## Phase 3: CSS Configuration
### Migrate tailwind.config.js to @theme
- [ ] Open tailwind.config.js
- [ ] Open main CSS file (e.g., src/index.css)
- [ ] Replace @tailwind directives
**Old:**
```css
@tailwind base;
@tailwind components;
@tailwind utilities;
```
**New:**
```css
@import 'tailwindcss';
```
- [ ] Convert theme.extend to @theme
**Example conversion:**
**tailwind.config.js:**
```javascript
module.exports = {
theme: {
extend: {
colors: {
brand: '#3b82f6',
accent: '#a855f7',
},
fontFamily: {
sans: ['Inter', 'sans-serif'],
},
spacing: {
18: '4.5rem',
},
},
},
};
```
**CSS:**
```css
@import 'tailwindcss';
@theme {
--font-sans: 'Inter', sans-serif;
--color-brand: oklch(0.65 0.25 270);
--color-accent: oklch(0.65 0.25 320);
--spacing-18: 4.5rem;
}
```
- [ ] Convert hex colors to oklch() using https://oklch.com/
- [ ] Test: colors render correctly
### Content Detection
- [ ] Remove content array (automatic detection)
- [ ] Add @source directives if needed
```css
@source "../packages/ui";
@source not "./legacy";
```
- [ ] Verify all template files are detected
- [ ] Check .gitignore excludes node_modules
### Custom CSS
- [ ] Migrate @layer components to CSS
```css
@layer components {
.btn {
padding: var(--spacing-2) var(--spacing-4);
background: var(--color-blue-600);
border-radius: var(--radius-md);
}
}
```
- [ ] Convert @layer utilities to @utility
**Old:**
```css
@layer utilities {
.content-auto {
content-visibility: auto;
}
}
```
**New:**
```css
@utility content-auto {
content-visibility: auto;
}
```
## Phase 4: Utility Class Updates
### Opacity Modifiers
- [ ] Search for opacity utilities
```bash
grep -r "bg-opacity-" src/
grep -r "text-opacity-" src/
grep -r "border-opacity-" src/
grep -r "ring-opacity-" src/
```
- [ ] Replace with slash syntax
**Find and replace:**
- `bg-{color} bg-opacity-{value}``bg-{color}/{value}`
- `text-{color} text-opacity-{value}``text-{color}/{value}`
- `border-{color} border-opacity-{value}``border-{color}/{value}`
**Example:**
```html
<div class="bg-black bg-opacity-50"></div>
<div class="bg-black/50"></div>
```
- [ ] Test: opacity values render correctly
### Flex Utilities
- [ ] Search for flex utilities
```bash
grep -r "flex-shrink" src/
grep -r "flex-grow" src/
```
- [ ] Replace with new names
**Find and replace:**
- `flex-shrink-0``shrink-0`
- `flex-shrink``shrink`
- `flex-grow-0``grow-0`
- `flex-grow``grow`
### Shadow Utilities
- [ ] Search for shadow-sm
```bash
grep -r "shadow-sm" src/
```
- [ ] Replace with shadow-xs
```
shadow-sm → shadow-xs
```
### Ring Utilities
- [ ] Search for bare `ring` class
```bash
grep -r 'class="[^"]*ring[^-"]' src/
```
- [ ] Add explicit width if expecting 3px default
```html
<input class="ring" />
<input class="ring-3" />
```
### Border Utilities
- [ ] Search for bare `border` class
```bash
grep -r 'class="[^"]*border[^-"]' src/
```
- [ ] Add explicit color if expecting gray
```html
<div class="border"></div>
<div class="border border-gray-200"></div>
```
## Phase 5: Arbitrary Values
### Space Handling
- [ ] Search for arbitrary values with commas
```bash
grep -r "grid-cols-\[.*,.*\]" src/
```
- [ ] Replace commas with underscores
```html
<div class="grid-cols-[1fr,500px,2fr]"></div>
<div class="grid-cols-[1fr_500px_2fr]"></div>
```
## Phase 6: Testing
### Build Tests
- [ ] Run development build: `npm run dev`
- [ ] Check console for errors
- [ ] Verify styles load
- [ ] Run production build: `npm run build`
- [ ] Check build output
- [ ] Test production bundle
### Visual Testing
- [ ] Test home page
- [ ] Test all major pages
- [ ] Check responsive breakpoints
- [ ] Verify dark mode (if used)
- [ ] Test hover states
- [ ] Test focus states
- [ ] Check form inputs
- [ ] Verify buttons
- [ ] Check modals/overlays
- [ ] Test animations
### Component Testing
- [ ] Test each component in isolation
- [ ] Verify colors match
- [ ] Check spacing
- [ ] Test typography
- [ ] Verify shadows and borders
- [ ] Check opacity values
### Browser Testing
- [ ] Safari 16.4+
- [ ] Chrome 111+
- [ ] Firefox 128+
- [ ] Mobile Safari
- [ ] Mobile Chrome
## Phase 7: Cleanup
### Remove Old Files
- [ ] Delete tailwind.config.js
- [ ] Remove old PostCSS config (if using Vite plugin)
- [ ] Clean node_modules
```bash
rm -rf node_modules package-lock.json
npm install
```
### Update Documentation
- [ ] Update README.md
- [ ] Document new setup process
- [ ] Update contribution guide
- [ ] Note new browser requirements
### Code Review
- [ ] Review all changed files
- [ ] Check for missed migrations
- [ ] Verify no broken styles
- [ ] Run linter: `npm run lint`
- [ ] Run tests: `npm test`
## Phase 8: Deploy
### Pre-Deploy Checks
- [ ] All tests passing
- [ ] No console errors
- [ ] Production build successful
- [ ] Visual regression tests pass
- [ ] Performance metrics acceptable
### Deploy
- [ ] Merge PR to main
- [ ] Deploy to staging
- [ ] Test staging environment
- [ ] Deploy to production
- [ ] Monitor for issues
### Post-Deploy
- [ ] Verify production site
- [ ] Check analytics for errors
- [ ] Monitor performance
- [ ] Gather feedback
## Common Issues Checklist
- [ ] Styles not applying → Check @import syntax
- [ ] Build errors → Verify PostCSS/Vite config
- [ ] Colors different → Convert hex to oklch
- [ ] Borders wrong color → Add explicit border color
- [ ] Placeholders wrong → Check preflight changes
- [ ] Buttons wrong cursor → Add cursor-pointer
- [ ] Missing utilities → Check for typos
- [ ] Dark mode broken → Verify class strategy
## Rollback Plan
If migration fails:
- [ ] Revert git branch: `git checkout main`
- [ ] Delete branch: `git branch -D upgrade-tailwind-v4`
- [ ] Reinstall dependencies: `npm install`
- [ ] Document issues encountered
- [ ] Plan remediation
## Success Criteria
- [ ] All pages render correctly
- [ ] No console errors
- [ ] Production build successful
- [ ] All tests passing
- [ ] Performance maintained or improved
- [ ] No visual regressions
- [ ] Browser support verified
- [ ] Documentation updated
## Estimated Timeline
- Pre-migration: 1 hour
- Dependencies & build config: 1-2 hours
- CSS migration: 2-4 hours
- Utility updates: 4-8 hours
- Testing: 4-8 hours
- Cleanup & documentation: 1-2 hours
- Deploy: 1-2 hours
**Total: 14-27 hours** depending on project size