Skip to content

Elbow Card

custom:lcards-elbow

The Elbow card creates the iconic LCARS corner/cap shapes — the L-shaped coloured bars that frame sections of an LCARS interface. Extends the button card so it inherits text, actions, rules, animations, and templates.


Quick Start

yaml
type: custom:lcards-elbow
elbow:
  type: header-left
  segment:
    bar_width: 90
    bar_height: 20

Top-Level Options

OptionTypeDescription
typestringcustom:lcards-elbow (required)
elbowobjectElbow geometry and styling (required)
entitystringEntity to monitor (for state-based styling)
presetstringStyle preset name (inherits from button presets, e.g. lozenge, pill)
ranges_attributestringEntity attribute used for above:/below:/between: range conditions — see Range Conditions
idstringCard ID for rule targeting — see Rules Engine
tagslistTags for rule targeting — see Rules Engine
heightstring / numberCard height — see Sizing
widthstring / numberCard width — see Sizing
min_heightstring / numberMinimum card height — see Sizing
min_widthstring / numberMinimum card width — see Sizing
textobjectText labels — see Text Fields
tap_actionobjectTap action — see Actions
hold_actionobjectHold action — see Actions
double_tap_actionobjectDouble-tap action — see Actions
animationslistCard animations — see Animations
background_animationlist / objectCanvas background animations — see Background Animations
shape_textureobjectSVG texture inside the elbow shape fill
filterslistVisual filters (CSS / SVG filter primitives) — see Filters
soundsobjectPer-card sound overrides — see Sounds
data_sourcesobjectDataSource subscriptions — see Data Sources
triggers_updatelistExtra entity IDs that force template re-evaluation
grid_optionsobjectHA grid layout options (columns, rows, min_columns, min_rows)

Elbow Types

Set via elbow.type. The type determines the corner position and shape of the L-bar.

TypeDescriptionStyles
header-leftTop-left corner — vertical bar on left, horizontal bar on topsimple, segmented
header-rightTop-right corner — vertical bar on right, horizontal bar on topsimple, segmented
footer-leftBottom-left corner — vertical bar on left, horizontal bar on bottomsimple, segmented
footer-rightBottom-right corner — vertical bar on right, horizontal bar on bottomsimple, segmented
header-containedHorizontal bar with mirrored elbows on both left and right ends (top)simple
footer-containedHorizontal bar with mirrored elbows on both left and right ends (bottom)simple
header-openSimple horizontal bar at top — no vertical armssimple
footer-openSimple horizontal bar at bottom — no vertical armssimple
diagonal-cap-leftTop-left with configurable diagonal cut on both corners (controlled by segment.diagonal_angle)simple, segmented
diagonal-cap-rightTop-right with configurable diagonal cut on both cornerssimple, segmented
diagonal-cap-footer-leftBottom-left with configurable diagonal cut on both cornerssimple, segmented
diagonal-cap-footer-rightBottom-right with configurable diagonal cut on both cornerssimple, segmented
frameFull rectangular frame — 2–4 sided border with per-side widths and per-corner radiisimple, segmented

Elbow Styles

Simple (default)

Single elbow — one curved L-shape.

yaml
elbow:
  type: header-left
  style: simple
  segment:
    bar_width: 90       # Vertical bar thickness (px)
    bar_height: 20      # Horizontal bar thickness (px)
    outer_curve: auto   # Corner radius — 'auto' = bar_width / 2 (LCARS formula)
    color:
      default: "var(--lcards-orange)"
      active: "var(--lcards-orange-medium)"

Segmented (TNG / Picard style)

Two concentric elbows with a gap — the double-elbow look from Star Trek TNG.

yaml
elbow:
  type: header-left
  style: segmented
  segments:
    gap: 4
    outer_segment:
      bar_width: 90
      bar_height: 20
      color: "var(--lcars-orange)"
    inner_segment:
      bar_width: 30
      bar_height: 10
      color: "var(--lcars-moonlight)"

Segment Options (Simple Style)

OptionTypeDefaultDescription
bar_widthnumber / "theme"90Vertical bar thickness in px. Use "theme" to bind to input_number.lcars_vertical
bar_heightnumber / "theme"20Horizontal bar thickness in px. Use "theme" to bind to input_number.lcars_horizontal
outer_curvenumber / "auto""auto"Corner arc radius. auto = bar_width / 2
inner_curvenumberInner arc radius (omit for LCARS formula: outer / 2)
diagonal_anglenumber45Angle of the diagonal cap in degrees (diagonal-cap elbow types only)
colorstring / objectFill colour — state map supported

Segments Options (Segmented Style)

OptionTypeDefaultDescription
gapnumber4Gap in px between outer and inner elbow
outer_segmentobjectOuter (frame) segment config — see below
inner_segmentobjectInner (content) segment config — see below

outer_segment and inner_segment fields

Both outer_segment and inner_segment share the same schema:

OptionTypeDescription
bar_widthnumberVertical bar thickness in px (required)
bar_heightnumberHorizontal bar thickness in px
outer_curvenumberOuter corner radius in px
inner_curvenumberInner corner radius in px
colorstring / objectFill colour — state map supported
entity_idstringEntity ID for state-based colour on this segment
tap_actionobjectTap action for this segment — see Actions
hold_actionobjectHold action for this segment
double_tap_actionobjectDouble-tap action for this segment

HA-LCARS Theme Binding

If you use the HA-LCARS theme, bind bar dimensions to the theme helpers to keep all elbows synchronised:

yaml
elbow:
  type: footer-right
  segment:
    bar_width: theme     # Reads input_number.lcars_vertical
    bar_height: theme    # Reads input_number.lcars_horizontal

Changing the helper value updates every elbow using theme binding simultaneously.


Text Labels

Elbows inherit the full button text system. Common use: a label on the horizontal bar.

yaml
type: custom:lcards-elbow
elbow:
  type: header-left
  segment:
    bar_width: 120
    bar_height: 22
text:
  section:
    content: NAVIGATION
    position: top-right
    font_size: 11
    font_weight: bold
    color: "var(--lcards-moonlight)"

See Text Fields for the complete reference.


Background Animation Inset

Elbow cards support a canvas-level inset on background_animation so the animation fills only the open content area, not the LCARS bars.

Use inset: auto to let the card automatically derive the correct inset from its bar geometry:

yaml
type: custom:lcards-elbow
elbow:
  type: header-left
  segment:
    bar_width: 90
    bar_height: 20
background_animation:
  inset: auto       # canvas sized to avoid the elbow bars
  effects:
    - preset: grid
      config:
        line_spacing: 40
        color: "alpha(var(--lcards-orange), 0.3)"

Manual inset

Supply explicit pixel values when you need precise control:

yaml
background_animation:
  inset:
    top: 20         # height of horizontal top bar
    left: 90        # width of vertical left bar
    right: 0
    bottom: 0
  effects:
    - preset: starfield
      config:
        count: 150

Note: inset: auto is computed from the resolved bar geometry at runtime and updates automatically when theme bar dimensions change via input_number helpers.


Shape Texture

Elbow cards support the same shape_texture feature as button cards — an SVG-native texture or animation clipped to the elbow shape fill (simple and segmented styles). Configuration is identical.

See Button card — Shape Texture for the full preset reference and examples.


Symbiont

The Symbiont feature embeds any Home Assistant card inside the elbow's content area. LCARdS mounts the card in the open frame and can optionally inject styles directly into the embedded card's shadow root ("imprinting"), keeping the look consistent with your LCARS theme without modifying the embedded card's own config.

Basic Example

yaml
type: custom:lcards-elbow
elbow:
  type: header-left
  segment:
    bar_width: 100
    bar_height: 22
symbiont:
  enabled: true
  card:
    type: alarm-panel
    entity: alarm_control_panel.home
    states:
      - arm_away
      - arm_home

Symbiont Options

OptionTypeDefaultDescription
enabledbooleanfalseEnable or disable the symbiont
cardobjectAny valid HA card config (type + card properties)
positionobjectPadding (px) within the elbow content area
position.topnumber10Top padding
position.leftnumber10Left padding
position.rightnumber10Right padding
position.bottomnumber0Bottom padding
imprintobjectShadow-root style injection — see below
custom_stylestringRaw CSS appended to the embedded card's shadow root (no card-mod required)

Imprint

Imprint injects a <style> element directly into the embedded card's shadow root. Properties are resolved against the elbow's entity state, so they react to state changes exactly like the elbow's own colours.

OptionTypeDescription
imprint.enabledbooleantrue by default — set false to disable all injection
imprint.backgroundstring / state mapBackground colour injected on ha-card
imprint.text.colorstring / state mapText colour injected on ha-card
imprint.text.font_sizestringFont size (e.g. "14px")
imprint.text.font_familystringFont family string
imprint.border_radiusobjectPer-corner border radii — see below

Colour values accept the same forms as everywhere else in LCARdS: hex, rgba(), var(--token), darken()/lighten()/alpha() expressions, and full state maps with default/active/inactive/named-state keys.

State-Reactive Imprint

yaml
symbiont:
  enabled: true
  card:
    type: alarm-panel
    entity: alarm_control_panel.home
  imprint:
    background:
      default: "rgba(0,0,0,0.5)"
      active: "alpha(var(--lcars-red), 0.25)"
    text:
      color:
        default: "var(--lcars-orange)"
        active: "var(--lcars-red)"
    border_radius:
      top_left: match       # copies the elbow inner arc radius
      top_right: 0
      bottom_left: 0
      bottom_right: 0

Border Radius Options

Each corner accepts one of:

ValueEffect
"match"Mirrors the elbow's inner arc radius (recommended for the corner adjacent to the elbow)
numberFixed radius in px
(absent)Not injected — card keeps its own radius

The legacy shorthand imprint.border_radius.match_host: true (default when border_radius is omitted) automatically applies match to only the single corner that is adjacent to the elbow hull, leaving the other three corners at 0. Set to false to suppress all radius injection.

Custom Style

custom_style lets you inject arbitrary CSS into the embedded card's shadow root without card-mod:

yaml
symbiont:
  enabled: true
  card:
    type: entities
    entities:
      - sensor.temperature
  custom_style: |
    ha-card {
      --ha-card-border-radius: 0;
      --secondary-text-color: var(--lcars-moonlight);
    }

The custom style is appended after imprint styles, so it takes precedence when both set the same property.

Using card-mod with Symbiont

card-mod works with symbiont cards. The card_mod block is part of the embedded card's config and is passed straight through to it.

Injection order:

  1. card-mod injects its <style> during setConfig
  2. LCARdS imprint appends its <style id="lcards-symbiont-imprint"> after the card is ready

Because imprint is appended later in the shadow root, imprint wins when both set the same property. For properties that do not overlap there is no conflict.

yaml
symbiont:
  enabled: true
  card:
    type: alarm-panel
    entity: alarm_control_panel.home
    card_mod:
      style: |
        ha-card {
          background: transparent !important;
          box-shadow: none !important;
          border: 1px solid var(--lcars-blue, #93e1ff) !important;
          border-radius: 0 !important;
        }
  imprint:
    text:
      color:
        default: "var(--lcars-orange)"
        active: "var(--lcars-red)"

Note: custom_style injects raw CSS without card-mod. For simple shadow-root overrides prefer custom_style — it avoids a card-mod dependency and is handled entirely by LCARdS.

Lazy-Loaded HA Card Types

HA lazy-loads many of its own built-in card modules (e.g. alarm-panel, thermostat, media-player) — they are only imported when they first appear on a dashboard. On a fresh page load, before another dashboard view has triggered the import, the element is not yet registered.

LCARdS handles this automatically: when the requested type is not yet registered, it routes through HA's internal hui-card wrapper which triggers the correct dynamic import. The card renders as soon as HA finishes loading the module — no configuration required.


Examples

Standard header cap pair

yaml
# Left cap
type: custom:lcards-elbow
elbow:
  type: header-left
  segment:
    bar_width: theme
    bar_height: theme

# Right cap
type: custom:lcards-elbow
elbow:
  type: header-right
  segment:
    bar_width: theme
    bar_height: theme

State-reactive elbow

Changes colour when a sensor is above threshold (using Rules Engine):

yaml
type: custom:lcards-elbow
id: alert-cap
elbow:
  type: header-left
  segment:
    bar_width: 90
    bar_height: 20
    color:
      default: "var(--lcards-orange)"

Then define a rule that patches id: alert-cap when the sensor is high.