v1.14.0
Minor Changes
-
#61
80448e0Thanks @MikeNotThePope! - Add aCountdowncomponent anduseCountdownhook, stealing the live half of Ant Design'sStatistic.StatCardalready covered the static metric — a title, a value, a change indicator. What it could not do was count down, so anything time-bound (a sale ending, a token expiring, doors opening) needed a hand-rolled timer. Ant Design'sStatistic.Countdownis the missing piece; its staticStatisticsibling is not, and was deliberately skipped rather than duplicated.<Countdown deadline={...} />ticks once a second and stops at zero.onFinishfires exactly once per deadline, not on every subsequent render.- No format-string DSL. The default output comes from
Intl.DurationFormat, so it follows the locale and drops units that are still zero —04:05, then3:04:05, then2 days, 3:04:05. Where Ant takesformat="HH:mm:ss", this takes a render prop:childrenreceives{ total, days, hours, minutes, seconds, formatted, finished, ready }and you lay it out yourself. useCountdown(deadline, options?)is the same logic without the markup, exported from@mikenotthepope/substrateui/hooks.- Accessibility: renders as
role="timer", whose implicitaria-liveis off — a polite live region would read the clock aloud once a second. The timer carries an accessible name instead ("Time remaining", overridable vialabels.remaining). - SSR: reports
ready: falseand an empty string until measured in the browser, so hydration cannot mismatch on a value that is different by the time it reaches the client.
StatCard'svalueprop widens fromstringtoReact.ReactNode, so a countdown drops straight into a metric card without a third component in between. Existing string values are unaffected.
Patch Changes
- #64
21e4d83Thanks @MikeNotThePope! - Make the built-in themes work when they are scoped to a subtree, not just set on the document element.[data-theme="default"]now selects the base palette by name (previously the base palette was only "the absence of an attribute", so a default-themed element nested inside another theme inherited that theme), and the lava dark tokens gained the.dark [data-theme="lava"]selector thatthemeToCss()already emits for user themes. Nothing changes for a theme applied to<html>.