shadcn.io is not affiliated with official shadcn/ui
Time Zone and Format Table Block for Solid
On-call handoffs whose time column can be read in UTC, New York, Berlin, Kolkata or Tokyo as a 24-hour clock, a 12-hour clock or hours before the report, with the full instant in a tooltip.
Installation
Overview
Let people read times in their own zone, with this time zone and format table for Solid with Ark UI. A compact header names the table, and a band above it holds a Select of five time zones and a three-way Toggle Group for the format: a 24-hour clock, a 12-hour clock, or Relative, which words each time as hours before the report ("3 h before the report"). Under it, a native table lists six on-call handoffs: the time, the rotation, who handed over, who took over and the kind of handoff, as an outline Badge. Each time is a button whose Tooltip gives the full instant in UTC and in the zone you picked. Every time is one fixed instant typed in UTC and written for the zone by Intl.DateTimeFormat, and Relative is measured from a typed report time, never the clock. The rows stay in instant order whatever you choose, and each row keeps the height of two lines. On a phone the type goes and the previous owner folds under the rotation. It's built from Select, Toggle Group, Tooltip, Badge and Guides, with a CSS entrance only. For on-call schedules, audit logs, shift rosters and any table read across time zones.
FAQ
How do I use my own instants and zones?
Edit HANDOFFS, whose instant is an ISO time in UTC, and ZONES, whose zone is an IANA name such as Asia/Kolkata. partsOf asks Intl.DateTimeFormat for the day, month, hour and minute in that zone and clockOf assembles them, so the output doesn't change between the server and the browser. Each zone also lists its offset for the label; if your range crosses a change of clocks, compute the offset instead of typing it.
How does Relative decide what to say?
It subtracts the instant from AS_OF, the typed time the report was run, and writes whole days and hours ("1 d 21 h before the report"). It never reads the current time, so the text is the same on every render and in every time zone, and a screenshot of it is stable. For a live "ago" in your own product, pass the current time into relativeOf after mount and update it on an interval.
What stays local, and how do I wire it to a server?
The handoffs, the zone and the format are all state in the page; nothing is saved or requested. Keep the zone and the format in your user's settings and send instants as ISO strings from your API; the table needs nothing else. The tooltip text is built from the same instant, so it stays correct when the data is real.
Is it accessible, with the time inside a button?
Yes. The table has a caption and th scope="col" heads, and each time is the row header. The time is a real button, so it takes Tab with a visible focus ring and opens its tooltip on focus as well as hover; the tooltip repeats the full instant for anyone who finds the short form ambiguous. The menu and the toggle have names, and a polite status line says what the table now shows ("Times in Berlin, UTC+2, 24-hour clock").
How does it look on a phone?
Below the small breakpoint the From column goes and the name folds into a line under the rotation ("From Linnea Haverkamp"), the avatar disappears and the Type column is dropped from the medium breakpoint down. The two controls stack above the table, and the time column is wide enough for the longest Relative wording on two lines.
Do the rows move when I change the format?
No. Every row is as tall as two lines, whichever format is chosen, and the time column has a fixed width, so a long Relative phrase wraps inside its row instead of making the row taller. The order of the rows never changes either: it is the order of the instants.