Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ Type-safe keyboard shortcuts for the web. Template-string bindings, parsed objec
> - [**Solid Hotkeys**](https://tanstack.com/hotkeys/latest/docs/framework/solid/reference)
> - [**Angular Hotkeys**](https://tanstack.com/hotkeys/latest/docs/framework/angular/reference)
> - [**Vue Hotkeys**](https://tanstack.com/hotkeys/latest/docs/framework/vue/reference)
> - Svelte Hotkeys – needs a contributor!
> - [**Svelte Hotkeys**](https://tanstack.com/hotkeys/latest/docs/framework/svelte/reference)

## Get Involved

Expand Down
137 changes: 137 additions & 0 deletions docs/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,15 @@
"to": "framework/vue/quick-start"
}
]
},
{
"label": "svelte",
"children": [
{
"label": "Quick Start",
"to": "framework/svelte/quick-start"
}
]
}
]
},
Expand Down Expand Up @@ -198,6 +207,31 @@
"to": "framework/vue/guides/formatting-display"
}
]
},
{
"label": "svelte",
"children": [
{
"label": "Hotkeys",
"to": "framework/svelte/guides/hotkeys"
},
{
"label": "Sequences",
"to": "framework/svelte/guides/sequences"
},
{
"label": "Hotkey Recording",
"to": "framework/svelte/guides/hotkey-recording"
},
{
"label": "Key State Tracking",
"to": "framework/svelte/guides/key-state-tracking"
},
{
"label": "Formatting & Display",
"to": "framework/svelte/guides/formatting-display"
}
]
}
]
},
Expand Down Expand Up @@ -254,6 +288,15 @@
"to": "framework/vue/reference/index"
}
]
},
{
"label": "svelte",
"children": [
{
"label": "Svelte APIs",
"to": "framework/svelte/reference/index"
}
]
}
]
},
Expand Down Expand Up @@ -376,6 +419,23 @@
"to": "framework/vue/reference/interfaces/HotkeysProviderOptions"
}
]
},
{
"label": "svelte",
"children": [
{
"label": "createHotkey",
"to": "framework/svelte/reference/functions/createHotkey"
},
{
"label": "CreateHotkeyOptions",
"to": "framework/svelte/reference/interfaces/CreateHotkeyOptions"
},
{
"label": "HotkeysProviderOptions",
"to": "framework/svelte/reference/interfaces/HotkeysProviderOptions"
}
]
}
]
},
Expand Down Expand Up @@ -470,6 +530,19 @@
"to": "framework/vue/reference/interfaces/UseHotkeySequenceOptions"
}
]
},
{
"label": "svelte",
"children": [
{
"label": "createHotkeySequence",
"to": "framework/svelte/reference/functions/createHotkeySequence"
},
{
"label": "CreateHotkeySequenceOptions",
"to": "framework/svelte/reference/interfaces/CreateHotkeySequenceOptions"
}
]
}
]
},
Expand Down Expand Up @@ -540,6 +613,15 @@
"to": "framework/vue/reference/functions/useKeyHold"
}
]
},
{
"label": "svelte",
"children": [
{
"label": "getIsKeyHeld",
"to": "framework/svelte/reference/functions/getIsKeyHeld"
}
]
}
]
},
Expand Down Expand Up @@ -630,6 +712,23 @@
"to": "framework/vue/reference/functions/useHeldKeyCodes"
}
]
},
{
"label": "svelte",
"children": [
{
"label": "getHeldKeys",
"to": "framework/svelte/reference/functions/getHeldKeys"
},
{
"label": "getHeldKeyCodesMap",
"to": "framework/svelte/reference/functions/getHeldKeyCodesMap"
},
{
"label": "getIsKeyHeld",
"to": "framework/svelte/reference/functions/getIsKeyHeld"
}
]
}
]
},
Expand Down Expand Up @@ -716,6 +815,19 @@
"to": "framework/vue/reference/interfaces/VueHotkeyRecorder"
}
]
},
{
"label": "svelte",
"children": [
{
"label": "createHotkeyRecorder",
"to": "framework/svelte/reference/functions/createHotkeyRecorder"
},
{
"label": "SvelteHotkeyRecorder",
"to": "framework/svelte/reference/interfaces/SvelteHotkeyRecorder"
}
]
}
]
},
Expand Down Expand Up @@ -906,6 +1018,31 @@
"to": "framework/vue/examples/useKeyhold"
}
]
},
{
"label": "svelte",
"children": [
{
"label": "createHotkey",
"to": "framework/svelte/examples/create-hotkey"
},
{
"label": "createHotkeySequence",
"to": "framework/svelte/examples/create-hotkey-sequence"
},
{
"label": "createHotkeyRecorder",
"to": "framework/svelte/examples/create-hotkey-recorder"
},
{
"label": "getHeldKeys",
"to": "framework/svelte/examples/get-held-keys"
},
{
"label": "getIsKeyHeld",
"to": "framework/svelte/examples/get-is-key-held"
}
]
}
]
}
Expand Down
70 changes: 70 additions & 0 deletions docs/framework/svelte/guides/formatting-display.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
---
title: Formatting & Display Guide
id: formatting-display
---

TanStack Hotkeys includes utilities for turning hotkey strings into display-friendly labels. These utilities are framework-agnostic, but they pair naturally with Svelte templates and reactive UI.

## `formatForDisplay`

```ts
import { formatForDisplay } from '@tanstack/svelte-hotkeys'

formatForDisplay('Mod+S')
formatForDisplay('Mod+Shift+Z')
```

## `formatWithLabels`

```ts
import { formatWithLabels } from '@tanstack/svelte-hotkeys'

formatWithLabels('Mod+S')
formatWithLabels('Mod+Shift+Z')
```

## `formatKeyForDebuggingDisplay`

```ts
import { formatKeyForDebuggingDisplay } from '@tanstack/svelte-hotkeys'

formatKeyForDebuggingDisplay('Meta')
formatKeyForDebuggingDisplay('Shift')
```

## Using Formatted Hotkeys in Svelte

### Keyboard Shortcut Badges

```svelte
<script lang="ts">
import { formatForDisplay } from '@tanstack/svelte-hotkeys'
</script>

<kbd class="shortcut-badge">{formatForDisplay(hotkey)}</kbd>
```

### Menu Items with Hotkeys

```svelte
<script lang="ts">
import { formatForDisplay, createHotkey } from '@tanstack/svelte-hotkeys'

let { label, hotkey, onAction } = $props()

createHotkey(hotkey, () => onAction())
</script>

<div class="menu-item">
<span>{label}</span>
<span class="menu-shortcut">{formatForDisplay(hotkey)}</span>
</div>
```

## Validation

```ts
import { validateHotkey } from '@tanstack/svelte-hotkeys'

const result = validateHotkey('Alt+A')
```
80 changes: 80 additions & 0 deletions docs/framework/svelte/guides/hotkey-recording.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
---
title: Hotkey Recording Guide
id: hotkey-recording
---

TanStack Hotkeys provides the `createHotkeyRecorder` function for building shortcut customization UIs in Svelte.

## Basic Usage

```svelte
<script lang="ts">
import { formatForDisplay, createHotkeyRecorder } from '@tanstack/svelte-hotkeys'

const recorder = createHotkeyRecorder({
onRecord: (hotkey) => {
console.log('Recorded:', hotkey)
},
})
</script>

<div>
<button
onclick={() =>
recorder.isRecording ? recorder.stopRecording() : recorder.startRecording()}
>
{recorder.isRecording
? 'Press a key combination...'
: recorder.recordedHotkey
? formatForDisplay(recorder.recordedHotkey)
: 'Click to record'}
</button>
{#if recorder.isRecording}
<button onclick={() => recorder.cancelRecording()}>Cancel</button>
{/if}
</div>
```

## Return Value

- `isRecording`: whether recording is active
- `recordedHotkey`: the most recently recorded hotkey
- `startRecording()`: start listening for key presses
- `stopRecording()`: stop listening and keep the current recording
- `cancelRecording()`: stop listening and discard the in-progress recording

## Options

```ts
createHotkeyRecorder({
onRecord: (hotkey) => {},
onCancel: () => {},
onClear: () => {},
})
```

## Global Default Options via Provider

```svelte
<script lang="ts">
import { HotkeysProvider } from '@tanstack/svelte-hotkeys'
</script>

<HotkeysProvider
defaultOptions={{
hotkeyRecorder: {
onCancel: () => console.log('Recording cancelled'),
},
}}
>
<AppContent />
</HotkeysProvider>
```

## Recording Behavior

- Modifier-only presses do not complete a recording.
- Modifier plus key combinations record the full shortcut.
- Escape cancels recording.
- Backspace and Delete clear the shortcut.
- Recorded values are normalized to portable `Mod` format.
Loading
Loading