đź’ˇ UIX Broker - turn browser events, keyboard shortcuts, and Home Assistant event-bus events into declarative interactions

:light_bulb: UIX Broker, part of UI eXtension (UIX) allows to turn browser events, keyboard shortcuts, and Home Assistant event-bus events into declarative interactions.

:page_facing_up: Read the DOCS

Now available in UIX 8.2.0-beta.2

WHY UIX Broker? :person_shrugging:
Check out the Make the card tab the default in the UI add-card dialog. This is one of the examples that seeded UIX Broker.

An interaction selects a browser element, checks optional rules, then runs directives in their configured order.

Realm → Listen → Interaction anchor → Rules (Optional anchors) → Directives (Optional anchors)

Use UIX Broker when an interface behaviour can be configured rather than written as a custom card, script, or patch. UIX Broker can react to a click, customise an event before redispatching it, focus an element, update an object property, invoke a safe element method, and run JavaScript actions with interaction variables available.

uix_broker:
  - realm: browser
    listen: click
    anchor: target
    rules:
      - ".action-button"
    directives:
      - type: block
      - type: event
        name: another-action
        data:
          source: action-button

UIX Broker guides

  • Broker — interaction structure, configuration sources, lifecycle, and debugging.
  • Realms — browser events, keyboard shortcuts, and Home Assistant event-bus events.
  • Interaction Anchors — composed event-path and select_tree element selection.
  • Rules — host-element, captured-data, and browser-identity matching.
  • Directives — block, property, event, call, and Home Assistant actions.
  • Examples — examples. Also see UIX Guides, where further detailed examples may be published.
4 Likes

:light_bulb: UIX Broker gets button directive :partying_face:

Hot off the press in 8.2.0-beta.7 is a button directive that allows to place a ha-button on UI. Also added uix-broker-ready event which can you listen for in browser realm, an independent wait directive if needed to wait for longer than usual before running further directives and new UIX action event which also can take an anchor to allow native Browser events to be fired via fire-dom-event.

Example: tools button on sidebar title
  - realm: browser
    listen: uix-broker-ready
    anchor: "&home-assistant $ home-assistant-main $ ha-sidebar"
    debug: true
    rules:
      - anchor: "&home-assistant"
        match: "{.hass.user.is_admin=true}"
    directives:
      - type: button
        anchor: "$ div.menu div.title"
        icon: mdi:hammer
        color: purple
        size: s
        tap_action:
          action: navigate
          navigation_path: /config/tools
        style:
          "--ha-button-box-shadow": rgba(0, 0, 0, 0.1) 0px 4px 12px
          "--ha-icon-button-size": 32px

UPDATES:

  • Added uix-broker-ready event as well as independent wait directive to be able to readily add UI elements to permanent elements like sidebar. Tools sidebar example updated.
  • new UIX event action. This now allows for a Broker button to wire in a browser event to its action. See updated Automation sidebar and YAML mode complete, also included below for the inclusion of a button to toggle YAML mode. (FYI @Cake1468 - you were asking for this).
Automation sidebar and YAML mode complete
uix_broker:
  - realm: browser
    listen: open-sidebar
    reentrant: false
    anchor: manual-automation-editor <$$ target
    rules:
      - '{!.uixBlockAutoYamlMode}'
      - anchor: $ ha-automation-sidebar $$ ha-automation-sidebar-card
        match: '{.yamlMode=false}'
    directives:
      - anchor: $ ha-automation-sidebar
        method: _toggleYamlMode
        type: call
      - type: button
        before: $ ha-automation-sidebar $$ ha-automation-sidebar-card $ ha-dialog-header slot:nth-of-type(3) ha-dropdown
        icon: mdi:code-braces
        tap_action:
          action: fire-dom-event
          uix:
            action: event
            name: toggle-yaml-mode
  - realm: browser
    listen: toggle-yaml-mode
    anchor: manual-automation-editor <$$ target
    directives:
      - type: block
      - type: property
        set: uixBlockAutoYamlMode
        value: true
      - anchor: $ ha-automation-sidebar
        method: _toggleYamlMode
        type: call
      - type: property
        clear: uixBlockAutoYamlMode
  - realm: shortcut
    enabled: true
    listen: $mod+Shift+Y
    anchor: '&home-assistant $$ manual-automation-editor'
    directives:
      - type: property
        set: uixBlockAutoYamlMode
        value: true
      - anchor: $ ha-automation-sidebar
        method: _toggleYamlMode
        type: call
      - type: property
        clear: uixBlockAutoYamlMode

Sep-01-2026 13-32-56

1 Like

before testing the new broker features, I went from beta 5 to beta 8 overnight…

Yes, lost of things to address as I worked through examples, specifically how to tie regular actions back to native events. I think we are nearky there - any changes are based on new examples and tweaks needed to Broker to make them as easy as possible to implement.

2 Likes

:light_bulb: UIX Broker updates in 8.2.0-beta.10

  • New rules panel, hash, search. Allows for matching on what the UIX panel variable holds (same panel variable available in templates). Allows for matching based on Browser hash and search string - useful for not running an interaction say if a search string exists as a bail out.
  • event directive can now target window or document. Default is anchor matching prior 8.2.0-beta.10
  • Browser realm can now listen to multiple events in the one interaction. Use a list for listen for multiple events.

These came about due to request from @Mariusthvdb to have a full type system log view. See GitHub Discussion where both the System Log link gets “_blank” target as well as tweaks to config/logs.

1 Like

:light_bulb: UIX Updates in 8.2.0-beta.12

  • Directives now have their own rules so a directive can set to only apply if rules match (block does not support rules, use interaction rules).
  • If you were using uix_update event prior to 8.2.0-beta.11, note that this is now updated to kebab-case uix-update.

With this update, the config/logs example now can include a button on the system->logs link to go straight to a different provider. I really like this solution provding for a 'dedicated` logs tab which is nice and focussed. :magnifying_glass_tilted_right:

… now I think UIX Broker is pretty much a complete tool that can set any sort of UI change. To be able to release 8.2.0 I will not try and add any other UI element other than button but it is plausible that other elements may come, bringing over other other forge sparks as base items.

right so now this is getting better and better, I feel I can safely add the new feature of beta 13 as revolutionary: templates!

and even both Javascript and Jinja

while we got the full log interaction that was announced in beta 10 above, I discussed with Darryn about making that log target dynamic, and use some input_select to set.

which is now a fact with beta 13!

- realm: browser
    reentrant: false
    listen:
      - uix-broker-ready
      - uix-update
    debug: true
    anchor: "&home-assistant"
    rules:
      - type: panel
        path: fullUrlPath
        match: "config/system"
      - anchor: "&home-assistant"
        match: "{!.hass.auth.external}"
    directives:
      - type: property
        anchor: "&home-assistant $ home-assistant-main $ ha-config-system-navigation $ ha-config-navigation-list $ ha-list-item-button:nth-of-type(4) $ a#item"
        set: target
        value: "_blank"
#      - type: template
#        id: log_provider_url
#        template: "/config/logs?provider={{ states('input_select.log_provider') }}"
#      - type: button
#        after: "&home-assistant $ home-assistant-main $ ha-config-system-navigation $ ha-config-navigation-list $ ha-list-item-button:nth-of-type(4) $ a#item div.content"
#        icon: mdi:package-variant
#        tap_action:
#          action: url
#          url_path: "@log_provider_url"
      - type: javascript
        id: config_path
        code: |
          const provider = hass.states['input_select.log_provider'].state;
          return {
            path: `/config/logs?provider=${provider}`,
            label: `Open ${provider.charAt(0).toUpperCase() + provider.slice(1)} logs`,
          };
      - type: button
        after: "&home-assistant $ home-assistant-main $ ha-config-system-navigation $ ha-config-navigation-list $ ha-list-item-button:nth-of-type(4) $ a#item div.content"
        label: "@config_path.label"
        tap_action:
          action: url
          url_path: "@config_path.path"

best of this is that in day to day operation this all feels so natural, one doesn’t suspect anything custom. (the truth is obvious when looking at that Broker, man the work that got into this is simply amazing)

thanks for this

1 Like

update:

had a bit of fun with the new possibilities of uix_broker and enhanced my sidebar a bit… (note the notification badges are made in custom-sidebar)

uix_broker_sidebar
# uix_broker_sidebar.yaml
# https://uix.lf.technology/broker/examples/
uix_broker:

  - realm: server
    listen: state_changed
    anchor: "&home-assistant"
#     debug: true
    rules:
      - type: captured
        path: data.entity_id
        match:
          or:
            - switch.cameras
            - switch.security_system
            - switch.opentherm_dhw_comfort_mode
            - binary_sensor.update_beschikbaar
    directives:
      - type: event
        name: uix-update-sidebar

  - realm: browser
    listen:
      - uix-broker-ready
      - uix-update-sidebar
    anchor: "&home-assistant $ home-assistant-main $ ha-sidebar"
    debug: true
    rules:
      - anchor: "&home-assistant"
        match: "{.hass.user.is_admin=true}"
    directives:
      - type: javascript
        id: button_beveiliging
        code: |
          const entity = 'switch.security_system';
          const state = hass.states[entity].state;
          return {
            entity: entity,
            icon: state === 'off' ? 'mdi:shield-off' : 'mdi:shield-home',
            color: state === 'off' ? 'var(--success-color)' : 'var(--error-color)'
          };
      - type: javascript
        id: button_cameras
        code: |
          const entity = 'switch.cameras';
          const state = hass.states[entity].state;
          return {
            entity: entity,
            icon: state === 'on' ? 'mdi:cctv' : 'mdi:cctv-off',
            color: state === 'on' ? 'var(--error-color)' : 'var(--no-power-color)',
            background: state === 'on' ? 'pink' : 'black'
          };
      - type: javascript
        id: button_zonneboiler
        code: |
          const entity = 'switch.opentherm_dhw_comfort_mode';
          const state = hass.states[entity].state;
          return {
            entity: entity,
            icon: state === 'on' ? 'mdi:water-boiler' : 'mdi:water-boiler-off',
            color: state === 'on' ? 'var(--error-color)' : 'var(--no-power-color)'
          };
      - type: javascript
        id: button_updates
        code: |
          const entity = 'binary_sensor.update_beschikbaar';
          const state = hass.states[entity].state;
          return {
            entity: entity,
            icon: state === 'on' ? 'mdi:package-up' : 'mdi:package',
            color: state === 'on' ? 'var(--ha-color)' : 'var(--no-power-color)'
          };
      - <<: &sidebar_button
          type: button
          tap_action:
            action: toggle
          tooltip: test
          size: s
          style:
            --ha-button-box-shadow: var(--ha-box-shadow-m)
            --mdc-icon-size: 18px
            --ha-icon-button-size: 24px
  #           --uix-button-margin: 6px
            --ha-button-border-radius: 50%
            transform: translateX(70%)
            margin-left: -24px

  #           border: '1px green solid'
        anchor: "$ ha-list-item-button#sidebar-panel-ui-instellingen $ a#item div.content"
        icon: "@button_beveiliging.icon"
        color: "@button_beveiliging.color"
        entity: "@button_beveiliging.entity"
#         appearance: outlined
#         variant: neutral

      - <<: *sidebar_button
        tap_action:
          confirmation:
            text: Bevestig schakeling
            confirm_text: Zonneboiler comfort-mode aan
            dismiss_text: Zonneboiler niet schakelen
        anchor: "$ ha-list-item-button#sidebar-panel-energy $ a#item div.content"
        icon: "@button_zonneboiler.icon"
        color: "@button_zonneboiler.color"
        entity: "@button_zonneboiler.entity"

      - <<: *sidebar_button
        type: button
        tap_action:
          action: perform-action
          perform_action: homeassistant.update_entity
          target:
            entity_id: binary_sensor.update_beschikbaar
        anchor: "$ ha-list-item-button#sidebar-panel-ui-develop $ a#item div.content"
        icon: "@button_updates.icon"
        color: "@button_updates.color"
        entity: "@button_updates.entity"

      - <<: *sidebar_button
        anchor: "$ ha-list-item-button#sidebar-panel-ui-cctv $ a#item div.content"
        icon: "@button_cameras.icon"
        color: "@button_cameras.color"
        entity: "@button_cameras.entity"

2 Likes

right.. so, with latest beta 15, I made this, to correct the UI showing Sources on each and every click on More in the History graphs on a more-info dialog.

I truly feel that is a UI design error, allowing my users to go into the realms of entities I dont want them to.

this prevents showing that (I still want to hide the Sources button completely, so half way there)

It opens a /history navigation completely and unchanged, if you happen to have that

# uix_broker_history_sources.yaml
# https://uix.lf.technology/broker/examples/
uix_broker:

  - realm: browser
    listen: click
    debug: true

    anchor: "&home-assistant $ ha-more-info-dialog $ ha-more-info-info $ ha-more-info-history $ div.header a"

    directives:
      - type: property
        anchor: "&home-assistant $ home-assistant-main $ ha-drawer partial-panel-resolver ha-panel-history"
        set: _showSources
        value: false

and not

another interception I now have is a guard on the Reload All Yaml configurations, I happen to click that accidentally more than I want, and it always breaks the connection

# uix_broker_guard_yaml_reload.yaml
# https://uix.lf.technology/broker/examples/
uix_broker:

# Config Tools Yaml confiormation for buttons
  - realm: browser
    listen:
      - uix-broker-ready
      - uix-update
    debug: true
    anchor: "&home-assistant $ home-assistant-main $ ha-panel-tools $ tools-yaml-config"
    rules:
      - type: panel
        path: fullUrlPath
        match: "config/tools/yaml"
    directives:
      - type: property
        anchor: "$ ha-call-service-button[service=reload_all]"
        set: confirmation
        value: "All YAML CONFIG WILL BE RELOADED" # a-call-service-button[ will show this text in confirmation if set

now gives me

how cool is that. no more accidents thanks to UIX-Broker!

2 Likes