Skip to content

feat: add ColorPicker, PinInput and Rating - #106

Open
Agustin-Delgado wants to merge 3 commits into
mainfrom
feat/colorpicker-pininput-rating
Open

Agustin-Delgado wants to merge 3 commits into
mainfrom
feat/colorpicker-pininput-rating

Conversation

@Agustin-Delgado

Copy link
Copy Markdown
Collaborator

Three components: Rating, PinInput and ColorPicker. Each one has its parts, its tests, its README, its TODO and a page in the docs.

Rating

Rating.Root, Rating.Label, Rating.Output and Rating.Item.

With whole items the root is a radio group, and each item is a radio with its own name. Each value is one item, and the focus follows the value. With precision={0.5} the root is a slider with aria-valuenow and aria-valuetext, because a radio group cannot say 3.5. The keyboard is the same in the two shapes.

The value follows the pointer before a press: Rating.Output and --rating-display-value show the answer of a press before it. Each item carries --rating-item-fill, from 0 to 1, thus one shape over the item gives you the half star.

PinInput

PinInput.Root, PinInput.Label and PinInput.Cell.

Each cell is a real input with its own name, its inputmode and its autocomplete. A telephone shows the correct keyboard, and a code from a message fills the cells with one touch. A paste goes across the cells from the cell it starts in, and the characters that type or pattern refuses are dropped.

The value has no holes. The characters fill the cells from the first one, and a character that goes away takes the ones after it one cell to the left.

ColorPicker

ColorPicker.Root, Label, Area, AreaThumb, Slider, SliderThumb, HexField, ChannelField, SwatchList, Swatch, Preview and EyeDropper.

The color is held as hue, saturation and brightness. The square keeps its shape at each hue in that model, and a color that goes to black keeps the hue it had. The value is text, and format decides which one.

ColorPicker.AreaThumb holds one native slider for each axis, each with the name of its channel and with aria-valuetext. That gives a two-dimensional control a value a screen reader can read, and the arrows move both axes from either of them.

Notes

  • Each root sends its value in a form with a hidden input, and a <form> reset takes the first value back.
  • The three components paint nothing. The custom properties of each one are in its page under "Style".
  • 89 tests for the three components, plus the SSR tests. The whole suite is green: 2163 tests.

Rating is a radio group with whole items and a slider with half items,
with a value that follows the pointer before a press.

PinInput gives each character its own real input, spreads a paste and a
code from a message across the cells, and keeps a value without holes.

ColorPicker holds the color as hue, saturation and brightness, with a
square, a slider per channel, a hex field, number fields, swatches and
the eye dropper of the browser.
@vercel

vercel Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
human-kit-ui-docs Ready Ready Preview Sep 25, 2026 12:01pm UTC

… finger

The three new pages wrote `<ApiReference {api} />`, which the markdown
pipeline leaves as text: the tag needs the full `api={api}`. They also
had no "API reference" heading, which each other page has.

A press on a `Rating.Item` with a finger left `data-hovering` on the root
and the preview on the value: a finger cannot rest on an item, and the
leave that ends a preview does not come from each browser. A press with a
pointer that is not a mouse now leaves no preview.
Rating, at a precision below 1, is a slider, and the root is its one tab
stop. A press moved the value and left the focus where it was, thus the
arrow that followed went to the body and the rating answered nothing
until the reader pressed Tab. A press now takes the focus, with the
modality of a pointer, so it paints no focus ring.

A Rating that is read only did not say so in a radio group: the reviews
of somebody else announced as a control the reader can change.

ColorPicker.Area wrote the two axes of a drag one after the other. That
reported two changes for one move of the pointer, and the color between
them is a color the pointer was never on. It is one write now.

Home, End and the page keys of ColorPicker.AreaThumb acted on the
saturation from either input, thus they moved the wrong axis while the
brightness had the focus. Each key follows the axis that has the focus.

The two thumbs took the focus with a plain focus() and not with the
modality of the press, which is what the rest of the library uses to
keep a focus ring off a press.

The hex field reported an end of a change for a text that names no
color, and a number field reported one for a field the reader only
passed through.

The eye dropper of the browser takes up to two seconds to paint, because
it must first read the screen. The button now carries aria-busy with
data-open, the demo gives that state a style, and the page says why.

The output of the half star demo goes under the stars.

This branch was successfully deployed

1 active deployment
Preview — 4f68599f Deployed Sep 25, 2026 by vercel[bot]
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.

1 participant