mirror of
https://github.com/PR0M3TH3AN/SeedPass.git
synced 2026-11-01 18:32:05 +00:00
Polish TUI v2 visual hierarchy and panel clarity
This commit is contained in:
1 parent
e667249ec4
commit
e1b87ff2df
2 files changed
+57
-24
No files matched your search
@@ -202,3 +202,5 @@
|
||||
- Added explicit one-release override flag `--legacy-tui` and updated test coverage (`test_typer_cli.py`) for default TUI v2 launch, forced legacy path, and root fallback behavior.
|
||||
- 2026-03-01: UX pass for TUI v2 added help overlay (`?`), quick jump input (`j`), pane focus switching (`1/2/3`) with visual focus borders, mode-tagged status line, and an activity log panel of recent actions.
|
||||
- Added document dirty-state UX improvements (`Edit mode [*]` marker, no-op save guard) and updated Textual interaction/parity tests for Textual 8-compatible action-driven control paths.
|
||||
- 2026-03-01: Visual polish pass for TUI v2 updated panel styling hierarchy (stronger status/pane contrast), refined left-panel summaries, improved help overlay readability, and added labeled headers for entry/detail and links sections.
|
||||
- UI copy now emphasizes current selection/filter context while keeping deterministic action affordances unchanged; full TUI-focused test slice remains green.
|
||||
+55
-24
@@ -104,16 +104,23 @@ def launch_tui2(
|
||||
|
||||
CSS = """
|
||||
#command-palette {
|
||||
height: 3;
|
||||
margin: 0 1;
|
||||
height: 2;
|
||||
margin: 0 1 1 1;
|
||||
border: solid $secondary;
|
||||
background: $panel;
|
||||
}
|
||||
#body { height: 1fr; }
|
||||
#status { height: 1; padding: 0 1; }
|
||||
#left { width: 30; border: solid $primary; padding: 1; }
|
||||
#center { width: 1fr; border: solid $primary; padding: 1; }
|
||||
#right { width: 1fr; border: solid $primary; padding: 1; }
|
||||
#status {
|
||||
height: 1;
|
||||
padding: 0 1;
|
||||
border: heavy $primary;
|
||||
background: $panel;
|
||||
}
|
||||
#left { width: 34; border: solid $primary; padding: 1; background: $panel; }
|
||||
#center { width: 1fr; border: solid $primary; padding: 1; background: $panel; }
|
||||
#right { width: 1fr; border: solid $primary; padding: 1; background: $panel; }
|
||||
#search { margin-bottom: 1; }
|
||||
#quick-jump { margin-bottom: 1; }
|
||||
#entry-list { height: 1fr; }
|
||||
#entry-detail {
|
||||
height: 1fr;
|
||||
@@ -293,11 +300,12 @@ def launch_tui2(
|
||||
|
||||
def _update_activity_panel(self) -> None:
|
||||
if not self._activity_log:
|
||||
text = "Activity\n\nNo actions yet."
|
||||
text = "Activity Log\n\nNo actions yet."
|
||||
else:
|
||||
lines = ["Activity", ""]
|
||||
lines = ["Activity Log", ""]
|
||||
for i, item in enumerate(reversed(self._activity_log), start=1):
|
||||
lines.append(f"{i}. {item}")
|
||||
short = item if len(item) <= 88 else f"{item[:85]}..."
|
||||
lines.append(f"{i}. {short}")
|
||||
text = "\n".join(lines)
|
||||
self.query_one("#activity", Static).update(text)
|
||||
|
||||
@@ -309,15 +317,15 @@ def launch_tui2(
|
||||
box.remove_class("hidden")
|
||||
text = "\n".join(
|
||||
[
|
||||
"TUI v2 Quick Help",
|
||||
"TUI v2 Quick Help (Esc to close)",
|
||||
"",
|
||||
"Core: / search, j jump-id, p/n page, r refresh",
|
||||
"Modes: Ctrl+P palette, e edit-doc, Ctrl+S save, Esc cancel/close",
|
||||
"Graph: l relation filter, [/] link select, o open link target",
|
||||
"Core : / search j jump-id p/n page r refresh",
|
||||
"Modes : Ctrl+P palette e edit-doc Ctrl+S save Esc cancel/close",
|
||||
"Graph : l relation filter [/] link select o open link target",
|
||||
"Resilience: x retry last error",
|
||||
"Pane Focus: 1 left, 2 center, 3 right",
|
||||
"Pane Focus: 1 left 2 center 3 right",
|
||||
"",
|
||||
"Palette examples:",
|
||||
"Palette examples",
|
||||
"help | filter document | open 12 | link-add 7 references note",
|
||||
]
|
||||
)
|
||||
@@ -376,6 +384,20 @@ def launch_tui2(
|
||||
return None
|
||||
return [self.filter_kind]
|
||||
|
||||
def _selected_summary(self) -> str:
|
||||
if (
|
||||
not isinstance(self._selected_entry, dict)
|
||||
or self._selected_entry_id is None
|
||||
):
|
||||
return "Selected: (none)"
|
||||
kind = str(
|
||||
self._selected_entry.get("kind")
|
||||
or self._selected_entry.get("type")
|
||||
or "unknown"
|
||||
)
|
||||
label = str(self._selected_entry.get("label", ""))
|
||||
return f"Selected: #{self._selected_entry_id} [{kind}] {label}"
|
||||
|
||||
def _update_filters_panel(self) -> None:
|
||||
fp_line = (
|
||||
f"Fingerprint: {fingerprint}"
|
||||
@@ -384,16 +406,18 @@ def launch_tui2(
|
||||
)
|
||||
text = "\n".join(
|
||||
[
|
||||
"TUI v2 (Phase 2/3)",
|
||||
"SeedPass TUI v2",
|
||||
fp_line,
|
||||
"",
|
||||
f"Active filter: {self.filter_kind}",
|
||||
self._selected_summary(),
|
||||
f"Filter : {self.filter_kind}",
|
||||
f"Links : {self.link_relation_filter}",
|
||||
(
|
||||
f"Results: {len(self._all_results)} "
|
||||
f"Results: {len(self._all_results)} | "
|
||||
f"Page: {self._result_page + 1}/{self._total_pages()}"
|
||||
),
|
||||
"",
|
||||
"Navigation:",
|
||||
"Nav",
|
||||
"- / search",
|
||||
"- j jump to id",
|
||||
"- f cycle kind filter",
|
||||
@@ -403,7 +427,7 @@ def launch_tui2(
|
||||
"- r refresh",
|
||||
"- x retry last error",
|
||||
"",
|
||||
"Actions:",
|
||||
"Actions",
|
||||
"- a archive/restore",
|
||||
"- e edit document",
|
||||
"- Ctrl+S save doc",
|
||||
@@ -472,7 +496,14 @@ def launch_tui2(
|
||||
payload = truncate_entry_for_display(
|
||||
entry, self.DETAIL_CONTENT_PREVIEW_LIMIT
|
||||
)
|
||||
return json.dumps(payload, indent=2, sort_keys=True)
|
||||
entry_id = (
|
||||
self._selected_entry_id
|
||||
if self._selected_entry_id is not None
|
||||
else payload.get("id", "?")
|
||||
)
|
||||
kind = payload.get("kind") or payload.get("type") or "unknown"
|
||||
header = f"Entry #{entry_id} [{kind}]"
|
||||
return f"{header}\n{'-' * len(header)}\n{json.dumps(payload, indent=2, sort_keys=True)}"
|
||||
|
||||
def _load_entries(self, query: str = "", *, reset_page: bool = False) -> None:
|
||||
self._last_query = query
|
||||
@@ -592,13 +623,13 @@ def launch_tui2(
|
||||
|
||||
if not links:
|
||||
self.query_one("#link-detail", Static).update(
|
||||
"Links\n\nNo graph links for this entry.\n"
|
||||
f"Links for #{self._selected_entry_id}\n\nNo graph links for this entry.\n"
|
||||
"Use Ctrl+P and run: link-add <target_id> [relation] [note]"
|
||||
)
|
||||
return
|
||||
if not filtered:
|
||||
self.query_one("#link-detail", Static).update(
|
||||
"Links\n\n"
|
||||
f"Links for #{self._selected_entry_id}\n\n"
|
||||
f"Relation filter: {self.link_relation_filter}\n\n"
|
||||
"No links match this relation filter.\n"
|
||||
"Press 'l' to cycle relation filter."
|
||||
@@ -606,7 +637,7 @@ def launch_tui2(
|
||||
return
|
||||
|
||||
lines = [
|
||||
"Links",
|
||||
f"Links for #{self._selected_entry_id}",
|
||||
"",
|
||||
f"Relation filter: {self.link_relation_filter}",
|
||||
(
|
||||
|
||||
Reference in new issue
Block a user