The vtui Navigation & Interaction Philosophy
August 4, 2026 · View on GitHub
Abstract
This document outlines the core principles of user experience (UX) and navigation that govern the vtui framework and its primary implementation, the f4 file manager. Our philosophy is rooted in blending the speed and power of classic keyboard-driven interfaces like Far Manager with the structured, predictable component model of Turbo Vision.
The goal is to create an environment that is instantly familiar to veterans of TUI applications while remaining discoverable and consistent for new users. We achieve this by ensuring that every navigation key has a clear, context-dependent purpose, maximizing user efficiency and respecting "muscle memory".
0. The Golden Rule: One Action, Three Faces
Every interactive capability of f4 (everything above vtui widget internals like Checkbox.ProcessKey) MUST exist in three equivalent forms, all driven by a single entry in the action registry (action_registry.go):
- A clickable menu or KeyBar item. Menus (
F9, available in the panels, the editor and the viewer) and KeyBar labels are generated from the registry, never hardcoded. - A macro command. The action's
Name(e.g.Editor.Save) is callable from macros viaActions.Run(...). - A hotkey. Default bindings ship with the action (
DefaultKeys) and users can rebind them in the Hotkey Configurator.
The built-in help pages for key bindings are generated from the same registry, so documentation, menus, KeyBar and actual behavior can never drift apart.
0.1. Adding a New Action: Checklist
- Implement the handler next to its Area's owner, as a method of the
view that does the work (e.g.
(*ViewerView).showCodepageDialog,(*PanelsFrame).moveFolderHistory). The registry entry only dispatches:
KeepHandler: withViewer(func(vv *ViewerView) { vv.showCodepageDialog() })action_registry.gothin — no business logic beyond a small glue closure. If the handler needs the frame, use thewithPF/withEditor/withVieweradapters; they resolve the top frame of the matching type and silently do nothing when it is absent. - Register the action with every field that applies:
Name(Area.Verbstyle),Area,DefaultKeys(Far-style, optional:Conditionper key),MenuPath(empty = key-only action),Checkedfor toggles,MenuSeparatorBeforefor menu grouping. - Localize: add
LabelKey/DescKeyentries to bothlang/en.lngandlang/ru.lng(Action.<Name>andAction.<Name>.Desc).Label/Descriptionremain the English fallbacks. Menus get a first-letter hotkey automatically unless the label carries its own&marker. - Do not add a hardcoded key handler in any
ProcessKey. If the key must lose to a modal input state (fast find, autocomplete), extend that frame'sVetoActionKeyinstead. - Tests: drive keys through the
pressKeytest helper (filter → ProcessKey), never through a bareProcessKeycall for action keys. Menus, KeyBar labels and the generated help topics pick the new action up for free — assert them instead of duplicating key tables.
1. The Four Tiers of Navigation
Every interactive screen in vtui adheres to a hierarchical navigation model. This ensures there is always a way to move focus, from global workspace management to specific character input.
Tier 0: Global Workspace Switching (Ctrl+Tab / Ctrl+Shift+Tab)
This is the highest level of navigation, allowing the user to jump between entire application states (Screens).
- Rule:
Ctrl+Tabcycles forward through active screens;Ctrl+Shift+Tabcycles backward. - Visuals: A switcher overlay appears in the center of the screen, showing titles and progress of all workspaces.
- Commit: The switch is finalized only when the
Ctrlkey is released.
Tier 1: The Reliable Cycle (Tab / Shift+Tab)
This is the most fundamental and predictable way to navigate.
- Rule:
Tabalways moves focus to the next focusable element in the logical order.Shift+Tabalways moves to the previous one. - Behavior: This cycle is typically wrapped. Pressing
Tabon the last element moves focus to the first, andShift+Tabon the first moves to the last. - Purpose: Guarantees that a user can always reach any interactive element on the screen, regardless of its visual layout. It is the bedrock of accessibility and predictability.
Tier 2: The Contextual Jump (Arrow Keys)
Arrow keys provide fast, spatial navigation. Their behavior is highly dependent on the currently focused widget.
- Rule: Arrow keys are primarily used for internal navigation within a component (e.g., moving up/down a list, left/right in a text field).
- Boundary Behavior: Arrow keys transfer focus to a neighboring component only when the cursor is at the absolute boundary of the current component's data set.
- Pressing
UporLefton the very first item of a list, table, or group will exit focus to the previous element in theTabcycle. - Pressing
DownorRighton the very last item will exit focus to the next element. - In all other cases (e.g., pressing
Upin the middle of a list), the event is "swallowed" by the component.
- Pressing
- Purpose: This creates an intuitive flow. The user stays "inside" a widget while working with its data, but can seamlessly "flow" to the next widget by continuing to press the arrow key after reaching the end.
Tier 3: The Direct Shortcut (Hotkeys)
Hotkeys provide the fastest way to activate a specific function.
- Rule: Hotkeys are typically activated with
Alt+<char>. An ampersand (&) in a label (e.g., "&Save") defines the hotkey. - Modeless Activation: In dialogs where no text input field is focused, hotkeys may be activated directly by pressing the character key without
Alt. - Purpose: To provide expert users with immediate access to any action on the screen, bypassing the
Tabcycle entirely.
2. Component-Specific Interaction Patterns
Dialogs and Windows
Enter: Triggers the "default" action. This is either the button marked asIsDefault, or the first actionable button in the tab order if none is marked. This applies even if anEditfield is focused.Esc: Closes the window or dialog.F1: Opens the help topic associated with the currently focused element.- Mouse: Click-and-drag on the top border moves the window. Click-and-drag on the bottom-right corner resizes it.
Groups (RadioGroup, CheckGroup)
- Interaction Model: These components separate the concepts of cursor and selection.
- Arrow Keys move the internal cursor/focus within the group. The selection itself does not change.
SpaceorEntertoggles the state (checked/unchecked, selected radio button) of the item under the cursor.
- Snake Navigation: In multi-column layouts, navigation is two-dimensional and wraps intuitively:
- Pressing
Rightat the end of a row moves the cursor to the beginning of the next row. - Pressing
Downat the bottom of a column moves the cursor to the top of the next column.Upat the top of a column moves to the bottom of the previous.
- Pressing
- Rationale: This model is vastly more efficient for keyboard users than the "arrows change selection" model, as it allows rapid navigation across many options without triggering an action on every key press.
Lists (Table, ListBox)
- Navigation:
Up/Down,PgUp/PgDn,Home/Endprovide standard list navigation. - Boundary Behavior: As per the core principle,
Upon the first item andDownon the last item will pass focus to the previous/next widget in the dialog. - Action:
EnterorDouble-Clicktriggers the primary action for the selected item (e.g., opening a file, confirming a choice). ListBoxas aTable:ListBoxis implemented as a single-columnTableand inherits all its navigation behaviors, ensuring consistency.
Text Input (Edit)
- Navigation:
Left/Right: Move the cursor by one character.Ctrl+Left/Ctrl+Right: Jump to the beginning of the previous/next word.Home/End: Jump to the beginning/end of the line.
- Selection: Holding
Shiftwhile using any navigation key creates or expands a selection.Ctrl+CandCtrl+Inscopy to the system clipboard. - Auto-Clear Logic: Fields that are opened with a default "unchanged" value (grayed out) will automatically clear their entire content the moment the user starts typing, unless a navigation key is pressed first.
Dropdowns (ComboBox)
- Interaction: Combines an
Editfield with a hiddenVMenu. - Activation:
Alt+Downor clicking the down arrow (↓) icon opens the list. - Selection: Selecting an item from the list automatically populates the
Editfield and returns focus to it. DropdownOnlyMode: If enabled, the user cannot type custom text and must select from the provided options usingEnteror the mouse.
File Panels (f4 Specific)
File panels are a special, highly optimized version of a Table.
Up/Down,PgUp/PgDn: Navigate vertically within the current column.Left/Right: Jump one full page (view height) up or down within the current column. If at the top/bottom, jump to the top/bottom of the adjacent column. These keys do not change the active panel.Enter: Enters a directory or executes a file.Ctrl+Enter: Inserts the selected filename into the command line.
Menus (MenuBar, VMenu)
MenuBar(Top-level):- Activated by
F9orAlt+<char>. - When active,
Left/Rightcycles through the main menu items (File,Edit, etc.), automatically opening their respective submenus. DownorEnteropens the submenu for the currently selected item.- Multi-level
Esc:Esccloses an open submenu but keeps theMenuBaractive. A secondEscdeactivates theMenuBarentirely.
- Activated by
VMenu(Vertical/Submenu):- As a Submenu: If opened from a
MenuBar,Left/Rightcloses the current submenu and opens the adjacent one from theMenuBar.Upon the first item orDownon the last item wraps around within theVMenuto provide fast circular access. - As a Standalone Dialog: If opened as a context menu (not tied to a
MenuBar), its boundary behavior follows the standardTier 2rule:Upon the first item orDownon the last will pass focus to the previous/next element in the parent dialog.
- As a Submenu: If opened from a
- Rationale: This dual behavior makes menus feel integrated when part of a larger structure, but behave like any other standard list widget when used for context-specific actions.
3. Mouse Interaction Principles
While vtui is keyboard-first, mouse interaction is designed to be consistent and predictable.
- Left Click: Focuses and/or activates an element.
- Double-Click: The primary "action" command, equivalent to
Enter. - Right Click (Contextual): In specific components like file panels, right-click can be used for secondary actions like multi-selection.
- Wheel: Scrolls the component under the cursor, regardless of focus.
By adhering to these rules, we aim to build TUI applications that are powerful, efficient, and a pleasure to use for both novice and expert users.