Skip to content

feat: add linear variant to ProgressGauge component#927

Merged
Aureliolo merged 3 commits intomainfrom
feat/progress-gauge-linear
Mar 30, 2026
Merged

feat: add linear variant to ProgressGauge component#927
Aureliolo merged 3 commits intomainfrom
feat/progress-gauge-linear

Conversation

@Aureliolo
Copy link
Copy Markdown
Owner

Summary

  • Add variant: 'circular' | 'linear' prop to ProgressGauge (default: 'circular', backward compatible)
  • Linear variant renders a horizontal bar gauge with the same color thresholds, percentage display, and accessibility attributes as the circular variant
  • Both variants share getHealthColor color logic, safe-value clamping, and role="meter" aria attributes
  • Update CLAUDE.md and docs/design/brand-and-ux.md component inventory to reflect the new variant

Test plan

  • 37 unit tests pass (15 circular + 22 linear), including property-based tests with fast-check
  • Linear variant tests cover: rendering, clamping, custom max, aria attributes (role, valuenow, valuemin, valuemax, label), color thresholds (danger/warning/accent/success), fill width, size variants, edge cases (NaN, Infinity, value=0)
  • TypeScript type-check clean
  • ESLint zero warnings
  • Storybook stories for both variants (7 circular + 7 linear + 1 comparison)
  • Visual verification: run npm --prefix web run storybook and check UI/ProgressGauge stories

Review coverage

Pre-reviewed by 5 agents (docs-consistency, frontend-reviewer, test-quality, issue-resolution-verifier, security-reviewer). 8 findings addressed, 0 skipped. Security: clean.

Closes #836

Aureliolo and others added 2 commits March 30, 2026 11:19
Add `variant: 'circular' | 'linear'` prop (default: 'circular') to
ProgressGauge. Linear variant renders a horizontal bar gauge with the
same color thresholds, percentage display, and accessibility attributes
as the circular variant. Includes Storybook stories and unit tests.

Closes #836

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Pre-reviewed by 5 agents, 8 findings addressed:
- Update CLAUDE.md and design spec component descriptions
- Replace inline transitionTimingFunction with Tailwind ease-in-out
- Add data-testid attributes to track/fill for stable test selectors
- Add aria-label, aria-valuenow with custom max, size-sm, value-0 tests

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 30, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 551706a6-b4fa-4c94-aedd-25a66394f4a1

📥 Commits

Reviewing files that changed from the base of the PR and between baabc69 and 4bf3b7b.

📒 Files selected for processing (2)
  • web/src/__tests__/components/ui/progress-gauge.test.tsx
  • web/src/components/ui/progress-gauge.tsx
📜 Recent review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Dashboard Test
  • GitHub Check: Build Backend
  • GitHub Check: Build Web
  • GitHub Check: Build Sandbox
  • GitHub Check: Dependency Review
  • GitHub Check: Analyze (python)
🧰 Additional context used
📓 Path-based instructions (3)
web/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

web/src/**/*.{ts,tsx}: React component reuse: ALWAYS reuse existing components from web/src/components/ui/ before creating new ones. The design system inventory covers all common patterns.
Design tokens: use Tailwind semantic classes (text-foreground, bg-card, text-accent, text-success, bg-danger, etc.) or CSS variables (var(--so-accent)). NEVER hardcode hex values in .tsx/.ts files.
Typography in web code: use font-sans or font-mono (maps to Geist tokens). NEVER set fontFamily directly.
Spacing in web code: use density-aware tokens (p-card, gap-section-gap, gap-grid-gap) or standard Tailwind spacing. NEVER hardcode pixel values for layout spacing.
Shadows/borders in web code: use token variables (var(--so-shadow-card-hover), border-border, border-bright).
Use cn() from @/lib/utils for conditional class merging in React components.
Do NOT recreate status dots inline - use <StatusBadge> component.
Do NOT build card-with-header layouts from scratch - use <SectionCard> component.
Do NOT create metric displays with text-metric font-bold - use <MetricCard> component.
Do NOT render initials circles manually - use <Avatar> component.
Do NOT create complex (>8 line) JSX inside .map() - extract to a shared component.
Do NOT use rgba() with hardcoded values - use design token variables.
React: TypeScript 6.0 has noUncheckedSideEffectImports defaulting to true - CSS side-effect imports need type declarations (Vite's /// <reference types='vite/client' /> covers this).
React/Web: ESLint zero warnings enforced on web/src/**/*.{ts,tsx} files.
React/Web: use React 19, react-router for routing, shadcn/ui + Radix UI for components, Tailwind CSS 4 for styling.
React/Web: use Zustand for state management and @tanstack/react-query for server state.

Files:

  • web/src/components/ui/progress-gauge.tsx
  • web/src/__tests__/components/ui/progress-gauge.test.tsx
web/src/components/ui/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

When creating new React components: place in web/src/components/ui/ with descriptive kebab-case filename. Create .stories.tsx file with all component states (default, hover, loading, error, empty). Export props as TypeScript interface. Use design tokens exclusively - no hardcoded colors, fonts, or spacing.

Files:

  • web/src/components/ui/progress-gauge.tsx
web/src/**/__tests__/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

React/Web: use Vitest for unit testing with coverage scoped to files changed vs origin/main.

Files:

  • web/src/__tests__/components/ui/progress-gauge.test.tsx
🧠 Learnings (8)
📚 Learning: 2026-03-30T06:54:37.737Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-30T06:54:37.737Z
Learning: Applies to web/src/**/*.{ts,tsx} : Do NOT create metric displays with `text-metric font-bold` - use `<MetricCard>` component.

Applied to files:

  • web/src/components/ui/progress-gauge.tsx
📚 Learning: 2026-03-30T06:54:37.737Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-30T06:54:37.737Z
Learning: Applies to web/src/**/*.{ts,tsx} : Design tokens: use Tailwind semantic classes (`text-foreground`, `bg-card`, `text-accent`, `text-success`, `bg-danger`, etc.) or CSS variables (`var(--so-accent)`). NEVER hardcode hex values in `.tsx`/`.ts` files.

Applied to files:

  • web/src/components/ui/progress-gauge.tsx
  • web/src/__tests__/components/ui/progress-gauge.test.tsx
📚 Learning: 2026-03-30T06:54:37.737Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-30T06:54:37.737Z
Learning: Applies to web/src/**/__tests__/**/*.{ts,tsx} : React/Web: use Vitest for unit testing with coverage scoped to files changed vs origin/main.

Applied to files:

  • web/src/__tests__/components/ui/progress-gauge.test.tsx
📚 Learning: 2026-03-20T08:28:32.845Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-20T08:28:32.845Z
Learning: Applies to web/src/__tests__/**/*.{ts,js} : Dashboard testing: Vitest unit tests organized by feature under `web/src/__tests__/`. Use fast-check for property-based testing (`fc.assert` + `fc.property`).

Applied to files:

  • web/src/__tests__/components/ui/progress-gauge.test.tsx
📚 Learning: 2026-03-30T06:54:37.737Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-30T06:54:37.737Z
Learning: Applies to web/.storybook/**/*.{ts,tsx} : Storybook 10: use `parameters.a11y.test: 'error' | 'todo' | 'off'` for a11y testing (replaces old `.element` and `.manual`). Set globally in `preview.tsx` to enforce WCAG compliance on all stories.

Applied to files:

  • web/src/__tests__/components/ui/progress-gauge.test.tsx
📚 Learning: 2026-03-30T06:54:37.737Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-30T06:54:37.737Z
Learning: Applies to web/src/**/*.{ts,tsx} : Do NOT use `rgba()` with hardcoded values - use design token variables.

Applied to files:

  • web/src/__tests__/components/ui/progress-gauge.test.tsx
📚 Learning: 2026-03-30T06:54:37.737Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-30T06:54:37.737Z
Learning: Applies to web/src/**/*.{ts,tsx} : Use `cn()` from `@/lib/utils` for conditional class merging in React components.

Applied to files:

  • web/src/__tests__/components/ui/progress-gauge.test.tsx
📚 Learning: 2026-03-30T06:54:37.737Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-30T06:54:37.737Z
Learning: Applies to web/src/**/*.{ts,tsx} : Do NOT create complex (>8 line) JSX inside `.map()` - extract to a shared component.

Applied to files:

  • web/src/__tests__/components/ui/progress-gauge.test.tsx
🔇 Additional comments (10)
web/src/components/ui/progress-gauge.tsx (5)

3-16: LGTM!

Clean separation of stroke classes for the SVG circular variant and background fill classes for the linear variant. Both use semantic Tailwind classes per design token guidelines.


17-26: LGTM!

Size configuration cleanly extends existing circular properties with linear-specific values. Uses Tailwind spacing (h-1.5, h-2) and typography classes as expected.


28-44: LGTM!

The variant prop addition with 'circular' default maintains backward compatibility. Existing consumers (e.g., OrgHealthSection.tsx, BudgetGauge.tsx from the relevant snippets) continue working without changes.


52-92: LGTM!

Well-implemented linear variant with proper accessibility attributes (role="meter", aria-valuenow/min/max), extracted percentageText for DRY, and consistent transition timing with the circular variant. The conditional label/percentage positioning logic is correct.


129-139: LGTM!

Good cleanup: moved ease-in-out from inline style to Tailwind class for consistency, and renamed to STROKE_COLOR_CLASSES to clearly distinguish from the linear variant's FILL_COLOR_CLASSES.

web/src/__tests__/components/ui/progress-gauge.test.tsx (5)

5-99: LGTM!

Excellent use of describe.each to reduce duplication across variants. The edge case coverage (NaN, Infinity, negative max, max=0) is thorough, and the property-based test properly constrains inputs and cleans up with unmount().


101-120: LGTM!

Circular-specific tests correctly verify SVG rendering as default and validate size calculations match the component's SIZE_CONFIG.


122-152: LGTM!

Comprehensive linear-specific tests covering DOM structure (no SVG, track/fill testids), and thorough accessibility testing including aria-label composition and aria-valuenow normalization with custom max.


154-168: LGTM!

Well-implemented parameterized tests with it.each, including boundary values (24/25, 49/50, 74/75) to verify threshold transitions. This addresses the previous review feedback.


170-185: LGTM!

Good coverage of styling assertions including fill width, size-dependent track height, and the zero-value edge case.


Walkthrough

The PR adds a variant?: 'circular' | 'linear' prop to ProgressGauge (default 'circular'). When variant === 'linear' the component renders a horizontal bar with percentage text, role="meter" and aria attributes, uses the same health-color logic, and applies linear-specific DOM/testids and classes. Documentation, unit tests, and Storybook stories were updated to document and exercise both circular and linear variants.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 40.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The PR title clearly and specifically describes the main change: adding a linear variant to the ProgressGauge component, which directly matches the primary objective.
Description check ✅ Passed The description is comprehensive and directly related to the changeset, providing clear details about the variant implementation, test coverage, and documentation updates.
Linked Issues check ✅ Passed All acceptance criteria from issue #836 are satisfied: variant prop added with circular/linear options, linear variant renders horizontal bar with percentage label, proper accessibility attributes implemented, Storybook stories added, and comprehensive unit tests included.
Out of Scope Changes check ✅ Passed All changes are directly aligned with issue #836 objectives: variant implementation, documentation updates, test additions, and Storybook stories are all within scope.

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


Comment @coderabbitai help to get the list of available commands and usage tips.

@Aureliolo Aureliolo temporarily deployed to cloudflare-preview March 30, 2026 09:39 — with GitHub Actions Inactive
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a linear variant to the ProgressGauge component, complementing the existing circular design. The changes include updates to the documentation, component logic, Storybook stories, and unit tests. The component now supports both circular and linear displays with configurable sizes and semantic coloring. Feedback focuses on improving code maintainability by refactoring the test suite to use describe.each for shared logic and extracting duplicated JSX elements within the linear rendering path to adhere to DRY principles.

})
})

describe('ProgressGauge linear variant', () => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

This new test suite for the linear variant duplicates many tests from the original suite for the circular variant (e.g., value clamping, percentage calculation, handling of NaN/Infinity).

To avoid code duplication and improve the maintainability of your tests, consider refactoring to use describe.each for tests that are common to both variants. This way, you can run the same test logic for both 'circular' and 'linear' variants, and keep variant-specific tests in separate describe blocks.

Here's an example structure:

describe.each([
  ['circular' as const],
  ['linear' as const],
])('ProgressGauge common logic (variant: %s)', (variant) => {
  it('clamps value to 0 minimum', () => {
    render(<ProgressGauge value={-10} variant={variant} />);
    expect(screen.getByText('0%')).toBeInTheDocument();
  });

  // ... other common tests
});

describe('ProgressGauge circular variant', () => {
  it('renders an SVG', () => {
    // ... test specific to circular
  });
});

describe('ProgressGauge linear variant', () => {
  it('does not render an SVG', () => {
    // ... test specific to linear
  });
});

Comment on lines +52 to +92
if (variant === 'linear') {
return (
<div
role="meter"
aria-valuenow={percentage}
aria-valuemin={0}
aria-valuemax={100}
aria-label={label ? `${label}: ${percentage}%` : `${percentage}%`}
className={cn('flex flex-col gap-1', className)}
>
{label && (
<div className="flex items-baseline justify-between">
<span className={cn('text-muted-foreground', config.barLabelSize)}>
{label}
</span>
<span className={cn('font-mono font-semibold text-foreground', config.percentSize)}>
{percentage}%
</span>
</div>
)}
<div
data-testid="progress-track"
className={cn('w-full overflow-hidden rounded-full bg-border', config.trackHeight)}
>
<div
data-testid="progress-fill"
className={cn(
'h-full rounded-full transition-all duration-[900ms] ease-in-out',
FILL_COLOR_CLASSES[color],
)}
style={{ width: `${percentage}%` }}
/>
</div>
{!label && (
<span className={cn('font-mono font-semibold text-foreground', config.percentSize)}>
{percentage}%
</span>
)}
</div>
)
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The rendering logic for the linear variant has some duplicated code for displaying the percentage. To improve maintainability and adhere to the DRY (Don't Repeat Yourself) principle, you can extract the percentage <span> into a constant and reuse it.

  if (variant === 'linear') {
    const percentageText = (
      <span className={cn('font-mono font-semibold text-foreground', config.percentSize)}>
        {percentage}%
      </span>
    );

    return (
      <div
        role="meter"
        aria-valuenow={percentage}
        aria-valuemin={0}
        aria-valuemax={100}
        aria-label={label ? `${label}: ${percentage}%` : `${percentage}%`}
        className={cn('flex flex-col gap-1', className)}
      >
        {label && (
          <div className="flex items-baseline justify-between">
            <span className={cn('text-muted-foreground', config.barLabelSize)}>
              {label}
            </span>
            {percentageText}
          </div>
        )}
        <div
          data-testid="progress-track"
          className={cn('w-full overflow-hidden rounded-full bg-border', config.trackHeight)}
        >
          <div
            data-testid="progress-fill"
            className={cn(
              'h-full rounded-full transition-all duration-[900ms] ease-in-out',
              FILL_COLOR_CLASSES[color],
            )}
            style={{ width: `${percentage}%` }}
          />
        </div>
        {!label && percentageText}
      </div>
    );
  }

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 30, 2026

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Snapshot Warnings

⚠️: No snapshots were found for the head SHA 4bf3b7b.
Ensure that dependencies are being submitted on PR branches. Re-running this action after a short time may resolve the issue. See the documentation for more information and troubleshooting advice.

Scanned Files

None

Copy link
Copy Markdown

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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@web/src/__tests__/components/ui/progress-gauge.test.tsx`:
- Around line 184-202: Replace the four nearly identical unit tests in
progress-gauge.test.tsx with a single table-driven test using test.each (or
it.each) that iterates over rows of {value, expectedClass}; for each row render
the ProgressGauge component (use ProgressGauge and variant="linear") and assert
screen.getByTestId('progress-fill') has the expected class; this reduces
duplication and centralizes threshold-to-class mappings so updates to
thresholds/classes require changing only the test table.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: f2f60776-0540-49c0-af59-0d2564dc97d2

📥 Commits

Reviewing files that changed from the base of the PR and between 7d815ca and baabc69.

📒 Files selected for processing (5)
  • CLAUDE.md
  • docs/design/brand-and-ux.md
  • web/src/__tests__/components/ui/progress-gauge.test.tsx
  • web/src/components/ui/progress-gauge.stories.tsx
  • web/src/components/ui/progress-gauge.tsx
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: Deploy Preview
  • GitHub Check: Dashboard Test
  • GitHub Check: Build Backend
  • GitHub Check: Build Sandbox
  • GitHub Check: Build Web
  • GitHub Check: Dependency Review
  • GitHub Check: Analyze (python)
🧰 Additional context used
📓 Path-based instructions (6)
docs/design/**/*.md

📄 CodeRabbit inference engine (CLAUDE.md)

When approved deviations from the spec occur, update the relevant docs/design/ page to reflect the new reality.

Files:

  • docs/design/brand-and-ux.md
docs/**/*.md

📄 CodeRabbit inference engine (CLAUDE.md)

Documentation: use Markdown in docs/ directory, built with Zensical. Design spec in docs/design/ (11 pages), Architecture in docs/architecture/, Roadmap in docs/roadmap/.

Files:

  • docs/design/brand-and-ux.md
web/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

web/src/**/*.{ts,tsx}: React component reuse: ALWAYS reuse existing components from web/src/components/ui/ before creating new ones. The design system inventory covers all common patterns.
Design tokens: use Tailwind semantic classes (text-foreground, bg-card, text-accent, text-success, bg-danger, etc.) or CSS variables (var(--so-accent)). NEVER hardcode hex values in .tsx/.ts files.
Typography in web code: use font-sans or font-mono (maps to Geist tokens). NEVER set fontFamily directly.
Spacing in web code: use density-aware tokens (p-card, gap-section-gap, gap-grid-gap) or standard Tailwind spacing. NEVER hardcode pixel values for layout spacing.
Shadows/borders in web code: use token variables (var(--so-shadow-card-hover), border-border, border-bright).
Use cn() from @/lib/utils for conditional class merging in React components.
Do NOT recreate status dots inline - use <StatusBadge> component.
Do NOT build card-with-header layouts from scratch - use <SectionCard> component.
Do NOT create metric displays with text-metric font-bold - use <MetricCard> component.
Do NOT render initials circles manually - use <Avatar> component.
Do NOT create complex (>8 line) JSX inside .map() - extract to a shared component.
Do NOT use rgba() with hardcoded values - use design token variables.
React: TypeScript 6.0 has noUncheckedSideEffectImports defaulting to true - CSS side-effect imports need type declarations (Vite's /// <reference types='vite/client' /> covers this).
React/Web: ESLint zero warnings enforced on web/src/**/*.{ts,tsx} files.
React/Web: use React 19, react-router for routing, shadcn/ui + Radix UI for components, Tailwind CSS 4 for styling.
React/Web: use Zustand for state management and @tanstack/react-query for server state.

Files:

  • web/src/__tests__/components/ui/progress-gauge.test.tsx
  • web/src/components/ui/progress-gauge.tsx
  • web/src/components/ui/progress-gauge.stories.tsx
web/src/**/__tests__/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

React/Web: use Vitest for unit testing with coverage scoped to files changed vs origin/main.

Files:

  • web/src/__tests__/components/ui/progress-gauge.test.tsx
web/src/components/ui/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

When creating new React components: place in web/src/components/ui/ with descriptive kebab-case filename. Create .stories.tsx file with all component states (default, hover, loading, error, empty). Export props as TypeScript interface. Use design tokens exclusively - no hardcoded colors, fonts, or spacing.

Files:

  • web/src/components/ui/progress-gauge.tsx
  • web/src/components/ui/progress-gauge.stories.tsx
web/src/**/*.stories.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Storybook 10: use storybook/test (not @storybook/test) and storybook/actions (not @storybook/addon-actions) for imports.

Files:

  • web/src/components/ui/progress-gauge.stories.tsx
🧠 Learnings (14)
📚 Learning: 2026-03-15T21:20:09.993Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:20:09.993Z
Learning: Applies to web/src/components/** : Vue components organized by feature (agents/, approvals/, budget/, common/, dashboard/, layout/, messages/, org-chart/, tasks/).

Applied to files:

  • CLAUDE.md
  • docs/design/brand-and-ux.md
📚 Learning: 2026-03-30T06:54:37.737Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-30T06:54:37.737Z
Learning: Applies to web/src/**/*.{ts,tsx} : Do NOT build card-with-header layouts from scratch - use `<SectionCard>` component.

Applied to files:

  • CLAUDE.md
  • docs/design/brand-and-ux.md
📚 Learning: 2026-03-30T06:54:37.737Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-30T06:54:37.737Z
Learning: Applies to web/src/**/*.{ts,tsx} : Do NOT create metric displays with `text-metric font-bold` - use `<MetricCard>` component.

Applied to files:

  • CLAUDE.md
  • docs/design/brand-and-ux.md
  • web/src/components/ui/progress-gauge.tsx
📚 Learning: 2026-03-30T06:54:37.737Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-30T06:54:37.737Z
Learning: Applies to web/src/components/ui/**/*.{ts,tsx} : When creating new React components: place in `web/src/components/ui/` with descriptive kebab-case filename. Create `.stories.tsx` file with all component states (default, hover, loading, error, empty). Export props as TypeScript interface. Use design tokens exclusively - no hardcoded colors, fonts, or spacing.

Applied to files:

  • docs/design/brand-and-ux.md
  • web/src/components/ui/progress-gauge.stories.tsx
📚 Learning: 2026-03-30T06:54:37.737Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-30T06:54:37.737Z
Learning: Applies to web/src/**/*.{ts,tsx} : React component reuse: ALWAYS reuse existing components from `web/src/components/ui/` before creating new ones. The design system inventory covers all common patterns.

Applied to files:

  • docs/design/brand-and-ux.md
📚 Learning: 2026-03-30T06:54:37.737Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-30T06:54:37.737Z
Learning: Applies to web/src/**/*.{ts,tsx} : Do NOT recreate status dots inline - use `<StatusBadge>` component.

Applied to files:

  • docs/design/brand-and-ux.md
  • web/src/components/ui/progress-gauge.tsx
📚 Learning: 2026-03-30T06:54:37.737Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-30T06:54:37.737Z
Learning: Applies to web/src/**/*.{ts,tsx} : Design tokens: use Tailwind semantic classes (`text-foreground`, `bg-card`, `text-accent`, `text-success`, `bg-danger`, etc.) or CSS variables (`var(--so-accent)`). NEVER hardcode hex values in `.tsx`/`.ts` files.

Applied to files:

  • docs/design/brand-and-ux.md
  • web/src/components/ui/progress-gauge.tsx
📚 Learning: 2026-03-30T06:54:37.737Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-30T06:54:37.737Z
Learning: Applies to web/src/**/*.{ts,tsx} : Spacing in web code: use density-aware tokens (`p-card`, `gap-section-gap`, `gap-grid-gap`) or standard Tailwind spacing. NEVER hardcode pixel values for layout spacing.

Applied to files:

  • docs/design/brand-and-ux.md
📚 Learning: 2026-03-30T06:54:37.737Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-30T06:54:37.737Z
Learning: Applies to web/src/**/__tests__/**/*.{ts,tsx} : React/Web: use Vitest for unit testing with coverage scoped to files changed vs origin/main.

Applied to files:

  • web/src/__tests__/components/ui/progress-gauge.test.tsx
📚 Learning: 2026-03-20T08:28:32.845Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-20T08:28:32.845Z
Learning: Applies to web/src/__tests__/**/*.{ts,js} : Dashboard testing: Vitest unit tests organized by feature under `web/src/__tests__/`. Use fast-check for property-based testing (`fc.assert` + `fc.property`).

Applied to files:

  • web/src/__tests__/components/ui/progress-gauge.test.tsx
📚 Learning: 2026-03-30T06:54:37.737Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-30T06:54:37.737Z
Learning: Applies to web/src/**/*.stories.{ts,tsx} : Storybook 10: use `storybook/test` (not `storybook/test`) and `storybook/actions` (not `storybook/addon-actions`) for imports.

Applied to files:

  • web/src/components/ui/progress-gauge.stories.tsx
📚 Learning: 2026-03-30T06:54:37.737Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-30T06:54:37.737Z
Learning: Applies to web/.storybook/**/*.{ts,tsx} : Storybook 10: use `parameters.backgrounds.options` (object keyed by name) + `initialGlobals.backgrounds.value` for backgrounds (replaces old `default` + `values` array).

Applied to files:

  • web/src/components/ui/progress-gauge.stories.tsx
📚 Learning: 2026-03-30T06:54:37.737Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-30T06:54:37.737Z
Learning: Applies to web/.storybook/**/*.{ts,tsx} : Storybook 10: use `parameters.a11y.test: 'error' | 'todo' | 'off'` for a11y testing (replaces old `.element` and `.manual`). Set globally in `preview.tsx` to enforce WCAG compliance on all stories.

Applied to files:

  • web/src/components/ui/progress-gauge.stories.tsx
📚 Learning: 2026-03-30T06:54:37.737Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-30T06:54:37.737Z
Learning: Applies to web/.storybook/{main,preview}.{ts,tsx} : Storybook 10: use `defineMain` from `storybook/react-vite/node` in main.ts and `definePreview` from `storybook/react-vite` in preview.tsx (must still include explicit `framework` field).

Applied to files:

  • web/src/components/ui/progress-gauge.stories.tsx
🔇 Additional comments (5)
web/src/components/ui/progress-gauge.tsx (1)

52-92: Linear variant implementation looks solid.

Shared clamping/color logic is reused correctly, ARIA meter attributes are complete, and styling stays within semantic design tokens.

docs/design/brand-and-ux.md (1)

204-204: Design inventory update is aligned with the component API.

The variant? prop and default 'circular' behavior are documented clearly.

web/src/__tests__/components/ui/progress-gauge.test.tsx (1)

117-248: Excellent linear-variant test coverage.

This suite meaningfully validates DOM structure, accessibility, clamping semantics, token class mapping, and edge-case handling.

web/src/components/ui/progress-gauge.stories.tsx (1)

59-101: Story coverage for the new variant is comprehensive.

The added linear and side-by-side stories are useful for regression checks and visual QA.

CLAUDE.md (1)

251-251: CLAUDE.md component inventory update is accurate.

The ProgressGauge description now correctly reflects the variant behavior and defaults.

- Extract duplicated percentage span to const in linear variant (DRY)
- Refactor color tests to it.each with boundary values (24/25, 49/50, 74/75)
- Add negative max test verifying Math.max(max, 1) guard
- Use describe.each for shared cross-variant tests (clamping, NaN, edge cases)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@Aureliolo Aureliolo temporarily deployed to cloudflare-preview March 30, 2026 09:53 — with GitHub Actions Inactive
@Aureliolo Aureliolo merged commit 89bf8d0 into main Mar 30, 2026
32 checks passed
@Aureliolo Aureliolo deleted the feat/progress-gauge-linear branch March 30, 2026 10:08
@Aureliolo Aureliolo temporarily deployed to cloudflare-preview March 30, 2026 10:08 — with GitHub Actions Inactive
Aureliolo added a commit that referenced this pull request Mar 30, 2026
🤖 I have created a release *beep* *boop*
---


##
[0.5.1](v0.5.0...v0.5.1)
(2026-03-30)


### Features

* add linear variant to ProgressGauge component
([#927](#927))
([89bf8d0](89bf8d0))
* frontend security hardening -- ESLint XSS ban + MotionConfig CSP nonce
([#926](#926))
([6592ed0](6592ed0))
* set up MSW for Storybook API mocking
([#930](#930))
([214078c](214078c))


### Refactoring

* **web:** replace Sidebar tablet overlay with shared Drawer component
([#928](#928))
([ad5451d](ad5451d))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).
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.

feat: add linear variant to ProgressGauge component

1 participant