Skip to content

feat: Add corner-shape for components with border-radius#3968

Open
sheelah wants to merge 2 commits into
Workday:masterfrom
sheelah:add-corner-shape
Open

feat: Add corner-shape for components with border-radius#3968
sheelah wants to merge 2 commits into
Workday:masterfrom
sheelah:add-corner-shape

Conversation

@sheelah

@sheelah sheelah commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Summary

Draft PR to test the visual changes from adding corner-shape on our elements that use border-radius. Circular elements have been left unchanged.

Note: This feature is NOT yet supported across all browsers (including Safari and Firefox) so we're using progressive enhancement. Browsers that don't support this property will fall back to using border-radius. This property also does nothing without border-radius also declared.

The desired value to use directly after border-radius is declared will be:
cornerShape: superellipse(1.1)

Release Category

Components

Release Note

Optional release note message. Changelog and release summaries will contain a pull request title. This section will add additional notes under that title. This section is not a summary, but something extra to point out in release notes. An example might be calling out breaking changes in a labs component or minor visual changes that need visual regression updates. Remove this section if no additional release notes are required.

BREAKING CHANGES

Optional breaking changes message. If your PR includes breaking changes. It is extremely rare to put breaking changes outside a prerelease/major branch. Anything in this section will show up in release notes. Remove this section if no breaking changes are present.


Checklist

For the Reviewer

  • PR title is short and descriptive
  • PR summary describes the change (Fixes/Resolves linked correctly)
  • PR Release Notes describes additional information useful to call out in a release message or removed if not applicable
  • Breaking Changes provides useful information to upgrade to this code or removed if not applicable

Where Should the Reviewer Start?

Areas for Feedback? (optional)

  • Code
  • Documentation
  • Testing
  • Codemods

Testing Manually

Screenshots or GIFs (if applicable)

Thank You Gif (optional)

Summary by CodeRabbit

Release Notes

  • Style
    • Updated corner styling across buttons, cards, checkboxes, radio buttons, menus, modals, pills, tabs, text inputs, toasts, tooltips, and other UI components to use a refined corner shape approach.

@coderabbitai

coderabbitai Bot commented Jun 5, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR introduces a CORNER_SHAPE design token across Canvas Kit by defining a superellipse(1.1) constant, integrating it into shape token resolution logic and AST transforms, and updating 30+ components to apply the corner shape token in their stencil styling alongside border radius.

Changes

Corner Shape System Implementation

Layer / File(s) Summary
Corner Shape Foundation
modules/styling/lib/cornerShape.ts, modules/styling/index.ts
Introduces and exports CORNER_SHAPE constant ('superellipse(1.1)') from the styling module for use throughout Canvas Kit.
Shape Token Integration and Testing
modules/react/layout/lib/utils/buildStyleFns.ts, modules/react/layout/spec/border.spec.ts
Updates buildStyleFns to conditionally emit CORNER_SHAPE alongside border radius when resolving non-circular shape tokens; adds test coverage for conditional cornerShape presence.
AST Transform and Configuration
styling.config.ts, modules/styling-transform/testing.ts, modules/styling-transform/spec/createProgramFromSource.ts
Registers handleWithCornerShape in the styling transform configuration and extends test utilities to support corner shape transform validation.
Container Components
modules/react/card/lib/Card.tsx, modules/react/modal/lib/ModalCard.tsx, modules/react/menu/lib/MenuCard.tsx, modules/react/menu/lib/MenuList.tsx, modules/react/combobox/lib/ComboboxCard.tsx, modules/react/popup/lib/PopupCard.tsx, modules/preview-react/color-picker/lib/parts/SwatchBook.tsx
Updates card, modal, menu, combobox, and popup stencils to apply CORNER_SHAPE token in base styles.
Button and Pill Components
modules/react/button/lib/Hyperlink.tsx, modules/react/button/lib/ToolbarDropdownButton.tsx, modules/react/pill/lib/Pill.tsx, modules/react/pill/lib/PillCount.tsx, modules/react/pill/lib/PillIconButton.tsx
Updates button and pill stencil styling to use CORNER_SHAPE in base configuration.
Input and Checkbox Components
modules/react/text-input/lib/TextInput.tsx, modules/react/checkbox/lib/CheckBackground.tsx, modules/react/checkbox/lib/CheckboxInput.tsx, modules/react/form-field/lib/FormFieldGroupList.tsx
Updates text input and checkbox stencil styles to apply CORNER_SHAPE in base styling.
Menu and Radio Components
modules/react/menu/lib/MenuItem.tsx, modules/react/radio/lib/RadioGroup.tsx, modules/preview-react/radio/lib/RadioGroup.tsx
Updates menu item and radio group stencils to include CORNER_SHAPE in base or container styling.
Segmented Control and Tabs Components
modules/react/segmented-control/lib/SegmentedControlItem.tsx, modules/react/segmented-control/lib/SegmentedControlList.tsx, modules/react/tabs/lib/TabsItem.tsx
Updates segmented control and tab item stencils to apply CORNER_SHAPE in base and pseudo-element styles.
Skeleton and Status Indicator Components
modules/react/skeleton/lib/parts/SkeletonHeader.tsx, modules/react/skeleton/lib/parts/SkeletonShape.tsx, modules/react/skeleton/lib/parts/SkeletonText.tsx, modules/react/status-indicator/lib/StatusIndicator.tsx, modules/react/toast/lib/Toast.tsx
Updates skeleton part stencils and status indicator styling to use CORNER_SHAPE token.
Expandable, Highlight, and Miscellaneous Components
modules/react/expandable/lib/ExpandableTarget.tsx, modules/react/information-highlight/lib/InformationHighlight.tsx, modules/react/color-picker/lib/parts/ColorSwatch.tsx, modules/react/table/lib/BaseTable.tsx, modules/react/tooltip/lib/TooltipContainer.tsx
Updates expandable, highlight, color picker, table, and tooltip stencils to apply CORNER_SHAPE in their base styles.
Preview Multi-Select and Status Indicator
modules/preview-react/multi-select/lib/MultiSelectInput.tsx, modules/preview-react/status-indicator/lib/StatusIndicator.tsx
Updates preview-react multi-select and status indicator components to use CORNER_SHAPE in stencil styling.

🎯 3 (Moderate) | ⏱️ ~25 minutes

🐰 A superellipse shape so fine,
CORNER_SHAPE in every line!
Curves that flow with design so bright,
Token-driven corners, a delightful sight. ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: adding corner-shape CSS property to components with border-radius styling.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@cypress

cypress Bot commented Jun 5, 2026

Copy link
Copy Markdown

Workday/canvas-kit    Run #10948

Run Properties:  status check passed Passed #10948  •  git commit a5add312b6 ℹ️: Merge 50fd557698bf24959f0e8d7bcf7e0d011b5c87a1 into 1595b29aabedbd7f9f3e4bc6316b...
Project Workday/canvas-kit
Branch Review add-corner-shape
Run status status check passed Passed #10948
Run duration 02m 26s
Commit git commit a5add312b6 ℹ️: Merge 50fd557698bf24959f0e8d7bcf7e0d011b5c87a1 into 1595b29aabedbd7f9f3e4bc6316b...
Committer Sheelah Brennan
View all properties for this run ↗︎

Test results
Tests that failed  Failures 0
Tests that were flaky  Flaky 0
Tests that did not run due to a developer annotating a test with .skip  Pending 17
Tests that did not run due to a failure in a mocha hook  Skipped 0
Tests that passed  Passing 809
View all changes introduced in this branch ↗︎
UI Coverage  19.58%
  Untested elements 1534  
  Tested elements 371  
Accessibility  99.41%
  Failed rules  5 critical   5 serious   0 moderate   2 minor
  Failed elements 68  

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
modules/styling-transform/spec/handleWithCornerShape.spec.ts (1)

5-25: ⚡ Quick win

Expand test coverage to include edge cases.

The test suite only covers the happy path with a string literal argument. Consider adding tests for:

  • Missing arguments: withCornerShape()
  • Multiple arguments: withCornerShape('24px', 'extra')
  • Numeric arguments: withCornerShape(24)
  • Non-static values (variables, expressions)
  • withCornerShape not imported from @workday/canvas-kit-styling

These edge cases will help catch issues like the missing argument validation flagged in handleWithCornerShape.ts.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@modules/styling-transform/spec/handleWithCornerShape.spec.ts` around lines 5
- 25, Add additional unit tests to handle edge cases for the withCornerShape
transform: add tests in handleWithCornerShape.spec.ts that call
createProgramFromSource + transform with objectTransforms:
[handleWithCornerShape] for (1) missing argument case withCornerShape()
expecting no radius/corner-shape output or a handled error, (2) multiple
arguments withCornerShape('24px', 'extra') ensuring only the first is used or
it's rejected, (3) numeric argument withCornerShape(24) verifying
numeric-to-string handling, (4) non-static/variable/expression arguments (e.g.,
const r='24px'; withCornerShape(r)) asserting it is not transformed, and (5)
calls to withCornerShape from a different import (not
`@workday/canvas-kit-styling`) to ensure the transformer ignores it; reference the
existing test that uses handleWithCornerShape and withCornerShape to mirror
setup and assertions (expecting border-radius and corner-shape presence or
absence) for each case.
modules/styling-transform/testing.ts (1)

2-2: Consider removing (or justifying) the parseObjectToStaticValue re-export from the testing barrel

modules/styling-transform/testing.ts re-exports parseObjectToStaticValue, but no specs in this repo import it from @workday/canvas-kit-styling-transform/testing—the dedicated spec imports it directly from modules/styling-transform/lib/utils/parseObjectToStaticValue. If this re-export isn’t required for consumers/other packages, it can likely be dropped to reduce the testing entrypoint surface area.

export {parseObjectToStaticValue} from './lib/utils/parseObjectToStaticValue';
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@modules/styling-transform/testing.ts` at line 2, The testing barrel currently
re-exports parseObjectToStaticValue which appears unused by this package's
specs—remove the line exporting parseObjectToStaticValue from
modules/styling-transform/testing.ts to shrink the public testing surface;
before deleting, run a repo-wide search for imports of parseObjectToStaticValue
from `@workday/canvas-kit-styling-transform/testing` and, if any are found, update
those imports to the original path
(modules/styling-transform/lib/utils/parseObjectToStaticValue) or
document/justify keeping the re-export.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@modules/styling-transform/lib/utils/handleWithCornerShape.ts`:
- Around line 9-20: The transform handleWithCornerShape currently reads
node.arguments[0] without validating arguments; update the createObjectTransform
callback so it first checks ts.isCallExpression(node) && node.arguments &&
node.arguments.length === 1 before calling parseNodeToStaticValue, and if the
length !== 1 then early-return undefined (or emit a diagnostic via the provided
context) to avoid a crash for zero args and to surface/report extra args rather
than silently ignoring them; keep the existing checks for
isIdentifier/node.expression text and isImportedFromStyling and still return the
object with borderRadius: parseNodeToStaticValue(node.arguments[0], context) and
cornerShape: CORNER_SHAPE when validation passes.

---

Nitpick comments:
In `@modules/styling-transform/spec/handleWithCornerShape.spec.ts`:
- Around line 5-25: Add additional unit tests to handle edge cases for the
withCornerShape transform: add tests in handleWithCornerShape.spec.ts that call
createProgramFromSource + transform with objectTransforms:
[handleWithCornerShape] for (1) missing argument case withCornerShape()
expecting no radius/corner-shape output or a handled error, (2) multiple
arguments withCornerShape('24px', 'extra') ensuring only the first is used or
it's rejected, (3) numeric argument withCornerShape(24) verifying
numeric-to-string handling, (4) non-static/variable/expression arguments (e.g.,
const r='24px'; withCornerShape(r)) asserting it is not transformed, and (5)
calls to withCornerShape from a different import (not
`@workday/canvas-kit-styling`) to ensure the transformer ignores it; reference the
existing test that uses handleWithCornerShape and withCornerShape to mirror
setup and assertions (expecting border-radius and corner-shape presence or
absence) for each case.

In `@modules/styling-transform/testing.ts`:
- Line 2: The testing barrel currently re-exports parseObjectToStaticValue which
appears unused by this package's specs—remove the line exporting
parseObjectToStaticValue from modules/styling-transform/testing.ts to shrink the
public testing surface; before deleting, run a repo-wide search for imports of
parseObjectToStaticValue from `@workday/canvas-kit-styling-transform/testing` and,
if any are found, update those imports to the original path
(modules/styling-transform/lib/utils/parseObjectToStaticValue) or
document/justify keeping the re-export.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 921a0284-95c1-4f0d-8886-1c0370d5d1a6

📥 Commits

Reviewing files that changed from the base of the PR and between 1595b29 and 50fd557.

📒 Files selected for processing (47)
  • modules/preview-react/color-picker/lib/parts/SwatchBook.tsx
  • modules/preview-react/multi-select/lib/MultiSelectInput.tsx
  • modules/preview-react/radio/lib/RadioGroup.tsx
  • modules/preview-react/status-indicator/lib/StatusIndicator.tsx
  • modules/react/banner/lib/Banner.tsx
  • modules/react/button/lib/Hyperlink.tsx
  • modules/react/button/lib/ToolbarDropdownButton.tsx
  • modules/react/button/lib/ToolbarIconButton.tsx
  • modules/react/card/lib/Card.tsx
  • modules/react/checkbox/lib/CheckBackground.tsx
  • modules/react/checkbox/lib/CheckboxInput.tsx
  • modules/react/color-picker/lib/parts/ColorSwatch.tsx
  • modules/react/combobox/lib/ComboboxCard.tsx
  • modules/react/expandable/lib/ExpandableTarget.tsx
  • modules/react/form-field/lib/FormFieldGroupList.tsx
  • modules/react/information-highlight/lib/InformationHighlight.tsx
  • modules/react/layout/lib/utils/buildStyleFns.ts
  • modules/react/layout/spec/border.spec.ts
  • modules/react/menu/lib/MenuCard.tsx
  • modules/react/menu/lib/MenuItem.tsx
  • modules/react/menu/lib/MenuList.tsx
  • modules/react/modal/lib/ModalCard.tsx
  • modules/react/pill/lib/Pill.tsx
  • modules/react/pill/lib/PillCount.tsx
  • modules/react/pill/lib/PillIconButton.tsx
  • modules/react/popup/lib/PopupCard.tsx
  • modules/react/radio/lib/RadioGroup.tsx
  • modules/react/segmented-control/lib/SegmentedControlItem.tsx
  • modules/react/segmented-control/lib/SegmentedControlList.tsx
  • modules/react/skeleton/lib/parts/SkeletonHeader.tsx
  • modules/react/skeleton/lib/parts/SkeletonShape.tsx
  • modules/react/skeleton/lib/parts/SkeletonText.tsx
  • modules/react/status-indicator/lib/StatusIndicator.tsx
  • modules/react/table/lib/BaseTable.tsx
  • modules/react/tabs/lib/TabsItem.tsx
  • modules/react/text-input/lib/TextInput.tsx
  • modules/react/toast/lib/Toast.tsx
  • modules/react/tooltip/lib/TooltipContainer.tsx
  • modules/styling-transform/index.ts
  • modules/styling-transform/lib/utils/handleWithCornerShape.ts
  • modules/styling-transform/spec/createProgramFromSource.ts
  • modules/styling-transform/spec/handleWithCornerShape.spec.ts
  • modules/styling-transform/testing.ts
  • modules/styling/index.ts
  • modules/styling/lib/cornerShape.ts
  • modules/styling/spec/cornerShape.spec.ts
  • styling.config.ts

Comment on lines +9 to +20
export const handleWithCornerShape = createObjectTransform((node, context) => {
if (
ts.isCallExpression(node) &&
ts.isIdentifier(node.expression) &&
node.expression.text === 'withCornerShape' &&
isImportedFromStyling(node.expression, context.checker)
) {
return {
borderRadius: parseNodeToStaticValue(node.arguments[0], context),
cornerShape: CORNER_SHAPE,
};
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Add argument validation before accessing node.arguments[0].

The transform accesses node.arguments[0] without verifying that exactly one argument was provided. If withCornerShape() is called with no arguments, this will cause a compilation error. If called with multiple arguments, the extras will be silently ignored.

🛡️ Proposed fix to add argument validation
 export const handleWithCornerShape = createObjectTransform((node, context) => {
   if (
     ts.isCallExpression(node) &&
     ts.isIdentifier(node.expression) &&
     node.expression.text === 'withCornerShape' &&
-    isImportedFromStyling(node.expression, context.checker)
+    isImportedFromStyling(node.expression, context.checker) &&
+    node.arguments.length === 1
   ) {
     return {
       borderRadius: parseNodeToStaticValue(node.arguments[0], context),
       cornerShape: CORNER_SHAPE,
     };
   }

   return;
 });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@modules/styling-transform/lib/utils/handleWithCornerShape.ts` around lines 9
- 20, The transform handleWithCornerShape currently reads node.arguments[0]
without validating arguments; update the createObjectTransform callback so it
first checks ts.isCallExpression(node) && node.arguments &&
node.arguments.length === 1 before calling parseNodeToStaticValue, and if the
length !== 1 then early-return undefined (or emit a diagnostic via the provided
context) to avoid a crash for zero args and to surface/report extra args rather
than silently ignoring them; keep the existing checks for
isIdentifier/node.expression text and isImportedFromStyling and still return the
object with borderRadius: parseNodeToStaticValue(node.arguments[0], context) and
cornerShape: CORNER_SHAPE when validation passes.

use CORNER_SHAPE inline, instead of a helper that couldn't be applied
consistently due to different use cases of border-radius (shorthand
vs longhand, etc).
@sheelah sheelah marked this pull request as ready for review June 8, 2026 22:06
@sheelah sheelah requested a review from a team as a code owner June 8, 2026 22:06
@sheelah sheelah added the experimental AI was involved in writing some or most of the code label Jun 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

experimental AI was involved in writing some or most of the code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant