-
-
Notifications
You must be signed in to change notification settings - Fork 4.8k
Add corner-shape utility classes (corner-*)
#19298
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Add corner-shape utility classes (corner-*)
#19298
Conversation
WalkthroughAdds an experimental corner-shape feature: a CHANGELOG entry, a new exported feature flag Pre-merge checks❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
Comment |
There was a problem hiding this 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 wellClear “experimental” note and examples; nothing else needed. Consider linking docs once published.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
packages/tailwindcss/src/__snapshots__/intellisense.test.ts.snapis 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 correctMapping
cornerShape→corner-shapealigns 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.cornerShape→theme('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 sensePlacing
corner-*-shapeafter 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 utilitiesThe verification confirms that
cornerShapetokens are properly consumed by utilities:
- Theme mapping chain is correct:
cornerShape→--corner-shape(viaapply-config-to-theme.ts)- Utilities reference tokens consistently via
themeKeys: ['--corner-shape'](line 2231 inutilities.ts)- Shapes array matches all non-DEFAULT theme keys
- Tests confirm correct CSS generation across all corner variants
DEFAULT: 'round'provides a sensible defaultpackages/tailwindcss/src/compat/apply-config-to-theme.test.ts (2)
38-40: LGTM - Test configuration follows established pattern.The
cornerShapeconfiguration 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-shapeproperty 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.tswas 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.
thecrypticace
left a comment
There was a problem hiding this 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
There was a problem hiding this 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 forcorner-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 withsuperellipse, adding a direct test for the namedsquircleutility 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 previouscornertest usestoMatchInlineSnapshot(). 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
cornerandcorner-tare 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-blAlternatively, 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
constdeclarations) 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:
- Separating the cleanup changes into a separate commit within this PR
- 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
📒 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
shapesarray—'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.
There was a problem hiding this 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: Preferconstfor theclassesaccumulator.
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
⛔ Files ignored due to path filters (1)
packages/tailwindcss/src/__snapshots__/utilities.test.ts.snapis 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-radiusutilities "register suggestions," but examining the codebase shows they do not. Bothborder-radius(lines 2173–2200) andcorner-shape(lines 2202–2231) use identicalfunctionalUtilitypatterns withoutsuggest()calls. Thesuggest()function is used selectively for specific utilities throughout the file—it is not a required pattern for all utilities.The
corner-shapeimplementation 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 withinutilities.ts.No code changes are needed.
Likely an incorrect or invalid review comment.
corner-shape utility classes (corner-*)
|
One issue with this approach is that it will look quite different now on browsers that support Check out this for example: https://play.tailwindcss.com/j0QURKzlvU
I would argue that |
@philipp-spiess I've been thinking about this too and have been trying to decide if we should try to use 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). |
|
@thecrypticace Yeah I think you're right, getting this right is non-trivial and should be up to the user. We do have the |
| shapes.map((shape) => [shape, properties.map((property) => decl(property, shape))]), | ||
| ), | ||
| }) | ||
| } |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
There was a problem hiding this 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/foomodifiers). 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 buildclassesviamap, which removes the repetitiveclasses.push(...)calls.- Optionally add a type annotation for
classes(e.g.,let classes: string[] = []) to avoid an implicitany[]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
📒 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
enableContainerSizeUtilitypattern 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 usingfunctionalUtility()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 explicitsuggest()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.

This PR adds utilities to control the shape of rounded corners of an element. These map to the new
corner-shapeproperty in CSS.You can use the
corner-*utilities to control the shape of all corners simultaneously or use utilities likecorner-t-*,corner-bl-*, etc… to control individual corners.corner-*corner-t-*corner-b-*corner-l-*corner-r-*corner-tl-*corner-tr-*corner-bl-*corner-br-*corner-s-*corner-e-*corner-ss-*corner-se-*corner-ee-*corner-es-*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:
corner-roundcorner-shape: roundcorner-scoopcorner-shape: scoopcorner-bevelcorner-shape: bevelcorner-notchcorner-shape: notchcorner-squarecorner-shape: squarecorner-squirclecorner-shape: squircleAdditionally, 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: