Skip to content

Conversation

@baptisthecht
Copy link

@baptisthecht baptisthecht commented Nov 12, 2025

This PR adds utilities to control the shape of rounded corners of an element. These map to the new corner-shape property in CSS.

You can use the corner-* utilities to control the shape of all corners simultaneously or use utilities like corner-t-*, corner-bl-*, etc… to control individual corners.

Utility Affected corners
corner-* all
corner-t-* top left, top right
corner-b-* bottom left, bottom right
corner-l-* top left, bottom left
corner-r-* top right, bottom right
corner-tl-* top left
corner-tr-* top right
corner-bl-* bottom left
corner-br-* bottom right
corner-s-* (logical) start start, end start
corner-e-* (logical) start end, end end
corner-ss-* (logical) start start
corner-se-* (logical) start end
corner-ee-* (logical) end end
corner-es-* (logical) end start

Each utility has a handful of pre-defined values that map to their counterparts in CSS. Shown here are the versions for shaping all corners but they're present individual corner utilities as well:

Utility Value
corner-round corner-shape: round
corner-scoop corner-shape: scoop
corner-bevel corner-shape: bevel
corner-notch corner-shape: notch
corner-square corner-shape: square
corner-squircle corner-shape: squircle

Additionally, arbitrary values are supported so you can use custom superellipse(…) values e.g. corner-[superellipse(1.333)].

For an idea of what each of these do you can use Chrome to look at this Play (or any other supported browser). Otherwise there's a screenshot below:

corner shape examples

@baptisthecht baptisthecht requested a review from a team as a code owner November 12, 2025 14:01
@coderabbitai
Copy link

coderabbitai bot commented Nov 12, 2025

Walkthrough

Adds an experimental corner-shape feature: a CHANGELOG entry, a new exported feature flag enableCornerShapeUtilities, and insertion of nine new property-order entries (corner-shape, corner-start-start-shape, corner-start-end-shape, corner-end-end-shape, corner-end-start-shape, corner-top-left-shape, corner-top-right-shape, corner-bottom-right-shape, corner-bottom-left-shape) before border-width. Introduces multiple new functional utilities (corner, corner-s, corner-e, corner-t, corner-r, corner-b, corner-l, corner-ss, corner-se, corner-ee, corner-es, corner-tl, corner-tr, corner-br, corner-bl) gated by the feature flag, using theme key --corner-shape with static shape mappings. Tests were extended to parameterize and cover these utilities. No exported API signatures changed.

Pre-merge checks

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and specifically summarizes the main change: adding new corner-shape utility classes with examples.
Description check ✅ Passed The description clearly explains the new corner-shape utilities, their naming conventions, affected corners, pre-defined values, and provides practical examples.

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
CHANGELOG.md (1)

17-17: Changelog entry reads well

Clear “experimental” note and examples; nothing else needed. Consider linking docs once published.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5bc90dd and 5232c86.

⛔ Files ignored due to path filters (1)
  • packages/tailwindcss/src/__snapshots__/intellisense.test.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (7)
  • CHANGELOG.md (1 hunks)
  • packages/tailwindcss/src/compat/apply-config-to-theme.test.ts (2 hunks)
  • packages/tailwindcss/src/compat/apply-config-to-theme.ts (1 hunks)
  • packages/tailwindcss/src/compat/config/create-compat-config.ts (1 hunks)
  • packages/tailwindcss/src/compat/default-theme.ts (1 hunks)
  • packages/tailwindcss/src/property-order.ts (1 hunks)
  • packages/tailwindcss/src/utilities.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
packages/tailwindcss/src/utilities.ts (1)
packages/tailwindcss/src/ast.ts (2)
  • AstNode (68-68)
  • decl (95-102)
🔇 Additional comments (7)
packages/tailwindcss/src/compat/apply-config-to-theme.ts (1)

161-161: Corner shape key mapping looks correct

Mapping cornerShapecorner-shape aligns with existing conventions and enables dot-notation resolution. LGTM.

packages/tailwindcss/src/compat/config/create-compat-config.ts (1)

37-39: Extend mapping is consistent

extend.cornerShapetheme('corner-shape', {}) matches existing patterns and keeps CSS the source of truth. LGTM.

packages/tailwindcss/src/property-order.ts (1)

194-202: Property order placement makes sense

Placing corner-*-shape after the radius group and before border width is logical and keeps related declarations adjacent. LGTM.

Consider a quick check that generated utilities use these exact property names to benefit from sorting.

packages/tailwindcss/src/compat/default-theme.ts (1)

174-182: Verified: cornerShape tokens correctly integrated with utilities

The verification confirms that cornerShape tokens are properly consumed by utilities:

  • Theme mapping chain is correct: cornerShape--corner-shape (via apply-config-to-theme.ts)
  • Utilities reference tokens consistently via themeKeys: ['--corner-shape'] (line 2231 in utilities.ts)
  • Shapes array matches all non-DEFAULT theme keys
  • Tests confirm correct CSS generation across all corner variants
  • DEFAULT: 'round' provides a sensible default
packages/tailwindcss/src/compat/apply-config-to-theme.test.ts (2)

38-40: LGTM - Test configuration follows established pattern.

The cornerShape configuration addition is consistent with other theme configurations in the test suite.


100-100: LGTM - Theme resolution test is correctly implemented.

The test assertion follows the established pattern for verifying theme value resolution.

packages/tailwindcss/src/utilities.ts (1)

2202-2237: No issues found—the implementation is complete and properly integrated.

The script and web search confirm:

  • The corner-shape property is defined in the CSS Borders and Box Decorations Module Level 4 and is legitimate, not non-standard.
  • The CHANGELOG properly marks it as "experimental."
  • property-order.ts was already updated with all corner-shape properties.
  • Tests show comprehensive coverage, including arbitrary value support (corner-[superellipse(0.6)]).
  • The compat layer and theme integration are complete.
  • Browser support is limited (Chrome/Edge 139+; not yet in Firefox or Safari), which is expected for an experimental feature.

Copy link
Contributor

@thecrypticace thecrypticace left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • I don't think we need to add anything to the compatibility config since these are new utilities. Seems fine if these are only customizable via CSS.
  • Please add utility tests to the utilities.test.ts file

@thecrypticace thecrypticace self-assigned this Nov 12, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (4)
packages/tailwindcss/src/utilities.test.ts (4)

11054-11109: Add explicit test for corner-squircle.

The PR description specifically highlights the "squircle" shape as the main feature ("the long-awaited corner-squircle"). However, the test doesn't explicitly verify corner-squircle. While an arbitrary value test exists with superellipse, adding a direct test for the named squircle utility would better validate the feature highlighted in the PR.

Consider adding 'corner-squircle' and 'corner-notch' to the test candidates to ensure all six shape values mentioned in the implementation are explicitly tested:

-    ['corner', 'corner-bevel', 'corner-scoop', 'corner-square', 'corner-[superellipse(0.6)]'],
+    ['corner', 'corner-bevel', 'corner-scoop', 'corner-square', 'corner-notch', 'corner-squircle', 'corner-[superellipse(0.6)]'],

11111-11162: Use consistent testing approach with inline snapshots.

This test uses regex matching with toMatch(), while the previous corner test uses toMatchInlineSnapshot(). The regex approach is less precise, harder to maintain, and makes it difficult to catch unintended changes in the CSS output.

Consider using toMatchInlineSnapshot() for consistency and better test coverage:

-  expect(output).toMatch(
-    /\.corner-t \{\s+corner-top-left-shape: var\(--corner-shape\);\s+corner-top-right-shape: var\(--corner-shape\);\s+\}/,
-  )
-  expect(output).toMatch(
-    /\.corner-t-scoop \{\s+corner-top-left-shape: var\(--corner-shape-scoop\);\s+corner-top-right-shape: var\(--corner-shape-scoop\);\s+\}/,
-  )
-  expect(output).toMatch(/\.corner-tr \{\s+corner-top-right-shape: var\(--corner-shape\);\s+\}/)
-  expect(output).toMatch(
-    /\.corner-tr-notch \{\s+corner-top-right-shape: var\(--corner-shape-notch\);\s+\}/,
-  )
-  expect(output).toMatch(/\.corner-tl \{\s+corner-top-left-shape: var\(--corner-shape\);\s+\}/)
-  expect(output).toContain('.corner-t-\\[superellipse\\(0\\.8\\)\\] {')
-  expect(output).toContain('corner-top-left-shape: superellipse(.8);')
-  expect(output).toContain('corner-top-right-shape: superellipse(.8);')
+  expect(output).toMatchInlineSnapshot(`...`)

11054-11162: Add test coverage for remaining corner utilities.

Based on the AI summary, the implementation includes many corner utility variants (corner-s, corner-e, corner-r, corner-b, corner-l, corner-ss, corner-se, corner-ee, corner-es, corner-br, corner-bl), but only corner and corner-t are tested. This leaves significant functionality untested.

Add test cases for the remaining corner utilities to ensure complete coverage:

  • Directional edges: corner-r, corner-b, corner-l, corner-s, corner-e
  • Logical corners: corner-ss, corner-se, corner-ee, corner-es
  • Physical corners: corner-br, corner-bl

Alternatively, if these utilities follow the same pattern, consider using parameterized tests to reduce duplication.


11237-11237: Consider separating unrelated code cleanup into a separate commit.

The changes from line 11237 onwards include multiple unrelated variable declaration updates (changing to explicit const declarations) that are mixed with the corner utility feature additions. While these cleanup changes improve code quality, they add noise to the feature review.

For easier review and clearer git history, consider either:

  1. Separating the cleanup changes into a separate commit within this PR
  2. Moving the cleanup changes to a separate PR

This helps reviewers focus on the feature logic and makes it easier to track changes in git blame.

Also applies to: 27185-28777

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5232c86 and a727bae.

📒 Files selected for processing (2)
  • packages/tailwindcss/src/utilities.test.ts (55 hunks)
  • packages/tailwindcss/src/utilities.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
packages/tailwindcss/src/utilities.test.ts (2)
integrations/utils.ts (2)
  • test (80-455)
  • css (518-518)
packages/tailwindcss/src/test-utils/run.ts (3)
  • compileCss (4-11)
  • run (13-16)
  • optimizeCss (18-20)
packages/tailwindcss/src/utilities.ts (1)
packages/tailwindcss/src/ast.ts (1)
  • decl (95-102)
🔇 Additional comments (1)
packages/tailwindcss/src/utilities.ts (1)

2202-2231: Original review comment contains incorrect information about CSS corner-shape values.

The web search confirms that all values in the shapes array—'round', 'square', 'bevel', 'scoop', 'notch', 'squircle'—are valid CSS corner-shape property values according to the specification. The original review comment incorrectly flagged both 'square' and 'squircle' as non-standard; both are actually part of the official CSS spec.

The only valid concern from the original comment is that corner-shape is an experimental property with limited browser support and is not baseline across major browsers. However, this is a documentation/awareness issue for the feature as a whole, not a code correctness issue.

The implementation at lines 2202-2231 is correct and requires no changes.

Likely an incorrect or invalid review comment.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
packages/tailwindcss/src/utilities.test.ts (1)

11076-11087: Prefer const for the classes accumulator.
Line 11076 only mutates the array contents, so keeping the binding constant matches the rest of these updated tests.

-    let classes = []
+    const classes = []
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a727bae and 7ef9884.

⛔ Files ignored due to path filters (1)
  • packages/tailwindcss/src/__snapshots__/utilities.test.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (2)
  • packages/tailwindcss/src/utilities.test.ts (55 hunks)
  • packages/tailwindcss/src/utilities.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
packages/tailwindcss/src/utilities.test.ts (4)
integrations/utils.ts (2)
  • test (80-455)
  • css (518-518)
packages/tailwindcss/src/test-utils/run.ts (3)
  • compileCss (4-11)
  • run (13-16)
  • optimizeCss (18-20)
packages/@tailwindcss-node/src/compile.ts (1)
  • compile (100-104)
packages/tailwindcss/src/index.ts (3)
  • compile (819-855)
  • build (749-813)
  • build (836-847)
packages/tailwindcss/src/utilities.ts (1)
packages/tailwindcss/src/ast.ts (1)
  • decl (95-102)
🔇 Additional comments (1)
packages/tailwindcss/src/utilities.ts (1)

2202-2231: The review comment is based on incorrect assumptions and should be disregarded.

The original comment claims that border-radius utilities "register suggestions," but examining the codebase shows they do not. Both border-radius (lines 2173–2200) and corner-shape (lines 2202–2231) use identical functionalUtility patterns without suggest() calls. The suggest() function is used selectively for specific utilities throughout the file—it is not a required pattern for all utilities.

The corner-shape implementation correctly follows the established codebase pattern. The browser support concern is valid (limited to Chromium-based browsers like Chrome 139+, Edge, and Android browsers; not supported in Firefox or Safari), but this is a product-level consideration, not a code implementation issue. The codebase contains no patterns for documenting experimental feature support within utilities.ts.

No code changes are needed.

Likely an incorrect or invalid review comment.

@thecrypticace thecrypticace changed the title feat(utility): add corner shape utility classes Add corner-shape utility classes (corner-*) Nov 12, 2025
@philipp-spiess
Copy link
Member

philipp-spiess commented Nov 17, 2025

One issue with this approach is that it will look quite different now on browsers that support corner-shape vs those that don't since the perceived radius is much smaller with e.g. a corner-shape: squircle:

Check out this for example: https://play.tailwindcss.com/j0QURKzlvU

CleanShot 2025-11-17 at 10 34 35@2x

I would argue that rounded-md is a much better fallback for rounded-xl corner-squircle. Especially now that only one browser supports it yet!

@thecrypticace
Copy link
Contributor

I would argue that rounded-md is a much better fallback for rounded-xl corner-squircle …

@philipp-spiess I've been thinking about this too and have been trying to decide if we should try to use @supports in this + some kind of calculation via calc(…) or if we should delegate that to the user.

Aside: The current implementation in Chrome renders with fairly poor aliasing for small values and I wonder if any tweaks to that rendering would change how different sizes compare optically (even if just by a small amount).

@philipp-spiess
Copy link
Member

@thecrypticace Yeah I think you're right, getting this right is non-trivial and should be up to the user. We do have the supports-corner-shape variant to help with this already.

shapes.map((shape) => [shape, properties.map((property) => decl(property, shape))]),
),
})
}
Copy link
Contributor

@thecrypticace thecrypticace Nov 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@RobinMalfait @philipp-spiess What are your thoughts on modifying this to accept corner-[<number>] that expands to corner-shape: superellipse(<number>). Or alternatively a second corner-superellipse-[<number>] utility?

We could also punt that decision down the road since we won't ship these in a stable release until v4.2 but just something to think about. I think a nice way to write custom super ellipse factors would be nice.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While I like the succinct corner-[<number>] version, I'm afraid if other corner-shape functions will exist in the future, that this will become ambiguous. Writing corner-superellipse-[<number>] is much safer imo, sadly also much longer.

We could also just use corner-[<number>], and if in the future more functions like superellipse(…) (I had to type this 3 times, so this is not great...) exist, then we can introduce the more specific versions then. Maybe that's the better play here. Thoughts?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm yeah — I say lets push that decision to later

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
packages/tailwindcss/src/utilities.test.ts (1)

11054-11112: Parametric corner- utility tests look solid; consider a tiny refactor for clarity*

The looped tests exercise all corner-* prefixes, expected shapes (including custom + @theme), an arbitrary value, and invalid variants (negatives and /foo modifiers). The behavior and expectations look correct.

If you want to tighten things up a bit, you could:

  • Extract the shape suffixes into a shared array (e.g., const shapes = ['round', 'scoop', 'bevel', 'notch', 'square', 'squircle', 'custom']) and build classes via map, which removes the repetitive classes.push(...) calls.
  • Optionally add a type annotation for classes (e.g., let classes: string[] = []) to avoid an implicit any[] in this TypeScript test file.

Both are purely stylistic and can be skipped if they don’t match existing patterns in utilities.test.ts.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7ef9884 and 0038ac9.

📒 Files selected for processing (4)
  • CHANGELOG.md (1 hunks)
  • packages/tailwindcss/src/feature-flags.ts (1 hunks)
  • packages/tailwindcss/src/utilities.test.ts (1 hunks)
  • packages/tailwindcss/src/utilities.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • CHANGELOG.md
🧰 Additional context used
🧬 Code graph analysis (2)
packages/tailwindcss/src/utilities.test.ts (2)
integrations/utils.ts (2)
  • test (80-455)
  • css (518-518)
packages/tailwindcss/src/test-utils/run.ts (2)
  • compileCss (4-11)
  • run (13-16)
packages/tailwindcss/src/utilities.ts (2)
packages/tailwindcss/src/feature-flags.ts (1)
  • enableCornerShapeUtilities (2-2)
packages/tailwindcss/src/ast.ts (1)
  • decl (95-102)
🔇 Additional comments (2)
packages/tailwindcss/src/feature-flags.ts (1)

2-2: LGTM! Feature flag follows the established pattern.

The implementation correctly mirrors the existing enableContainerSizeUtility pattern and properly gates the experimental corner-shape utilities.

packages/tailwindcss/src/utilities.ts (1)

2202-2231: Verify the comparison claim about rounded utilities.

The original review contains an inaccurate premise. Neither the rounded utilities (lines 2174-2200) nor the corner-shape utilities (lines 2202-2231) include explicit suggest() calls. Both implementations follow the identical pattern of using functionalUtility() with static values defined inline.

The codebase shows that functionalUtility() is called in the same manner for both:

  • Rounded: functionalUtility(root, { themeKeys: ['--radius'], ... })
  • Corner-shape: functionalUtility(root, { themeKeys: ['--corner-shape'], ... })

No suggest() calls appear after either loop. The suggestion to add autocomplete support is therefore not specific to corner-shape utilities—it would apply equally to rounded utilities, which already exist and function without explicit suggest() calls.

Regarding CSS property validity: The corner-shape keyword values ('round', 'scoop', 'bevel', 'notch', 'square', 'squircle') and all longhand properties are valid. The property is currently supported in Chrome/Edge 139+ and remains experimental; it is not yet supported in Firefox or Safari.

Likely an incorrect or invalid review comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants