From 59936c6cbb69eae114bc52d0a3c9315b18c70a94 Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Fri, 8 May 2026 21:22:07 +0200 Subject: [PATCH] Add `tab-*` utilities (#20022) This PR adds new `tab-*` utilities. The `tab-*` utilities set the `tab-size` property. They support positive integer bare values, and arbitrary values: | Class | CSS | | -- | -- | | `tab-2` | `tab-size: 2;` | | `tab-[12px]` | `tab-size: 12px;` | This also adds `tab-size` to the property order near the other text layout properties. ## Test plan 1. Added new `tab-*` utility tests 2. Updated the intellisense snapshot 3. Other existing tests still pass --- CHANGELOG.md | 3 +- .../__snapshots__/intellisense.test.ts.snap | 3 ++ packages/tailwindcss/src/property-order.ts | 1 + packages/tailwindcss/src/utilities.test.ts | 44 +++++++++++++++++++ packages/tailwindcss/src/utilities.ts | 10 +++++ 5 files changed, 60 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fd441caaa..5cb3eb2e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,8 +14,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Allow using `@variant` with stacked variants (e.g. `@variant hover:focus { … }`) ([#19996](https://github.com/tailwindlabs/tailwindcss/pull/19996)) - Allow using `@variant` with compound variants (e.g. `@variant hover, focus { … }`) ([#19996](https://github.com/tailwindlabs/tailwindcss/pull/19996)) - Support `--default(…)` in `--value(…)` and `--modifier(…)` for functional `@utility` definitions ([#19989](https://github.com/tailwindlabs/tailwindcss/pull/19989)) -- Add `zoom-*` utilities ([#20020](https://github.com/tailwindlabs/tailwindcss/pull/20020)) - Add `scrollbar-gutter-*` utilities ([#20018](https://github.com/tailwindlabs/tailwindcss/pull/20018)) +- Add `zoom-*` utilities ([#20020](https://github.com/tailwindlabs/tailwindcss/pull/20020)) +- Add `tab-*` utilities ([#20022](https://github.com/tailwindlabs/tailwindcss/pull/20022)) ### Fixed diff --git a/packages/tailwindcss/src/__snapshots__/intellisense.test.ts.snap b/packages/tailwindcss/src/__snapshots__/intellisense.test.ts.snap index 01636618d..a58af9445 100644 --- a/packages/tailwindcss/src/__snapshots__/intellisense.test.ts.snap +++ b/packages/tailwindcss/src/__snapshots__/intellisense.test.ts.snap @@ -11492,6 +11492,9 @@ exports[`getClassList 1`] = ` "stroke-transparent/95", "stroke-transparent/100", "subpixel-antialiased", + "tab-2", + "tab-4", + "tab-8", "table", "table-auto", "table-caption", diff --git a/packages/tailwindcss/src/property-order.ts b/packages/tailwindcss/src/property-order.ts index 016200c6c..bf9f0791a 100644 --- a/packages/tailwindcss/src/property-order.ts +++ b/packages/tailwindcss/src/property-order.ts @@ -360,6 +360,7 @@ export default [ 'text-overflow', 'hyphens', 'white-space', + 'tab-size', 'color', 'text-transform', diff --git a/packages/tailwindcss/src/utilities.test.ts b/packages/tailwindcss/src/utilities.test.ts index b2873294d..78997b433 100644 --- a/packages/tailwindcss/src/utilities.test.ts +++ b/packages/tailwindcss/src/utilities.test.ts @@ -11865,6 +11865,50 @@ test('whitespace', async () => { ).toEqual('') }) +test('tab', async () => { + expect( + await compileCss( + css` + @theme { + --tab-size-github: 8; + } + + @tailwind utilities; + `, + ['tab-2', 'tab-8', 'tab-[12px]', 'tab-[3]'], + ), + ).toMatchInlineSnapshot(` + " + .tab-2 { + tab-size: 2; + } + + .tab-8 { + tab-size: 8; + } + + .tab-\\[3\\] { + tab-size: 3; + } + + .tab-\\[12px\\] { + tab-size: 12px; + } + " + `) + expect( + await run([ + 'tab', + '-tab-2', + 'tab-2.5', + 'tab-1/2', + 'tab-unknown', + 'tab-2/foo', + 'tab-[12px]/foo', + ]), + ).toEqual('') +}) + test('text-wrap', async () => { expect(await run(['text-wrap', 'text-nowrap', 'text-balance', 'text-pretty'])) .toMatchInlineSnapshot(` diff --git a/packages/tailwindcss/src/utilities.ts b/packages/tailwindcss/src/utilities.ts index 74e39ee5f..9c9693ada 100644 --- a/packages/tailwindcss/src/utilities.ts +++ b/packages/tailwindcss/src/utilities.ts @@ -2294,6 +2294,16 @@ export function createUtilities(theme: Theme) { staticUtility('whitespace-pre-wrap', [['white-space', 'pre-wrap']]) staticUtility('whitespace-break-spaces', [['white-space', 'break-spaces']]) + functionalUtility('tab', { + handleBareValue: ({ value }) => { + if (!isPositiveInteger(value)) return null + return value + }, + handle: (value) => [decl('tab-size', value)], + }) + + suggest('tab', () => [{ values: ['2', '4', '8'] }]) + staticUtility('text-wrap', [['text-wrap', 'wrap']]) staticUtility('text-nowrap', [['text-wrap', 'nowrap']]) staticUtility('text-balance', [['text-wrap', 'balance']])