# Resolution Segmented

A segmented resolution row with a sliding plate and a dot matrix that carries sampling density — two dots standard, three high, four retina.

> For the complete documentation index, see [llms.txt](/llms.txt). Markdown variants are available by appending `.md` to any URL or sending an `Accept: text/markdown` header. An agent skill is available at [/.well-known/agent-skills/site-skill.md](/.well-known/agent-skills/site-skill.md).





<ComponentPreview name="resolution-segmented">
  <ResolutionSegmentedDemo />
</ComponentPreview>

## Installation [#installation]

```bash
npx shadcn@latest add https://motif-ui.vercel.app/r/resolution-segmented.json
```

## Usage [#usage]

```tsx
import { ResolutionSegmented } from "@/components/ui/resolution-segmented";

export function Output() {
  const [resolution, setResolution] = useState("2K");

  return (
    <div className="space-y-2">
      <div className="font-medium text-muted-foreground text-xs">
        Resolution
      </div>
      <ResolutionSegmented
        aria-label="Resolution"
        onChange={setResolution}
        value={resolution}
      />
    </div>
  );
}
```

## The heading is yours [#the-heading-is-yours]

The control draws no label. A field's label belongs to the form around it — above,
beside, in a `<legend>` — and that is layout the caller owns, not something a select
should decide for the page it lands in. So the component renders the row and nothing
else.

That leaves one line of wiring: a heading you write is plain text, so pass `aria-label`
with the same words and the name reaches a screen reader too.

## The plate, not the button [#the-plate-not-the-button]

The selected state is a plate that slides between cells rather than a cell that lights up
and another that goes dark. A highlight appearing and disappearing in two places reads as
two independent buttons; one plate travelling between positions reads as a single control
changing state, which is what it is. The travel uses the same `0.25rem` gutter the grid
uses, so the plate lands exactly on the cell it belongs to rather than near it, and
`motion-reduce:transition-none` parks it instantly for anyone who has asked for less
movement.

## The dot matrix [#the-dot-matrix]

Resolution is sampling density, so the glyph is a matrix of dots and its count encodes
the tier: two dots for standard, three for high, four for retina. The mapping is
*positional* — the component never parses `"2K"` — which is why it works for any list of
resolutions you pass. Two options get the endpoints (two dots and four) instead of a false
middle tier.

Because the tiers are ordered, keep `options` in ascending order; the first entry is the
one the glyphs treat as the smallest.

<ResolutionSegmentedPairDemo />

## Accessibility [#accessibility]

The row is a group of `<button>`s with `aria-pressed`, focusable and operable by keyboard.
The grid is a `role="group"` named by `aria-label`, so it is announced as one control. The
dots are `aria-hidden` — the tier is decorative and the value already says `2K`.

## Component source [#component-source]

<ComponentSource name="resolution-segmented" src="registry/new-york/resolution-segmented.tsx" title="resolution-segmented.tsx" />
