feat: configurable main icon→name gap via name_gap#401
Open
BlackZork wants to merge 1 commit into
Open
Conversation
Add a `name_gap` option (and a `--multiple-entity-row-name-gap` CSS variable) that controls the spacing between the main entity icon and the row name. Accepts a CSS length string (`8px`, `0.5em`, `var(--x)`) or a number (treated as px). Default rendering is unchanged. That gap is core `hui-generic-entity-row`'s `.info` `padding-inline-start`, hardcoded at 16px inside that element's own shadow DOM. It is not a CSS variable, `padding` is not an inherited property, and styles from outside a shadow tree (themes, card-mod) cannot cross the boundary — so until now it could not be adjusted at all. Since this card creates that child element, it sets the variable on the child's host in `render()` and, only when `name_gap` is configured, injects a one-time scoped `.info` override into the child's shadow that reads the variable with a 16px fallback. Rows that don't set `name_gap` get zero shadow modification and render byte-for-byte as before. Also exposes the option in the visual editor, documents it in the README (options table + Theming), and adds unit tests for the host-variable half (the deep shadow injection is only exercisable against a real core row, so it's verified at runtime rather than in the jsdom suite). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
jpettitt
requested changes
Jul 18, 2026
jpettitt
left a comment
Collaborator
There was a problem hiding this comment.
Thanks — this is a well-put-together PR, and the shadow-injection analysis is correct (verified against the current frontend bundle: .info{padding-left:16px;padding-right:8px;flex:30%;padding-inline:16px 8px}, no variable exposed).
One fix needed: the injected padding-left line breaks RTL rather than supporting it. Core's end-padding is 8px (padding-inline: 16px 8px); in RTL, padding-left is the inline-end side, so your rule overrides that 8px with the gap value. padding-inline-start alone is correct in both directions (universally supported on any browser running HA 2024.4+, this card's minimum) — please drop the physical property and the RTL sentence from the comment.
Happy to merge with that change.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Disclaimer
Changes in this PR and description below were entirely generated by Claude Code with my supervision only. Please verify. I needed to shorten the hard-coded 16px gap between main icon and main label. 16px is way to big for RPI 800x480 display.
Summary
Adds a card-level
name_gapoption (and a matching--multiple-entity-row-name-gapCSS variable) that controls the horizontal spacing between the main entity's icon and the
row name.
Default rendering is completely unchanged — the option is opt-in and a no-op when unset.
Motivation
That gap is HA core
hui-generic-entity-row's.infopadding-inline-start, hardcoded at16pxinside that element's own shadow DOM. It is not exposed as a CSS variable,paddingis not an inherited property, and styles from outside a shadow tree can't cross the boundary
(a theme or card-mod can't reach it). So today the icon→name spacing on a multiple-entity-row
simply can't be adjusted. On dense/compact dashboards (e.g. a wall-panel layout)
16pxis oftentoo wide.
Because this card creates the
hui-generic-entity-rowit wraps, it can legitimately reach intothat child to expose the setting.
How it works
When (and only when)
name_gapis set:render()sets--multiple-entity-row-name-gap: <value>on thehui-generic-entity-rowhost (same mechanism as the existing
icon_color→iconColorCssinline var).updated()injects a one-time<style>into that child'sshadowRoot:Design points:
:host .info(specificity 0,2,0), not!important. Core'sstatic stylesare applied viaadoptedStyleSheets, which the cascade orders after a<style>appended to the shadow root —so an equal-specificity rule would lose. Higher specificity wins regardless of order, and leaving
!importantoff means a user's own override still wins.var()keeps the default byte-for-byte identical.name_gap— rows that don't use it get zero shadow modification and no injectedstyle at all.
name_gaplater only updates thehost variable via re-render; no re-injection. Injection is idempotent (guarded by a marker attr).
px; a string passes through (8px,0.5em,var(--x));0is honored.Changes
src/types.ts—name_gap?: string | numberonMultipleEntityRowConfig.src/entity.js—nameGapCss()helper (alongsideiconColorCss).src/index.js— host variable inrender();updated()shadow injection.src/editor_schemas.ts—name_gapfield + label in the visual editor (Main tab).README.md— options table row + a Theming section entry documenting the variable.src/index.test.js— unit tests for the host-variable half (see note below).Testing
yarn lintclean, fullvitestsuite passes (161 tests, incl. 4 newname_gapcases).0honored, omittedwhen unset). The deep shadow injection can only be exercised against a real core
hui-generic-entity-row(the jsdom stub has no shadow), so it's verified at runtime rather thanin the suite.
name_gap: 5px/8pxthe row's core.infopadding-inline-startcomputes to the configured value across multiple rows; unset rows stay at16px; toggling the value updates it without re-injection; default rows are untouched.Notes
hui-generic-entity-rowinternals alreadyrelied upon for the main row).