Button Icon-Only interaction states (DES-87)
Version: 0.2.0 · Type: ✨ Feature
2026-06-16 DES-87 Button Icon-Only interaction states (Tertiary / Quaternary)
Problem
The Figma Design System adjusted the background tokens for the Button Icon-Only Tertiary / Quaternary interaction states, but in the frontend implementation the interaction states of tertiary / quaternary shared one set of styles across all sizes, with no distinction for Icon-Only. As a result, the Hover / Clicked feedback of Icon-Only buttons was inconsistent with the new Figma:
- Tertiary Icon-Only Hover still used the Gray-series background (should be the Tinted series)
- Quaternary Icon-Only Hover / Clicked still overlaid a Tinted background (should remove the background and only change the icon color)
Changed Files
packages/design/src/components/Button/styles.tspackages/design/src/components/Button/Button.test.tsxpackages/design-site/docs/components/atomic/button.mdx
Changes
- Added
BUTTON_ICON_ONLY_VARIANT_CLASS: provides dedicated interaction styles fortertiary/quaternaryonly whensize === 'icon'; text buttons (other sizes) behave exactly as before- Tertiary Icon-Only: Hover
Grays/Tinted/Default, ClickedGrays/Tinted/Emphasized(replacing the original Gray-1 / Gray-2) - Quaternary Icon-Only: removes the hover/active background and switches to icon color changes — Default
Labels/Tertiary→ HoverLabels/Primary→ ClickedLabels/Secondary
- Tertiary Icon-Only: Hover
- When
size === 'icon',getButtonTokenClassprefers the Icon-Only variant class, falling back to the generic variant class on a miss - Added unit tests: cover the new state classes for Tertiary / Quaternary Icon-Only, and assert that text-size buttons keep their original background
- design-site Button docs add an Icon-Only interaction state description in the Icon Button section
Notes
(Figma nodes)
- Tertiary Hover:
20935:1573 - Quaternary Hover:
21220:2584 - Quaternary Clicked:
21220:2586
(Linear)
- Parent issue: DES-113 Button
- Sub issue: DES-114 Button: Icon-Only 交互状态调整 + disabled/loading 光标修复
- Design request: DES-87 Button Icon-Only 交互状态调整 — Tertiary Hover / Quaternary Hover & Clicked
2026-06-16 Button disabled / loading state restores the not-allowed cursor
Problem
Every variant of BUTTON_DISABLED_CLASS already declared disabled:cursor-not-allowed, but it had no effect: the UI structure layer BUTTON_STRUCTURE_CLASS always carries disabled:pointer-events-none (unstyledVisual only turns off visuals and keeps the structure classes), and pointer-events: none disables cursor styling. The result was that disabled buttons, as well as loading buttons (loading sets the disabled attribute), showed only the default cursor instead of not-allowed.
Changed Files
packages/design/src/components/Button/styles.tspackages/design/src/components/Button/Button.test.tsx
Changes
BUTTON_BASE_CLASSaddsdisabled:pointer-events-auto, which viamergeClass(tailwind-merge) overrides the structure layer'sdisabled:pointer-events-none, making the existingdisabled:cursor-not-allowedactually take effect; clicks are still intercepted by the nativedisabledattribute- Disabled visuals are unaffected: in Tailwind, the
disabled:variant is generated afterhover:/active:, so at the same specificity disabled still overrides hover/active colors - loading and disabled share the
disabledattribute, so a single fix covers both states - Knock-on fix for the link variant: after
disabled:pointer-events-autore-enables pointer events, hovering a link triggershover:underline, causing an underline to appear on hover in the disabled/loading state. Addeddisabled:no-underlineto the disabled classes oflink-color/link-gray(thedisabled:variant is generated afterhover:, overridinghover:underline) - Added unit tests: the loading state asserts
disabled:pointer-events-auto+disabled:cursor-not-allowed; the primary disabled case adds the same two assertions; the link variant disabled/loading assertsdisabled:no-underline - Audited the remaining interactive components (Input / Textarea / Select / Checkbox / RadioGroup / Switch / Upload / DatePicker / TimePicker / Calendar / Tree / Tabs / DropdownMenu / AiButton, etc.): found no actual instance of the same "cursor-not-allowed canceled out by pointer-events-none" issue (most use
unstyledVisualto remove the UI-layer pointer-events-none, or use Radixdata-disabledwith a cursor element that has no pointer-events-none); Button is the only existing instance