Primitives
Progress
Determinate task progress with optional label and value rows.
Composition
Anatomy
- <Progress>
- <ProgressLabel />
- <ProgressValue />
- <ProgressTrack>
- <ProgressIndicator />
Installation
First install and activate one skin. Core deliberately contains no visual token defaults.
The Control UI source installs this primitive from src/registry/sources/control-ui/ui/progress.tsx.
npx shadcn@latest add https://control-ui.dev/r/progress.jsonRaw code
Primary installed source
"use client";import { Progress as ProgressPrimitive } from "@base-ui/react/progress";import type { ComponentProps, CSSProperties, ReactNode } from "react";import type { RangeKnobStyle } from "@/components/control-ui/knob-contracts/range-knobs";import { cn } from "@/components/control-ui/lib/cn";export type ProgressProps = Omit< ComponentProps<"div"> & { value: number | null; min?: number; max?: number; format?: Intl.NumberFormatOptions; getAriaValueText?: (formattedValue: string | null, value: number | null) => string; locale?: Intl.LocalesArgument; }, "style"> & { style?: CSSProperties & RangeKnobStyle };export type ProgressTrackProps = Omit<ComponentProps<"div">, "style"> & { style?: CSSProperties & RangeKnobStyle };export type ProgressIndicatorProps = Omit<ComponentProps<"div">, "style"> & { style?: CSSProperties & RangeKnobStyle };export type ProgressLabelProps = Omit<ComponentProps<"span">, "style"> & { style?: CSSProperties & RangeKnobStyle };export type ProgressValueProps = Omit< Omit<ComponentProps<"span">, "children"> & { children?: ((formattedValue: string | null, value: number | null) => ReactNode) | null; }, "style"> & { style?: CSSProperties & RangeKnobStyle };// value null = indeterminate.export function Progress({ className, ...props }: ProgressProps) { return ( <ProgressPrimitive.Root data-control-ui="progress" data-range-kind="progress" data-slot="root" data-control-family="range" className={cn("flex w-full flex-col", className)} {...props} /> );}export function ProgressLabel({ className, ...props }: ProgressLabelProps) { return ( <ProgressPrimitive.Label data-control-ui="progress" data-control-family="range" data-range-kind="progress" data-slot="label" className={className} {...props} /> );}export function ProgressValue({ className, ...props }: ProgressValueProps) { return ( <ProgressPrimitive.Value data-control-ui="progress" data-control-family="range" data-range-kind="progress" data-slot="value" className={className} {...props} /> );}export function ProgressTrack({ className, ...props }: ProgressTrackProps) { return ( <ProgressPrimitive.Track data-control-ui="progress" data-control-family="range" data-range-kind="progress" data-slot="track" className={cn("relative w-full overflow-hidden", className)} {...props} /> );}export function ProgressIndicator({ className, ...props }: ProgressIndicatorProps) { return ( <ProgressPrimitive.Indicator data-control-ui="progress" data-control-family="range" data-range-kind="progress" data-slot="indicator" className={className} {...props} /> );}Knobs
Typed custom properties the recipe paints with. Set one on the root — style, a utility class, or a skin — and every slot inherits it.
--cui-range-* · 13 knobsHow the cascade resolves--cui-range-level-warning-background<color>var(--warning)--cui-range-level-clip-background<color>var(--destructive)--cui-range-level-size<length-percentage>calc(var(--spacing) * 2)--cui-range-level-scale-foreground<color>var(--muted-foreground)--cui-range-indeterminate-size<length-percentage>40%--cui-range-track-radius<length-percentage>9999px--cui-range-track-background<color>var(--muted)--cui-range-indicator-radius<length-percentage>9999px--cui-range-indicator-background<color>var(--primary)--cui-range-thumb-radius<length-percentage>9999px--cui-range-thumb-background<color>var(--background)--cui-range-thumb-border-color<color>var(--control-rim)--cui-range-thumb-shadow*var(--shadow-sm)