Some apps show each button's shortcut only while the user holds a modifier, so the hints are there when the user reaches for the keyboard, and out of the way otherwise. useHotkeyHint returns an object whose tracked value is true while the user holds modifiers that belong to a hotkey that can fire. It's an optional helper, and it doesn't register anything, so use it alongside the useHotkey helper.
import Component from '@glimmer/component'
import { on } from '@ember/modifier'
import {
formatForDisplay,
useHotkey,
useHotkeyHint,
} from '@tanstack/ember-hotkeys'
const saveHotkey = 'Mod+S'
export default class SaveButton extends Component {
hint = useHotkeyHint(this, saveHotkey)
label = formatForDisplay(saveHotkey)
save = () => {
/* ... */
}
<template>
{{useHotkey saveHotkey this.save}}
<button type='button' {{on 'click' this.save}}>
Save {{#if this.hint.value}}<kbd>{{this.label}}</kbd>{{/if}}
</button>
</template>
}While the user holds Command on macOS, or Control elsewhere, the button reads "Save ⌘ S" or "Save Ctrl+S". Formatting & Display covers labels and keycaps.
To show a hint only while every modifier is held, pass exact:
hint = useHotkeyHint(this, 'Alt+Shift+[KeyK]', { exact: true }) // Needs Alt and ShiftIf the hotkey sets platform, pass the same platform to useHotkeyHint, so Mod resolves the same way. The hotkey and the options can also be getters.
A sequence shows its hint while the user holds the modifiers of its first step:
hint = useHotkeyHint(this, ['Mod+K', 'Mod+C']) // hint.value is true while Mod is heldPass an app hotkey to show the user's current hotkey, including one they changed. An app hotkey with no hotkey assigned shows no hint. A small component keeps every button's hint the same:
import Component from '@glimmer/component'
import {
formatForDisplay,
useAppHotkeys,
useHotkeyHint,
} from '@tanstack/ember-hotkeys'
import type { AppHotkeyId } from '@tanstack/ember-hotkeys'
export default class Hint extends Component<{ Args: { id: AppHotkeyId } }> {
appHotkeys = useAppHotkeys(this)
hint = useHotkeyHint(this, () => this.appHotkeys.value[this.args.id])
get label() {
const { hotkey } = this.appHotkeys.value[this.args.id]
return this.hint.value && hotkey ? formatForDisplay(hotkey) : null
}
<template>
{{#if this.label}}<kbd>{{this.label}}</kbd>{{/if}}
</template>
}import Component from '@glimmer/component'
import { on } from '@ember/modifier'
import { useAppHotkeys, useHotkey } from '@tanstack/ember-hotkeys'
import Hint from './hint'
export default class Toolbar extends Component {
appHotkeys = useAppHotkeys(this)
save = () => {
/* ... */
}
get saveHotkey() {
return this.appHotkeys.value['doc.save']
}
<template>
{{useHotkey this.saveHotkey this.save}}
<button type='button' {{on 'click' this.save}}>Save <Hint @id='doc.save' /></button>
</template>
}To check outside a component, such as while drawing on a canvas, pass the held keys to matchesHeldModifiers. It takes the same options, but it only looks at held keys. To also check that the hotkey can fire, call hasActiveRegistration on the hotkey manager:
import {
getHotkeyManager,
getKeyStateTracker,
matchesHeldModifiers,
} from '@tanstack/ember-hotkeys'
const tracker = getKeyStateTracker()
matchesHeldModifiers('Mod+S', tracker.getHeldKeys()) // true while Mod is held
const showHint =
matchesHeldModifiers('Mod+S', tracker.getHeldKeys()) &&
getHotkeyManager().hasActiveRegistration('Mod+S') // Same check as the utilityHeld Key State Helpers covers the tracker and the other held-key utilities.
The Kitchen Sink example shows hints next to its navigation links and buttons while Alt or Option is held.