fix(config): fix empty General tab — height collapse and invalid CSS variable

_GeneralTab and _PluginConfigTab inherited from Widget (height: auto), causing
the inner VerticalScroll to get height: 1fr of an auto-height parent, which
collapsed to 0. Fix: inherit from VerticalScroll directly and remove the inner
wrapper. _PluginsTab gets DEFAULT_CSS to fill its TabPane.

Also replace $text-muted (invalid in Textual 8.x) with $foreground 50%.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
curo1305
2026-05-18 22:15:45 +02:00
parent 51029d4a2d
commit 54241a9e4e
+27 -27
View File
@@ -67,20 +67,19 @@ def _pfid(plugin_name: str, key: str) -> str:
# ── Tab widgets ─────────────────────────────────────────────────────────────── # ── Tab widgets ───────────────────────────────────────────────────────────────
class _GeneralTab(Widget): class _GeneralTab(VerticalScroll):
def compose(self) -> ComposeResult: def compose(self) -> ComposeResult:
cfg = load_config() cfg = load_config()
with VerticalScroll(): for f in GENERAL_FIELDS:
for f in GENERAL_FIELDS: current = _get_nested(cfg, f.path)
current = _get_nested(cfg, f.path) with Horizontal(classes="row"):
with Horizontal(classes="row"): yield Label(f.label)
yield Label(f.label) if f.type == "bool":
if f.type == "bool": yield Switch(value=bool(current), id=_fid(f.path))
yield Switch(value=bool(current), id=_fid(f.path)) else:
else: yield Input(value=str(current), id=_fid(f.path))
yield Input(value=str(current), id=_fid(f.path)) with Horizontal(classes="actions"):
with Horizontal(classes="actions"): yield Button("Save", id="save-general", variant="primary")
yield Button("Save", id="save-general", variant="primary")
def on_button_pressed(self, event: Button.Pressed) -> None: def on_button_pressed(self, event: Button.Pressed) -> None:
if event.button.id != "save-general": if event.button.id != "save-general":
@@ -99,6 +98,8 @@ class _GeneralTab(Widget):
class _PluginsTab(Widget): class _PluginsTab(Widget):
DEFAULT_CSS = "_PluginsTab { height: 1fr; width: 1fr; }"
def compose(self) -> ComposeResult: def compose(self) -> ComposeResult:
cfg = load_config() cfg = load_config()
enabled = set(cfg.plugins.enabled) enabled = set(cfg.plugins.enabled)
@@ -150,7 +151,7 @@ class _PluginsTab(Widget):
) )
class _PluginConfigTab(Widget): class _PluginConfigTab(VerticalScroll):
def __init__(self, name: str, plugin: Any) -> None: def __init__(self, name: str, plugin: Any) -> None:
super().__init__() super().__init__()
self._name = name self._name = name
@@ -159,19 +160,18 @@ class _PluginConfigTab(Widget):
def compose(self) -> ComposeResult: def compose(self) -> ComposeResult:
cfg = load_config() cfg = load_config()
settings = cfg.plugin_settings.get(self._name, {}) settings = cfg.plugin_settings.get(self._name, {})
with VerticalScroll(): for f in self._plugin.config_fields():
for f in self._plugin.config_fields(): current = settings.get(f.key, f.default)
current = settings.get(f.key, f.default) with Horizontal(classes="row"):
with Horizontal(classes="row"): yield Label(f.label)
yield Label(f.label) if f.type == "bool":
if f.type == "bool": yield Switch(value=bool(current), id=_pfid(self._name, f.key))
yield Switch(value=bool(current), id=_pfid(self._name, f.key)) else:
else: yield Input(value=str(current), id=_pfid(self._name, f.key))
yield Input(value=str(current), id=_pfid(self._name, f.key)) if f.description:
if f.description: yield Label(f.description, classes="hint")
yield Label(f.description, classes="hint") with Horizontal(classes="actions"):
with Horizontal(classes="actions"): yield Button("Save", id=f"save-{self._name}", variant="primary")
yield Button("Save", id=f"save-{self._name}", variant="primary")
def on_button_pressed(self, event: Button.Pressed) -> None: def on_button_pressed(self, event: Button.Pressed) -> None:
if event.button.id != f"save-{self._name}": if event.button.id != f"save-{self._name}":
@@ -202,7 +202,7 @@ class ConfigApp(App):
Screen { background: $surface; } Screen { background: $surface; }
.row { height: 3; margin: 0 2; } .row { height: 3; margin: 0 2; }
.row Label { width: 26; content-align: left middle; } .row Label { width: 26; content-align: left middle; }
.hint { color: $text-muted; margin: 0 2 1 28; } .hint { color: $foreground 50%; margin: 0 2 1 28; }
.actions { height: 3; align: right middle; margin: 1 2; } .actions { height: 3; align: right middle; margin: 1 2; }
DataTable { height: 1fr; } DataTable { height: 1fr; }
""" """