Skip to content

Instantly share code, notes, and snippets.

@ngocjohn
Created February 22, 2026 11:33
Show Gist options
  • Select an option

  • Save ngocjohn/1ef04e78e0bddb9903534206eaf37df6 to your computer and use it in GitHub Desktop.

Select an option

Save ngocjohn/1ef04e78e0bddb9903534206eaf37df6 to your computer and use it in GitHub Desktop.
let _cachedQuickBarDialogImport = null;
let _quickBarImportPromise = null;
const getHa = () => document.querySelector('home-assistant');
const dispatchQuickBar = (ha, dialogImport, mode) => {
ha.dispatchEvent(
new CustomEvent('show-dialog', {
bubbles: true,
cancelable: false,
composed: true,
detail: {
dialogTag: 'ha-quick-bar',
dialogImport,
dialogParams: { mode },
},
}),
);
};
const simulateKeyPressE = () => {
window.dispatchEvent(
new KeyboardEvent('keydown', {
key: 'e',
code: 'KeyE',
keyCode: 69,
charCode: 69,
bubbles: true,
cancelable: true,
}),
);
};
const waitForQuickBar = (ha, timeoutMs = 2000) =>
new Promise((resolve) => {
const find = () => ha?.renderRoot?.querySelector('ha-quick-bar');
const existing = find();
if (existing) return resolve(existing);
const done = (qb) => {
observer.disconnect();
clearTimeout(timer);
resolve(qb);
};
const observer = new MutationObserver(() => {
const qb = find();
if (qb) done(qb);
});
observer.observe(ha.renderRoot, { childList: true, subtree: true });
const timer = setTimeout(() => done(null), timeoutMs);
});
async function toggleQuick() {
if (customElements.get('ha-quick-bar')) return;
const ha = getHa();
simulateKeyPressE();
const qb = await waitForQuickBar(ha);
if (qb)
qb._dialogClosed?.(); // or qb.closeDialog?.()
else console.warn('ha-quick-bar component failed to load');
}
async function getQuickBarImport() {
if (_cachedQuickBarDialogImport) return _cachedQuickBarDialogImport;
if (_quickBarImportPromise) return _quickBarImportPromise;
_quickBarImportPromise = (async () => {
const haPanelConfig = document.createElement('ha-panel-config');
if (!customElements.get('ha-config-dashboard')) {
await haPanelConfig.routerOptions.routes.dashboard.load();
await customElements.whenDefined('ha-config-dashboard');
}
const ha = getHa();
const haConfigDashboard = document.createElement('ha-config-dashboard');
haConfigDashboard.hass = ha.hass;
const dialogImport = await new Promise((resolve) => {
haConfigDashboard.addEventListener(
'show-dialog',
(event) => resolve(event.detail.dialogImport()),
{ once: true },
);
haConfigDashboard._showQuickBar();
});
_cachedQuickBarDialogImport = dialogImport;
return dialogImport;
})();
try {
return await _quickBarImportPromise;
} finally {
_quickBarImportPromise = null;
}
}
async function showDialogBar(mode = 'navigate') {
await toggleQuick();
const ha = getHa();
const dialogImport = await getQuickBarImport();
dispatchQuickBar(ha, dialogImport, mode);
}
const canOverrideAlphanumericInput = (composedPath) => {
if (
composedPath.some(
(el) => 'tagName' in el && (el.tagName === 'HA-MENU' || el.tagName === 'HA-CODE-EDITOR'),
)
) {
return false;
}
const el = composedPath[0];
if (el.tagName === 'TEXTAREA') {
return false;
}
if (el.parentElement?.tagName === 'HA-SELECT') {
return false;
}
if (el.tagName !== 'INPUT') {
return true;
}
switch (el.type) {
case 'button':
case 'checkbox':
case 'hidden':
case 'radio':
case 'range':
return true;
default:
return false;
}
};
/**
* Call initQuickBarShortcut() once (e.g. after HA loads)
*/
function initQuickBarShortcut() {
console.info('%cInit quick bar shortcut', 'color: lightgreen; font-style: italic');
window.addEventListener('keydown', (e) => {
// Require Shift + Backquote (` key)
const isShortcut =
e.code === 'Backquote' && e.shiftKey && !e.ctrlKey && !e.metaKey && !e.altKey;
if (isShortcut) {
const path = e.composedPath();
const override = canOverrideAlphanumericInput(path);
if (!override) return;
if (e.defaultPrevented) {
return;
}
e.preventDefault(); // prevent accidental character input
showDialogBar('navigate');
}
});
}
initQuickBarShortcut();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment