[JS+Editor Module] Relative Time Enhanced v1.4.0 #2445
Replies: 7 comments 23 replies
|
this is cool - but it looks like it overides the entire attributes line. For instance, I can no longer have "Armed Home" on my security system when I also have this enabled? |
|
I'm getting the overwrite warning even though the module is listed as last in the array for that card? The only think I can think of is global modules are triggering it ? |
|
Would not be surprised. I wasnt 100% on it. Can you paste your module list from yaml for that card so I can recreate? modules:
|
Patch Note - v1.3.1Released: Patch on top of v1.3.0 SummaryInternal exceptions in the module's render function are now caught and surfaced with the BackgroundIn v1.3.0, the module's conflict-detection system watches for its rendered output being overwritten by a downstream module and warns the user about module-ordering issues when that happens. Two failure modes shared the same observable symptom (a missing
The detector couldn't tell these apart and would surface case 2 as if it were case 1, leading to confusing diagnostics where the user would see both an unattributed stack trace AND an incorrect "move this module to the end" warning. ChangeThe const render = () => {
try {
// ... existing render logic ...
} catch (e) {
const msg = (e && e.message) ? e.message : String(e);
console.warn('[relative_time_enhanced] Internal render error: ' + msg);
}
};Impact on usersUsers who were not experiencing internal exceptions see no change. The module behaves identically. Users who were seeing two messages (an unattributed stack trace plus a "overwritten by later module" warning) for what was actually a single internal bug will now see one clearly-prefixed error message that points back to this module directly. This makes the root cause easier to diagnose and report. What this is NOTThis patch does not change:
Upgrade pathReplace the module YAML with the v1.3.1 version. No config edits needed. |
Patch Note - v1.3.2Released: Patch on top of v1.3.1 SummaryTwo fixes:
Fix 1: Separator whitespace preservationBackgroundThe separator string was being inserted into the DOM as a bare text node between the original state text and the time span: <div class="bubble-state">
Closed<!-- text -->
" || "<!-- bare text node, the separator -->
<span class="rte-time">2d 7h 42m ago</span>
</div>Under the default CSS This was a rendering issue, not a storage issue. The YAML value was always preserved correctly. ChangeThe separator is now rendered inside a dedicated span with <div class="bubble-state">
Closed
<span class="rte-sep" style="white-space: pre"> || </span>
<span class="rte-time">2d 7h 42m ago</span>
</div>
Impact on usersUsers who never customized the separator, or who used single-space separators, see no visible change. Users who configured multi-space separators and found them visually collapsed will now see their literal value rendered. Fix 2: Render error included in overwrite warningBackgroundIn v1.3.1, the render function was wrapped in try/catch so internal exceptions surface with the module's prefix. However, when a render error occurred, the user saw two seemingly unrelated console warnings: The conflict detector saw no ChangeThe catch block now stores the trapped error message on the card. The conflict-detection warning consults this state and, if a recent error was trapped, appends it to the warning: The visual editor banner gets the same treatment, with the error appended after the standard text. Impact on usersUsers whose render path never errors see no change. Users who encounter a render error now see a single coherent diagnostic that connects the missing time display to the underlying error. The note "ordering may not be the actual cause" steers them toward fixing the error rather than reordering modules in vain. Related improvementThe visual editor warning element now refreshes its text on each render rather than freezing on first insertion. Previously, if the error state changed between renders (different exception caught), the visible warning would show stale text. Now it always reflects the current error state. What this is NOTThis patch does not change:
Upgrade pathReplace the module YAML with the v1.3.2 version. No config edits needed. |
|
DerHerzog7 Are you still having an issue after this ver? |


Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Relative Time Enhanced
Version: 1.4.0
Creator: Based on Relative Time by pterhu
License: MIT, the same license as Bubble Card
Important
Supported cards:
Tip
What's new in v1.4.0 (since v1.3.2)
Note
What's new since v1.0 (cumulative)
A configurable module that replaces or augments a card's state line, and optionally its sub-buttons, with a human-readable relative time string. Source the time from any entity's state, last_changed, or last_updated. Choose which time units to display, cap output length, customize every label for translation or visual preference, and optionally apply per-threshold colors and animations based on how stale the value is.
I have wanted since I converted my home automation to Home Assistant to have full control of the inbuilt Relative Time formatting. Pterhu's module gave me the inspiration to code it up myself finally.
This is a fork of pterhu's Relative Time module (#2259), expanded with a multi-unit cascade, per-unit toggles, multiple time sources, auto-refresh control, full translation hooks, threshold-based coloring with separate foreground and background slots, an animation system with sixteen presets, display-mode options that let the time coexist with the card's existing state text, sub-button targets, and runtime conflict detection. I added everything I ever wanted to use and then some. Please let me know if you find any errors or have more features that would be useful.
Features
Output examples
With defaults (years, weeks, days, hours, minutes, seconds enabled; months off; max 5 units; no auto-refresh; suffix display mode with " - " separator):
- 1y 6w 3d ago- 4w 2d ago- 2w 3d ago- 3h 5m ago- 30s ago- just now- unavailableIn
replacemode the dash and space are omitted; only the time string is shown.Editor layout
The editor is organized into one always-visible source section and six collapsible expanders so common options stay accessible without overwhelming the user:
bubble-sub-button-Nclass, 1 = first)Every field shows its default value in the label, so users know what to expect when they leave a field empty.
Display modes and module ordering
Three display modes are available, selectable in the Display expander:
replaceshow_stateconfigprefixsuffix(default)show_state: trueto show "Armed Home - 5m ago" or similarPrefix and suffix never touch what Bubble Card rendered: name, state, attribute, and Bubble Card's own "last changed" / "last updated" text all stay, and the time is added next to them. Only replace removes that content. On a sub-button with Show last changed on, suffix therefore shows both Bubble Card's "5 minutes ago" and this module's "5m 12s"; to show only this module's time, turn Show last changed off on that sub-button or set the entry's display mode to replace.
The
display_separatorsetting (default" - ") sits between the time and the original content. It's skipped automatically when there is no other content (e.g. whenshow_stateis off).Module ordering with other modules
This module wraps around whatever was last written to the card's state line, or to a targeted sub-button's text, by Bubble Card or by earlier modules in the same render cycle. When combining with other modules that ALSO write to those places (for example: get_state_attribute (#1232)), list this module LAST in the
modules:array so it wraps around their composed output.If a later module overwrites this module's output, the module detects this on the next render frame and surfaces a warning:
The detection is based on whether this module's injected output actually survived the render cycle, not just on position in the array. Modules that come after this one but don't touch the state line or the sub-button text (for example, modules that only modify the icon or name) are not flagged as conflicts.
Recommended ordering when combining with
get_state_attribute:Sub-buttons
Each entry uses the main card display settings (time source, display mode, separator, effects target, and the card's thresholds) unless you override a field in the entry. The time entity defaults to that sub-button's own entity, then to the card entity; set it explicitly if your card's sub-buttons are arranged in rows or groups and the default picks the wrong one.
Two switches matter here:
With the effects target set to whole, colors and animations apply to the whole pill rather than just the time text; combined with a background glow target, the pill itself glows.
Common configurations
Use the card's main entity
For when the card already points at the entity you want time from. Leave the Time entity field empty and the module reads from the card's own entity:
Combine with show_state to display both state and time
The default
suffixmode appends the time after the state. Make sure this module is listed LAST in the modules array if you have other state-line modules:Replace mode for state-line-only time display
Set
display_mode: replaceto override the existing state with just the time:Prefix mode with custom separator
Show the time first, separated from the state with a pipe character:
Sub-buttons-only card: last activity on each pill
Motion, person, pet and vehicle detections from a doorbell, each pill showing how long ago it last fired, red and glowing for the first minute, amber until five minutes, then plain:
Button card: time on the state line and on one sub-button
The state line shows when the alarm last changed; the second sub-button shows when the front door was last opened, using its own entity by default:
Sub-buttons only, state line untouched
Per-sub-button thresholds
The first pill follows the card's thresholds; the second has its own, quieter set:
Z-Wave / Zigbee device last seen
For a battery device that exposes a "last_seen" timestamp sensor, with
replacemode for a clean single-value display:Light last toggled
Sensor last reported, regardless of value change
Cover (door, blind, shutter) last operated
Verbose English: "2 hours 5 minutes ago"
French: "il y a 2 heures 5 minutes"
Auto-refresh enabled, second-level precision
Threshold coloring for staleness warning
Green when fresh, yellow over 1 hour, red over 1 day. Note the
set_foreground: truetoggle per threshold; colors are opt-in:Alert that fades back to normal
High alert for the first minute, medium until five minutes, low until an hour, then back to the card's normal look. The last threshold has no color and no animation, which ends the chain:
Effects scope: color the whole state line, not just the time
By default, threshold colors and animations target only the
.rte-timespan (the time string) in prefix/suffix mode, so the original state keeps its theme color. Seteffects_scope: wholeto apply colors to the whole.bubble-stateelement instead (or to the whole pill, on a sub-button):Background color thresholds
Useful for high-visibility warnings where the foreground color is preserved by the card's theme. Set background only (no foreground color change):
Combined foreground and background
Both color slots can be on simultaneously. Each opt-in toggle controls one slot:
Threshold animation: subtle ambient pulse for moderately stale items
A gentle pulse without any color change. The animation is selected on the threshold; no color toggles are needed if you only want motion:
Threshold animation: critical alert for very stale items
Combined shake, flash, and glow for a "needs attention now" presentation. Pairs nicely with a red foreground:
Threshold animation: background glow on a pill
A halo around the whole sub-button in its background color rather than around the letters. Needs the effects target set to whole so the pill is the animated element:
Threshold animation: custom flash color
For non-red flash. Useful when the urgency category isn't a generic alarm. For example, a maintenance reminder in blue rather than red:
Threshold animation: flash-glow for inverted halo emphasis
The flash-glow preset inverts the glow size with the background flash: the halo is at maximum when the background is calm, and contracts to zero when the background flashes. Pairs well with a moderate glow size:
Refresh behavior
The module recomputes whenever Bubble Card re-renders the card. On a busy Home Assistant that happens many times a second, on any state change anywhere in the system, so the display effectively ticks by itself. On a quiet installation, or for a card whose entities rarely update, enable Auto-refresh and set a sensible Refresh interval (default 30 seconds) to guarantee ticking. For seconds-level precision, set the interval to 1 second, but be aware that many such cards on one view add up on lower-end displays.
Threshold-based coloring
Apply colors to the rendered time string based on how much time has elapsed. The
color_thresholdsconfig is a list of per-threshold settings. Each threshold matches elapsed values at and above its seconds value, up to (but not including) the next higher threshold. The highest threshold is the catch-all for anything beyond it. Negative seconds work, so future timestamps can pick up their own settings.Colors are opt-in. Each threshold has two independent toggles:
set_foreground: trueenables the foreground color slot for that threshold. Thecolortext andcolor_pickerfields are only applied when this toggle is on.set_background: trueenables the background color slot. Same pattern withbackground_colorandbackground_color_picker.A threshold can use foreground only, background only, both, or neither. With neither, the row applies only its animation if one is set; with no animation either, the row switches all effects off from its seconds value upward, which is how a chain like "alert, then calmer, then normal" ends.
Two ways to set each color:
color,background_color): accepts any valid CSS color string. Named colors (red), hex (#f44336), rgb/rgba, or theme variables (var(--warning-color)). Theme variables follow dark mode and theme changes automatically and are recommended for most use cases.color_picker,background_color_picker): a color picker widget that outputs an RGB array. The module converts torgb(r, g, b)at render time. Useful for one-off colors that don't need to adapt to themes.Precedence: if both fields are set on the same slot, the text field wins. Leave the text field empty to use the picker.
For scheduled-event sensors where the state is a future timestamp, negative seconds let you color the "in the future" display too:
Threshold animations
In addition to colors, each threshold can specify an animation preset that runs continuously while the elapsed time matches that threshold. Animations are implemented via the Web Animations API and apply to the rendered time span, or to the whole state line or whole sub-button pill when
effects_scopeiswhole.Available presets
nonepulsefade-pulseslow-blinkblinkstatic-glowglowglow-pulsescale-pulseshakefast-shakebouncecircular-bounceflashflash-glowcriticalThe five glow presets (static-glow, glow, glow-pulse, flash-glow, critical) draw their halo around the letters by default. Set the threshold's glow target to background for a halo around the whole element instead: the pill, with the effects target set to whole. The background halo takes the threshold's background color, then its foreground color.
Per-threshold animation override fields
Each threshold can override the defaults of its selected animation:
animation_durationanimation_opacity_minanimation_scale_maxanimation_distanceanimation_glow_sizeglow_targettext(halo around the letters, default) orbackground(halo around the element or pill)animation_flash_coloranimation_flash_color_pickerOverride fields are optional. Anything left blank uses the preset's default value.
Performance and accessibility notes
Animations run continuously while their threshold matches. Many simultaneously animating cards on a single dashboard view can affect rendering performance on lower-end displays. Presets that animate opacity or position (pulse, blink, scale, shake, bounce) are cheap; the glow and flash presets repaint every frame and are the ones to ration on a tablet.
The module does not honor OS-level
prefers-reduced-motion. Animations are explicit-opt-in via threshold config, so the user has already chosen to enable motion when configuring the card. If reduced-motion behavior is needed, omit the animation field from the threshold.Flash color
The
flashandflash-glowpresets, and the flash component ofcritical, use a default alarm-red color (rgba(244, 67, 54, 0.6)). Override per threshold via either of:animation_flash_color(text field): any valid CSS color string. Recommended form isrgba(r, g, b, a)so the alpha channel can be tuned for visibility against the underlying card.animation_flash_color_picker: RGB picker; converts to opaquergb(r, g, b)at render time. For a more transparent flash, use the text field instead.Unit cascade behavior
Each enabled unit takes its full integer share of the elapsed time. Whatever is left over flows into the next enabled unit. The smallest enabled unit absorbs the final remainder and is NOT capped at its natural maximum value.
Examples with custom unit selections:
1y 45d ago235m 55s ago1h 1845s ago1439m ago1d 30m agoUnavailable handling
The "unavailable" label is shown in these cases:
unavailableorunknown.For last_changed and last_updated sources, an unavailable state is NOT treated as unavailable, because the timestamp metadata is still valid (it indicates when the entity went unavailable, which is usually the answer the user wants). Only a missing entity or missing timestamp triggers the label in those modes.
Credits and lineage
Originally derived from pterhu's Relative Time module (#2259). Iterated through six revisions before being renamed for release at v1.0. The v1.4.0 release adds sub-button targets with per-entry overrides and per-sub-button thresholds, a background glow target, an empty threshold that ends an effect chain, and support for pop-up, separator, calendar and sub-buttons cards. Earlier: v1.3 added display modes (replace, prefix, suffix), a configurable separator, an effects-scope option for threshold styling, and real-time module-ordering conflict detection with editor warning; v1.2 added background coloring, the sixteen-preset animation system with per-threshold overrides, and a configurable flash color; v1.1 added threshold foreground coloring and the empty-time-entity fallback.
🧩 Get this Module
Full configuration example
All reactions