From b431d4eca11284ca5df792c93168fc49a503d8da Mon Sep 17 00:00:00 2001 From: Evyatar Bluzer Date: Thu, 23 Jul 2026 05:31:54 +0700 Subject: [PATCH] fix(a11y): add ARIA progressbar to QuotaBar component (#1878) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - Operators run those agents against paid model providers, so the web UI has a Costs surface that reports spend and quota utilisation > - Those figures are drawn as horizontal bars by the shared `QuotaBar` component (`ui/src/components/QuotaBar.tsx`), consumed by `BillerSpendCard` and `ProviderQuotaCard` > - `QuotaBar` renders its fill as a plain `
` whose CSS width is the only encoding of the percentage — no `role`, no value attributes, no accessible name > - A screen reader therefore announces nothing at all for these bars, so the spend and quota numbers they convey are unavailable to assistive-technology users (WCAG 2.1 SC 4.1.2, Name/Role/Value) > - The same gap is being closed for the other bars in this area by #1805 (BudgetPolicyCard) and #1869 (ProviderQuotaCard's inline bars); `QuotaBar` is the remaining shared component with no ARIA semantics > - This pull request adds the standard ARIA progressbar attributes to `QuotaBar`'s fill element, reusing the `label` prop the component already takes > - The benefit is that every progress bar on the Costs screen exposes its name and current value to assistive technology, with no visual or behavioural change for sighted users ## Linked Issues or Issue Description No existing GitHub issue — the problem is described in-PR below, following [`bug_report.yml`](.github/ISSUE_TEMPLATE/bug_report.yml). Related PRs from the same accessibility sweep (each covers a *different* component, so these are companions rather than duplicates — all three are currently open): - Refs #1805 — ARIA attributes for the BudgetPolicyCard progress bar - Refs #1869 — ARIA attributes for the ProviderQuotaCard inline bars **What happened?** On the Costs screen, the spend/quota bars rendered by `QuotaBar` (via `BillerSpendCard` and `ProviderQuotaCard`) are non-semantic `
` elements. Screen readers skip them entirely: no role, no value, no label is announced, so the percentage information is available only visually. **Expected behavior** Each bar should be exposed as a progress bar with an accessible name and its current value — e.g. announced as "Weekly spend: 45%, progress bar". **Steps to reproduce** 1. Run the app and open the Costs page. 2. Expand any provider or biller card so a quota/spend bar is visible. 3. Navigate to the bar with a screen reader (VoiceOver, NVDA, or Chrome DevTools → Accessibility pane). 4. Observe that the fill element has no role, no value, and no accessible name. **Paperclip version or commit** Reproduces on `master`; `ui/src/components/QuotaBar.tsx` has carried no ARIA attributes since the component was introduced. **Deployment mode** Not deployment-specific — the missing markup is in the shipped component. Verified in local dev (`pnpm dev`). **Agent adapter(s) involved** Not adapter-specific (core UI). ## What Changed - `ui/src/components/QuotaBar.tsx`: added `role="progressbar"` to the fill `
`. - Added `aria-valuenow={Math.round(clampedPct)}` with `aria-valuemin={0}` / `aria-valuemax={100}`, using the already-clamped percentage so the reported value can never fall outside 0–100. - Added an `aria-label` of the form `