Time picker
Takes a time of day: typed as hh:mm, with AM or PM and, where it matters, a timezone. Pair it with a Date picker for a date and time, or use it on its own.
Live preview
Rendered by the component itself from the same generated tokens as the rest of the site.
const [value, setValue] = useState<TimeValue>({ time: '', period: 'AM', timezone: 'ET' })
<TimePicker
timezones={TIMEZONES}
label="Choose a time"
value={value}
onChange={setValue}
/>Installation
Install it with the shadcn CLI, along with everything it uses. New project? Set it up first, as Quick start shows.
npx shadcn@latest add https://www.graphite-ui.com/r/time-picker.jsonimport { TimePicker } from '@/components/ui/time-picker'
import type { TimeValue } from '@/components/ui/time-picker'Anatomy
The label over a row of three, 1 apart: the time typed as hh:mm, a Select for AM or PM, and a Select for the timezone. Each keeps its own name for assistive tech; the label names the group.
- LabelRequiredDefault draws it over the row in Caption/1, on-surface-variant, 8 above. Fluid names the group with it and labels each box instead.
- TimeRequiredThe kit's Time picker items - Fixed. The governed Text input, typed as hh:mm (the kit's placeholder), 76 wide in Default and 100 in Fluid; it takes the error ring and the status glyph and grows to 101 to hold it.
- ClockRequiredThe kit's Time picker items - Clock. The governed Select with AM and PM, 85 wide in Default and 100 in Fluid.
- TimezoneOptionalThe kit's Time picker items - Timezone. The governed Select, 127 wide in Default and 200 in Fluid. Leaving it out is the kit's two-input Fluid form.
- Supporting textOptionalHelp, error or warning text, 8 under the row.
Variants
Default sets the row at 48, 40 or 32. Fluid is one 64px row of boxes with a label inside each and a rule between. Without timezones it is the kit’s two-input form.
States
Error and warning flag the time alone, with its status glyph, and put the message under the row; the Selects keep their rest state, as the kit draws them. Disabled and Read-only reach all three.
API reference
Generated from the contract, versioned with it, and checked by drift-check. This table cannot describe props the component does not have.
| Prop | Type | Default | Notes |
|---|---|---|---|
| value / onChange | — | — | Controlled. The time as typed, the period (AM or PM) and the timezone. Checking the time is the caller's, reported through errorText. |
| timezones | — | — | The Timezone options; without them there is no Timezone item. |
| layout | 'fixed' | 'fluid' | — | The kit's Default and Fluid sets. |
| size | 'sm' | 'md' | 'lg' | — | Fixed only, 32, 40 or 48. Large by default. |
| label / timeLabel / clockLabel / timezoneLabel | — | — | The label is required. The items' labels default to Time, Clock and Timezone; Fluid shows them, Default keeps them as each field's accessible name. |
| helpText / errorText / warningText | — | — | Through the shared field-message rule. Error and warning flag the time alone, as the kit draws them; the Selects keep their rest state. |
| disabled | boolean | — | |
| readOnly | boolean | — |
Design tokens
Every swatch is live. Change the source color in the header and this table repaints, because it reads the same roles the component does.
on-surface-variantThe label (Text/text-secondary).on-surfaceWarning text (Text/text-primary); the warning colour is carried by the time's status glyph.outlineThe rule between Fluid boxes, through the strong step (Border/border-strong-01).dangerError text.primaryThe disabled label, through primary-disabled-content.textCaption/1 for the label and supporting text.spacingThe 8 gap.
Usage
The contract's prohibitions, written as the choices you will actually face.
Do
- Check the typed time on the page and say what is wrong with errorText.
- Offer timezones where the reader and the event may not share one.
- Pair it with a Date picker when a date and a time belong together.
- Keep the label to what the time is for, such as “Meeting starts”.
Don’t
- Correct a typed time silently. Say what was wrong.
- Offer a timezone that makes no difference.
- Restyle the field or the Selects. They are the governed Text input and Select.
- Use it for a duration. That is a number, not a time of day.
Accessibility
What the component does for you, and what it leaves to you.
- Roles
- A labelled group of a text input and one or two native selects, each with its own name (Time, Clock, Timezone).
- Keyboard
- Tab moves through the three. The selects open with the keyboard as any native select does.
- Messages
- Error and warning text are linked to the time with
aria-describedby; an error is announced as it appears. - Focus
- Each field takes its own focus ring, Text input’s and Select’s.
Figma parity
The kit draws Time picker on its Date picker page: two public sets, Default and Fluid, built from three item sets. The code is one component with a layout.
| Kit axis | Values | Code | How it maps |
|---|---|---|---|
| Set | Time picker - Default · Fluid | layout | fixed and fluid. |
| Size | Large · Medium · Small | size | Default only: 48, 40 and 32. |
| Inputs | 3 · 2 | timezones | With timezones, three; without, two. |
| State | Enabled · Error · Warning · Disabled · Read-only | errorText, warningText, disabled, readOnly | Error and warning flag the time alone; the time grows from 76 to 101 for its glyph. |
| State | Skeleton | — | No counterpart by rule. |
| Items | Fixed · Clock · Timezone | — | Text input and two Selects. Their Hover and Focus are the fields’ own. |
| Clock | AM · True · False | value.period | AM or PM. |
| Fluid label | Tooltip trigger | — | Not drawn: Text input’s and Select’s Fluid labels stand alone. |
