Registry Index

Search the catalog

Type to search items across every indexed registry, or pick a page.

ComponentReactregistry:uiSelf-contained

Time Zone Select

timezone-select

A time zone picker: every IANA zone the browser knows, grouped by region and labelled with the UTC offset it is actually on — "New York (UTC-04:00)", "Kolkata (UTC+05:30)", "Chatham (UTC+12:45)". Reach for it wherever an app has to store which zone a time is meant in: the "Your time zone" row in profile, account or notification settings; a workspace or organisation default for a distributed team; scheduling and booking flows where the two parties are in different places; meeting, event and webinar creation; availability and working-hours editors; quiet hours and do-not-disturb windows; shift rosters and on-call rotations; the zone a cron job, scheduled report, digest email or CI job is read in; billing and invoice cycle boundaries; the "display times in" control on a dashboard, log viewer or analytics report; and any form that already collects a date and needs to know which midnight it meant. Common asks it answers: "timezone picker", "timezone select", "time zone dropdown", "timezone selector react", "IANA timezone select", "select timezone component", "list of timezones react", "timezone select with UTC offset", "shadcn timezone picker", "shadcn time zone select", "react-timezone-select alternative", "timezone combobox", "choose timezone for scheduling", "user timezone setting component". Official shadcn/ui has nothing for this and no combination of its parts gets there: select, native-select and combobox are empty controls that know no zones, and calendar and date-picker choose a day and never say which zone that day is counted in. The component here is the data and the labelling, not the control. The zone list comes from `Intl.supportedValuesOf("timeZone")`, so it is the runtime's own tzdata — 418 zones on current browsers — and it ages with the browser instead of with a package you have to remember to bump. UTC is added explicitly, because that call omits it on several runtimes and it is the one zone a scheduling or logging UI is most likely to want. Offsets are read through `Intl` at a reference date rather than computed by subtracting two Dates, which is what keeps the zones that are not on a whole hour honest: India at +05:30, Chatham at +12:45, Marquesas at -09:30. And because an offset is a property of the date and not of the zone — Berlin is +01:00 in January and +02:00 in July — `referenceDate` moves the whole list to the instant being scheduled, so a picker for a meeting in three months does not label its options with today's daylight saving. It renders a native `<select>`, so keyboard support, the mobile wheel and form submission come from the platform rather than from a listbox reimplementation, which for a list this long is the difference between usable and not. That choice decides the labels too: a native select's only search is type-ahead, and labelling the options "(UTC-04:00) New York" the way most pickers do points all 418 entries at "(" and throws the feature away — so the city comes first, the offset trails in parentheses, and each region group is sorted alphabetically, in the same order type-ahead walks. Three failure modes it settles that only show up in production. The option list is built after mount, never during the server render, because the zone list, the tzdata behind the offsets and "now" are all properties of the machine — rendering them on both sides is a hydration mismatch on a page that was otherwise deterministic; before mount the field renders the current value under its raw id, so it is still present and submittable. The select is controlled internally even when the caller leaves it uncontrolled, because replacing the children of an uncontrolled select drops the DOM's selection and the field would silently reset on hydration. And a value the list does not contain is added back as its own option — the runtime offers canonical ids only, so a legacy form saved years ago is absent (current runtimes still answer to "US/Pacific" but do not list it), as is any zone picked before a narrowed list was narrowed instead of letting the select fall to its first entry and read as though the user had picked Abidjan. Works controlled (`value` + `onValueChange`) or uncontrolled (`defaultValue`), always emitting the IANA id and never a display label; `placeholder` adds an empty first option that `required` still rejects; `timeZones` narrows the list to the places a product actually operates in; and `getLocalTimeZone()` is exported for seeding the field with the visitor's own zone from an effect rather than from a render the server also runs. Labelled for assistive technology either way: it falls back to an accessible name only when no `aria-label`, `aria-labelledby` or `id` says one already exists, so a visible `<Label htmlFor>` is never overridden. Styled entirely with shadcn tokens (input, ring, muted-foreground), so it follows light and dark mode, and it ships zero dependencies — no timezone package, no icon package, one file.

Couldn't load the source right now — try refreshing.