Replace main menu buttons with OptionList for arrow key navigation

OptionList supports up/down arrow keys and Enter to select,
giving a proper menu feel instead of Tab-through buttons.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
shuki
2026-03-05 23:49:06 +02:00
parent fd0ccefad0
commit b13514e478
2 changed files with 31 additions and 31 deletions

View File

@@ -19,10 +19,10 @@ Screen {
overflow-y: auto; overflow-y: auto;
} }
#main-menu Button { #menu-list {
width: 100%; width: 100%;
height: 3; height: auto;
margin: 0; max-height: 100%;
} }
#logo { #logo {

View File

@@ -1,6 +1,7 @@
from textual.app import ComposeResult from textual.app import ComposeResult
from textual.screen import Screen from textual.screen import Screen
from textual.widgets import Header, Footer, Static, Button from textual.widgets import Header, Footer, Static, OptionList
from textual.widgets.option_list import Option
from textual.containers import Vertical, Center from textual.containers import Vertical, Center
LOGO = """\ LOGO = """\
@@ -13,6 +14,20 @@ LOGO = """\
gniza - Linux Backup Manager gniza - Linux Backup Manager
""" """
MENU_ITEMS = [
("backup", "Backup"),
("restore", "Restore"),
("targets", "Targets"),
("remotes", "Remotes"),
("snapshots", "Snapshots"),
("verify", "Verify"),
("retention", "Retention"),
("schedule", "Schedules"),
("logs", "Logs"),
("settings", "Settings"),
("quit", "Quit"),
]
class MainMenuScreen(Screen): class MainMenuScreen(Screen):
@@ -23,36 +38,21 @@ class MainMenuScreen(Screen):
with Center(): with Center():
with Vertical(id="main-menu"): with Vertical(id="main-menu"):
yield Static(LOGO, id="logo", markup=True) yield Static(LOGO, id="logo", markup=True)
yield Button("Backup", id="menu-backup", variant="primary") yield OptionList(
yield Button("Restore", id="menu-restore") *[Option(label, id=mid) for mid, label in MENU_ITEMS],
yield Button("Targets", id="menu-targets") id="menu-list",
yield Button("Remotes", id="menu-remotes") )
yield Button("Snapshots", id="menu-snapshots")
yield Button("Verify", id="menu-verify")
yield Button("Retention", id="menu-retention")
yield Button("Schedules", id="menu-schedule")
yield Button("Logs", id="menu-logs")
yield Button("Settings", id="menu-settings")
yield Button("Quit", id="menu-quit", variant="error")
yield Footer() yield Footer()
def on_button_pressed(self, event: Button.Pressed) -> None: def on_mount(self) -> None:
button_map = { self.query_one("#menu-list", OptionList).focus()
"menu-backup": "backup",
"menu-restore": "restore", def on_option_list_option_selected(self, event: OptionList.OptionSelected) -> None:
"menu-targets": "targets", option_id = event.option.id
"menu-remotes": "remotes", if option_id == "quit":
"menu-snapshots": "snapshots",
"menu-verify": "verify",
"menu-retention": "retention",
"menu-schedule": "schedule",
"menu-logs": "logs",
"menu-settings": "settings",
}
if event.button.id == "menu-quit":
self.app.exit() self.app.exit()
elif event.button.id in button_map: elif option_id:
self.app.push_screen(button_map[event.button.id]) self.app.push_screen(option_id)
def action_quit_app(self) -> None: def action_quit_app(self) -> None:
self.app.exit() self.app.exit()