tosijs-timezone-picker
A web-component that
provides a graphical timezone picker, inspired by the one Apple used to provide before it
gave up and gave you a drop-down. Click the map, arrow-key around
it, or type — the field autocompletes on the timezone name and the GMT offset, so Los
and -7 both get you to America/Los_Angeles.
<tosijs-timezone-picker></tosijs-timezone-picker>
tosijs-timezone-picker {
width: 100%;
height: 100%;
--active-color: #ee257b;
--active-zone-color: #f273aa;
--map-land: #aaa;
--map-ocean: #ccd;
--font-color: black;
}
It is made as compact and fast-loading as possible by keeping the geometry to a minimum,
taking everything it can from Intl at runtime, and generating the SVG
on-the-fly. There is no timezone dataset in the package, and no network request at all.
Install
bun add tosijs-timezone-picker # or npm / yarn / pnpm
tosijs is a peer dependency, so your app ships exactly one copy of it.
Use it
As an element
import 'tosijs-timezone-picker'
<tosijs-timezone-picker timezone="Australia/Sydney"></tosijs-timezone-picker>
Programmatically
import { timezonePicker } from 'tosijs-timezone-picker'
document.body.append(timezonePicker({ timezone: 'Europe/Rome' }))
timezonePicker is a standard tosijs ElementCreator — a function that takes
ElementPart parameters and returns the element. TimezonePicker, the class behind
the tag, is exported too.
From a CDN, with your own tag name
The component is written as a tosijs blueprint, so it can be loaded at runtime with no build step — and the consumer picks the tag name:
<script type="module" src="https://cdn.jsdelivr.net/npm/tosijs/dist/module.js"></script>
<tosi-loader>
<tosi-blueprint
tag="my-timezone-picker"
src="https://cdn.jsdelivr.net/npm/tosijs-timezone-picker/dist/blueprint.js"
></tosi-blueprint>
</tosi-loader>
<my-timezone-picker></my-timezone-picker>
The value
value and timezone are two names for one thing, and both always hold a valid IANA
timezone name. Setting either updates the other and fires change; setting a name the
runtime doesn't know is rejected rather than accepted into an impossible state.
Full attribute, property, styling and keyboard reference:
<tosijs-timezone-picker>.
timezones, localTimezone, Timezone
Rather than shipping a static dataset, this package builds its zone list from
Intl
at import time. That keeps the component small and guarantees it agrees with the runtime
it is running in — including the current DST state. See timezones.
interface Timezone {
name: string // the IANA name
shortName?: string // e.g. 'America/Knox' for 'America/Indiana/Knox'
abbr: string // the runtime's short name, e.g. 'PDT'
offset: number // hours from GMT — fractional zones are decimals (5.5, 5.75, -3.5)
}
Styling
Everything is a CSS custom property, so you can theme the picker from outside its shadow
DOM without ::part gymnastics — --scale, --map-ocean, --map-land, --active-color,
--tooltip-bg and the rest are listed on the component page.
Annoyances
The text field uses the browser's built-in <datalist> autocomplete. Most people will
never type a zone name, but for those who do, its behavior is entirely the browser's:
Firefox and Safari are lovely, Chrome's menu jumps around as you type. Swapping in
tosijs-ui's editable <tosi-select> would fix it and roughly double the component's size,
so it stays as it is.
Acknowledgements
Built on region data from Keval Bhatt's excellent jQuery-based timezone-picker. These things are a huge pain to get right — an SVG map I had paid for got binned in favour of Keval's data. Bravo!
To improve the geometry, IANA's page is
the place to start: there are tools that build GeoJSON timezone layers, and a fairly simple
transformation would give exactly correct polygons. The polygons module could then
simplify them — the raw GeoJSON is over 100MB.
License
MIT. Copyright ©2023-2026 Tonio Loewald.