T48f Docs · Focus and keyboard: what init binds, the root scope, making a Tab stop, buttons, overlays; the focus example compiles

This commit is contained in:
ZacharyZhang-NY committed 2026-10-01 12:38:02 -04:00
1 parent 85e1fc923a
commit 73c79bc79a
4 files changed
+120 -1

No files matched your search

+43
View File
@@ -0,0 +1,43 @@
# Focus and keyboard
Every Ely control that takes a press is a Tab stop. Focus moves with Tab and Shift-Tab, shows as a 1px ring, and comes back where it was when an overlay closes.
## What `init` binds
`init` binds `tab` to the `FocusNext` action and `shift-tab` to `FocusPrev`, with no key context, so they reach every window. A `FocusScope` turns the two actions into focus moves.
## The root scope
Wrap each window's content in `FocusScope::new(&handle).root()` and focus `handle` when the window opens.
| Behavior | Detail |
| --- | --- |
| Tab and Shift-Tab | Move to the next or previous Tab stop in the window. |
| A focused element leaves the tree | The root takes focus, and logs `focus: its element left the tree; the root takes it`. Keys keep reaching the window. |
| `.trap()` | Keeps Tab inside the scope. A trap with no Tab stop inside logs a warning and leaves focus where it is. |
## Make a control a Tab stop
Four parts make a box a Tab stop that shows Ely's ring:
| Part | Why |
| --- | --- |
| `cx.focus_handle().tab_stop(true)` | GPUI tabs only to handles built with `tab_stop(true)`. Keep the handle in the view. |
| `.track_focus(&handle)` | Registers the handle on the box each frame. |
| `.border_1()` with a transparent color | Room for the ring, so the box does not shift when it shows. |
| `.focus_ring(cx)` | From `FocusRing`: the border takes the theme's `focus` color while focused. |
With an `on_click`, GPUI presses the focused box when Enter or Space is released.
```rust example=focus
```
Tab from the window moves through First, the tile and Last. Enter or Space on the tile turns it on and off.
## Buttons
A `Button` stays out of focus when clicked: it stops GPUI's focus on mouse down. Tab still reaches it, unless it is disabled; a loading button stays a Tab stop, so focus holds through the wait. A button whose words and action change with a mode keeps one handle through `Button::focus_handle(&handle)`, so focus holds across the change.
## Overlays
Ely's dialogs, popovers, menus, palettes, sheets and lightbox take focus when they open and hand it back to what held it before, on every way they close. While open, they take focus back when the focused element leaves the tree. An app writes no focus code for them.
+1 -1
View File
@@ -6,7 +6,7 @@ import { Marked, type Tokens } from "marked";
const at = (relative: string) => fileURLToPath(new URL(relative, import.meta.url));
/** The guides in reading order, by file name. */
const ORDER = ["introduction", "installation", "getting-started", "theme"];
const ORDER = ["introduction", "installation", "getting-started", "theme", "focus"];
export interface Guide {
/** The path segment; the introduction has none. */