Skip to content

fix(Button): restore loading state visuals broken by CSS Modules migration#1043

Merged
elizabetdev merged 2 commits into
mainfrom
fix/button-loading-state-css-modules
May 27, 2026
Merged

fix(Button): restore loading state visuals broken by CSS Modules migration#1043
elizabetdev merged 2 commits into
mainfrom
fix/button-loading-state-css-modules

Conversation

@elizabetdev
Copy link
Copy Markdown
Member

@elizabetdev elizabetdev commented May 27, 2026

Summary

The CSS Modules migration of Button regressed two pieces of the original loading behavior introduced in #741. The regression landed as part of #931chore(css-modules): support local visual regression testing via docker — which bundled the Button-to-CSS-Modules migration together with the initial CSS Modules tooling and Playwright setup, so the snapshots were captured against the already-broken implementation and no pre-migration baseline existed to diff against.

The two regressions:

  • :disabled background applied while loading. The original styled-components only emitted the disabled background-color rule when !$loading, so a loading danger button kept its default light-red background under the shimmer. After the migration the disabled rule was unconditional, so loading buttons rendered with the gray disabled background.
  • Single shimmer keyframe. The original shipped two keyframes: shimmerFullWidth (100% → -100%, 200% size, repeat) for fillWidth, and shimmerFixedWidth (-200px → 200px, 200px size, no-repeat) for fixed-width. The migration collapsed both into one fill-width-style keyframe.

This PR restores both behaviors in Button.module.css:

  • Qualify each .button_<type>:disabled rule with :not(.button_loading), so the per-type background-color stays under the shimmer overlay while loading.
  • Reintroduce shimmer-fixed and shimmer-fill keyframes, switched on .button_fill.
  • Set the loading gradient via background-image (not the background shorthand) so per-type rules don't clobber background-size / background-repeat.
  • Widen the prefers-reduced-motion selector to cover both shimmer variants.

A new FillWidthLoading story plus a fill-width loading entry in the Playwright spec lock in the second shimmer mode. Snapshots regenerated.

Before / after

Before (broken) After (this PR)
Danger / Loading (light) gray disabled background, half-frozen gradient light-red default background with shimmer overlay
Primary / Loading (fill width) one shared keyframe, behaved as fill-width fixed-width and fill-width animate independently

Test plan

  • yarn lint:css
  • yarn lint:code
  • yarn test Button (10/10)
  • yarn build
  • yarn test:visual tests/buttons/button.spec.ts (46/46, snapshots regenerated)
  • Manual: live storybook side-by-side against PR Add button loading states #741 behavior — danger, primary, secondary, empty, and fill-width loading all render with the correct default background and a smooth shimmer sweep

Note

Low Risk
Scoped to Button CSS, stories, and visual tests; no API or runtime logic changes beyond styling.

Overview
Restores Button loading visuals that regressed during the CSS Modules migration.

Disabled vs loading: :disabled styles for primary, secondary, empty, and danger now use :not(.button_loading), so loading buttons keep their variant default background (e.g. danger stays light red) instead of the gray disabled fill.

Shimmer: Brings back two animations—fixed-width (shimmer-fixed-width) for normal buttons and fill-width (shimmer-fill-width) when fillWidth is set—via renamed button_fill_width and a dedicated .button_fill_width.button_loading::before rule. Loading gradients use background-image so size/repeat on the pseudo-element are not reset.

Adds a FillWidthLoading Storybook story, Playwright snapshots for fill-width loading (light/dark), and a patch changeset for @clickhouse/click-ui.

Reviewed by Cursor Bugbot for commit 64354e0. Bugbot is set up for automated code reviews on this repo. Configure here.

…ation

Pre-migration the styled-components Button skipped the :disabled background
when loading and shipped two distinct shimmer keyframes (200px fixed-width
vs 200% fill-width). The CSS Modules migration applied :disabled
unconditionally and collapsed the shimmer to a single fill-width keyframe,
so a loading danger button rendered gray with a half-frozen gradient
instead of light red with a sweeping shimmer.

- Qualify .button_<type>:disabled with :not(.button_loading) so the
  per-type background-color stays under the shimmer overlay while loading.
- Reintroduce shimmer-fixed (-200px → 200px) and shimmer-fill
  (100% → -100%) keyframes, switched on .button_fill.
- Set the loading gradient via background-image so the per-type rule no
  longer clobbers background-size / background-repeat.
- Add a FillWidthLoading story and a fill-width loading spec entry, and
  regenerate the affected snapshots.

Co-authored-by: Cursor <cursoragent@cursor.com>
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 27, 2026

🦋 Changeset detected

Latest commit: 64354e0

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@clickhouse/click-ui Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Comment thread src/components/Button/Button.module.css Outdated
}

@keyframes shimmer {
@keyframes shimmer-fixed {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

For clarity, can we call this shimmer-fixed-width? shimmer-fixed reads kind of like it's fixing a problem.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Renamed to shimmer-fixed-width in 64354e0. Good catch on the "fixing" ambiguity.

Comment thread src/components/Button/Button.module.css Outdated
}
}

@keyframes shimmer-fill {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

For clarity, I think this would be better named shimmer-fill-width

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Renamed to shimmer-fill-width in 64354e0 for parallel naming.

Comment thread src/components/Button/Button.module.css Outdated
animation: shimmer-fixed 1.5s ease-in-out infinite;
}

.button_fill.button_loading::before {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

in the vein of the other changes, I think this would be clearer named button_fill_width

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Renamed .button_fill.button_fill_width in 64354e0 (matches the fillWidth prop name). All cva, CSS, and reduced-motion references updated; visual snapshots still pass byte-for-byte since this is a pure CSS-name rename.

Address review feedback from @hoorayimhelping:

- .button_fill → .button_fill_width (matches the fillWidth prop)
- shimmer-fixed → shimmer-fixed-width (avoids reading like "fixing")
- shimmer-fill → shimmer-fill-width (parallel naming)

Pure CSS-name rename; visual snapshots unchanged.

Co-authored-by: Cursor <cursoragent@cursor.com>
@elizabetdev elizabetdev enabled auto-merge (squash) May 27, 2026 13:53
@elizabetdev elizabetdev merged commit 55c69af into main May 27, 2026
11 checks passed
@elizabetdev elizabetdev deleted the fix/button-loading-state-css-modules branch May 27, 2026 13:53
@workflow-authentication-public
Copy link
Copy Markdown
Contributor

Storybook Preview Deployed

✅ Preview URL: https://click-9gc30bmay-clickhouse.vercel.app

Built from commit: 9fcfad594f866aea47c93fa2e25aaca6990e4900

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.

3 participants