GP

gpui-focus-handle

Facilitates focus tracking and keyboard navigation implementation in GPUI-based applications.

Install

mkdir -p .claude/skills/gpui-focus-handle-reviu-dev && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/18694" && unzip -o skill.zip -d .claude/skills/gpui-focus-handle-reviu-dev && rm skill.zip

Installs to .claude/skills/gpui-focus-handle-reviu-dev

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Focus management and keyboard navigation in GPUI. Use when handling focus, focus handles, or keyboard navigation. Enables keyboard-driven interfaces with proper focus tracking and navigation between focusable elements.
218 chars✓ has a “when” trigger
Intermediate

Key capabilities

  • Create FocusHandles for components
  • Make UI elements focusable
  • Manage focus state (focus, blur, is_focused)
  • Handle focus and blur events
  • Control keyboard navigation with Tab order
  • Implement custom focus navigation within containers

How it works

The system uses FocusHandles to track the currently focused element and provides methods to explicitly focus or blur elements. It automatically enables Tab/Shift-Tab navigation for elements with track_focus().

Inputs & outputs

You give it
GPUI component
You get back
Focusable GPUI component with keyboard navigation

When to use gpui-focus-handle

  • Implementing keyboard navigation
  • Managing focus states in components
  • Creating accessible input forms

About this skill

Overview

GPUI's focus system enables keyboard navigation and focus management.

Key Concepts:

  • FocusHandle: Reference to focusable element
  • Focus tracking: Current focused element
  • Keyboard navigation: Tab/Shift-Tab between elements
  • Focus events: on_focus, on_blur

Quick Start

Creating Focus Handles

struct FocusableComponent {
    focus_handle: FocusHandle,
}

impl FocusableComponent {
    fn new(cx: &mut Context<Self>) -> Self {
        Self {
            focus_handle: cx.focus_handle(),
        }
    }
}

Making Elements Focusable

impl Render for FocusableComponent {
    fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
        div()
            .track_focus(&self.focus_handle)
            .on_action(cx.listener(Self::on_enter))
            .child("Focusable content")
    }

    fn on_enter(&mut self, _: &Enter, cx: &mut Context<Self>) {
        // Handle Enter key when focused
        cx.notify();
    }
}

Focus Management

impl MyComponent {
    fn focus(&mut self, cx: &mut Context<Self>) {
        self.focus_handle.focus(cx);
    }

    fn is_focused(&self, cx: &App) -> bool {
        self.focus_handle.is_focused(cx)
    }

    fn blur(&mut self, cx: &mut Context<Self>) {
        cx.blur();
    }
}

Focus Events

Handling Focus Changes

impl Render for MyInput {
    fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
        let is_focused = self.focus_handle.is_focused(cx);

        div()
            .track_focus(&self.focus_handle)
            .on_focus(cx.listener(|this, _event, cx| {
                this.on_focus(cx);
            }))
            .on_blur(cx.listener(|this, _event, cx| {
                this.on_blur(cx);
            }))
            .when(is_focused, |el| {
                el.bg(cx.theme().focused_background)
            })
            .child(self.render_content())
    }
}

impl MyInput {
    fn on_focus(&mut self, cx: &mut Context<Self>) {
        // Handle focus gained
        cx.notify();
    }

    fn on_blur(&mut self, cx: &mut Context<Self>) {
        // Handle focus lost
        cx.notify();
    }
}

Keyboard Navigation

Tab Order

Elements with track_focus() automatically participate in Tab navigation.

div()
    .child(
        input1.track_focus(&focus1)  // Tab order: 1
    )
    .child(
        input2.track_focus(&focus2)  // Tab order: 2
    )
    .child(
        input3.track_focus(&focus3)  // Tab order: 3
    )

Focus Within Containers

impl Container {
    fn focus_first(&mut self, cx: &mut Context<Self>) {
        if let Some(first) = self.children.first() {
            first.update(cx, |child, cx| {
                child.focus_handle.focus(cx);
            });
        }
    }

    fn focus_next(&mut self, cx: &mut Context<Self>) {
        // Custom focus navigation logic
    }
}

Common Patterns

1. Auto-focus on Mount

impl MyDialog {
    fn new(cx: &mut Context<Self>) -> Self {
        let focus_handle = cx.focus_handle();

        // Focus when created
        focus_handle.focus(cx);

        Self { focus_handle }
    }
}

2. Focus Trap (Modal)

impl Modal {
    fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
        div()
            .track_focus(&self.focus_handle)
            .on_key_down(cx.listener(|this, event: &KeyDownEvent, cx| {
                if event.key == Key::Tab {
                    // Keep focus within modal
                    this.focus_next_in_modal(cx);
                    cx.stop_propagation();
                }
            }))
            .child(self.render_content())
    }
}

3. Conditional Focus

impl Searchable {
    fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
        div()
            .track_focus(&self.focus_handle)
            .when(self.search_active, |el| {
                el.on_mount(cx.listener(|this, _, cx| {
                    this.focus_handle.focus(cx);
                }))
            })
            .child(self.search_input())
    }
}

Best Practices

✅ Track Focus on Interactive Elements

// ✅ Good: Track focus for keyboard interaction
input()
    .track_focus(&self.focus_handle)
    .on_action(cx.listener(Self::on_enter))

✅ Provide Visual Focus Indicators

let is_focused = self.focus_handle.is_focused(cx);

div()
    .when(is_focused, |el| {
        el.border_color(cx.theme().focused_border)
    })

❌ Don't: Forget to Track Focus

// ❌ Bad: No track_focus, keyboard navigation won't work
div()
    .on_action(cx.listener(Self::on_enter))

Reference Documentation

  • API Reference: See api-reference.md
    • FocusHandle API, focus management
    • Events, keyboard navigation
    • Best practices

When not to use it

  • When focus management is not required
  • When keyboard navigation is not a concern
  • When UI elements do not need to be focusable

Limitations

  • Elements must use `track_focus()` to participate in Tab navigation
  • Custom focus navigation logic needs to be implemented for specific container behaviors
  • Visual focus indicators must be explicitly provided

How it compares

This approach provides a structured way to manage focus and keyboard navigation within GPUI, offering explicit control over focus states and events, unlike a generic UI framework that might lack built-in focus management.

Compared to similar skills

gpui-focus-handle side by side with the closest alternatives in the catalog.

SkillInstallsUpdatedSafetyDifficulty
gpui-focus-handle (this skill)05moNo flagsIntermediate
radix-ui-design-system331moReviewIntermediate
ui425dReviewIntermediate
reusable-ui-components16moReviewIntermediate

Try saying

Example prompts that trigger this skill in your AI assistant.

Search skills

Search the agent skills registry