🎯

gpui-focus-handle

🎯Skill

from longbridge/gpui-component

VibeIndex|
What it does

Enables keyboard-driven focus management and navigation between focusable elements in GPUI user interfaces.

gpui-focus-handle

Installation

Install skill:
npx skills add https://github.com/longbridge/gpui-component --skill gpui-focus-handle
23
Last UpdatedJan 26, 2026

Skill Details

SKILL.md

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.

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

```rust

struct FocusableComponent {

focus_handle: FocusHandle,

}

impl FocusableComponent {

fn new(cx: &mut Context) -> Self {

Self {

focus_handle: cx.focus_handle(),

}

}

}

```

Making Elements Focusable

```rust

impl Render for FocusableComponent {

fn render(&mut self, _: &mut Window, cx: &mut Context) -> 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) {

// Handle Enter key when focused

cx.notify();

}

}

```

Focus Management

```rust

impl MyComponent {

fn focus(&mut self, cx: &mut Context) {

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) {

cx.blur();

}

}

```

Focus Events

Handling Focus Changes

```rust

impl Render for MyInput {

fn render(&mut self, _: &mut Window, cx: &mut Context) -> 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) {

// Handle focus gained

cx.notify();

}

fn on_blur(&mut self, cx: &mut Context) {

// Handle focus lost

cx.notify();

}

}

```

Keyboard Navigation

Tab Order

Elements with track_focus() automatically participate in Tab navigation.

```rust

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

```rust

impl Container {

fn focus_first(&mut self, cx: &mut Context) {

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) {

// Custom focus navigation logic

}

}

```

Common Patterns

1. Auto-focus on Mount

```rust

impl MyDialog {

fn new(cx: &mut Context) -> Self {

let focus_handle = cx.focus_handle();

// Focus when created

focus_handle.focus(cx);

Self { focus_handle }

}

}

```

2. Focus Trap (Modal)

```rust

impl Modal {

fn render(&mut self, _: &mut Window, cx: &mut Context) -> 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

```rust

impl Searchable {

fn render(&mut self, _: &mut Window, cx: &mut Context) -> 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

```rust

// βœ… Good: Track focus for keyboard interaction

input()

.track_focus(&self.focus_handle)

.on_action(cx.listener(Self::on_enter))

```

βœ… Provide Visual Focus Indicators

```rust

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

```rust

// ❌ 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](references/api-reference.md)

- FocusHandle API, focus management

- Events, keyboard navigation

- Best practices

More from this repository10

🎯
gpui-style-guide🎯Skill

Enforces consistent GPUI component design patterns by providing a comprehensive style guide for creating and reviewing Rust UI components.

🎯
gpui-async🎯Skill

Enables asynchronous operations and background tasks in GPUI, allowing seamless coordination between UI updates and concurrent computations.

🎯
gpui-layout-and-style🎯Skill

Provides CSS-like layout and styling for Rust GPUI components using type-safe, chainable methods for flexbox, sizing, colors, and spacing.

🎯
gpui-entity🎯Skill

Manages application state through safe, concurrent entities with read, update, and weak reference capabilities for reactive and async-friendly state handling in GPUI.

🎯
gpui-action🎯Skill

Defines and manages keyboard-driven actions and key bindings for declarative UI interactions in GPUI applications.

🎯
gpui-event🎯Skill

Enables type-safe event handling, subscriptions, and observations for coordinating component interactions in GPUI applications.

🎯
gpui-context🎯Skill

gpui-context skill from longbridge/gpui-component

🎯
gpui-test🎯Skill

Enables comprehensive testing of GPUI applications with deterministic, single-threaded test execution for UI components and async operations.

🎯
gpui-element🎯Skill

Enables low-level, performance-critical custom UI element creation with precise control over layout, painting, and interaction phases in GPUI.

🎯
gpui-global🎯Skill

Manages global application state and configuration in GPUI, enabling centralized data access and sharing across components.