docs: spec for New Session dialog UX refinements
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
# New Session Dialog UX Refinements — Design
|
||||
|
||||
**Goal:** Three focused UX improvements to the New Session modal: hide sandbox
|
||||
sub-options until sandboxing is enabled, unify the focus highlight to the
|
||||
dialog's Peach accent, and add context-aware j/k field navigation.
|
||||
|
||||
**Scope:** `src/hqt/tui/screens/new_session.py` and `src/hqt/tui/styles.tcss`.
|
||||
No service, DB, or sandbox-policy changes.
|
||||
|
||||
---
|
||||
|
||||
## 1. Hide sandbox sub-options until the toggle is on
|
||||
|
||||
The "Filesystem access" and "Network" rows are sub-options of the sandbox
|
||||
switch and should only appear when sandboxing is enabled — mirroring the
|
||||
existing worktree-checkbox → branch-input reveal pattern already in this screen.
|
||||
|
||||
- Wrap the two label/widget pairs (`Filesystem access:` + `#fs-select`,
|
||||
`Network:` + `#net-switch`) in a `Vertical(id="sandbox-options")` container so
|
||||
they toggle as a single unit.
|
||||
- Set `display = False` on the container at compose time.
|
||||
- Add `on_switch_changed(self, event: Switch.Changed)`: when
|
||||
`event.switch.id == "sandbox-switch"`, set `#sandbox-options` `display` to
|
||||
`event.value`.
|
||||
- The sandbox switch starts off — and is `disabled` when bwrap is absent — so
|
||||
the sub-options start hidden in every case. No separate handling for the
|
||||
unavailable case is needed.
|
||||
- `_submit()` still reads `#fs-select` / `#net-switch` unconditionally. Their
|
||||
values are valid defaults (`rw` / net on) even while hidden, and the policy is
|
||||
only built when the sandbox switch is on, so hidden values are never used.
|
||||
|
||||
## 2. Unify the focus highlight to Peach (`$accent`)
|
||||
|
||||
Buttons already get a Peach focus highlight from `styles.tcss`, but
|
||||
`Switch` / `Checkbox` / `Select` / `Input` fall back to Textual's default
|
||||
Lavender (`$border`) focus border. That inconsistency is the "off-palette"
|
||||
highlight. Add scoped rules so every focusable control in the dialog shares the
|
||||
Peach accent:
|
||||
|
||||
```css
|
||||
#new-session-dialog Switch:focus,
|
||||
#new-session-dialog Checkbox:focus,
|
||||
#new-session-dialog Select:focus,
|
||||
#new-session-dialog Input:focus {
|
||||
border: tall $accent;
|
||||
}
|
||||
```
|
||||
|
||||
`Switch` / `Checkbox` / `Input` use a `tall` border by default, so matching
|
||||
`tall` keeps layout height identical — only the color changes.
|
||||
|
||||
## 3. Soft context-aware j/k navigation
|
||||
|
||||
Add screen-level bindings that walk the dialog's focus chain:
|
||||
|
||||
```python
|
||||
BINDINGS = [
|
||||
Binding("j", "focus_next", "Next field", show=False),
|
||||
Binding("k", "focus_previous", "Prev field", show=False),
|
||||
]
|
||||
```
|
||||
|
||||
`Input` consumes printable keys before screen bindings fire, so j/k type
|
||||
literally while editing a text field and only move focus when the focused widget
|
||||
is a toggle / select / button — the "soft" (context-aware) model the user chose.
|
||||
`focus_next` / `focus_previous` are built-in Textual screen actions. Tab /
|
||||
Shift+Tab / arrows keep working unchanged.
|
||||
|
||||
---
|
||||
|
||||
## Testing
|
||||
|
||||
All three are testable against the screen in isolation via Textual's
|
||||
`run_test()` pilot:
|
||||
|
||||
- **Sub-options reveal:** mount with `sandbox_available=True`; assert
|
||||
`#sandbox-options` `.display` is `False` initially, flip the sandbox switch,
|
||||
assert it becomes `True`, flip back, assert `False`.
|
||||
- **j/k navigation:** assert the `j` / `k` bindings map to
|
||||
`focus_next` / `focus_previous`; drive the pilot to confirm focus moves
|
||||
between toggles and that j/k typed into a focused `Input` land as literal text
|
||||
rather than moving focus.
|
||||
- **Focus highlight:** the color is visual, but the presence of the scoped
|
||||
`:focus` rule is assertable by reading the compiled CSS / `styles.tcss`.
|
||||
|
||||
## Out of scope
|
||||
|
||||
- No modal (normal/insert) vim mode — the soft model was chosen deliberately.
|
||||
- No change to Enter-to-submit behavior.
|
||||
- No restyling of controls outside the New Session dialog.
|
||||
Reference in New Issue
Block a user