[WEB-8163] fix(progress): tint value readout to fill tone + production-readiness hardening#232
[WEB-8163] fix(progress): tint value readout to fill tone + production-readiness hardening#232codingwolf-at wants to merge 6 commits into
Conversation
…lue readout - Updated `LinearProgressValue` to accept a `tone` prop, allowing the percentage readout to match the fill's tone as per design specifications. - Modified related stories to demonstrate the new tone functionality, ensuring consistent visual representation across different progress states. - Adjusted the `linearProgressValueVariants` to include tone variants, improving the semantic color application on the readout.
…ponent - Introduced a new story, `ClampsOutOfRange`, to demonstrate the clamping of values exceeding the maximum limit, ensuring `aria-valuenow` reflects the clamped value. - Updated `CircularProgressProps` to exclude the `render` prop, streamlining the component's API. - Enhanced LinearProgress component to support an optional `aria-label` when a `label` is provided, improving accessibility. - Removed unnecessary prop documentation comments in circular progress elements for cleaner code.
|
Linked to Plane Work Item(s) This comment was auto-generated by Plane |
|
📚 Storybook preview: https://pr-232-propel-storybook.vamsi-906.workers.dev |
|
@codingwolf-at The build is failing. Please take a look. |
| @@ -27,8 +30,8 @@ export type LinearProgressProps = Omit<BaseProgress.Root.Props, "className" | "s | |||
| showValue?: boolean; | |||
There was a problem hiding this comment.
aria-label is now optional while label is optional too, so an unnamed progressbar type-checks and renders. Could the props require at least one accessible name (label or aria-label) to preserve the a11y invariant?
There was a problem hiding this comment.
Done. LinearProgressProps is now a discriminated union — label or aria-label is required, so an unnamed progressbar is a compile error:
export type LinearProgressProps = LinearProgressOwnProps &
({ label: string; "aria-label"?: string } | { label?: undefined; "aria-label": string });
Labeled → named by the visible label; no label → aria-label required. (Same pattern as Badge.)
| export function CircularProgress({ value, magnitude, tone, ...props }: CircularProgressProps) { | ||
| const { box, radius } = RING_GEOMETRY[magnitude]; | ||
| const circumference = 2 * Math.PI * radius; | ||
| const max = props.max ?? 100; |
There was a problem hiding this comment.
min still forwards from BaseProgress.Root.Props, but clamping and the arc fraction assume a zero minimum. For min={20} max={100} value={60}, the ring paints 60% instead of 50%. Could we derive both bounds and the fraction from min/max (or omit min from this API)?
There was a problem hiding this comment.
Fixed — the arc fraction and clamp now derive from both bounds:
const min = props.min ?? 0;
const span = max - min;
const clampedValue = value == null ? null : Math.min(Math.max(value, min), max);
const fraction = clampedValue == null ? 0.25 : span > 0 ? (clampedValue - min) / span : 0;
min=20 max=100 value=60 now paints (60−20)/80 = 50%, and the clamp floors at min. span > 0 guards min===max.
There was a problem hiding this comment.
CircularProgress now clamps out-of-range values, but LinearProgress still passes them through. value={150} produces aria-valuenow="150" with aria-valuemax="100" and a 150% label. Could we apply the same clamp before passing the value to Base UI?
There was a problem hiding this comment.
Fixed — LinearProgress now clamps to [min, max] before Base UI derives the fill, aria-valuenow, and the % label, matching CircularProgress:
const clampedValue = value == null ? null : Math.min(Math.max(value, min), max);
alue={150} now reads aria-valuenow="100" and a 100% label instead of overflowing.
|
@codingwolf-at Build is failing. Please take a look into this. |
- Removed the `tone` prop from `LinearProgressValue`, simplifying the component's API and ensuring the percentage readout is a neutral number. - Updated the `linearProgressValueVariants` to reflect the change, aligning the styling with the design specifications that emphasize a neutral readout. - Adjusted related stories to remove tone references, ensuring consistent representation across different progress states.
Build failed on an axe color-contrast violation in LinearProgress > Tones: The change tinted the % readout to the fill Reverting the readout to neutral |
…ility - Changed the type definition for `LinearProgressProps` to enforce a union of `label` and `aria-label`, ensuring that one of them is always provided for accessibility. - Updated the story type to be directly tied to `LinearProgress`, enhancing type-checking for individual stories. - Added documentation comments to clarify the new prop requirements and improve code readability.
…lue calculation - Introduced `min` prop to allow for customizable lower bounds in value clamping, ensuring accurate representation of progress. - Updated the clamping logic to derive the fraction based on both `min` and `max`, improving the component's flexibility and correctness. - Enhanced comments for clarity on the clamping behavior and its impact on accessibility attributes.
…ogress representation - Introduced `min` and `max` props to allow customizable bounds for value clamping, ensuring that the displayed progress does not exceed defined limits. - Updated clamping logic to prevent discrepancies between the displayed value and accessibility attributes, enhancing overall component reliability. - Improved comments for clarity on the clamping behavior and its implications for accessibility.
Description
Design-system finalization pass on the Progress family (LinearProgress + CircularProgress).
Design fix
tone(per Figmatext/accent/primary).LinearProgressValuegains atoneaxis mapping totext-{accent,success,warning,danger}-primary;the ready-made and element stories pass it through. Previously a fixed neutral gray.
Audit hardening
renderfrom the publicPropsand spread{...props}beforerender. Circular previously spread afterrender, letting a consumer-suppliedrenderclobber the ring element.aria-labeloptional on LinearProgress: it's no longer required when a visiblelabelis set (the label names the bar viaaria-labelledby). Was forcing avisible/accessible name mismatch.
ClampsOutOfRangeplay test asserting out-of-rangevalueclamps to[0, max]viaaria-valuenow.Cleanup
Props for {@link X}JSDoc from circular element parts.LinearProgressLabelto the component storysubcomponents(was missing from docs).Test
vp checkandvp testgreen.Type of Change
Screenshots and Media (if applicable)
Figma URL