RoadieRoadie
  • Home
  • Foundations
  • Tokens
  • Components
  • Charts
  • Widgets
  • Appearance
HomeFoundationsComponents
Appearance

Components

  • Navigation

    • Breadcrumb
    • Navigator
    • Steps
    • Tabs
  • Layout

    • Pane
    • ScrollArea
    • Separator
  • Actions

    • Button
    • IconButton
    • Toggle
    • Toggle group
  • Forms

    • Forms overview
    • Autocomplete
    • Checkbox
    • Combobox
    • Field
    • Fieldset
    • Input
    • Label
    • Number field
    • OTP field
    • Radio group
    • Select
    • Slider
    • Switch
    • Textarea
  • Overlays

    • Dialog
    • Drawer
    • Menu
    • Popover
    • Toast
    • Tooltip
  • Collections

    • Accordion
    • Card
    • Carousel
    • Collapsible
    • DataTable
    • List
    • Marquee
    • Table
  • Status

    • Badge
    • Callout
    • Countdown
    • Empty state
    • Meter
    • Progress
    • Skeleton
    • Sparkline
    • StatTile
  • Media & brand

    • Avatar
    • Icon Tile
    • Image
    • Logo
    • QR code
    • SpotIllustration
  • Text

    • CalendarTile
    • Code
    • DateTime
    • Duration
    • Highlight
    • Mark
    • Prose

Duration

A length of time, rendered as a time element.

Import

import { Duration } from '@oztix/roadie-components/duration'

Examples

Default

<Duration of='PT2H30M' />

The length

of takes three forms. A string is an ISO 8601 duration, which is the language the time element's own attribute speaks. A number is milliseconds, because that is what end - start gives you. The object form is what Temporal.Duration exposes, so a Temporal value works here today.

<div className='grid gap-2'>
  <Duration of='PT2H30M' />
  <Duration of={9000000} />
  <Duration of={{ hours: 2, minutes: 30 }} />
</div>

Years and months render nothing. Neither has a fixed length, so P1M cannot become a number without a calendar and a start date. For a run of calendar days use formatDurationDays, which counts them against real dates.

Units

Coarse on purpose. Seconds appear only under a minute, where they are the whole answer. Minutes fall away once there are days.

<div className='grid gap-2'>
  <Duration of='PT30S' />
  <Duration of='PT45M' />
  <Duration of='PT2H' />
  <Duration of='PT2H30M' />
  <Duration of='P3D' />
  <Duration of='P3DT4H' />
</div>

Style

One scale, from spelled out to compressed, the same shape as the date scale.

<div className='grid gap-2'>
  <Duration of='PT2H30M' />
  <Duration of='PT2H30M' durationStyle='medium' />
  <Duration of='PT2H30M' durationStyle='short' />
</div>

Guidelines

A duration is a length, not a moment. Four of them come up and they are not interchangeable.

What you meanUseReadsWhen
How long a thing runsDuration2 hours 30 minutesA running time, a support window. Measured, not scheduled.
How many days a run coversformatDurationDays3 daysA festival or a season. Calendar days, not elapsed hours.
How much time is leftCountdown4:32A held cart, a registration opening.
The machine valueformatMachineDurationPT2H30MA time element carrying a length rather than a moment.

Picking a style

The style is a question about the room the surface has, not about the value. The same two and a half hours is 2 hours 30 minutes in a sentence and 2h 30m in a badge.

StyleReadsReach for it when
long2 hours 30 minutesThe default. Prose, a detail line, anywhere the reader is reading rather than scanning.
medium2 hrs 30 minsA card, a table cell, a list row. Space is tight but it still has to read as words.
short2h 30mA badge, a chip, a chart tooltip, a dense column. Every character is paid for.

Under a second, each style has its own way of saying so: less than a minute, under a min, 0m. None of them say 0 minutes, because the answer is nearly nothing rather than nothing. Between one second and a minute the seconds are the whole answer, so PT30S reads 30 seconds.

Pick one style per view and keep it. Two registers in one list reads as two systems, which is the same mistake as mixing an abbreviated weekday with a full month. See Date and time.

Say the largest unit that answers the question

A running time is planning information. A person deciding whether to book a sitter does not need the seconds.

2 hours
1 hour 30 minutes
3 days

Do

Enough to plan around. Nothing spare.

2 hours 31 minutes 12 seconds
150 minutes
0.5 days

Don’t

False precision. A unit nobody converts in their head. And a fraction of a unit, which is not how anyone says it.

Attach it to the range it describes with a middot, which is the separator for a date and an adjacent fact.

Fri 27 to Sun 29 Nov 2026 · 3 days
Doors 7:30pm · runs 2 hours

Days are not hours

Do not compute a day count by passing elapsed milliseconds. A festival running Friday night to Sunday night is three days, not two and a bit. That is formatDurationDays, which counts calendar days and knows a set finishing at 3am belongs to the night before.

It returns nothing in two cases, and both are deliberate. A range inside a single day has no day count worth stating. So does a range past 30 days, because 365 days tells a reader nothing they wanted to know. Render whatever you get back, and show nothing when it is null.

On a range, DateTime calls it for you through showDuration.

Without React

Reach for the formatter where the output never becomes an element on the page. A tooltip string, an export column, a datetime attribute written by hand.

import {
formatDuration,
formatDurationDays,
formatMachineDuration
} from '@oztix/roadie-core/datetime'
formatDuration('PT2H30M')
// → '2 hours 30 minutes'
formatDuration(endsAt - startsAt, 'short')
// → '2h 30m'
formatDurationDays(startsAt, endsAt, { timeZone: venue.timeZone })
// → '3 days', or null inside one day and past 30
formatMachineDuration({ hours: 2, minutes: 30 })
// → 'PT2H30M'

formatDurationDays takes a timeZone because a calendar day only exists in one. The other two take the same three forms as of.

Accessibility

The dateTime attribute is an ISO 8601 duration, so the markup says how long rather than when.

<time datetime="PT2H30M">2 hours 30 minutes</time>
<time datetime="P3D">3 days</time>

API reference

Duration

A length of time, rendered as a `time` element. For a measured length: a running time, a support window. Not for time remaining, which is a Countdown, and not for a moment, which is a DateTime. Sets `dateTime` to an ISO 8601 duration, so the markup says how long rather than when.

ofDurationish
Required

The length. A number is milliseconds, a string is an ISO 8601 duration (`PT2H30M`), and the object form is what `Temporal.Duration` exposes. Years and months render nothing, because neither has a fixed length.

durationStyle"long" | "medium" | "short"

How much room the surface has. `long` reads '2 hours 30 minutes', `medium` reads '2 hrs 30 mins', `short` reads '2h 30m'. Pick one per view.

Previous page← DateTimeNext pageHighlight →