dsh-keys-palette
v0.2.0
Published
DSH web plugin: a Cmd+/ floating shortcut palette with a public keys.actions registry (other plugins register bindable behaviors) and durable per-user bindings.
Downloads
25
Readme
dsh-keys-palette
A lightweight DSH web plugin that adds a floating shortcut palette to the
workspace: press Cmd+/ (macOS) / Ctrl+/ (elsewhere) to open it, see what
keys DSH currently uses, and bind your own key combos to common behaviors.
Published on npm: [email protected].
Features
- Floating palette — non-modal card, toggled by
Cmd+//Ctrl+/, dismissed withEscor the close button. Styled with DSH design tokens, Bézier (squircle) corners, and light enter/exit animations. - Built-in shortcut catalog — a curated, read-only list of the keys the
DSH web app actually handles (
Esc,Enter,Shift+Enter, …). - Custom bindings — record any key combo (must include
Cmd/Ctrl/Alt; the palette trigger is reserved) for any registered action, with conflict detection, per-action clear, and reset-to-defaults. - Durable — bindings persist in
localStorage(dsh.keys-palette.v1). - Settings page — the same binding UI is available under Settings → 快捷键 (Shortcuts).
- Public extension registry — other plugins register their own bindable
behaviors through the
keys.actionsservice; they appear automatically in the palette and the settings page.
Usage
# install into the web profile of a running dsh (npm / bundle channel)
dsh plugin --profile web add [email protected]The bundle channel composes at profile boot — it takes effect on the next
dsh start. (Alternative: ./scripts/install.sh web plugins/dsh-keys-palette
hot-applies without restart; pick one channel, mixing them double-mounts
the plugin.)
Then, in the browser:
- Press
Cmd+/to open the palette. - In Custom bindings, press 录制 (Record) on a row, then press your combo — done.
- 清除 (Clear) unbinds; 恢复默认 (Reset defaults) resets only the built-in actions (external bindings are kept).
Built-in actions and their defaults:
| id | label | default |
| --- | --- | --- |
| toggle-sidebar | 切换侧边栏 | Mod+Shift+E |
| new-session | 新建会话 | Mod+Shift+Enter |
| cycle-theme | 切换明暗主题 | Mod+Shift+K |
| open-details / close-details | 打开 / 关闭详情栏 | — |
| cycle-locale | 切换界面语言 | — |
Mod = Cmd on macOS, Ctrl elsewhere. Browser-reserved combos (e.g.
Cmd+S) never reach the page and can't be bound.
Standardized shortcut extension
The plugin exposes one public client service, visible to every plugin (static web plugin or dynamic Cordis plugin) in the same page:
keys.actions
register(def: { id, label?, description?, source?, run }) => disposer
list() : { id, label, description, source }[]
subscribe(fn) => unsubscribe// any dsh web plugin's client half
export function apply(ctx) {
const keys = ctx.get('keys.actions'); // undefined until this plugin is installed
if (!keys) return;
const dispose = keys.register({
id: 'my-feature.open-panel',
label: 'Open my panel',
run: () => { /* your behavior */ },
});
ctx.effect(() => dispose); // unregister on unload — your job
}Rules:
idmust be unique (built-ins:toggle-sidebar,open-details,close-details,new-session,cycle-theme,cycle-locale); duplicates are rejected with a console error.- Cleanup is the registrant's responsibility: call the returned disposer
on unload (
ctx.effect(() => dispose)). There is no per-registrant fiber tracking; the whole registry is removed when this plugin unloads. runexecutes in the registering plugin's context, so it can use its own services freely.- User bindings are never overwritten when the action list changes.
Implementation
- Service:
keys.actionsis provided app-wide viactx.reflect.provide()— the same mechanism the DSH shell uses forlayout/theme. - UI: the palette mounts in the
shell.overlayslot; the settings page insettings.section. Both share one in-memory store viaReact.useSyncExternalStore(cached snapshot + version counter). - Dispatch: a single capture-phase
windowkeydownlistener matches combos (modifier-strict, IME-composition and key-repeat aware) and runs the bound action; recording, validation, and dispatch are all in one path. - Persistence: bindings are saved to
localStorageon change and sanitized (valid combo ornull) on load. - Styling: DSH design tokens, an SVG Bézier mask for the squircle shape, a
two-layer mask-composite ring for the border,
drop-shadowglow, andprefers-reduced-motion-aware animations — with@supportsfallbacks for older browsers. - Safety: double-mount guard (
window.__dshKeysPaletteMounted), style tag owned by the plugin fiber, per-action error isolation.
Development
node --check lib/client.js lib/index.jsEdits to lib/ are picked up live when installed as a link: dependency;
refresh the browser page after changing client code.
License
MIT — see LICENSE.
