Skip to content

feat(#48): redesign and implement loader animation (skeleton loader family)#102

Draft
RudoiDmytro wants to merge 1 commit into
mainfrom
feat/48-loader-animation
Draft

feat(#48): redesign and implement loader animation (skeleton loader family)#102
RudoiDmytro wants to merge 1 commit into
mainfrom
feat/48-loader-animation

Conversation

@RudoiDmytro

@RudoiDmytro RudoiDmytro commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Summary

Closes #48. Redesigns the CRM's fragmented loading experience (disabled gray submit button +
detached 70px CircularProgress, inconsistent loaders elsewhere, no prefers-reduced-motion,
failing disabled-label contrast) around one skeleton-based loader family of five types that
share the existing CSS shimmer as a single motion source-of-truth.

This PR ships in two stages, both landing here:

  • Planning artifacts — full BMAD suite under specs/planning-artifacts/loader-animation/
  • Implementation — epics E1–E6 from the suite, to follow in subsequent commits on this branch

Planning suite (read in this order)

# Document What it covers
1 prd.md Goals, personas, FR1–FR25 / NFR1–NFR16, acceptance criteria mapped to the issue
2 ux-design.md Motion/timing scale, reduced-motion strategy, the 5 loader spec cards, L2 deep-dive, WCAG mapping
3 architecture.md Shared motion module, the 5 UI* components, submit-button refactor, DRY/complexity/perf/testing strategy, migration plan
4 epics-and-stories.md Epics E1–E6, implementable stories with acceptance criteria, FR→story coverage matrix

There is intentionally no product brief: for this scoped brownfield enhancement the GitHub
issue is the analysis-phase artifact, and the PRD's Overview/Context absorbs it.

The loader family

ID Component (UI*) Context
L1 UISkeletonPlaceholder Page / form initial load (formalizes today's auth skeleton)
L2 UISubmitLoadingButton Submit-button loading state — the issue's hero case: the pressed button morphs in place into a shimmering skeleton track
L3 UIInlineLoader Small inline indeterminate indicator (e.g. the auth switcher)
L4 UISectionLoader Route / section / overlay load (opt-in region veil)
L5 UIProgressBar Determinate progress (reserved primitive, opt-in)

All five inherit one motion source, one prefers-reduced-motion contract, and one
accessible-status primitive, so the family stays within the jscpd DRY gate, the
rust-code-analysis complexity caps, and the auth-page mobile Lighthouse budget
(pure CSS, no new dependencies). Each loader ships a co-located Storybook preview
covering animated and reduced-motion states.

Repo plumbing

  • .markdownlintignore now excludes specs/ — prose planning artifacts with wide
    tables, not code-grade markdown. make lint-md passes; the full pre-commit gate
    (format + lint + all unit tests) ran green on commit.

Summary by cubic

Adds the planning suite for a unified skeleton loader family (five types) to replace inconsistent loaders across the app, per issue #48. Also updates .markdownlintignore to exclude specs/.

Written for commit 40901a7. Summary will update on new commits.

Review in cubic

…rchitecture, epics)

Exclude specs/ from markdownlint: prose artifacts with wide tables, not code-grade markdown.
@coderabbitai

coderabbitai Bot commented Jun 12, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2819c0ed-5ee2-42a9-bbdf-873101ce4031

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

@cubic-dev-ai cubic-dev-ai 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.

1 issue found across 6 files

Confidence score: 5/5

  • In specs/planning-artifacts/loader-animation/README.md, the summary claims FR1–FR25 while the PRD includes FR26–FR28, which could mislead reviewers about scope and cause focus-management/Storybook preview requirements to be missed later—update the README coverage line to include FR26–FR28 before or immediately after merge.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="specs/planning-artifacts/loader-animation/README.md">

<violation number="1" location="specs/planning-artifacts/loader-animation/README.md:22">
P3: README summary understates PRD FR coverage: says FR1–FR25 but PRD defines FR26, FR27, FR28 (focus management + Storybook previews).</violation>
</file>
Architecture diagram
sequenceDiagram
    participant User as User
    participant App as React App Shell
    participant AuthPage as Auth Page
    participant FormSection as FormSection (lazy chunk)
    participant UIForm as UIForm / SubmitControls
    participant UIButton as UIButton
    participant LoaderFamily as Loader Family (L1-L5)
    participant SharedMotion as Shared Motion Module (base/styles.ts)
    participant ScreenReader as Screen Reader
    participant VisualTest as Visual Snapshot Test

    Note over User,VisualTest: CURRENT STATE BEFORE PR (fragmented loading)

    User->>App: Navigate to auth page
    App->>AuthPage: Mount
    AuthPage->>AuthPage: <Suspense fallback={<AuthSkeleton/>}>
    Note over AuthPage: Renders region landmark on decorative content
    AuthPage-->>User: Shimmer skeleton (animated, no reduced-motion support)
    AuthPage->>FormSection: Lazy load

    User->>UIForm: Fill form, press submit
    UIForm->>UIButton: Set disabled=true
    UIForm->>UIForm: Show <CircularProgress size={70}> beside button
    Note over UIForm: Button goes flat gray (#E1E7EA) + detached spinner
    Note over UIForm: White text on #E1E7EA = ~1.25:1 contrast failure
    UIButton-->>User: Disabled button + spinner

    User->>ScreenReader: Focus / navigate
    ScreenReader->>AuthPage: Reads region landmark on decorative skeleton
    ScreenReader->>UIForm: Hears disabled button, no loading feedback from spinner

    VisualTest->>VisualTest: emulateMedia({ reducedMotion: 'reduce' })
    VisualTest->>AuthPage: Takes snapshot - captures static fallback (not animated shimmer)

    Note over User,VisualTest: Silent waits with no loader at all
    User->>FormSection: Switch login/register form
    FormSection->>UIButton: Set disabled=true (no spinner, no loader)
    UIButton-->>User: Just disabled switch - no pending feedback

    User->>FormSection: Click retry on registration error
    FormSection->>UIButton: Set disabled=true (inside role="alert" live region)
    UIButton-->>User: Disabled button, no loading signal
Loading

Tip: cubic can generate docs of your entire codebase and keep them up to date. Try it here.

Re-trigger cubic


| # | Document | What it covers |
| --- | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------ |
| 1 | [`prd.md`](./prd.md) | Goals, personas, FR1–FR25 / NFR1–NFR16, acceptance criteria mapped to the issue |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P3: README summary understates PRD FR coverage: says FR1–FR25 but PRD defines FR26, FR27, FR28 (focus management + Storybook previews).

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At specs/planning-artifacts/loader-animation/README.md, line 22:

<comment>README summary understates PRD FR coverage: says FR1–FR25 but PRD defines FR26, FR27, FR28 (focus management + Storybook previews).</comment>

<file context>
@@ -0,0 +1,54 @@
+
+| #   | Document                                         | What it covers                                                                                                                 |
+| --- | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------ |
+| 1   | [`prd.md`](./prd.md)                             | Goals, personas, FR1–FR25 / NFR1–NFR16, acceptance criteria mapped to the issue                                                |
+| 2   | [`ux-design.md`](./ux-design.md)                 | Motion/timing scale, reduced-motion strategy, the 5 loader spec cards, L2 deep-dive, WCAG mapping                              |
+| 3   | [`architecture.md`](./architecture.md)           | Shared motion module, the 5 `UI*` components, the submit-button refactor, DRY/complexity/perf/testing strategy, migration plan |
</file context>
Suggested change
| 1 | [`prd.md`](./prd.md) | Goals, personas, FR1–FR25 / NFR1–NFR16, acceptance criteria mapped to the issue |
| 1 | [`prd.md`](./prd.md) | Goals, personas, FR1–FR28 / NFR1–NFR16, acceptance criteria mapped to the issue |

@RudoiDmytro RudoiDmytro self-assigned this Jun 12, 2026
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.

Redesign and implement loader animation

1 participant