Countdown
An element for displaying a countdown.
Showcase
import { Countdown, CountdownAnnouncer, CountdownGroup, CountdownLabel, CountdownSegmentFlipClock, CountdownSegments} from '@klnjs/react-countdown'import classes from './countdown.module.css'
const newYears = new Date(`January 1, ${new Date().getFullYear() + 1} 00:00:00`)
export default () => ( <Countdown until={newYears} locale="en-GB" largestUnit="days" smallestUnit="seconds" className={classes.countdown} > <CountdownAnnouncer /> <CountdownLabel className={classes.label}> Time left til New Years </CountdownLabel> <CountdownGroup className={classes.group}> <CountdownSegments format="short"> {({ unit, value, label }) => ( <CountdownSegmentFlipClock key={`flipclock-${unit}`} unit={unit} label={label} value={value.toString().padStart(2, '0')} className={classes.flipclock} /> )} </CountdownSegments> </CountdownGroup> </Countdown>)
.countdown { display: flex; gap: 16px; align-items: center; flex-direction: column;}
.label { font-size: 22px;}
.group { display: flex; gap: 8px;}
.flipclock { text-align: center;}
.flipclock [data-clock] { width: 60px; height: 60px; line-height: 1; font-size: 24px; font-weight: bold; color: var(--sl-color-white); border-radius: 0.5rem; user-select: none;}
.flipclock [data-clock-upper] { border-radius: 0.5rem; background: var(--sl-color-black); border: 1px solid var(--sl-color-hairline-light);}
.flipclock [data-clock-lower] { border-radius: 0.5rem; background: var(--sl-color-gray-6); border: 1px solid var(--sl-color-hairline-light);}
.flipclock [data-clock-upper]::after,.flipclock [data-clock-lower]::after { position: absolute; content: ''; height: 1px; width: 100%; background: var(--sl-color-text-invert);}
.flipclock [data-clock-text] { transform: translateY(-0.05em);}
Features
-
Fully localised.
-
Right-to-Left support.
-
Screen reader support (optional).
-
Listen for status changes.
-
Define largest and smallest unit.
-
Customise rendering of each segments.
Installation
The countdown component relies on a temporal polyfill for handling date and duration operations. Ensure the polyfill is included in your project dependencies.
bun install @klnjs/react-countdown temporal-polyfill
Definitions
Type | Definition |
---|---|
CountdownUnit | 'years' | 'months' | 'weeks' | 'days' | 'hours' | 'minutes' | 'seconds' | 'milliseconds' |
CountdownUntil | number | string | Date | Instant | PlainDate | PlainDateTime |
CountdownStatus | 'active' | 'ended' |
CountdownSegmentItem | { unit: CountdownUnit, label: string, value: number } |
Components
Countdown
Contains all the parts of an countdown. The throttle
property is used to control the update frequency of the countdown. The until
property is used to set the end date of the countdown. The largestUnit
and smallestUnit
properties are used to control the display of the countdown. The onStatusChange
property is used to provide a callback when the countdown ends.
Prop | Type | Default |
---|---|---|
asChild | boolean | false |
locale | string | - |
until | CountdownUntil | - |
throttle | number | 200 |
largestUnit | CountdownUnit | - |
smallestUnit | CountdownUnit | - |
onStatusChange | (status: CountdownStatus) => void | - |
Announcer
Optionally used to announce the remaining time to screen readers, should only be included if the information is critical. Behaviour can be customized using standard aria-*
attributes.
Label
Used to optionally render a label, and associate it with the countdown so it is accessible. If omitted, you should add a label to the announcer with property aria-label
, so the component stays accessible.
Prop | Type | Default |
---|---|---|
asChild | boolean | false |
Group
Used to group segments.
Prop | Type | Default |
---|---|---|
asChild | boolean | false |
Segments
Given the dynamic length of a countdown, this utility component provides means to render segements of the countdown using a render function as child.
Use display properties to control the visibility of the segments. If display is set to auto
, it will only show the segments that have a value greater than 0 which means the amount of segments can change during the countdown.
Use the format property to control the format of the segments. The format can be set to short
, narrow
or long
.
Prop | Type | Default |
---|---|---|
format | 'short' | 'narrow' | 'long' | - |
display | 'auto' | 'always' | - |
children | (item: CountdownSegmentItem) => ReactNode | - |
Segment
A segment is primarily visual, and it provides data-*
attributes enabling styling of the different states. To support screen readers, use the announcer component.
Prop | Type | Default |
---|---|---|
asChild | boolean | false |
unit | CountdownUnit | - |
Data attribute | Present when |
---|---|
data-unit | CountdownUnit |
SegmentFlipClock (Advanced)
Used to render segments in a flip clock style, use the duration
and perspective
prop to control the flip animation. This component is not a primitive as it builds a complex dom structure to accomodate the flip animation. Inline styles are used for required styles to prevent overriding, and data-*
attributes can be used to style the different parts.
Prop | Type | Default |
---|---|---|
asChild | boolean | false |
unit | CountdownUnit | - |
value | string | - |
label | string | - |
duration | number | 1000 |
perspective | number | 200 |
Data attribute | Present when |
---|---|
data-label | Element is label |
data-clock | Element is clock |
data-clock-upper | Element is upper |
data-clock-lower | Element is lower |
data-clock-text | Element is text |