feat(kanban-dashboard): native <details> collapse + skip empty metadata

Two follow-up improvements to Tranquil-Flow's metadata-panel restyle.
Both stay within the parent PR's "tone down the panel" scope.

1. Native <details>/<summary> collapse for verbose metadata.

   The parent PR consciously deferred this ("adding native expand/collapse
   would be the next step but requires UX agreement"). The default they
   asked for is straightforward: collapsed when the rendered JSON exceeds
   300 chars (the threshold where the max-height: 8.5rem cap actually
   starts mattering), expanded otherwise. <details>/<summary> is the right
   primitive — zero JS, browser-handled state, accessible by default
   (keyboard-navigable, screen-reader announces the disclosure state),
   and survives any react-state churn for free.

   The OS-default disclosure marker is suppressed (list-style: none +
   ::-webkit-details-marker hidden) and replaced with a CSS ::before
   chevron that rotates 90deg on the [open] attribute, so the look is
   consistent across Firefox/WebKit/Blink without the double-marker
   that would otherwise appear on the platforms that still render the
   default triangle.

2. Skip rendering when metadata is an empty object.

   `r.metadata && ...` truthy-checks, but `{}` is truthy in JS — so a
   completed task with no actual metadata would render a "Metadata"
   labeled disclosure block containing literal `{}`. Adds an
   Object.keys(r.metadata).length > 0 guard so empty payloads render
   nothing instead of an empty disclosure stub.

Tests: three new static-asset assertions covering the <details> shape,
the empty-object skip, and the suppress-default-marker + animated-chevron
CSS — all in `tests/plugins/test_kanban_dashboard_plugin.py`.
This commit is contained in:
Teknium 2026-05-10 08:30:02 -07:00
parent 0e0ddaac8f
commit a91e5a8759
3 changed files with 77 additions and 6 deletions

View file

@ -1833,3 +1833,49 @@ def test_run_metadata_secondary_styling():
assert "max-height" in meta_decl
assert "overflow: auto" in meta_decl
assert "color: var(--color-muted-foreground)" in meta_decl
def test_run_metadata_uses_native_collapse():
"""Metadata panel uses <details>/<summary> for zero-JS collapse.
Native <details> means the browser handles state no event handlers,
no React-state coupling, accessible by default (keyboard navigable,
screen-reader announces the disclosure state). Default-open state is
decided per-render based on payload length.
"""
js = _dashboard_dist_path("index.js").read_text(encoding="utf-8")
# Element must be <details> / <summary>, not plain <div>s.
assert 'h("details"' in js
assert 'h("summary"' in js
# The open prop is computed from json length (collapsed when verbose).
assert "open: !collapsed" in js or "open:!collapsed" in js
assert "json.length > 300" in js
def test_run_metadata_skips_empty_object():
"""Empty `{}` metadata renders nothing — no useless labeled block.
`r.metadata && {} && ...` would render a "Metadata" labeled block
containing just `{}`, which is visual noise. The render predicate now
also checks Object.keys(r.metadata).length > 0.
"""
js = _dashboard_dist_path("index.js").read_text(encoding="utf-8")
assert "Object.keys(r.metadata).length > 0" in js
def test_run_metadata_disclosure_indicator_styled():
"""Native disclosure marker is hidden + replaced with a CSS-only chevron.
Browsers render an OS-specific arrow next to <summary> by default. For a
consistent look across OSes the hermes dashboard hides that marker and
renders a CSS ::before chevron that rotates on [open]. Pin it so a
future CSS rebuild can't silently lose it (which would put two markers
side-by-side on Firefox/WebKit).
"""
css = _dashboard_dist_path("style.css").read_text(encoding="utf-8")
# Default markers suppressed.
assert "list-style: none" in css
assert "::-webkit-details-marker" in css
# CSS-only chevron present + animates on open state.
assert ".hermes-kanban-run-meta-block[open]" in css
assert "rotate(90deg)" in css