Gpui Action

Build keyboard-driven UI interactions with declarative actions in GPUI

✨ The solution you've been looking for

Verified
Tested and verified by our team
9771 Stars

Action definitions and keyboard shortcuts in GPUI. Use when implementing actions, keyboard shortcuts, or key bindings.

gpui keyboard-shortcuts actions ui-framework rust key-bindings event-handling desktop-apps
Repository

See It In Action

Interactive preview & real-world examples

Live Demo
Skill Demo Animation

AI Conversation Simulator

See how users interact with this skill

User Prompt

I need to add keyboard shortcuts to my GPUI editor component. I want cmd-s for save, arrow keys for navigation, and cmd-q to quit.

Skill Processing

Analyzing request...

Agent Response

Complete action definitions with keyboard bindings and event handlers for a functional editor interface

Quick Start (3 Steps)

Get up and running in minutes

1

Install

claude-code skill install gpui-action

claude-code skill install gpui-action
2

Config

3

First Trigger

@gpui-action help

Commands

CommandDescriptionRequired Args
@gpui-action create-editor-keyboard-shortcutsImplement standard editor actions like save, quit, and navigation with keyboard shortcutsNone
@gpui-action context-aware-key-bindingsSet up different keyboard behaviors for different UI contexts like modals vs main editorNone
@gpui-action parameterized-actionsCreate actions that accept parameters for dynamic behavior like digit input or text insertionNone

Typical Use Cases

Create Editor Keyboard Shortcuts

Implement standard editor actions like save, quit, and navigation with keyboard shortcuts

Context-Aware Key Bindings

Set up different keyboard behaviors for different UI contexts like modals vs main editor

Parameterized Actions

Create actions that accept parameters for dynamic behavior like digit input or text insertion

Overview

Overview

Actions provide declarative keyboard-driven UI interactions in GPUI.

Key Concepts:

  • Define actions with actions! macro or #[derive(Action)]
  • Bind keys with cx.bind_keys()
  • Handle with .on_action() on elements
  • Context-aware via key_context()

Quick Start

Simple Actions

 1use gpui::actions;
 2
 3actions!(editor, [MoveUp, MoveDown, Save, Quit]);
 4
 5const CONTEXT: &str = "Editor";
 6
 7pub fn init(cx: &mut App) {
 8    cx.bind_keys([
 9        KeyBinding::new("up", MoveUp, Some(CONTEXT)),
10        KeyBinding::new("down", MoveDown, Some(CONTEXT)),
11        KeyBinding::new("cmd-s", Save, Some(CONTEXT)),
12        KeyBinding::new("cmd-q", Quit, Some(CONTEXT)),
13    ]);
14}
15
16impl Render for Editor {
17    fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
18        div()
19            .key_context(CONTEXT)
20            .on_action(cx.listener(Self::move_up))
21            .on_action(cx.listener(Self::move_down))
22            .on_action(cx.listener(Self::save))
23    }
24}
25
26impl Editor {
27    fn move_up(&mut self, _: &MoveUp, cx: &mut Context<Self>) {
28        // Handle move up
29        cx.notify();
30    }
31
32    fn move_down(&mut self, _: &MoveDown, cx: &mut Context<Self>) {
33        cx.notify();
34    }
35
36    fn save(&mut self, _: &Save, cx: &mut Context<Self>) {
37        // Save logic
38        cx.notify();
39    }
40}

Actions with Parameters

 1#[derive(Clone, PartialEq, Action, Deserialize)]
 2#[action(namespace = editor)]
 3pub struct InsertText {
 4    pub text: String,
 5}
 6
 7#[derive(Action, Clone, PartialEq, Eq, Deserialize)]
 8#[action(namespace = editor, no_json)]
 9pub struct Digit(pub u8);
10
11cx.bind_keys([
12    KeyBinding::new("0", Digit(0), Some(CONTEXT)),
13    KeyBinding::new("1", Digit(1), Some(CONTEXT)),
14    // ...
15]);
16
17impl Editor {
18    fn on_digit(&mut self, action: &Digit, cx: &mut Context<Self>) {
19        self.insert_digit(action.0, cx);
20    }
21}

Key Formats

 1// Modifiers
 2"cmd-s"         // Command (macOS) / Ctrl (Windows/Linux)
 3"ctrl-c"        // Control
 4"alt-f"         // Alt
 5"shift-tab"     // Shift
 6"cmd-ctrl-f"    // Multiple modifiers
 7
 8// Keys
 9"a-z", "0-9"    // Letters and numbers
10"f1-f12"        // Function keys
11"up", "down", "left", "right"
12"enter", "escape", "space", "tab"
13"backspace", "delete"
14"-", "=", "[", "]", etc.  // Special characters

Action Naming

Prefer verb-noun pattern:

1actions!([
2    OpenFile,      // ✅ Good
3    CloseWindow,   // ✅ Good
4    ToggleSidebar, // ✅ Good
5    Save,          // ✅ Good (common exception)
6]);

Context-Aware Bindings

 1const EDITOR_CONTEXT: &str = "Editor";
 2const MODAL_CONTEXT: &str = "Modal";
 3
 4// Same key, different contexts
 5cx.bind_keys([
 6    KeyBinding::new("escape", CloseModal, Some(MODAL_CONTEXT)),
 7    KeyBinding::new("escape", ClearSelection, Some(EDITOR_CONTEXT)),
 8]);
 9
10// Set context on element
11div()
12    .key_context(EDITOR_CONTEXT)
13    .child(editor_content)

Best Practices

✅ Use Contexts

1// ✅ Good: Context-aware
2div()
3    .key_context("MyComponent")
4    .on_action(cx.listener(Self::handle))

✅ Name Actions Clearly

1// ✅ Good: Clear intent
2actions!([
3    SaveDocument,
4    CloseTab,
5    TogglePreview,
6]);

✅ Handle with Listeners

1// ✅ Good: Proper handler naming
2impl MyComponent {
3    fn on_action_save(&mut self, _: &Save, cx: &mut Context<Self>) {
4        // Handle save
5        cx.notify();
6    }
7}
8
9div().on_action(cx.listener(Self::on_action_save))

Reference Documentation

  • Complete Guide: See reference.md
    • Action definition, keybinding, dispatch
    • Focus-based routing, best practices
    • Performance, accessibility

What Users Are Saying

Real feedback from the community

Environment Matrix

Dependencies

Rust with GPUI framework

Framework Support

GPUI ✓ (required)

Context Window

Token Usage ~1K-3K tokens for typical action implementations

Security & Privacy

Information

Author
longbridge
Updated
2026-01-30
Category
ide-plugins