Skip to content

Releases: francois-le-ko4la/lovelace-entity-progress-card

1.6.2-rc1

1.6.2-rc1 Pre-release
Pre-release

Choose a tag to compare

@francois-le-ko4la francois-le-ko4la released this 19 Aug 19:55
409709d

✨ New

  • --epb-icon-shape-opacity: new CSS hook, 0 removes the circular shape behind the icon entirely. See CSS hooks.
  • hide: [shape]: same result as the hook above, without card_mod — Card and Template, Badge/BadgeTemplate have no shape by default. ➡️ [Feature]: Configuration possibility for the icon background visibility #136 (@RkcCorian)
  • alert_when.jinja: new Advanced mode (Simple/Advanced chip in the editor) — a Jinja condition replaces above/below as the trigger, returning true/false or an object overriding any of color/animation/highlight/label for that push. See alert_when.
  • alert_when on Template/Badge Template: new, Jinja-only — neither variant had alert_when in any form before. No above/below/color/highlight/animation/label, so the object return is the only form with a visible effect.
  • value_compact: Card and Badge, opt-in — abbreviates large values using locale-aware suffixes (12500001.3M) instead of the full number. decimal still caps the fraction digits, trailing zeros are trimmed. See value_compact.
  • unit_position: Card and Badge, opt-in — moves the unit before the value instead of after ($100 rather than 100$) for currency-style display. See unit_position.
  • value_sign: Card and Badge, opt-in — forces an explicit +/- on the displayed value (zero stays unsigned), clarifying the direction of a center_zero/bar_stack: { mode: net } delta at a glance. See value_sign.
  • Editor: 2-mode chip selectors now render as a single fused segmented pill instead of two separate chips or a plain toggle - theme_mode (Preset/Custom), alert_when_mode/bar_effect_mode/hide_mode (Simple/Advanced, replacing their old boolean toggle), the new icon_animation_mode (Auto/Template, same replacement), and force_circular_background_mode (Auto/Forced, same replacement).
  • Editor: hold_action/double_tap_action/icon_hold_action/icon_double_tap_action now stay hidden behind a "+ Add interaction" button, revealed one at a time — replaces the old "show all" toggle.

🐛 Fixes

  • status_label's own Jinja pill stayed permanently hidden once alert_when.highlight: 'label' was configured, even while the alert itself was inactive.
  • The editor's "Alert" toggle wiped the whole alert_when config (including a typed alert_when.jinja template) every time it was switched off, unlike status_label's own toggle — now preserves a draft, same pattern.
  • Same bug on the "Markers" toggle: switching it off permanently discarded the whole watermark setup (type, thresholds, colors, …) instead of just hiding it — now preserves a draft too. bar_max_width's toggle had the milder version (lost a custom value, fell back to the 300px default) — fixed the same way.
  • The editor's "Compact" toggle (density: compact) stayed visible and clickable with layout: vertical selected, even though compact density only has a meaningful shape in horizontal — toggling it on silently forced layout back to horizontal instead. Now hidden while vertical.
  • Editor translations are now complete across all 39 supported languages — several labels had silently stayed in English since the day they shipped, invisible to the usual checks.
  • Translations are organized more consistently under the hood, with a welcome side effect: a noticeably lighter download.
  • A few editor labels were simplified or clarified where two different fields ended up showing the exact same text.

📚 Documentation

  • The --epb-* CSS styling API is now fully documented. Most of it was built during 1.6.1's browser-compat CSS rework, but stayed undocumented — there wasn't yet a test bench to confirm every hook actually did what it claimed. 13 previously-undocumented variables added to docs/theme.md (icon battery-charging bolt geometry, bar_segments/progress-bar-min-width, the rainbow_full marker set, status_label pill colors), backed by a new CSS hooks view in docs/demo-dashboard.yaml — one card per --epb-* variable, each isolating a single override.
  • graphic-effects-compatibility.html links (release notes + CHANGELOG) now go through htmlpreview.github.io so the page renders instead of showing as raw source.
  • configuration.md updated: hide's shape option, alert_when's Advanced mode (with two new examples) and its reach onto Template/Badge Template, value_compact, unit_position, and value_sign.
  • editor.option.hide.shape added to all 39 languages + template, using a descriptive phrase ("Icon's circular background") instead of a bare "Shape".
  • alert_when.jinja's editor labels/field-helper added to all 39 languages + template; two demo cards in docs/demo-dashboard.yaml (plain boolean, and an object with a partial override).
  • One more demo card for Template's own alert_when.jinja — reuses the same translation keys, no new ones needed.
  • value_compact's editor label added to all 39 languages + template; three demo cards in docs/demo-dashboard.yaml (default, compact, compact with decimal: 2) on a new input_number.epb_demo_total_energy helper.
  • unit_position's editor label + after/before options, and value_sign's editor label, added to all 39 languages + template; a currency-prefix demo card and a center_zero + value_sign demo card in docs/demo-dashboard.yaml.
  • docs/troubleshooting.md: a version check that still shows the old one right after updating is usually HACS lagging behind the actual release — use ⋮ → Redownload to force a fresh install instead of assuming the update failed. ➡️ #137

🧹 Under the hood

  • translations/template.json (the structural reference file, never shipped) no longer picks up stray real text — it should only ever hold placeholders.
  • Badge's schema silently accepted hide: [shape] even though Badge has no shape to hide in the first place (Badge Template already excluded it) — now consistently blocked for both.
  • Bundle down ~195 KB (-27%): the generated translations file used to repeat every key's full name in each of the 39 languages. Restated once, with each language's values kept separately — same translated text, same behavior, meaningfully less to download. Verified against the previous version value-by-value before shipping (9672 values × 39 languages, 0 mismatches). See Internationalization.
  • A further ~32 KB shaved off on top of that: a long tail of internally-duplicated text — the same word or sentence stored separately for half a dozen near-identical fields or error messages — now shares one entry instead of a copy each (mode-toggle option words like "Simple"/"Advanced", the Jinja-helper hints, several developer-console-only validation messages). Purely internal; nothing translated changed.
  • Net result: the full prod bundle (dist/entity-progress-card.js) ships ~109 KB smaller than 1.6.1 (-16%), even after every feature and fix above — verified by comparing the built file between the two tags.
  • A handful of editor fields that happened to carry the exact same label as a neighboring one (bar_position/unit_position both said "Position", alert_when_mode/icon_animation_mode both said "Trigger mode") now share one, shorter label instead of two redundant copies.

1.6.1

Choose a tag to compare

@francois-le-ko4la francois-le-ko4la released this 16 Aug 23:48
847834f

What's new

A bigger release than it looks: combine several bars into one card, themes and per-icon animations reach Template, status_label/badge_icon can drive their own color from a single Jinja condition, a proper keyboard/screen reader pass, and a handful of layout options that couldn't quite do what people needed yet. Fully backward compatible — nothing to change in your existing dashboards.

⭐ Highlights

📊 Combine several bars into one card or Tile feature

entity-progress-multi-card / entity-progress-multi-feature stack several full-featured progress bars (each with its own colors, state and tap actions) into a single card or a single Tile feature row, instead of one card per entity — handy for printer ink cartridges, a set of batteries, or any group of related sensors. A new, thinner bar_size: xsmall helps fit more of them in a tight space.

A small bar is enough on its own for something like a printer cartridge, but not when the number itself matters. Set show_value: true to show each entity's own value right next to its bar.

See [multi] and [show_value].

➡️ [Feature]: Multi-bar card/feature #126 (@EDelsman)

📐 A more compact layout: bar_position: compact_below

name and the value now share one row (value right-justified), freeing the progress bar to use the card's full width on its own row underneath — instead of the bar and the value fighting for the same narrow space, or the value sitting in empty, unused room. See [bar_position].

➡️ [Enhancement]: Display value above bar #123 (@davidcoulson)

🎬 Trigger icon animations from a template

icon_animation now accepts a Jinja condition ({ effect, jinja }) instead of relying only on automatic entity-state detection. See [icon_animation].

➡️ [Enhancement]: template/condition to trigger the icon animation directly #125 (@FoxP)

🏷️ Status label pill

status_label draws a small rounded status pill in the card's corner ({ jinja, position, color_source }) — colored automatically from whatever color the progress bar currently shows by default (color_source: icon to follow the icon instead), or set your own color directly by returning {label, color} from the template instead of plain text. alert_when.highlight: 'label' reuses the same pill to flash a fixed alert label instead of tinting the border or background. See [status_label] and [alert_when].

🎫 One template, both badge icon and color

badge_icon can now return a {icon, color} object instead of just an icon name — one condition drives both at once.

See [badge_icon].

🌈 A hue-picker style bar: bar_color_mode: rainbow_full

The track always shows the theme's complete gradient end to end — not just the filled portion, like rainbow already does — with a small marker sliding along it to show where the current value sits, closer to a hue-picker strip than a traditional progress bar. Works with center_zero too, each arm showing its own half of the gradient in full.

See [bar_color_mode].

⏱️ Smarter countdown refresh (and a fix for stalled Template timers)

A Template card's now()-driven countdown (e.g. a secondary: line ticking down a timer) could freeze after its first render — Home Assistant only pushes a fresh now()/utcnow() value once a minute on its own. Add fast_refresh: true to opt that Template card into a forced per-second refresh instead. Not automatic (it re-subscribes every second), and standard cards/badges/features don't need it — they already self-correct on their own. See [fast_refresh].

🎨 A friendlier theme picker

The built-in theme list is reordered for readability: battery_adaptive (the one most people reach for) comes first, and each Critical when X/Optimal when X pair now sits together instead of being split into two separate groups.

🎯 A center_zero-aware "Critical when extreme" theme

theme: critical_when_extreme_center brings critical_when_extreme's "danger at both ends, safe in the middle" shape to center_zero — green at zero, red at both extremes, one continuous -100%/100% scale. Handy for a net power flow or a deviation from a setpoint that can swing either way. See theme.md.

🖌️ Theme support for Template

entity-progress-card-template / -badge-template can now pick a built-in [theme] instead of writing your own color Jinja by hand — the icon and bar color follow your percent: value automatically. [bar_color_mode] (segment/rainbow/rainbow_full) is available too, for a gradient look instead of a flat color.

📏 A hardened height

Card sizing got a real pass end to end: the min-height-as-a-floor protection (never clip text when the OS/browser text-size accessibility setting is scaled up) now applies consistently everywhere a card can live — Sections, Masonry, or embedded in another card. An explicit height: now always wins outright as a real, exact size everywhere too, instead of just another floor tall content could still outgrow. See height.

➡️ [Bug]: Some parts of the card are not visible on Android #131 (@zkurzyns)

🧹 Consistent hide: behavior

Hiding a field (hide: [icon, name, secondary_info, progress_bar]) now always gives its reserved space back, the same way, in every layout — previously each field followed its own inconsistent rule. An empty value/unit row now collapses too, whatever made it empty. See hide.

📶 Sturdier bar_segments

bar_segments: N's divider lines are real elements now, not a CSS gradient/mask trick — all N segments are the same width now (the two end ones used to read wider), and divider thickness can scale with the bar's own length instead of a fixed size, tunable via --epb-bar-segment-gap hook. See bar_segments.

📱 A compact density

density: compact shrinks the card to the smallest a complete card (icon, name, value, bar) can be in a Sections grid, in one toggle — instead of hand-tuning layout/bar_position/multiline yourself. Flipping it on through the visual editor also pins the card's size outright, restored automatically if you switch it back off. See density.

🃏 Show up when you pick an entity, not just when you search for a card

Home Assistant 2026.6 added an entity-first card picker: pick an entity, and compatible cards show live previews right there instead of you having to search for this card by name first. The Card and Badge now opt in — pick a compatible entity (a numeric sensor, a cover, a light...) and they show up under "Community" with a working config already filled in. Template/Badge Template don't suggest themselves — they need a hand-written Jinja percent: to render anything meaningful.

✍️ More inline styles for Jinja-rendered text

name/secondary/custom_info templates now also accept font-size, font-weight, text-align, width, display, position and z-index (on top of the existing color/background-color) — enough to build simple multi-column layouts directly in a template.
➡️ [Enhancement]: JINJA Should accept more STYLE tags #129 (@emartoni)

♿ Better keyboard and screen reader support

The card and its icon (when either has its own tap action) are now properly reachable and understandable for keyboard and screen-reader users, not just mouse/touch:

  • Tab reaches the card, and separately the icon if it has its own distinct action (icon_tap_action) — each now announces something meaningful (the entity's name and current value for the card, "Icon action" for the icon) instead of a bare, unlabeled "button". A badge, where only the card itself is ever clickable, no longer exposes its icon as a confusing extra stop.
  • Enter/Space activates each one, same as a mouse click.
  • Tabbing to the card or the icon now shows a clear, colored outline (matching the entity's own color, following the card's rounded corners properly) instead of the browser's plain default rectangle.
  • Fixed a structural issue where the card and its icon were both marked as "buttons" nested one inside the other — some screen readers and touch navigation handle that inconsistently. They're independent controls now, side by side rather than one inside the other.

🔧 Improvements

  • The visual editor now remembers a field's value across a mode toggle (standard/entity/Jinja) instead of resetting it to blank — switch min_value/max_value/watermark.low/.high/alert_when.above/.below, badge_icon/badge_color, bar_effect, hide, icon_animation, or status_label away from Jinja and back, and your template is still there.
  • Jinja-capable fields in the editor now show a short hint under the field for what the template is expected to return (a number, a boolean, a string, or an object with specific keys) instead of leaving you to guess from the docs.
  • Several fields in the editor's theme panel (icon/color, bar_orientation, bar_size, bar_segments, bar_scale, bar_color_mode, interpolate) could end up alone in their row instead of sharing it with their usual neighbor, depending on which other options were active — all paired up correctly now.

🐛 Notable fixes

  • The card could fail to load entirely on some older or embedded browsers (ki...
Read more

1.6.1-rc8

1.6.1-rc8 Pre-release
Pre-release

Choose a tag to compare

@francois-le-ko4la francois-le-ko4la released this 15 Aug 00:34
f233c1a

What's new

🐛 Fixes

  • A Jinja-driven icon_animation: { effect, jinja } could briefly fall back to the automatic entity-based detection instead of staying off — configuring jinja mode only ever overrode the automatic detection once a push had resolved to a real boolean; right after connect, or right after a config change reset the cache, it silently ran the automatic detection instead of just staying off until the real result arrived.
  • Jinja-driven badge_icon/badge_color/icon_animation fields could get visually stuck on a value that never matched the final, settled state — a multi-step automation/script (e.g. turning an input_boolean on, then picking an input_select option right after) makes Home Assistant re-evaluate a template once per intermediate state, not just once for the final one, since the entities referenced by an and condition don't change atomically. Applied immediately, that transient push could render (and get stuck showing) a value nothing in the final state actually supports. Every Jinja field now settles for ~80ms before rendering, so only the last, settled push of a rapid burst is ever shown. ➡️ [Bug]: Cached / invalid Jinja result? #135 (@FoxP)

🧰 Internal

  • Continuing 1.6.0's TypeScript hardening pass (HassHomeAssistant, removing hand-maintained any blobs): Config is now derived directly from the YAML validation schema instead of a separately maintained type — one less place for the two to silently drift apart. No behavior change.

1.6.1-rc7

1.6.1-rc7 Pre-release
Pre-release

Choose a tag to compare

@francois-le-ko4la francois-le-ko4la released this 13 Aug 21:43
37dd3dc

What's new

✨ New

  • Card/Badge suggest themselves in Home Assistant's entity-first card picker
    (HA 2026.6+, "Pick a card, any card") — pick an entity there and, for a
    compatible one, the card/badge shows up under "Community" with a live preview
    already wired to it: entities whose own state is a plain number (sensor,
    number, input_number, counter), timer (native support), and entities
    whose value lives in an attribute (cover/valve's current_position,
    fan's percentage, light's brightness, humidifier's
    current_humidity). Deliberately conservative — anything more
    context-dependent (climate targets, a text sensor...) is left out rather than
    guessed, so the suggestion never shows up somewhere it'd render empty or
    nonsensical. Template/Badge Template don't suggest themselves: they need a
    hand-written Jinja percent: to render anything meaningful.

🔧 Improvements

  • Template/Badge Template gained theme (percentage-based themes only —
    battery_adaptive, critical_when_low/_high, optimal_when_low/_high,
    critical_when_extreme/_center, light, humidity) and bar_color_mode
    (segment/rainbow/rainbow_full) — drives icon/bar color straight off the
    percent: Jinja field, no manual color Jinja needed.
  • New theme: critical_when_extreme_centercritical_when_extreme's own
    shape, built for center_zero specifically (green at zero, red at both ends,
    one continuous -100%/100% scale instead of the same zones mirrored onto each
    arm).
  • status_label.jinja can return {label, color}, and badge_icon can
    return {icon, color}
    — one Jinja condition drives text/icon and color
    together, instead of two separate fields kept in sync by hand.
  • New status_label.color_source (bar default, or icon) — picks which
    color the pill falls back to when its own jinja doesn't return an explicit
    {label, color}.
  • badge_icon/badge_color moved to the editor's Markers panel (were in
    Theme/appearance) — same "reacts to a condition" grouping as
    watermark/status_label/alert_when. New toggle shows/hides both together.

🐛 Fixes

  • A conditional badge_icon/badge_color (only showing while some state holds)
    could flicker back on right after correctly hiding — any unrelated dashboard
    update was enough to force it back, ignoring the template's own current
    result.
  • bar_color_mode: rainbow_full's marker got clipped near a value close to
    0%/100% (or either end with center_zero) - it's centered on its own
    position, so at the extremes part of it pushed past the bar row's own boundary
    and got cut off by the card's overflow: hidden. Its position now clamps to
    stay fully inside instead. A second, unrelated clip also showed at the bottom
    regardless of value, bar_position: default included - the marker's soft
    shadow wasn't accounted for in the vertical room reserved for it; now sized
    off the same variable that room already comes from.
  • A Template card with percent: '' (empty, e.g. still waiting on the entity it
    depends on) never painted its icon/bar/theme at all - an empty percent was
    never subscribed to in the first place, so nothing ever called the code that
    renders them. Now falls back to a plain 0% render instead of staying blank.
  • badge_icon's own {icon, color} object (see the highlight above): if a
    later push kept the icon but dropped color, the badge's background stayed on
    whatever color it last showed instead of clearing.
  • center_zero with a theme and bar_color_mode set (segment/rainbow/
    rainbow_full) could leave a gap in the fill instead of a clean edge, for any
    value past max_value (or below min_value) — the two arms' own gradient
    size wasn't capped at 100% the way the fill itself already is.
  • Template's watermark.low/.high in { jinja: ... } mode never resolved —
    no subscription was ever wired for it, so the mark just never appeared.
    entity/plain-number modes were unaffected.
  • bar_color_mode: rainbow_full's marker didn't mirror with
    bar_orientation: rtl — the fill visually flipped, the marker stayed put and
    ended up on the wrong side of it.

1.6.1-rc6

1.6.1-rc6 Pre-release
Pre-release

Choose a tag to compare

@francois-le-ko4la francois-le-ko4la released this 11 Aug 09:35
5a9fce2

What's new

🔧 Improvements

  • watermark editor labels reworded to "marker(s)" (issue #133, @Ascathon)
    Watermark toggle → Markers, Low/High watermark source
    Low/High marker source. Editor wording only, the watermark: YAML option
    itself is unchanged.
  • round/triangle watermark markers now center precisely on their value,
    same pixel-rounding fix bar_segments' own dividers already got.
  • Browser-compat fallbacks (round()/color-mix()) cleaned up and extended
    across the file — same graceful-degradation behavior, less duplicated CSS to
    maintain. Turned up several real gaps along the way, see Fixes.
  • New --epb-alert-background-opacity hook tunes the
    alert_when.highlight: background tint on browsers using the fallback above
    (defaults to matching the same look modern browsers already get).

🐛 Fixes

  • The icon's circular background could disappear entirely on an older browser
    (Chrome/Edge < 111, Firefox < 113, Safari < 16.2 — see issue #128) —
    simplified to a technique that renders the same way on every supported
    browser, so there's no gap left to fall back from.
  • bar_effect: gradient/gradient_reverse could silently do nothing on the
    same class of browser — now falls back to a softly lightened bar instead of a
    flat, un-lightened one.
  • The alert blink animation's background color could glitch mid-cycle on the
    same class of browser — now falls back consistently.
  • icon_animation: ping and alert_when's ping/blink animations could fail
    to start at all on the same class of browser — not just lose the color
    blending like the others above, the animation itself never ran. Same fallback
    approach applied there too.
  • Clicking the icon also lit up the whole card — a real double-ripple,
    confirmed and fixed by rebuilding the click-feedback layering after comparing
    directly against Home Assistant's own native Tile card. The icon now gives its
    own visual feedback (a quick highlight/scale) instead of triggering a second
    ripple.

♿ Accessibility

A full pass on keyboard and screen-reader support for the card and its icon:

  • The card (and its icon, when it has its own separate icon_tap_action) are
    now correctly announced as buttons with a real, specific name — the entity's
    own name and current value for the card, "Icon action" for the icon — instead
    of a generic, unlabeled one. A badge (only ever the card itself is clickable
    there) no longer exposes its icon as a confusing extra keyboard stop.
  • The icon's own action, when it has one, is now reachable and activatable from
    the keyboard (Tab, then Enter/Space) — previously mouse/touch only.
  • Tabbing to the card or the icon now shows a clear, colored focus outline (the
    entity's own color, following the card's rounded corners correctly) instead of
    the browser's plain default rectangle.
  • Fixed the card and its icon being marked as two "buttons" nested one inside
    the other — inconsistent handling on some screen readers/touch navigation.
    They're independent, side-by-side controls now.

1.6.1-rc5

1.6.1-rc5 Pre-release
Pre-release

Choose a tag to compare

@francois-le-ko4la francois-le-ko4la released this 09 Aug 21:04
baa3e5e

What's new

🔧 Improvements

  • Hardened height handling. Left unset, the card's height has always been a floor rather than a fixed size on purpose (issue #131 - it lets the card grow instead of clipping text when the OS/browser text-size accessibility setting is scaled up). The gap: an explicit height: used to become that same floor too, so it could be silently outgrown by the card's own content (a bigger font-scale setting, a taller theme, secondary_info wrapping...) with no way for a deliberate value to actually pin an exact size — a "sometimes my height isn't respected" report that traced back to exactly this.
    • Left unset — unchanged: still a floor, can still grow past it, everywhere (Sections, Masonry, embedded in any other card).
    • Set explicitly — now wins outright as a real, exact height, everywhere, no exceptions. The trade-off (clipping if the value is too small for the actual content) is the user's to make once they've set it on purpose, not something the card second-guesses for them.
    • First attempt at this only applied inside a handful of containers the card could auto-detect via a class a card_mod convention injects (entities, picture-elements - not native HA, needs card_mod installed) - type: grid looked like a good next candidate (confirmed live: hui-grid-card does mark itself the same way) until a live DOM dump showed that marker never actually reaches this card's own ha-card. Rather than chase down containers one at a time, height: set explicitly is now unconditional - it doesn't need to detect anything about its surroundings anymore, so it works the same everywhere, type: grid/custom:combined-card (which never got auto-detected at all) included. The one exception: type: grid with square: true (the default) forces a 1:1 cell regardless of any height, explicit or not - see the height note and the "Inside another Lovelace card" table.
    • entities's hardcoded ~44.8px row-height guess for the unconfigured default (based on a Tile row with secondary_info shown - not a real HA constant, and wrong the moment secondary_info is hidden) is gone too, replaced by ordinary content-driven sizing there by default. ➡️ Discord @RKT62
    • That entities default surfaced two more edge cases live-tested inside a real entities row: bar_size: xlarge and bar_position: background were both getting squeezed down to the tiny default bar thickness instead of their own dedicated size, since they shared the same override slot the new default was feeding - both excluded now.
    • bar_orientation: up combined with bar_position: overlay lost the vertical room it needs to actually show a vertical bar. Root cause: the overlay bar is position: absolute, so it never contributed to the card's own auto-height in the first place - harmless under the old unconditional height: 100% fallback, exposed once unset height became genuinely content-driven (auto) above. That specific combination now gets its own 100% fallback instead of auto, everything else unaffected.
  • label renamed to status_label. It shared its name with alert_when.label (a different field - a fixed string, not a Jinja template) despite both driving the same status pill, an ambiguity made more visible now that the two live in the same editor panel (see below). Safe to rename now: status_label only ever shipped in a 1.6.1 release candidate, alert_when.label has been stable since 1.6.0 and keeps its name. See status_label.
  • The visual editor's "Look & Feel" panel had regrown to ~28 fields, the same size that justified splitting watermark/alert_when into their own "Markers & Alerts" panel earlier. status_label moves into that same panel too - it's the same "react to a condition" status-pill marker alert_when.highlight: label reuses, not core entity/display content.
  • hide: reclaims space consistently everywhere, not just in the cases each field happened to already handle:
    • hide: icon with layout: horizontal - .content's width formula (calc(100% - 56px)) deducted a fixed 56px column for the icon unconditionally, on purpose, matching how Mushroom/Tile-style cards keep name/value aligned to the same column with or without an icon shown. Traded that alignment for consistency instead - the 56px is given back once the icon is hidden, same as every other field below.
    • hide: name/hide: secondary_info with layout: vertical - only layout: horizontal zeroed the hidden row's height term before (issue #129's fix never got a vertical equivalent). layout: vertical + bar_position: default stacks name/secondary-info/bar as 3 independent rows (unlike horizontal's default, which shares one row between secondary-info and the bar) - safe to always zero either one's height term with no conditional needed, unlike horizontal's own exception just above it.
    • hide: progress_bar - only ever hid the fill (.bar), never .bar-container itself, which kept its own height/min-width regardless - an empty box wherever bar_position gave the bar a dedicated row (below/top/bottom), or extra reserved width sharing secondary_info's row by default. .bar-container's height now reads from --current-specific-progress-container-height (the same dedicated top-priority override slot .bar-container already checked first for everything else) whenever hide: progress_bar is set, so this one rule collapses it the same way regardless of bar_position or layout, min-width/flex-grow reset alongside it.
    • layout: vertical + bar_position: default's own padding-top (proportional to --progress-size, pushes the icon+content group down so it stays visually centered against just the text once the bar renders below it) now drops to 0 once the bar itself is hidden - nothing left below to stay centered against. Left untouched by hide: icon: that padding was never about the icon, so it stays regardless.
    • hide: value/hide: unit closed the same way, but differently: neither has a CSS class (both are a pure text-level omission, see ViewBase#secondaryInfoMain), so reclaiming an empty row needs the parent to react to that emptiness - not something plain CSS can do at this card's documented browser floor without :has() (Firefox 121+ vs. the 94+ floor - see the Prerequisites table in README.md, and note that styles.ts's existing .info-multiline collapse rule already relies on it anyway, an inconsistency worth revisiting separately). Solved with a JS-computed flag instead, following the pattern the rest of hide: already uses: _processStandardFields (the one place secondaryInfoMain's final string is both computed and written) pushes --detail-height: 0px inline on ha-card whenever that string comes out empty, removeStyle otherwise - content-driven, not config-driven, so it reclaims the row regardless of why it's empty.
  • hide: value/hide: unit as a Jinja template never actually worked - found while building the reclaim logic above. Root cause: no single source of truth for "what's hidden right now". _handleHiddenComponents toggled CSS classes straight from a Jinja push and threw the resolved list away afterward; hasComponentHiddenFlag (which secondaryInfoMain's value/unit omission and minGridRows's icon check both call) independently re-read config.hide directly, which only ever works for the static array shape - a Jinja string silently fails is.array(), so the check always came back "nothing hidden", regardless of what the template actually resolved to.
    • New ViewCore#resolvedHide (a Set<string> | null, null until a real Jinja push writes to it via the new setResolvedHide(), reset on every set config) is now the one state everything reads. hasComponentHiddenFlag checks it first, falling back to config.hide directly only when it's still null - which is also exactly what a plain static hide: [...] array leaves it at forever, so one code path now covers both shapes with no branching.
    • _baseJinjaHandlers.hide now also calls _processStandardFields() after _handleHiddenComponents(content) - icon/name/secondary_info/progress_bar are purely visual (CSS class, no text to recompute), but value/unit need the assembled string itself redone the moment the template's result changes, not just on the next unrelated entity refresh.
    • minGridRows (Sections grid row reservation) reads the same resolved state now too, but stays effectively static-only regardless: it's computed once at config negotiation, and HA's own getGridOptions() isn't reactive - a Jinja hide: icon was never going to resize the grid reservation live, before or after this fix. Not a regression, a pre-existing ceiling.
  • Two :has()-based CSS rules replaced with a JS-computed check - found while reviewing this card's own browser-compat floor (Firefox 94+ per README.md) against features actually in use. Both collapsed .secondary-info-wrapper (display: none) once every line inside it (custom_info/Template's secondary, single- or multi-line) had gone empty, using .secondary-info-extra-1:empty/.secondary-info-extra-2:empty/.secondary-info-main:empty chained through :has()/:not(:has()) - :has() itself needs Firefox 121+, well past the documented floor; below that version the rule was just silently invalid, leaving a small empty gap instea...
Read more

1.6.1-rc4

1.6.1-rc4 Pre-release
Pre-release

Choose a tag to compare

@francois-le-ko4la francois-le-ko4la released this 07 Aug 08:50
61d03ef

What's new

✨ New

  • New bar_position: compact_belowname and the secondary info
    (state/value) now share one row, with the value right-justified, and the
    progress bar takes the full width of its own row underneath instead of
    squeezing next to the text. Reclaims the dead space that used to sit empty to
    the right of name on a horizontal card, and lets the bar grow to the card's
    full width. Horizontal-only — with layout: vertical, where there's no such
    row to reuse, it silently falls back to default. See
    bar_position.
    ➡️ [Enhancement]: Display value above bar #123 (@davidcoulson)
  • New label — a small rounded status pill in the card's corner
    ({ jinja, position }), colored automatically from whatever color the icon
    currently shows (theme, custom_theme, or a plain color override).
    alert_when.highlight: 'label' reuses the same pill to flash a fixed alert
    label instead of tinting the border or background. See
    label
    and
    alert_when.
  • New bar_color_mode: rainbow_full — the track always shows the theme's
    complete gradient end to end, not just the filled portion, like a hue-picker
    strip — with a small marker sliding along it to show where the current value
    sits. Works with
    center_zero
    (each arm shows its own half of the theme in full, the marker crosses the
    visual center at zero). Falls back to plain rainbow with
    bar_stack
    — several entities, no single position for one marker. See
    bar_color_mode.

🐛 Fixes

  • icon_animation's { effect, jinja } docs didn't warn that jinja must be a
    bare {{ ... }} expression — a {% if %} block or a literal string like
    "true" renders back as text instead of a native boolean, and silently falls
    back to automatic detection instead of erroring.
  • layout: vertical's min-height formula for the name/value/bar column never
    accounted for the small gaps between those three rows, so the card's real
    rendered height consistently ran a couple pixels taller than the formula
    claimed — harmless on its own (nothing clipped), but it meant
    grid_options: rows: auto could never land on a clean Sections grid row
    multiple.

🧪 Try it: demo dashboard

docs/demo-dashboard.yaml's
"Layout & bar_position" view got a compact_below card in both the horizontal
and vertical "every bar_position" galleries (the vertical one shows the
fallback to default), plus a new "Série 2 — compact_below, hide progressif
(#123)" section walking through hide combinations on top of it. The
"bar_color_mode, custom_theme, alert_when, trend" view gets new label demo
cards (custom-theme-based, built-in-theme-based, position: left, and
alert_when.highlight: label), a "Full rainbow" section showing rainbow_full
at every bar_size, and a showcase section covering different
temperatures/layouts/center_zero combinations with labels enabled. The
"Sunset" real-world example (#60) gets a second, alternate version contributed
by @WarC0zes (HACF).

1.6.1-rc3

1.6.1-rc3 Pre-release
Pre-release

Choose a tag to compare

@francois-le-ko4la francois-le-ko4la released this 04 Aug 13:23
396b8fe

What's new

✨ New

  • entity-progress-multi-card/entity-progress-multi-feature can now show each entity's own value next to its bar (show_value: true, shared or per item) — a bare bar is enough on its own for something like a printer cartridge, but not for values where the number itself matters (energy in Watts, a tank in liters…). The bar gives up part of its width for the value instead of an overlay - a bare feature bar is already thin enough that overlaid text would fight it for contrast. decimal/unit/disable_unit/unit_spacing all work the same as on the standard card. value_position: left/right (default left) picks which side it sits on, and every value takes up the same fixed width instead of sizing to its own text, so bars meant to read as comparable actually line up regardless of digit count. See show_value.

  • The built-in theme picker (dropdown and docs) is reorganized for readability: battery_adaptive now sits first (it's the one most people reach for), and each critical_when_*/optimal_when_* pair sits together (Critical when low next to Optimal when low, Critical when high next to Optimal when high) instead of all the criticals then all the optimals. Optimal when low/Optimal when high's labels also drop their parenthetical examples ((CPU, RAM...)/(Battery...)) — plain text now, matching every other theme's label. No config keys changed, purely a picker/docs reordering. See theme.

🐛 Fixes

  • icon_animation: { effect, jinja } never actually triggered the animation on a Template card (entity-progress-card-template and its badge), even for a template that always resolves true. Every other Jinja-driven option re-applies whatever it just changed itself right after resolving (e.g. min_value/max_value call _updateCSS(), alert_when calls _applyAlertClasses()) - icon_animation's own handler was missing this and only ever set the resolved value, relying on some other, unrelated refresh to happen to re-check it afterward. A standard card gets one soon enough from its regular entity-driven updates, masking the bug there, but a Template card has no such incidental refresh to piggyback on, so the animation never started. It now re-applies its own CSS classes right after resolving, the same way every other option already does.

    ➡️ [Enhancement]: template/condition to trigger the icon animation directly #125 (@FoxP)

  • center_zero's negative arm with bar_color_mode: segment/rainbow and a theme (or custom_theme) could render as a single flat color instead of a gradient — e.g. theme: temperature with center_zero: { value: 20 } showed solid blue (or another single theme color) across the whole negative arm instead of fading through the zones its actual range covers. Two independent bugs combined here, both pre-existing and never exercised until now (not related to the min_value/max_value/theme-scope changes above): the negative arm's projection window is reversed (it grows away from center, toward the scale's own low end), which flips the zones' position order relative to their value-ascending declaration order (e.g. temperature's coldest zone ends up at the highest local position) - CSS linear-gradient clamps any stop whose position is lower than the previous one up to that same position, so once one out-of-order stop hit, every stop after it collapsed onto it; zones are now sorted by their projected local position before building gradient stops (a no-op for the normal, non-reversed direction), keeping stops properly ordered either way. Separately, the negative arm's CSS grows in the opposite direction from every other bar (it slides toward the low end instead of away from it), which puts its "current value" and "zeroValue" ends on the opposite box edges from what the gradient math assumes - the real color transitions ended up computed entirely outside the visible portion, leaving only a single held-flat color showing; the gradient is now painted in the mirrored CSS direction for this arm specifically, which corrects this without changing any of the position math itself.

  • On a compressed horizontal card, the progress bar could shrink to a near-invisible sliver (or get pushed out past the card's edge entirely) while the name/secondary-info text next to it never gave up any of its own space. The bar had no minimum width at all, while the text already had one (45px) - every bit of horizontal squeeze landed on the bar alone instead of being shared. The two now hold coupled, proportional floors: the bar keeps a 30px minimum (--epb-progress-bar-min-width, overridable via card_mod for anyone who wants a different balance) and the text keeps 45px, but each caps at a fraction of the row (33% for the bar, 25% for the text - the bar gets the bigger guaranteed share, since a squeezed bar loses its whole purpose as a progress indicator while squeezed text still has ellipsis to fall back on) once the row can't fit both floors at once, so they can never sum past the row's width and force one or the other to overflow. The gap between them (10px by default) shrinks the same way under pressure, freeing a few more pixels right where the text and bar floors are already fighting for room.

  • The card could clip name/secondary_info text when the OS or browser's own font-size accessibility setting was scaled up (e.g. Android's system "Font size" option) — text rendered larger than the fixed-height row it sat in, and got cut off mid-glyph instead of the row growing to fit. name/secondary_info rows now hold a min-height (not a fixed height) with a line-height that only ever grows past the default (max(default, 1.2em)) - identical look at the default font scale, but room to grow instead of clip once the actual font is genuinely larger. Not applied to layout: vertical + bar_position: overlay + bar_orientation: up: there, the text row is a flex item competing with the icon section (flex-shrink: 0) for space, and letting it grow broke that specific layout (confirmed via DevTools computed styles) - it keeps its original fixed-height behavior for now (see docs/ideas.md for a possible follow-up).

    ➡️ [Bug]: Some parts of the card are not visible on Android #131 (@zkurzyns)

  • A percent-based sensor (unit_of_measurement: "%") with custom_theme zones could stop filling the bar all the way at 100%, if any zone's max went past 100 (e.g. a top zone of 80-120 used purely as a color buffer for values that might drift slightly above 100). 1.6.1-rc2 had max_value auto-default from the active theme's/custom_theme's own top zone bound whenever left unset, so it picked up 120 here and used it as the bar's own fill scale - a 100.0 reading only filled to 100/120 ≈ 83%. custom_theme is now dropped from that auto-default entirely - its zones are user-defined and may extend past the entity's real range on purpose, with no reliable way to tell that apart from a genuine max_value. A built-in theme with real-world value zones (temperature, voc, pm25) keeps the auto-default for max_value only - picking one of them is already a deliberate, specific choice, so the theme's own top bound is safe to assume as the entity's real range; min_value stays at its own default (0, or the theme's own lowest bound with center_zero - see max_value for the full explanation). bar_color_mode: segment/rainbow always projects a theme's zones onto [min_value, max_value] - the visible "scope": a mismatch between an entity's real range and its theme's/custom_theme's own zone scale now only ever clips or shifts which zones are reachable, never the fill percentage itself.

    ➡️ [Bug]: JINJA Should accept more STYLE tags #129 (@emartoni)

🧪 Try it: demo dashboard

docs/demo-dashboard.yaml got several new sections worth a look:

  • "Error / edge-case states" — what the card looks like when things go wrong: an entity that's unavailable, one that's unknown, one that doesn't exist at all, and a request for an attribute the entity doesn't have. Useful to check before reporting something as a bug — it might just be one of these.
  • "Compare with tile" — the same entity shown with this card side-by-side with Home Assistant's own built-in Tile card, across several kinds of entities (fan, battery, cover, light, timer, counter), so you can see how the two compare at a glance.
  • "custom_theme — use cases" — color-only zones, color + a per-zone icon override, and a full negative/positive range (shown standalone, then with center_zero at two different zero points), right next to the built-in theme examples.

The "Energy (consumption vs production)" example also got a fix: its "Net" bar now shows the actual balance (production minus consumption) as a single value, instead of showing both raw numbers stacked on top of each other, which never actually matched what "Net" was supposed to mean.

Almost every section across the whole dashboard now starts with a small YAML snippet showing the config it's demonstrating, plus a short note on what changes from one card to the next — meant to make the dashboard readable on its own, not just clickable.

1.6.1-rc2

1.6.1-rc2 Pre-release
Pre-release

Choose a tag to compare

@francois-le-ko4la francois-le-ko4la released this 02 Aug 22:28
df331ef

What's new

✨ New

  • icon_animation can now be triggered by a Jinja condition instead of entity state{ effect, jinja }, where jinja resolves to true/false and fully replaces the automatic entity-based detection. Covers cases like a plain numeric sensor with no active/inactive concept at all, which nothing in the automatic detection could ever match. See icon_animation.
    ➡️ [Enhancement]: template/condition to trigger the icon animation directly #125 (@FoxP)
  • The refresh rate of an active timer's countdown is now driven by what's actually displayed, and self-corrects against real time instead of drifting. Standard cards/badges/features refresh every second when unit shows seconds (s/timer/flextimer), once a minute otherwise (min/h/ d/natural format) — replacing the old fixed duration-based formula. Template cards get this once-a-minute refresh for free from Home Assistant's own push (no extra subscriptions); a new fast_refresh: true opts into a forced once-a-second refresh for a real ticking MM:SS countdown, at a real cost (see fast_refresh) — not tied to entity being a timer, any now()-driven countdown benefits the same way (e.g. a sunrise/sunset countdown against sun.sun). Every tick, standard or template, now lands on a round second/minute boundary and re-aligns itself on every cycle, instead of drifting from whatever moment the card happened to load. Each tick also does only the minimal work its own display actually needs (the bar + value for cards/badges, the bar alone for Tile features, a forced Jinja resubscribe for templates) instead of the full icon/badge/shape/trend/Jinja-processing pipeline - lighter, and less prone to per-tick timing jitter from that pipeline's own variable cost. The bar-only part is shared by every card type (defined once, not duplicated per type) since it's the one thing a ticking timer always needs to repaint, regardless of what else a given card type shows on top. The countdown text itself now writes to the DOM immediately instead of through the usual RAF batching (new DOMHelper.setTextNow, mirroring the existing setStyleNow) - a RAF callback runs at the next display frame, whose cadence isn't aligned to our wall-clock-second scheduling, so batching it reintroduced up to a frame's worth of per-tick unevenness on the one thing a ticking countdown makes visible (a discrete text jump, unlike the bar's own width change, which already glides on its CSS transition regardless of paint timing).
  • Timer/duration seconds were rounded instead of truncated (NumberFormatter.formatTiming), unlike the hours/minutes next to them, which already floored. A timer at 332.847s truly elapsed floored to minute 5 but rounded its seconds to "33", showing 05:33 up to ~500ms before the 33rd second had actually passed - a real-value discrepancy against any reference that floors (e.g. HA's own Tile), not a timing/jitter issue like the fixes above. Seconds now floor the same way hours/minutes do.

🐛 Fixes

  • bar_size: xlarge (or bar_position: below) with the icon hidden got squeezed into a single grid row instead of the extra row that size/position needs, cutting the bar off. A 1.6.0 regression - hiding the icon and needing an extra row for a large bar were wrongly treated as mutually exclusive instead of composing. Fixed for Home Assistant's own Sections grid, and also for everywhere else the card can be placed (Masonry, embedded in another card) - that fallback sizing had a second, independent copy of the same row-count logic (a hardcoded "always 1 row (horizontal) / always 2 rows (vertical)"), so the identical squeeze could still happen there even after the Sections-only fix, just never reported. Both now read the same row count from one place.
    ➡️ [Bug]: Card not rendering correctly with xlarge bar and icon hidden #133 (@Ascathon)
  • bar_size: xsmall wasn't treated the same as small in the card's height/grid-row calculation, even though it's the smaller of the two - a vertical card with bar_size: xsmall still reserved the extra row meant for medium/large/xlarge bars, unlike small, which never needed it.
  • alert_when with animation: ping and highlight: background silently degraded to static instead of ringing. ping animates a box-shadow around the whole card, independent of highlight's border-color/background-color - the two combine fine, the fallback was based on a wrong assumption that no matching CSS rule existed.
  • bar_color_mode: segment/rainbow collapsed to a single flat color with a theme whose zones are real-world values instead of % (temperature, voc, pm25…), or with custom_theme, unless max_value happened to already match the theme's own scale. Each zone boundary is projected onto the min_value/max_value window to paint the bar - left at the flat 100 default while the theme's zones went into the thousands (voc), every zone past the first got clamped to zero width and filtered out, leaving one color for the whole bar. max_value now defaults to the active theme's (or custom_theme's) own highest zone bound instead of 100 whenever it's left unset, so the fill and the color zones share one coherent scale out of the box - an explicit max_value always overrides this and is used as-is. See max_value.
  • Secondary info (unit/state text) stayed capped at its narrow bar-sharing width budget (45px–60%) with bar_position: below, overlay or
    background
    , even though the bar renders elsewhere for those positions and isn't actually competing for room in that row. top/ bottom were already exempted from that cap; below/overlay/ background share the exact same "bar renders elsewhere" condition (see StructureElements.createSecondaryInfo) but were missing from the CSS rule that lifts it.
  • A Jinja-templated countdown (e.g. secondary: {{ now() - ... }}) froze after a few seconds instead of ticking every second. Home Assistant only pushes a fresh render for a now()/utcnow() template once a minute on its own, absent a state change on a tracked entity - the 1.6.0 rewrite removed an incidental resubscribe-on-every-hass-update that used to paper over this on Template cards/badges. Fix: a new opt-in, fast_refresh: true, forces a per-second resubscribe instead - it isn't automatic (Template's display is arbitrary Jinja text, not a fixed field the card can key a local tick off of the way standard cards do for an active timer), so it needs to be added explicitly to any Template card with a now()-driven countdown.
    ➡️ Reported alongside [Bug]: "Run" status not catched #127 (@annaoskarson)
  • Hiding name or secondary_info on a horizontal card left an empty gap where the hidden row used to be, instead of shrinking the card. The content area's height was a fixed name+detail sum regardless of which rows were actually visible. Fixed for horizontal layout - vertical's ring-shaped bar still needs that reserved space, so it's unchanged for now. For a card embedded outside Home Assistant's own grid sizing (e.g. as a custom:button-card field), combine this with height: auto (an existing, previously-undocumented valid value) and frameless: true to get a card that shrinks fully to its content instead of stretching to fill the surrounding element. With the default bar_position, the bar itself shares that row with the secondary-info text rather than living in its own container - the first pass at this fix zeroed the row's height whenever secondary_info was hidden regardless, which starved the still-visible bar and shrank the name above it too (flex-shrink pulling from the wrong row). Now that height is only reclaimed when the row actually goes empty (bar elsewhere, or also hidden via hide: [progress_bar]).
    ➡️ Follow-up to [Enhancement]: JINJA Should accept more STYLE tags #129 (@emartoni)

🔧 Improvements

  • The height field in the visual editor now has a toggle to switch between the slider and a free-text value (e.g. auto, calc(...)). Previously that mode only activated if the config already held a non-number+unit value (set through YAML) - there was no way to reach it from the visual editor alone.
  • theme: humidity's ranges rebalanced. The comfort zone (40–60%) is now one solid green band instead of a green/teal split that read as a washed-out green rather than a distinct color, and the remaining ranges now mirror symmetrically around it (10/10/10/20 on each side) instead of the old lopsided split - a 95% reading (mold/condensation risk) used to land on deep-purple, which doesn't read as "alert" the way a 15% reading's red does, understating the actual risk on the humid end. See theme: humidity.
  • bar_position: overlay's name/secondary_info text now keeps 10px of breathing room on the right edge, matching the existing 7px it already had on the left, instead of running flush against the card's edge.

🧪 Try it: demo dashboard

docs/demo-dashboard.yaml got a full rebuild — a comprehensive showroom covering essentially every option in this changelog (themes, watermarks, bar_effect, icon_animation, center_zero, bar_stack, aggregation, card_mod/UIX styling…) plus a regression-test view with one card per statically-reproducible closed issue. Import it and move the helper sliders to see everything react live: docs/demo-dashboard-helpers.yaml (all the demo helper entities as a drop-in homeassistant: packages: file, instead of creating them one by one).

...

Read more

1.6.1-rc1

1.6.1-rc1 Pre-release
Pre-release

Choose a tag to compare

@francois-le-ko4la francois-le-ko4la released this 31 Jul 19:44
e7d0acd

What's new

✨ New

  • entity-progress-multi-card / entity-progress-multi-feature: aggregate several progress bars — each a real, fully-featured bar (its own colors, state, more-info tap) — into a single card or a single Tile feature, instead of one bar per entity. See Configuration Reference.
  • bar_size: xsmall: a new, thinner bar size (6px) — mainly useful to fit more bars in a tight space, e.g. inside entity-progress-multi-feature. See bar_size.
  • Jinja-rendered name/secondary/custom_info now accept more inline styles: font-size, font-weight, text-align, width, display, position and z-index, on top of the existing color/background-color — enough to build simple multi-column layouts directly in a template.
    ➡️ [Enhancement]: JINJA Should accept more STYLE tags #129 (@emartoni)

🐛 Fixes

  • The card could fail to load entirely on older/embedded browsers (e.g. Chromium-based kiosk panels), even though it worked fine on 1.5.x. The 1.6.0 build pipeline could emit ES2022-only syntax that these engines can't even parse - the whole module failed silently, showing an error card instead of the progress bar. The build now targets ES2021 (matching what 1.5.x actually required), and a new release-time check (npm run check:es-target) catches this class of regression before it ever ships again.
    ➡️ [Browser Support]: chromium 92.0.4515.98 / After upgrade to 1.6.0 it stopped working on chromium #128 (@Slomo5)
  • name: { type: device } ignored a renamed device. It only read the device's original/manufacturer name, never the name you set yourself in Settings → Devices → rename (name_by_user) — now it follows the same precedence Home Assistant's own UI uses.
    ➡️ [Bug]: Friendly name is not used #130 (@zkurzyns)