Do not migrate variant = 'outline' during upgrades (#18922)

This PR improves the upgrade tool for shadcn/ui projects where the
`variant = "outline"` is incorrectly migrated to `variant =
"outline-solid"`.

This PR also handles a few more cases:

```ts
// As default argument
function Button({ variant = "outline", ...props }: ButtonProps) { }

// With different kinds of quotes (single, double, backticks)
function Button({ variant = 'outline', ...props }: ButtonProps) { }

// Regardless of whitespace
function Button({ variant="outline", ...props }: ButtonProps) { }

// In JSX
<Button variant="outline" />

// With different quotes and using JavaScript expressions
<Button variant={'outline'} />

// As an object property
buttonVariants({ variant: "outline" })
```
This commit is contained in:
Robin Malfait 2025-09-12 11:20:18 +02:00 • committed by GitHub
parent d1fd645beb
commit 65bad11380
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 16 additions and 0 deletions

View file

@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Do not generate `grid-column` utilities when configuring `grid-column-start` or `grid-column-end` ([#18907](https://github.com/tailwindlabs/tailwindcss/pull/18907))
- Do not generate `grid-row` utilities when configuring `grid-row-start` or `grid-row-end` ([#18907](https://github.com/tailwindlabs/tailwindcss/pull/18907))
- Prevent duplicate CSS when overwriting a static utility with a theme key ([#18056](https://github.com/tailwindlabs/tailwindcss/pull/18056))
- Do not migrate `variant = 'outline'` during upgrades ([#18922](https://github.com/tailwindlabs/tailwindcss/pull/18922))
## [4.1.13] - 2025-09-03

View file

@ -91,6 +91,18 @@ describe('is-safe-migration', async () => {
[`function foo(blur, foo)`, 'blur'],
[`function foo(blur,foo)`, 'blur'],
// shadcn/ui variants
[`<Button variant="outline" />`, 'outline'],
[`<Button variant='outline' />`, 'outline'],
[`<Button variant={"outline"} />`, 'outline'],
[`<Button variant={'outline'} />`, 'outline'],
[`function Button({ variant = "outline" }) {}`, 'outline'],
[`function Button({ variant = 'outline' }) {}`, 'outline'],
[`function Button({ variant="outline" }) {}`, 'outline'],
[`function Button({ variant='outline' }) {}`, 'outline'],
[`Button({ variant: "outline" })`, 'outline'],
[`Button({ variant: 'outline' })`, 'outline'],
])('does not replace classes in invalid positions #%#', async (example, candidate) => {
expect(
await migrateCandidate(designSystem, {}, candidate, {

View file

@ -18,6 +18,9 @@ const CONDITIONAL_TEMPLATE_SYNTAX = [
/x-if=['"]$/,
/x-show=['"]$/,
/wire:[^\s]*?$/,
// shadcn/ui variants
/variant\s*[:=]\s*\{?['"`]$/,
]
const NEXT_PLACEHOLDER_PROP = /placeholder=\{?['"`]$/
const VUE_3_EMIT = /\b\$?emit\(['"`]$/