Support explicit micro thresholds#354
Conversation
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR updates <relative-time> to make format="micro" honor an explicitly provided threshold attribute (while keeping legacy micro behavior when threshold is not set), and to allow data-prefers-absolute-time="true" to override micro output to an absolute format. It also adds/updates tests and documentation to describe and verify the new behavior.
Changes:
- Update
format="micro"resolution to fall back to absolute datetime output when an explicitthresholdattribute is present and exceeded. - Allow
data-prefers-absolute-time="true"to activate even when micro resolves toduration. - Add tests and documentation clarifying the “explicit threshold only” behavior for micro.
Show a summary per file
| File | Description |
|---|---|
src/relative-time-element.ts |
Implements explicit-threshold handling for micro and enables user absolute-time preference for micro-resolved duration. |
test/relative-time.js |
Adds new micro/threshold coverage and updates absolute-time preference expectations for format="micro". |
README.md |
Documents explicit micro threshold behavior and updates threshold guidance. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 3/3 changed files
- Comments generated: 2
| ##### threshold (`string`, default: `P30D`) | ||
|
|
||
| If `tense` is anything other than `'auto'`, or `format` is `'relative'` (or the deprecated `'auto'` or `'micro'` values), then this value will be ignored. | ||
| If `tense` is anything other than `'auto'`, or `format` is `'relative'` (or the deprecated `'auto'` value), then this value will be ignored. For `format="micro"`, `threshold` is honored only when the `threshold` attribute is explicitly set. | ||
|
|
There was a problem hiding this comment.
Addressed in 26ca974 by correcting the threshold docs: threshold applies to relative/auto when tense is auto, and micro only honors it when explicitly set.
| } | ||
|
|
||
| #shouldDisplayUserPreferredAbsoluteTime(format: ResolvedFormat): boolean { | ||
| // Never override duration format with absolute format. | ||
| if (format === 'duration') return false | ||
| // Never override duration or elapsed format with absolute format. | ||
| if (format === 'duration' && this.format !== 'micro') return false | ||
|
|
There was a problem hiding this comment.
Addressed in 26ca974 by making observation conditional on rendered output: user-preferred absolute micro output no longer keeps duration-style polling except for Today/current-year absolute-time updates.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
| const threshold = getExplicitThreshold(el) | ||
| if (el.format === 'micro' && threshold) { | ||
| const thresholdDuration = Duration.from(threshold) | ||
| const signedThresholdDuration = date.getTime() > now ? negateDuration(thresholdDuration) : thresholdDuration |
There was a problem hiding this comment.
This is the important live-update bit for threshold fallback: the normal observer cadence can be too late, so explicit micro thresholds schedule at date - threshold for future dates and date + threshold for past dates.
| observe(element: RelativeTimeElement) { | ||
| if (this.elements.has(element)) return | ||
| this.elements.add(element) | ||
| if (this.updating) return |
There was a problem hiding this comment.
This intentionally allows already-observed elements to be rescheduled when threshold is added or changed. The updating guard keeps that from creating duplicate timers while the observer loop is running.
|
|
||
| const duration = elapsedTime(date, this.precision, now) | ||
| const format = this.#resolveFormat(duration) | ||
| const format = this.#resolveFormat(duration, elapsedTime(date, 'millisecond', now)) |
There was a problem hiding this comment.
Using a millisecond-precision duration here keeps threshold resolution independent of display precision. Micro still renders with its normal minute floor, but threshold cutoffs are based on the actual elapsed time.
| const shouldObserve = | ||
| format === 'relative' || | ||
| format === 'duration' || | ||
| (!displayUserPreferredAbsoluteTime && (format === 'relative' || format === 'duration')) || |
There was a problem hiding this comment.
This keeps user-preferred absolute output from polling like duration output. Micro only remains observed for explicit threshold transitions or the existing Today/current-year absolute-time cases.
| assert.isAtLeast(delays[0], 59000) | ||
|
|
||
| delays.length = 0 | ||
| time.setAttribute('threshold', 'PT1M') |
There was a problem hiding this comment.
This test covers the dynamic attribute case: a micro element can already be observed, then gain an explicit threshold that requires an earlier reschedule.
Summary
format="micro"currently ignoresthresholdbecause it always resolves to duration output. This makes consumers compose their own cutoff logic, which can drift from the element's live updates.This PR makes threshold support opt-in for micro timestamps:
format="micro" threshold="P30D"shows compact durations within the threshold and absolute dates outside itformat="micro"usages withoutthresholdkeep rendering old dates as compact durationsdata-prefers-absolute-time="true"now applies to micro output whiledurationandelapsedremain excludedRefs #353
Tests
npm testnpm run lint