--- name: gpui-focus-handle description: 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