From ab93fa7991dc13483d9d7bd731c88e758e0fcb81 Mon Sep 17 00:00:00 2001 From: theFirstCodeManiac Date: Sat, 4 Jul 2026 08:51:15 +0100 Subject: [PATCH] feat: define branded loading state hierarchy with shimmer token - Add --shimmer-gradient design token to :root in index.css - Add @keyframes shimmer, spin-loader with prefers-reduced-motion fallback - Add CSS classes: .animate-shimmer, .animate-spin-loader, .skeleton, .skeleton-text/title/avatar/rect, .progress-bar-*, .page-loader-* - New LoadingSpinner component: aria-hidden-aware, uses animate-spin-loader - New ProgressBar component: determinate + indeterminate modes, WCAG progressbar role - New PageLoader component: full-screen overlay, role=status, aria-live=polite - New Skeleton component: 5 variants, count prop, aria-hidden=true - Refactor Button to use LoadingSpinner instead of raw Loader2 - Refactor AuthSubmitButton to use LoadingSpinner - Refactor StatusTimeline in-progress icon to use LoadingSpinner - Add docs/LOADING_STATES.md: latency thresholds, usage guidelines, examples WCAG 2.1 AA: - Spinners include role=img + aria-label when visible; aria-hidden when decorative - Shimmer pauses under prefers-reduced-motion - ProgressBar exposes aria-valuenow / aria-valuemin / aria-valuemax - PageLoader announces via aria-live=polite Refs: feat/loading-progress-hierarchy --- docs/LOADING_STATES.md | 85 + src/components/AuthSubmitButton.tsx | 12 +- src/components/Button.tsx | 6 +- src/components/LoadingSpinner.tsx | 32 + src/components/PageLoader.tsx | 23 + src/components/ProgressBar.tsx | 55 + src/components/Skeleton.tsx | 70 + .../StatusTimeline/StatusTimeline.tsx | 5 +- src/index.css | 1984 +++++++++-------- 9 files changed, 1340 insertions(+), 932 deletions(-) create mode 100644 docs/LOADING_STATES.md create mode 100644 src/components/LoadingSpinner.tsx create mode 100644 src/components/PageLoader.tsx create mode 100644 src/components/ProgressBar.tsx create mode 100644 src/components/Skeleton.tsx diff --git a/docs/LOADING_STATES.md b/docs/LOADING_STATES.md new file mode 100644 index 0000000..4b7892c --- /dev/null +++ b/docs/LOADING_STATES.md @@ -0,0 +1,85 @@ +# Revora Loading States Hierarchy & Guidelines + +Standardized progress and loading indicators across the Revora-Frontend platform. + +--- + +## 1. Design Tokens & Motion + +To maintain a premium, glassmorphic aesthetic while ensuring accessibility, all loading components utilize a single, high-contrast shimmer token. + +### Tokens +- `--shimmer-gradient`: `linear-gradient(90deg, rgba(148, 163, 184, 0.06) 25%, rgba(148, 163, 184, 0.18) 50%, rgba(148, 163, 184, 0.06) 75%)` +- Animation: `shimmer 1.6s infinite linear` + +### Motion Accessibility (WCAG 2.1 AA) +For users who prefer reduced motion (`prefers-reduced-motion: reduce`): +- **Shimmer animations**: Paused (`animation-play-state: paused`) and fallback to a static, low-contrast solid background (`rgba(148, 163, 184, 0.1)`). +- **Spinning loader animations**: Slowed down to `3s` duration to avoid rapid, distracting motion. + +--- + +## 2. Loading Hierarchy & Latency Thresholds + +| Loading State | Component | Latency Threshold | Best Use Cases | Accessibility Requirement | +| :--- | :--- | :--- | :--- | :--- | +| **Button Spinner** | `` | `< 1s` | In-context actions (e.g., submitting forms, primary CTAs). | `aria-hidden="true"` if label text is present. | +| **Inline Progress** | `` | `1s - 3s` | Background tasks, file uploads, multi-step actions. | `role="progressbar"`, `aria-valuenow`. | +| **Section Skeleton** | `` | `1s - 3s` | Dashboard cards, lists, table row replacements. | `aria-hidden="true"` (purely decorative). | +| **Page-Level Loader** | `` | `> 3s` | Full application boot, major router transitions. | `role="status"`, `aria-live="polite"`. | + +--- + +## 3. Component Details & Examples + +### A. Button Spinner (`LoadingSpinner`) +Renders a brand-consistent spinner using Lucide's `Loader2`. Included automatically inside the ` +``` + +### B. Inline Progress Bar (`ProgressBar`) +Supports both determinate (percentage-based) and indeterminate (shimmering) loading behavior. + +```tsx +import { ProgressBar } from './components/ProgressBar'; + +// Indeterminate Progress + + +// Determinate Progress with label text + +``` + +### C. Section Skeleton (`Skeleton`) +Generates structural shape placeholders to minimize layout shift (CLS) during content fetching. + +```tsx +import { Skeleton } from './components/Skeleton'; + +// Avatar placeholder + + +// Titled text paragraph block (renders 3 lines of text) +
+ + +
+``` + +### D. Page-Level Loader (`PageLoader`) +A full-screen frosted glass overlay designed for initial loading states. + +```tsx +import { PageLoader } from './components/PageLoader'; + +// Full Screen Page Loader + +``` diff --git a/src/components/AuthSubmitButton.tsx b/src/components/AuthSubmitButton.tsx index fc1cfc4..874aad3 100644 --- a/src/components/AuthSubmitButton.tsx +++ b/src/components/AuthSubmitButton.tsx @@ -1,5 +1,6 @@ import React from 'react'; -import { CheckCircle, Loader2 } from 'lucide-react'; +import { CheckCircle } from 'lucide-react'; +import { LoadingSpinner } from './LoadingSpinner'; export type SubmitButtonState = 'idle' | 'loading' | 'success'; @@ -32,9 +33,16 @@ export const AuthSubmitButton: React.FC = ({ aria-busy={isLoading} data-state={state} > - {isLoading &&