Skip to content

fix: added loading state for initial load#7486

Open
cchirag wants to merge 1 commit intousebruno:mainfrom
cchirag:fix/initial-load
Open

fix: added loading state for initial load#7486
cchirag wants to merge 1 commit intousebruno:mainfrom
cchirag:fix/initial-load

Conversation

@cchirag
Copy link
Contributor

@cchirag cchirag commented Mar 14, 2026

Description

Contribution Checklist:

  • I've used AI significantly to create this pull request
  • The pull request only addresses one issue or adds one feature.
  • The pull request does not introduce any breaking changes
  • I have added screenshots or gifs to help explain the change if applicable.
  • I have read the contribution guidelines.
  • Create an issue and link to the pull request.

Note: Keeping the PR small and focused helps make it easier to review and merge. If you have multiple changes you want to make, please consider submitting them as separate pull requests.

Publishing to New Package Managers

Please see here for more information.

Summary by CodeRabbit

Release Notes

  • New Features

    • Spinner component now supports multiple size variants (xs, sm, md, lg, xl).
    • Spinner can display accompanying text content.
  • Style

    • Redesigned spinner with improved animation and visual appearance.
    • Loading indicator now displays when workspace is initializing.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 14, 2026

Walkthrough

The Spinner component is refactored with configurable sizes and CSS keyframe animations, and RequestTabPanel now displays a loading state when the active workspace lacks scratchCollectionUid.

Changes

Cohort / File(s) Summary
Spinner Component Refactor
packages/bruno-app/src/components/Spinner/StyledWrapper.js, packages/bruno-app/src/components/Spinner/index.js
Enhanced Spinner with size variants (xs, sm, md, lg, xl), CSS keyframe animations, and inline SVG spinner. API signature changed: removed color prop, added size prop with 'md' default.
RequestTabPanel Integration
packages/bruno-app/src/components/RequestTabPanel/index.js
Added guard condition to render centered Spinner when active workspace lacks scratchCollectionUid, preventing further UI rendering.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • helloanoop
  • lohit-bruno
  • naman-bruno
  • bijin-bruno

Poem

A spinner twirls with grace so fine, ✨
In sizes five, it comes to shine,
When workspaces lack their sacred key,
A loading state waits patiently! 🌀

🚥 Pre-merge checks | ✅ 3
✅ 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 accurately describes the main change: adding a loading state (Spinner) when initial workspace data lacks scratchCollectionUid before UI renders.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
📝 Coding Plan
  • Generate coding plan for human review comments

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.

Tip

You can disable the changed files summary in the walkthrough.

Disable the reviews.changed_files_summary setting to disable the changed files summary in the walkthrough.

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

🧹 Nitpick comments (1)
packages/bruno-app/src/components/Spinner/StyledWrapper.js (1)

54-57: Respect reduced-motion for the infinite spinner animation.

This now animates forever for every spinner. Please disable it under prefers-reduced-motion so motion-sensitive users get a static indicator instead.

Possible fix
   .spinner {
     display: inline-flex;
     animation: ${spin} 0.75s linear infinite;
   }
+
+  `@media` (prefers-reduced-motion: reduce) {
+    .spinner {
+      animation: none;
+    }
+  }
 
   .spinner-text {
     font-size: 0.875rem;
     color: inherit;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/bruno-app/src/components/Spinner/StyledWrapper.js` around lines 54 -
57, The spinner CSS currently always applies animation: ${spin} 0.75s linear
infinite on the .spinner selector; add a prefers-reduced-motion media query that
targets .spinner and disables the animation (e.g., set animation: none) so
motion-sensitive users see a static indicator. Update the StyledWrapper where
.spinner and the spin keyframe are defined to include `@media`
(prefers-reduced-motion: reduce) { .spinner { animation: none; } }.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/bruno-app/src/components/RequestTabPanel/index.js`:
- Around line 180-186: RequestTabPanel is using the absence of
activeWorkspace?.scratchCollectionUid to show a loading spinner which can
permanently block rendering when mountScratchCollection() returns null (and
switchWorkspace() continues); change the guard so that rendering is keyed off an
explicit workspace-loading flag (e.g., workspaceLoading from the workspace slice
or the action that calls mountScratchCollection/switchWorkspace) or move the
scratchCollectionUid check below the branches that render tabs which do not
depend on the scratch collection (for example the "preferences",
"global-environment-settings", and workspace tabs). Specifically, in
RequestTabPanel replace the current top-level check on
activeWorkspace?.scratchCollectionUid with either (a) a check for a dedicated
loading boolean provided by the workspaces reducer/actions (consume
workspaceLoading) before showing the spinner, or (b) relocate the
scratchCollectionUid-dependent guard to only wrap components that need it,
leaving tab branches that don't depend on scratchCollectionUid to render
normally; reference mountScratchCollection, switchWorkspace, activeWorkspace,
scratchCollectionUid and the RequestTabPanel component to locate the code to
change.

In `@packages/bruno-app/src/components/Spinner/index.js`:
- Around line 4-35: The Spinner component currently renders an unlabeled SVG;
update the component (Spinner, StyledWrapper and the span.spinner wrapper) to
include role="status" on the wrapper and provide an accessible label when no
children are passed (e.g., set aria-label="Loading" or aria-live if you prefer)
so assistive tech announces the loading state, and mark the SVG as purely
decorative by adding aria-hidden="true" (and focusable="false") on the svg
element; ensure existing visible children still render as the announcement
instead of the default label.

---

Nitpick comments:
In `@packages/bruno-app/src/components/Spinner/StyledWrapper.js`:
- Around line 54-57: The spinner CSS currently always applies animation: ${spin}
0.75s linear infinite on the .spinner selector; add a prefers-reduced-motion
media query that targets .spinner and disables the animation (e.g., set
animation: none) so motion-sensitive users see a static indicator. Update the
StyledWrapper where .spinner and the spin keyframe are defined to include `@media`
(prefers-reduced-motion: reduce) { .spinner { animation: none; } }.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 473681db-d16e-44cb-8d0f-eab14b489258

📥 Commits

Reviewing files that changed from the base of the PR and between 83ddfc3 and c994e44.

📒 Files selected for processing (3)
  • packages/bruno-app/src/components/RequestTabPanel/index.js
  • packages/bruno-app/src/components/Spinner/StyledWrapper.js
  • packages/bruno-app/src/components/Spinner/index.js

Comment on lines +180 to +186
if (!activeWorkspace?.scratchCollectionUid) {
return (
<div className="w-full h-full flex items-center justify-center">
<Spinner size="lg" />
</div>
);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Don't use scratchCollectionUid absence as the loading signal.

mountScratchCollection() can return null in packages/bruno-app/src/providers/ReduxStore/slices/workspaces/actions.js:986-1049, and switchWorkspace() still continues in packages/bruno-app/src/providers/ReduxStore/slices/workspaces/actions.js:347-398. In that path, Line 180 becomes a permanent spinner, and it also blocks tabs like preferences, global-environment-settings, and workspace tabs that do not depend on the scratch collection at all. Please key this off an explicit workspace-loading flag, or move the guard below the branches that can render without scratchCollectionUid.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/bruno-app/src/components/RequestTabPanel/index.js` around lines 180
- 186, RequestTabPanel is using the absence of
activeWorkspace?.scratchCollectionUid to show a loading spinner which can
permanently block rendering when mountScratchCollection() returns null (and
switchWorkspace() continues); change the guard so that rendering is keyed off an
explicit workspace-loading flag (e.g., workspaceLoading from the workspace slice
or the action that calls mountScratchCollection/switchWorkspace) or move the
scratchCollectionUid check below the branches that render tabs which do not
depend on the scratch collection (for example the "preferences",
"global-environment-settings", and workspace tabs). Specifically, in
RequestTabPanel replace the current top-level check on
activeWorkspace?.scratchCollectionUid with either (a) a check for a dedicated
loading boolean provided by the workspaces reducer/actions (consume
workspaceLoading) before showing the spinner, or (b) relocate the
scratchCollectionUid-dependent guard to only wrap components that need it,
leaving tab branches that don't depend on scratchCollectionUid to render
normally; reference mountScratchCollection, switchWorkspace, activeWorkspace,
scratchCollectionUid and the RequestTabPanel component to locate the code to
change.

Comment on lines +4 to +35
const Spinner = ({ size = 'md', children }) => {
const sizeMap = {
xs: 12,
sm: 16,
md: 20,
lg: 24,
xl: 32
};

const spinnerSize = sizeMap[size] || 20;

return (
<StyledWrapper>
<div className="animate-spin"></div>
{children && <div>{children}</div>}
<StyledWrapper $size={size}>
<span className="spinner">
<svg
width={spinnerSize}
height={spinnerSize}
viewBox="0 0 24 24"
fill="none"
>
<circle
cx="12"
cy="12"
r="10"
stroke="currentColor"
strokeWidth="3"
strokeLinecap="round"
strokeDasharray="31.4 31.4"
/>
</svg>
</span>
{children && <div className="spinner-text">{children}</div>}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Expose status semantics for standalone spinners.

The new initial-load path in packages/bruno-app/src/components/RequestTabPanel/index.js:180-184 renders this with no text. Right now it's just an unlabeled SVG, so assistive tech gets no loading announcement. Please give the wrapper a status role/label and mark the SVG decorative.

Possible fix
-const Spinner = ({ size = 'md', children }) => {
+const Spinner = ({ size = 'md', children, label = 'Loading' }) => {
   const sizeMap = {
     xs: 12,
     sm: 16,
     md: 20,
     lg: 24,
     xl: 32
   };

   const spinnerSize = sizeMap[size] || 20;

   return (
-    <StyledWrapper $size={size}>
-      <span className="spinner">
+    <StyledWrapper
+      $size={size}
+      role="status"
+      aria-label={children ? undefined : label}
+    >
+      <span className="spinner" aria-hidden="true">
         <svg
           width={spinnerSize}
           height={spinnerSize}
           viewBox="0 0 24 24"
           fill="none"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const Spinner = ({ size = 'md', children }) => {
const sizeMap = {
xs: 12,
sm: 16,
md: 20,
lg: 24,
xl: 32
};
const spinnerSize = sizeMap[size] || 20;
return (
<StyledWrapper>
<div className="animate-spin"></div>
{children && <div>{children}</div>}
<StyledWrapper $size={size}>
<span className="spinner">
<svg
width={spinnerSize}
height={spinnerSize}
viewBox="0 0 24 24"
fill="none"
>
<circle
cx="12"
cy="12"
r="10"
stroke="currentColor"
strokeWidth="3"
strokeLinecap="round"
strokeDasharray="31.4 31.4"
/>
</svg>
</span>
{children && <div className="spinner-text">{children}</div>}
const Spinner = ({ size = 'md', children, label = 'Loading' }) => {
const sizeMap = {
xs: 12,
sm: 16,
md: 20,
lg: 24,
xl: 32
};
const spinnerSize = sizeMap[size] || 20;
return (
<StyledWrapper
$size={size}
role="status"
aria-label={children ? undefined : label}
>
<span className="spinner" aria-hidden="true">
<svg
width={spinnerSize}
height={spinnerSize}
viewBox="0 0 24 24"
fill="none"
>
<circle
cx="12"
cy="12"
r="10"
stroke="currentColor"
strokeWidth="3"
strokeLinecap="round"
strokeDasharray="31.4 31.4"
/>
</svg>
</span>
{children && <div className="spinner-text">{children}</div>}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/bruno-app/src/components/Spinner/index.js` around lines 4 - 35, The
Spinner component currently renders an unlabeled SVG; update the component
(Spinner, StyledWrapper and the span.spinner wrapper) to include role="status"
on the wrapper and provide an accessible label when no children are passed
(e.g., set aria-label="Loading" or aria-live if you prefer) so assistive tech
announces the loading state, and mark the SVG as purely decorative by adding
aria-hidden="true" (and focusable="false") on the svg element; ensure existing
visible children still render as the announcement instead of the default label.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant