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 ───────────────────────────────────────────────────────────────
class _GeneralTab(Widget):
class _GeneralTab(VerticalScroll):
def compose(self) -> ComposeResult:
cfg = load_config()
with VerticalScroll():
for f in GENERAL_FIELDS:
current = _get_nested(cfg, f.path)
with Horizontal(classes="row"):
yield Label(f.label)
if f.type == "bool":
yield Switch(value=bool(current), id=_fid(f.path))
else:
yield Input(value=str(current), id=_fid(f.path))
with Horizontal(classes="actions"):
yield Button("Save", id="save-general", variant="primary")
for f in GENERAL_FIELDS:
current = _get_nested(cfg, f.path)
with Horizontal(classes="row"):
yield Label(f.label)
if f.type == "bool":
yield Switch(value=bool(current), id=_fid(f.path))
else:
yield Input(value=str(current), id=_fid(f.path))
with Horizontal(classes="actions"):
yield Button("Save", id="save-general", variant="primary")
def on_button_pressed(self, event: Button.Pressed) -> None:
if event.button.id != "save-general":
@@ -99,6 +98,8 @@ class _GeneralTab(Widget):
class _PluginsTab(Widget):
DEFAULT_CSS = "_PluginsTab { height: 1fr; width: 1fr; }"
def compose(self) -> ComposeResult:
cfg = load_config()
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:
super().__init__()
self._name = name
@@ -159,19 +160,18 @@ class _PluginConfigTab(Widget):
def compose(self) -> ComposeResult:
cfg = load_config()
settings = cfg.plugin_settings.get(self._name, {})
with VerticalScroll():
for f in self._plugin.config_fields():
current = settings.get(f.key, f.default)
with Horizontal(classes="row"):
yield Label(f.label)
if f.type == "bool":
yield Switch(value=bool(current), id=_pfid(self._name, f.key))
else:
yield Input(value=str(current), id=_pfid(self._name, f.key))
if f.description:
yield Label(f.description, classes="hint")
with Horizontal(classes="actions"):
yield Button("Save", id=f"save-{self._name}", variant="primary")
for f in self._plugin.config_fields():
current = settings.get(f.key, f.default)
with Horizontal(classes="row"):
yield Label(f.label)
if f.type == "bool":
yield Switch(value=bool(current), id=_pfid(self._name, f.key))
else:
yield Input(value=str(current), id=_pfid(self._name, f.key))
if f.description:
yield Label(f.description, classes="hint")
with Horizontal(classes="actions"):
yield Button("Save", id=f"save-{self._name}", variant="primary")
def on_button_pressed(self, event: Button.Pressed) -> None:
if event.button.id != f"save-{self._name}":
@@ -202,7 +202,7 @@ class ConfigApp(App):
Screen { background: $surface; }
.row { height: 3; margin: 0 2; }
.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; }
DataTable { height: 1fr; }
"""