Skip to content

feat: standardize button loading state#221

Merged
Devasy merged 2 commits intomainfrom
palette-button-loading-state-10913018087186906385
Jan 1, 2026
Merged

feat: standardize button loading state#221
Devasy merged 2 commits intomainfrom
palette-button-loading-state-10913018087186906385

Conversation

@google-labs-jules
Copy link
Contributor

@google-labs-jules google-labs-jules bot commented Dec 30, 2025

🎨 Palette UX Improvement

What: Standardized the loading state for buttons.
Why: The "Sign in" button used manual text replacement ("Processing...") which caused layout shifts and inconsistency.
How:

  • Created a reusable Spinner component.
  • Added isLoading prop to the shared Button component.
  • Updated Auth.tsx to use this new prop.

Accessibility:

  • Button receives aria-disabled="true" when loading.
  • Spinner has a default "Loading" aria-label (customizable).
  • Focus management is handled by the disabled attribute.

Verification:

  • Verified visually with Playwright screenshot (checked for spinner appearance and layout stability).
  • Verified build and type safety.

PR created automatically by Jules for task 10913018087186906385 started by @Devasy23

Summary by CodeRabbit

  • New Features

    • Buttons now show a standardized loading spinner and become disabled during async actions to prevent duplicate submissions.
  • Improvements

    • Unified loading state across the app for consistent appearance and behavior.
  • Documentation

    • Added a journal entry describing the standardized button loading state and rationale.

✏️ Tip: You can customize this high-level summary in your review settings.

Refactors the Button component to support an `isLoading` prop, ensuring consistent loading feedback across the application. Replaces manual "Processing..." text in Auth page with this new standard.

- Adds `isLoading` prop to `Button` component
- Creates `Spinner` component
- Updates Auth page to use `isLoading`
- Improves accessibility with `aria-disabled` and `role="status"`
@google-labs-jules
Copy link
Contributor Author

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!


For security, I will only act on instructions from the user who triggered this task.

New to Jules? Learn more at jules.google/docs.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 30, 2025

Walkthrough

Adds a reusable Spinner component and an isLoading prop to the Button component; updates the Auth page to use the new Spinner and isLoading pattern; documents the change in .Jules/palette.md.

Changes

Cohort / File(s) Change Summary
Documentation
./.Jules/palette.md
Added journal entry: "2024-05-22 - Standardized Button Loading State" describing the decision to standardize loading UI and prevent layout shifts/multiple submissions.
UI Components
web/components/ui/Button.tsx, web/components/ui/Spinner.tsx
Added Spinner component (SpinnerProps: size?: number, className?: string, ariaLabel?: string). Extended ButtonProps with isLoading?: boolean; button disables and sets aria-disabled when isLoading and conditionally renders Spinner.
Page Integration
web/pages/Auth.tsx
Replaced manual inline loading UI with the Spinner in the Google sign-in button and switched submit button to use isLoading (removed prior processing text logic).

Pre-merge checks

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: standardize button loading state' accurately and concisely describes the main objective of the pull request—introducing a standardized loading state mechanism for buttons to improve consistency and prevent layout shifts.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

📜 Recent review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f937234 and 8a2fcee.

📒 Files selected for processing (1)
  • web/components/ui/Spinner.tsx
🧰 Additional context used
🪛 Biome (2.1.2)
web/components/ui/Spinner.tsx

[error] 16-16: The elements with this role can be changed to the following elements:

For examples and more information, see WAI-ARIA Roles

(lint/a11y/useSemanticElements)

🔇 Additional comments (3)
web/components/ui/Spinner.tsx (3)

1-2: LGTM! Clean imports.

The imports are correctly structured for the component's needs.


4-8: LGTM! Well-defined interface.

The props interface provides good flexibility with appropriate types for customization.


10-24: Excellent accessibility implementation! Static analysis warning can be ignored.

The component correctly implements the accessibility pattern requested in the previous review—wrapping the icon in a container with role="status" and aria-label while hiding the decorative icon with aria-hidden="true".

Regarding the Biome warning suggesting <output> instead of role="status": this is a false positive. The <output> element is semantically intended for form calculation results, not loading indicators. The role="status" on a div is the correct WAI-ARIA pattern for announcing polite loading state changes to assistive technologies.


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.

@netlify
Copy link

netlify bot commented Dec 30, 2025

Deploy Preview for split-but-wiser ready!

Name Link
🔨 Latest commit 8a2fcee
🔍 Latest deploy log https://app.netlify.com/projects/split-but-wiser/deploys/6956601b9aaa9300081b6dde
😎 Deploy Preview https://deploy-preview-221--split-but-wiser.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

Devasy
Devasy previously approved these changes Jan 1, 2026
Copy link
Owner

@Devasy Devasy left a comment

Choose a reason for hiding this comment

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

Lgtm

@Devasy Devasy marked this pull request as ready for review January 1, 2026 11:45
@Devasy Devasy requested a review from vrajpatelll as a code owner January 1, 2026 11:45
@Devasy
Copy link
Owner

Devasy commented Jan 1, 2026

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 1, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Contributor

@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: 2

📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 22f39f1 and f937234.

📒 Files selected for processing (4)
  • .Jules/palette.md
  • web/components/ui/Button.tsx
  • web/components/ui/Spinner.tsx
  • web/pages/Auth.tsx
🧰 Additional context used
📓 Path-based instructions (1)
web/pages/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Web pages should be created as components in web/pages/ and added to routing configuration

Files:

  • web/pages/Auth.tsx
🧬 Code graph analysis (2)
web/pages/Auth.tsx (2)
web/components/ui/Spinner.tsx (1)
  • Spinner (10-23)
web/components/ui/Button.tsx (1)
  • Button (12-62)
web/components/ui/Button.tsx (1)
web/components/ui/Spinner.tsx (1)
  • Spinner (10-23)
🪛 markdownlint-cli2 (0.18.1)
.Jules/palette.md

3-3: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)

🔇 Additional comments (7)
web/components/ui/Button.tsx (4)

4-4: LGTM: Clean integration of Spinner component.

The import is properly added and used consistently within the Button implementation.


9-9: LGTM: isLoading prop added to interface.

The new optional prop integrates cleanly with existing ButtonProps, maintaining backward compatibility.


16-18: LGTM: Proper prop extraction and defaults.

The isLoading default of false ensures backward compatibility, and explicitly extracting the disabled prop allows proper combination logic.


54-59: LGTM: Excellent loading state implementation.

The implementation correctly:

  • Combines isLoading || disabled to prevent interaction during loading
  • Sets both disabled and aria-disabled for robust accessibility
  • Sizes the spinner appropriately (16px for sm, 20px for md/lg buttons)
  • Renders the spinner before children to provide immediate visual feedback

This pattern prevents multiple submissions and provides consistent loading UX while minimizing layout shifts compared to text-replacement approaches.

web/pages/Auth.tsx (3)

7-7: LGTM: Spinner import added for reusable loading indicators.

The Spinner component is properly imported and used for both the Google sign-in button and the main submit Button's internal loading state.


173-179: LGTM: Google button now uses standardized Spinner.

The inline loading indicator has been replaced with the reusable Spinner component, featuring:

  • Appropriate size (20px)
  • Theme-aware styling via className
  • Descriptive aria-label for better accessibility

This aligns the Google sign-in button with the standardized loading pattern.


255-261: LGTM: Submit button successfully migrated to isLoading pattern.

Excellent refactoring that:

  • Uses the standardized isLoading prop instead of manual text changes
  • Maintains consistent button text ("Log In" / "Create Account") during loading
  • Prevents layout shifts caused by text replacement
  • Automatically handles disabled state and accessibility through the Button component

The Spinner now appears alongside the text and ArrowRight icon, providing clear visual feedback without the jarring text swap to "Processing...".

Wraps the Spinner icon in a div with proper role and label, hiding the decorative icon from screen readers as requested in review.
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 1, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Owner

@Devasy Devasy left a comment

Choose a reason for hiding this comment

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

Lgtm

@Devasy Devasy merged commit e24679c into main Jan 1, 2026
12 checks passed
@Devasy Devasy deleted the palette-button-loading-state-10913018087186906385 branch January 1, 2026 11:58
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.

1 participant