diff --git a/src/editor/blocks/testMeta.tsx b/src/editor/blocks/testMeta.tsx index 4f0f009..b4ee6ba 100644 --- a/src/editor/blocks/testMeta.tsx +++ b/src/editor/blocks/testMeta.tsx @@ -187,9 +187,23 @@ export const testMetaBlock = createReactBlockSpec( .map((field, index) => ({ field, index })) .filter(({ field }) => !ID_KEYS.has(field.key.trim().toLowerCase())); + // Compact (reading) view: collapse the rows into a single truncated line + // built only from fields that actually have a value — keys without values + // are an editing-only concern and never appear in the compact summary (the + // expanded rows still show them so they can be filled in). The + // expand/collapse toggle pinned to the far right reveals the full rows. + const summaryText = editableFields + .filter(({ field }) => field.key.trim().length > 0 && field.value.trim().length > 0) + .map(({ field }) => `${field.key}: ${field.value}`) + .join(" · "); + // Nothing readable to summarise (no fields, or only empty values) -> start + // expanded so the block is immediately editable. `expanded` is UI-only + // state — never serialized. + const [expanded, setExpanded] = useState(() => summaryText.length === 0); + return (
{kind.toUpperCase()} {idField?.value && {idField.value}} - + {!expanded && ( + + )} +
+ {expanded && } + +
- {editableFields.length > 0 && ( + {expanded && editableFields.length > 0 && (
{editableFields.map(({ field, index }) => (
diff --git a/src/editor/styles.css b/src/editor/styles.css index 945aa6b..9248ede 100644 --- a/src/editor/styles.css +++ b/src/editor/styles.css @@ -752,8 +752,69 @@ html.dark .bn-teststep__view-toggle--compact svg { margin-left: 8px; } -.bn-testmeta__header .bn-testmeta__add-wrap { +/* Add button + expand/collapse toggle live in a right-pinned action group. */ +.bn-testmeta__header .bn-testmeta__actions { margin-left: auto; + display: inline-flex; + align-items: center; + gap: 2px; + flex-shrink: 0; +} + +/* Compact one-liner: the metadata rendered as truncated read text, click to + expand. Takes the remaining header width and ellipsizes when it overflows. */ +.bn-testmeta__summary { + flex: 1 1 auto; + min-width: 0; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + text-align: left; + font-family: inherit; + font-size: 13px; + color: var(--text-muted); + background: transparent; + border: none; + padding: 0; + cursor: pointer; +} + +.bn-testmeta__summary:hover { + color: var(--text-primary); +} + +.bn-testmeta__summary--empty { + font-style: italic; + opacity: 0.7; +} + +.bn-testmeta__toggle { + width: 24px; + height: 24px; + display: inline-flex; + align-items: center; + justify-content: center; + color: var(--text-muted); + background: transparent; + border: none; + border-radius: 6px; + cursor: pointer; + padding: 0; + flex-shrink: 0; + transition: background-color 120ms ease; +} + +.bn-testmeta__toggle:hover { + background: var(--step-bg-button-hover); + color: var(--text-primary); +} + +.bn-testmeta__toggle svg { + transition: transform 150ms ease; +} + +.bn-testmeta__toggle--expanded svg { + transform: rotate(180deg); } .bn-testmeta__label {