Quick Bar Customization & Hotkeys

I would love to be able to customize the default keyboard shortcuts (or hotkeys) used to invoke the Quick Bar. (e.g. Cmd+Shift+P, as it is a common keybinding used in editors and IDEs to launch a global command palette).

Has anyone had any luck doing this? The documentation doesn’t seem to offer any customization options aside from disabling shortcuts altogether.

If nothing else, I would be curious to know if it’s possible to manually invoke the Quick Bar via JavaScript – in which case I could just create a quick-and-dirty JavaScript Module to listen for the keyboard event.

Any guidance or suggestions would be greatly appreciated. Thanks!

1 Like

There is no out of the box option to change the shortcuts. Was discussed at some point for the future as a potential addition, but no concrete plans that I am aware of.

Cmd + Shift + P was also floated as a triggering option early during dev, but e.g. in Firefox that does not work as it triggers the printing menu and that cannot be overriden.

1 Like

Someone in Discord (I think) turned me on to adding this as a resource:

customElements.whenDefined("ha-quick-bar").then(() => {
  const fireEvent = (node, type, detail, options) => {
    options = options || {};
    detail = detail === null || detail === undefined ? {} : detail;
    const event = new Event(type, {
        bubbles: options.bubbles === undefined ? true : options.bubbles,
        cancelable: Boolean(options.cancelable),
        composed: options.composed === undefined ? true : options.composed,
    });
    event.detail = detail;
    node.dispatchEvent(event);
    return event;
  };

  const navigate = (path, replace = false) => {
    if (replace) {
      history.replaceState(null, "", path);
    } else {
      history.pushState(null, "", path);
    }

    fireEvent(window, "location-changed", {
      replace,
    });
  };

  const haQuickBar = customElements.get("ha-quick-bar");

  haQuickBar.prototype._generateServerControlCommandsDefault = haQuickBar.prototype._generateServerControlCommands;
  haQuickBar.prototype._generateServerControlCommands = function() {
    let commands = [
      {
        text: "Navigate to Overview",
        icon: "mdi:view-dashboard",
        action: () => navigate("/lovelace"),
      },
      {
        text: "Navigate to Integrations",
        icon: "mdi:puzzle",
        action: () => navigate("/config/integrations"),
      },
      {
        text: "Navigate to States",
        icon: "mdi:code-tags",
        action: () => navigate("/developer-tools/state"),
      },
      {
        text: "Navigate to Services",
        icon: "mdi:remote",
        action: () => navigate("/developer-tools/service"),
      },
      {
        text: "Navigate to Template",
        icon: "mdi:file-code",
        action: () => navigate("/developer-tools/template"),
      },
      {
        text: "Navigate to Events",
        icon: "mdi:radio-tower",
        action: () => navigate("/developer-tools/event"),
      },
      {
        text: "Navigate to Lovelace Dashboards",
        icon: "mdi:view-dashboard",
        action: () => navigate("/config/lovelace/dashboards"),
      },
      {
        text: "Navigate to Lovelace Resources",
        icon: "mdi:cog-box",
        action: () => navigate("/config/lovelace/resources"),
      },
      {
        text: "MQTT",
        icon: "mdi:cog-box",
        action: () => navigate("/config/mqtt"),
      },
    ];

    return [...commands, ...this._generateServerControlCommandsDefault()];
  };
});

Customize as required, stick it in config/www/commands.js, and add this to your resources:

  - url: /local/commands.js?v=1
    type: module

Edit: It was the incomparable @dale3h!

1 Like

Late to the party, but yeah. As @spacegaier said, I originally coded it as Cmd+P and Cmd+Shift+P (for entity list and command bar, respectively).

But Cmd+Shift+P is a reserved, non-overridable shortcut in firefox for launching a private window. Also, it was easy to accidentally launch the print dialog (e.g. trying to launch entity list after switching tabs back to HA).

On top of that are tons of issues with accessibility, cross-browser inconsistencies, and even cross-os! Because of this, we opted for the least of all evils which was a single-key hotkey like what github does.

That said, I’m still very interested in adding customizable shortcuts someday. But it’s a ways off.

1 Like

please allow me to ask why this line does?

asking, because I have the event listed in custom-ui, and I dont know why :wink:

window.addEventListener("location-changed", window.setTimeout.bind(null, 100))

put it differently, when would this even happen?

Presumably the ‘fire’ variant switches to a different page and the ‘listen’ variant triggers on moving to a different page.

Glad to find this.
Looks like things have changed a bit in the past few years, so I worked out a simple set of changes to get the basic functionality. In case someone else would like to use this.
Change the commands array to be structured as just primaryText and path and then give them the built-in “navigation” treatment.

    let commands = [
      {
        path: "/lovelace",
        primaryText: "Navigate to Overview",
      },
  ...
      {
        path: "/config/mqtt",
        primaryText: "MQTT",
      },
    ];

    return [...this._finalizeNavigationCommands([...commands,]), ...this._generateServerControlCommandsDefault()];

What’s a little frustrating (presumably always been a limitation of this approach) is that this only kicks in when the last “fully-refreshed” page was a Dashboard. So when I’m spending my time in the admin/configuration areas, opening something in a new tab suddenly loses this extra convenience.