Skip to content

Combination

The Combination component and its associated hooks provide a powerful way to handle keyboard combinations in your Svelte applications. This feature allows you to create complex keyboard shortcuts and trigger actions based on multiple key presses.

The combination system consists of two main parts:

  • Combination component: A declarative way to handle keyboard combinations
  • useCombination hook: A lower-level hook for custom combination handling

The Combination component provides a simple way to show/hide content based on keyboard combinations.

<script lang="ts">
import { Combination } from '@invokey/svelte'
</script>
<Combination combinations={['ctrl+k', 'meta+k']}>
<div>Search panel</div>
</Combination>
PropTypeDefaultDescription
combinationsstring | string[]RequiredThe keyboard combination(s) to detect
childrenSnippet-Content to render when combination is detected
activeCombinationSnippet<[string | null]>-Snippet to render content with active combination info
hideAfternumber0Time in ms after which to hide content (0 = never hide)
seperatorstring+Character used to separate keys in combinations
refHTMLElement | WindowwindowTarget element to listen for keyboard events
preventDefaultEnabledtrueWhether to prevent default browser behavior
enabledEnabledtrueWhether the combination detection is enabled
disabledOnTagsstring[][]List of HTML tags where shortcuts should be disabled
disabledOnFormTagsbooleanfalseWhether to disable shortcuts on form elements
disabledOnContentEditablebooleanfalseWhether to disable shortcuts on contentEditable elements
scopestring*The scope this shortcut belongs to

For more control over combination handling, you can use the useCombination hook directly.

<script lang="ts">
import { useCombination } from '@invokey/svelte'
useCombination(
['ctrl+k', 'meta+k'],
(event, shortcut) => {
console.log('Combination matched:', shortcut)
}
)
</script>
ParameterTypeDescription
combinationsstring | string[]The combination(s) to listen for
handler(event: KeyboardEvent, combination: string) => voidFunction called when combination is matched
optionsCombinationOptionsOptional configuration

The hook accepts the same options as the component:

PropTypeDefaultDescription
seperatorstring+Character used to separate keys in combinations
refHTMLElement | WindowwindowTarget element to listen for keyboard events
preventDefaultEnabledtrueWhether to prevent default browser behavior
enabledEnabledtrueWhether the combination detection is enabled
disabledOnTagsstring[][]List of HTML tags where shortcuts should be disabled
disabledOnFormTagsbooleanfalseWhether to disable shortcuts on form elements
disabledOnContentEditablebooleanfalseWhether to disable shortcuts on contentEditable elements
scopestring*The scope this shortcut belongs to

Combinations are specified as strings with keys separated by the separator character (default: ’+’). For example:

  • 'ctrl+k'
  • 'meta+shift+s'
  • Letter keys: 'a', 'b', etc.
  • Number keys: '1', '2', etc.
  • Special keys: 'space', 'enter', 'escape', etc.
  • Modifier keys: 'ctrl', 'alt', 'shift', 'meta'

The simplest use case with a single keyboard combination:

<script lang="ts">
import { Combination } from '@invokey/svelte'
</script>
<Combination combinations={['ctrl+a']}>
<span>Content shown when Ctrl+A is pressed</span>
</Combination>

Handle multiple keyboard combinations with the same content:

<script lang="ts">
import { Combination } from '@invokey/svelte'
</script>
<Combination combinations={['ctrl+a', 'ctrl+b']}>
{#snippet activeCombination(shortcut)}
{#if shortcut}
<span>Active shortcut: {shortcut}</span>
{/if}
{/snippet}
</Combination>

Show content temporarily after a combination is pressed:

<script lang="ts">
import { Combination } from '@invokey/svelte'
</script>
<Combination
combinations={'ctrl+a'}
hideAfter={50}
>
<span>Content that disappears after 50ms</span>
</Combination>

Temporarily disable combination detection:

<script lang="ts">
import { Combination } from '@invokey/svelte'
</script>
<Combination
combinations={['ctrl+b']}
enabled={false}
>
<span>Content won't show even if Ctrl+B is pressed</span>
</Combination>

Listen for combinations on a specific element instead of the window:

<script lang="ts">
import { Combination } from '@invokey/svelte'
let leftPanel: HTMLElement | null = $state(null);
let righPanel: HTMLElement | null = $state(null);
</script>
<div bind:this={leftPanel} tabindex={-1}>
<label for="leftPanel">Left panel</label>
<Combination combinations={['ctrl+c']} ref={leftPanel}>
<span>Content shown when Ctrl+C is pressed within the left panel</span>
</Combination>
</div>
<div bind:this={righPanel} tabindex={-1}>
<label for="rightPanel">Right panel</label>
<Combination combinations={['ctrl+c']} ref={righPanel}>
<span>Content shown when Ctrl+C is pressed within the right panel</span>
</Combination>
</div>

Use a different separator for combinations:

<script lang="ts">
import { Combination } from '@invokey/svelte'
</script>
<Combination
combinations={['ctrl.a', 'meta.a']}
seperator="."
>
<span>Content shown when Ctrl.A or Meta.A is pressed</span>
</Combination>

Prevent the component from stopping default browser behavior:

<script lang="ts">
import { Combination } from '@invokey/svelte'
</script>
<Combination
combinations={['ctrl+s', 'meta+s']}
preventDefault={false}
>
<span>Content shown when Ctrl+S is pressed (browser save dialog will also appear)</span>
</Combination>

Show different content based on the active combination:

<script lang="ts">
import { Combination } from '@invokey/svelte'
</script>
<Combination
combinations={['ctrl+shift+p', 'meta+shift+p']}
activeCombination={(shortcut) => (
<div class="command-palette">
<div class="shortcut-hint">
{#if shortcut === 'ctrl+shift+p'}
Windows/Linux Command Palette
{:else}
macOS Command Palette
{/if}
</div>
<input type="text" placeholder="Type a command..." />
</div>
)}
>
<div class="command-palette">
<input type="text" placeholder="Type a command..." autofocus />
<div class="command-list">
<!-- Command list items -->
</div>
</div>
</Combination>

Handle combinations at different levels of your application:

<script lang="ts">
import { Combination } from '@invokey/svelte'
</script>
<!-- Global combinations -->
<Combination combinations={['ctrl+p', 'meta+p']}>
<div class="global-command-palette">Global Commands</div>
</Combination>
<!-- Editor-specific combinations -->
<div class="editor">
<Combination combinations={['ctrl+s', 'meta+s']}>
<div class="save-indicator">Saving...</div>
</Combination>
<Combination combinations={['ctrl+z', 'meta+z']}>
<div class="undo-indicator">Undoing...</div>
</Combination>
</div>
  1. Use Semantic Combinations: Choose combinations that make sense for your application and follow platform conventions.
  2. Consider Platform Differences: Use both ctrl and cmd combinations for cross-platform support.
  3. Avoid Conflicts: Be mindful of existing browser shortcuts and other application shortcuts.
  4. Provide Visual Feedback: Always show some indication when a combination is active.
  5. Document Shortcuts: Make sure to document available shortcuts for your users.
  6. Handle Edge Cases: Consider what happens when multiple combinations are pressed simultaneously.
  7. Test Across Platforms: Ensure your combinations work consistently across different operating systems.
  8. Use Appropriate Timeouts: Set reasonable hideAfter values based on your use case.
  9. Consider Accessibility: Provide alternative ways to access functionality beyond keyboard shortcuts.
  10. Clean Up Resources: Use the enabled prop to disable combinations when components are not in use.