Fix inferring data type of border-[…] with multiple values (#17248)

This PR fixes an issue where arbitrary values such as
`border-[12px_4px]` were incorrectly producing `border-color` instead of
`border-width` values.

To solve it, I extended the `<line-width>` check to make sure that every
part of the value is a valid `<line-width>`.

In order for a `line-width` to be valid, every part should be one of:

1. A keyword: `thin`, `medium`, `thick`
2. A length: `12px`
3. A number: `0`

Fixes: #17221

# Test plan

1. Added test to verify this works
2. All existing tests pass
This commit is contained in:
Robin Malfait 2025-03-17 12:35:55 +01:00 • committed by GitHub
parent 1a88518d80
commit 448949318e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 193 additions and 1 deletions

View file

@ -21,6 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed
- Fix incorrect angle in `-bg-conic-*` utilities ([#17174](https://github.com/tailwindlabs/tailwindcss/pull/17174))
- Fix `border-[12px_4px]` being interpreted as a `border-color` instead of a `border-width` ([#17248](https://github.com/tailwindlabs/tailwindcss/pull/17248))
## [4.0.14] - 2025-03-13

View file

@ -30,11 +30,26 @@ exports[`border-* 1`] = `
border-width: 123px;
}
.border-\\[0_1\\] {
border-style: var(--tw-border-style);
border-width: 0 1px;
}
.border-\\[0_2px_0_2px\\] {
border-style: var(--tw-border-style);
border-width: 0 2px;
}
.border-\\[12px\\] {
border-style: var(--tw-border-style);
border-width: 12px;
}
.border-\\[12px_8px\\] {
border-style: var(--tw-border-style);
border-width: 12px 8px;
}
.border-\\[length\\:var\\(--my-width\\)\\], .border-\\[line-width\\:var\\(--my-width\\)\\] {
border-style: var(--tw-border-style);
border-width: var(--my-width);
@ -55,6 +70,11 @@ exports[`border-* 1`] = `
border-width: thin;
}
.border-\\[thin_2px\\] {
border-style: var(--tw-border-style);
border-width: thin 2px;
}
.border-\\[\\#0088cc\\] {
border-color: #08c;
}
@ -152,11 +172,26 @@ exports[`border-b-* 1`] = `
border-bottom-width: 123px;
}
.border-b-\\[0_1\\] {
border-bottom-style: var(--tw-border-style);
border-bottom-width: 0 1;
}
.border-b-\\[0_2px_0_2px\\] {
border-bottom-style: var(--tw-border-style);
border-bottom-width: 0 2px 0 2px;
}
.border-b-\\[12px\\] {
border-bottom-style: var(--tw-border-style);
border-bottom-width: 12px;
}
.border-b-\\[12px_8px\\] {
border-bottom-style: var(--tw-border-style);
border-bottom-width: 12px 8px;
}
.border-b-\\[length\\:var\\(--my-width\\)\\], .border-b-\\[line-width\\:var\\(--my-width\\)\\] {
border-bottom-style: var(--tw-border-style);
border-bottom-width: var(--my-width);
@ -177,6 +212,11 @@ exports[`border-b-* 1`] = `
border-bottom-width: thin;
}
.border-b-\\[thin_2px\\] {
border-bottom-style: var(--tw-border-style);
border-bottom-width: thin 2px;
}
.border-b-\\[\\#0088cc\\] {
border-bottom-color: #08c;
}
@ -274,11 +314,26 @@ exports[`border-e-* 1`] = `
border-inline-end-width: 123px;
}
.border-e-\\[0_1\\] {
border-inline-end-style: var(--tw-border-style);
border-inline-end-width: 0 1;
}
.border-e-\\[0_2px_0_2px\\] {
border-inline-end-style: var(--tw-border-style);
border-inline-end-width: 0 2px 0 2px;
}
.border-e-\\[12px\\] {
border-inline-end-style: var(--tw-border-style);
border-inline-end-width: 12px;
}
.border-e-\\[12px_8px\\] {
border-inline-end-style: var(--tw-border-style);
border-inline-end-width: 12px 8px;
}
.border-e-\\[length\\:var\\(--my-width\\)\\], .border-e-\\[line-width\\:var\\(--my-width\\)\\] {
border-inline-end-style: var(--tw-border-style);
border-inline-end-width: var(--my-width);
@ -299,6 +354,11 @@ exports[`border-e-* 1`] = `
border-inline-end-width: thin;
}
.border-e-\\[thin_2px\\] {
border-inline-end-style: var(--tw-border-style);
border-inline-end-width: thin 2px;
}
.border-e-\\[\\#0088cc\\] {
border-inline-end-color: #08c;
}
@ -396,11 +456,26 @@ exports[`border-l-* 1`] = `
border-left-width: 123px;
}
.border-l-\\[0_1\\] {
border-left-style: var(--tw-border-style);
border-left-width: 0 1;
}
.border-l-\\[0_2px_0_2px\\] {
border-left-style: var(--tw-border-style);
border-left-width: 0 2px 0 2px;
}
.border-l-\\[12px\\] {
border-left-style: var(--tw-border-style);
border-left-width: 12px;
}
.border-l-\\[12px_8px\\] {
border-left-style: var(--tw-border-style);
border-left-width: 12px 8px;
}
.border-l-\\[length\\:var\\(--my-width\\)\\], .border-l-\\[line-width\\:var\\(--my-width\\)\\] {
border-left-style: var(--tw-border-style);
border-left-width: var(--my-width);
@ -421,6 +496,11 @@ exports[`border-l-* 1`] = `
border-left-width: thin;
}
.border-l-\\[thin_2px\\] {
border-left-style: var(--tw-border-style);
border-left-width: thin 2px;
}
.border-l-\\[\\#0088cc\\] {
border-left-color: #08c;
}
@ -518,11 +598,26 @@ exports[`border-r-* 1`] = `
border-right-width: 123px;
}
.border-r-\\[0_1\\] {
border-right-style: var(--tw-border-style);
border-right-width: 0 1;
}
.border-r-\\[0_2px_0_2px\\] {
border-right-style: var(--tw-border-style);
border-right-width: 0 2px 0 2px;
}
.border-r-\\[12px\\] {
border-right-style: var(--tw-border-style);
border-right-width: 12px;
}
.border-r-\\[12px_8px\\] {
border-right-style: var(--tw-border-style);
border-right-width: 12px 8px;
}
.border-r-\\[length\\:var\\(--my-width\\)\\], .border-r-\\[line-width\\:var\\(--my-width\\)\\] {
border-right-style: var(--tw-border-style);
border-right-width: var(--my-width);
@ -543,6 +638,11 @@ exports[`border-r-* 1`] = `
border-right-width: thin;
}
.border-r-\\[thin_2px\\] {
border-right-style: var(--tw-border-style);
border-right-width: thin 2px;
}
.border-r-\\[\\#0088cc\\] {
border-right-color: #08c;
}
@ -640,11 +740,26 @@ exports[`border-s-* 1`] = `
border-inline-start-width: 123px;
}
.border-s-\\[0_1\\] {
border-inline-start-style: var(--tw-border-style);
border-inline-start-width: 0 1;
}
.border-s-\\[0_2px_0_2px\\] {
border-inline-start-style: var(--tw-border-style);
border-inline-start-width: 0 2px 0 2px;
}
.border-s-\\[12px\\] {
border-inline-start-style: var(--tw-border-style);
border-inline-start-width: 12px;
}
.border-s-\\[12px_8px\\] {
border-inline-start-style: var(--tw-border-style);
border-inline-start-width: 12px 8px;
}
.border-s-\\[length\\:var\\(--my-width\\)\\], .border-s-\\[line-width\\:var\\(--my-width\\)\\] {
border-inline-start-style: var(--tw-border-style);
border-inline-start-width: var(--my-width);
@ -665,6 +780,11 @@ exports[`border-s-* 1`] = `
border-inline-start-width: thin;
}
.border-s-\\[thin_2px\\] {
border-inline-start-style: var(--tw-border-style);
border-inline-start-width: thin 2px;
}
.border-s-\\[\\#0088cc\\] {
border-inline-start-color: #08c;
}
@ -762,11 +882,26 @@ exports[`border-t-* 1`] = `
border-top-width: 123px;
}
.border-t-\\[0_1\\] {
border-top-style: var(--tw-border-style);
border-top-width: 0 1;
}
.border-t-\\[0_2px_0_2px\\] {
border-top-style: var(--tw-border-style);
border-top-width: 0 2px 0 2px;
}
.border-t-\\[12px\\] {
border-top-style: var(--tw-border-style);
border-top-width: 12px;
}
.border-t-\\[12px_8px\\] {
border-top-style: var(--tw-border-style);
border-top-width: 12px 8px;
}
.border-t-\\[length\\:var\\(--my-width\\)\\], .border-t-\\[line-width\\:var\\(--my-width\\)\\] {
border-top-style: var(--tw-border-style);
border-top-width: var(--my-width);
@ -787,6 +922,11 @@ exports[`border-t-* 1`] = `
border-top-width: thin;
}
.border-t-\\[thin_2px\\] {
border-top-style: var(--tw-border-style);
border-top-width: thin 2px;
}
.border-t-\\[\\#0088cc\\] {
border-top-color: #08c;
}
@ -884,11 +1024,26 @@ exports[`border-x-* 1`] = `
border-inline-width: 123px;
}
.border-x-\\[0_1\\] {
border-inline-style: var(--tw-border-style);
border-inline-width: 0 1px;
}
.border-x-\\[0_2px_0_2px\\] {
border-inline-style: var(--tw-border-style);
border-inline-width: 0 2px 0 2px;
}
.border-x-\\[12px\\] {
border-inline-style: var(--tw-border-style);
border-inline-width: 12px;
}
.border-x-\\[12px_8px\\] {
border-inline-style: var(--tw-border-style);
border-inline-width: 12px 8px;
}
.border-x-\\[length\\:var\\(--my-width\\)\\], .border-x-\\[line-width\\:var\\(--my-width\\)\\] {
border-inline-style: var(--tw-border-style);
border-inline-width: var(--my-width);
@ -909,6 +1064,11 @@ exports[`border-x-* 1`] = `
border-inline-width: thin;
}
.border-x-\\[thin_2px\\] {
border-inline-style: var(--tw-border-style);
border-inline-width: thin 2px;
}
.border-x-\\[\\#0088cc\\] {
border-inline-color: #08c;
}
@ -1006,11 +1166,26 @@ exports[`border-y-* 1`] = `
border-block-width: 123px;
}
.border-y-\\[0_1\\] {
border-block-style: var(--tw-border-style);
border-block-width: 0 1px;
}
.border-y-\\[0_2px_0_2px\\] {
border-block-style: var(--tw-border-style);
border-block-width: 0 2px 0 2px;
}
.border-y-\\[12px\\] {
border-block-style: var(--tw-border-style);
border-block-width: 12px;
}
.border-y-\\[12px_8px\\] {
border-block-style: var(--tw-border-style);
border-block-width: 12px 8px;
}
.border-y-\\[length\\:var\\(--my-width\\)\\], .border-y-\\[line-width\\:var\\(--my-width\\)\\] {
border-block-style: var(--tw-border-style);
border-block-width: var(--my-width);
@ -1031,6 +1206,11 @@ exports[`border-y-* 1`] = `
border-block-width: thin;
}
.border-y-\\[thin_2px\\] {
border-block-style: var(--tw-border-style);
border-block-width: thin 2px;
}
.border-y-\\[\\#0088cc\\] {
border-block-color: #08c;
}

View file

@ -9881,6 +9881,10 @@ for (let prefix of prefixes) {
classes.push(`${prefix}-[medium]`)
classes.push(`${prefix}-[thick]`)
classes.push(`${prefix}-[12px]`)
classes.push(`${prefix}-[12px_8px]`)
classes.push(`${prefix}-[0_2px_0_2px]`)
classes.push(`${prefix}-[0_1]`)
classes.push(`${prefix}-[thin_2px]`)
classes.push(`${prefix}-[length:var(--my-width)]`)
classes.push(`${prefix}-[line-width:var(--my-width)]`)

View file

@ -67,7 +67,14 @@ function isUrl(value: string): boolean {
/* -------------------------------------------------------------------------- */
function isLineWidth(value: string): boolean {
return value === 'thin' || value === 'medium' || value === 'thick'
return segment(value, ' ').every(
(value) =>
isLength(value) ||
isNumber(value) ||
value === 'thin' ||
value === 'medium' ||
value === 'thick',
)
}
/* -------------------------------------------------------------------------- */