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.zipInstalls 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.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
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.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| gpui-focus-handle (this skill) | 0 | 5mo | No flags | Intermediate |
| radix-ui-design-system | 33 | 1mo | Review | Intermediate |
| ui | 4 | 25d | Review | Intermediate |
| reusable-ui-components | 1 | 6mo | Review | Intermediate |
Try saying
Example prompts that trigger this skill in your AI assistant.
You might also like
radix-ui-design-system
sickn33
Build accessible design systems with Radix UI primitives. Headless component customization, theming strategies, and compound component patterns for production-grade UI libraries.
ui
nuxt
Build UIs with @nuxt/ui v4 — 125+ accessible Vue components with Tailwind CSS theming. Use when creating interfaces, customizing themes to match a brand, building forms, or composing layouts like dashboards, docs sites, and chat interfaces.
reusable-ui-components
EvanBacon
Guidelines for creating reusable, portable UI components with native-first design, compound patterns, and accessibility
verify-bulk-action-bar
junnv93
BulkActionBar 패턴 SSOT 검증 — count chip aria-live, role=toolbar, Esc clear, indeterminate Radix, focus management, IME guard. 일괄 작업 UI 변경 시 트리거. canonical = components/common/BulkActionBar.tsx (도메인 무관 generic), components/approvals/BulkActionBar.tsx는 approvals 특화 wrapper.
frontend-patterns
forgivesam168
Frontend development patterns for React, Next.js, state management, performance optimization, and UI best practices.
mobile-android-design
wshobson
Master Material Design 3 and Jetpack Compose patterns for building native Android apps. Use when designing Android interfaces, implementing Compose UI, or following Google's Material Design guidelines.