{
  "$schema": "https://pi-tui.ratstack.sh/schema/pattern.schema.json",
  "aka": [
    "Responsive panel"
  ],
  "animated": false,
  "apis": [
    {
      "name": "Component",
      "url": "https://github.com/earendil-works/pi/blob/v1.0.3/packages/coding-agent/docs/tui.md#understand-the-component-model"
    },
    {
      "name": "truncateToWidth",
      "url": "https://github.com/earendil-works/pi/blob/v1.0.3/packages/coding-agent/docs/tui.md#understand-the-component-model"
    },
    {
      "name": "visibleWidth",
      "url": "https://github.com/earendil-works/pi/blob/v1.0.3/packages/coding-agent/docs/tui.md#understand-the-component-model"
    }
  ],
  "applicability": [
    "Use this when a panel must remain readable in narrow or short terminals."
  ],
  "category": "layout",
  "categoryLabel": "Layout",
  "consequences": [
    "The same panel remains usable across terminal sizes.",
    "Narrow layouts stack or omit visible detail."
  ],
  "family": "structural",
  "familyLabel": "Structural",
  "id": "hinge-panel",
  "implementation": [
    "Use the supplied width rather than a fixed fallback.",
    "Reserve rows for framing and controls."
  ],
  "intent": "Switch between side-by-side and stacked sections as available space changes.",
  "jsonUrl": "https://pi-tui.ratstack.sh/patterns/hinge-panel.json",
  "kind": "component",
  "knownUses": [
    {
      "example": "adaptive-panel",
      "moreRefs": 0,
      "refs": [
        {
          "file": "mcp-setup-panel.ts",
          "lines": "12-37",
          "sha": "85db03d8",
          "url": "https://github.com/nicobailon/pi-mcp-adapter/blob/85db03d87cd0f7461b55eab8d25c10bce473b801/mcp-setup-panel.ts#L12-L37"
        },
        {
          "file": "mcp-setup-panel.ts",
          "lines": "45-84",
          "sha": "85db03d8",
          "url": "https://github.com/nicobailon/pi-mcp-adapter/blob/85db03d87cd0f7461b55eab8d25c10bce473b801/mcp-setup-panel.ts#L45-L84"
        }
      ],
      "repo": "pi-mcp-adapter",
      "repoUrl": "https://github.com/nicobailon/pi-mcp-adapter",
      "title": "Responsive list/detail TUI panels"
    },
    {
      "example": "width-aware-lines",
      "moreRefs": 0,
      "refs": [
        {
          "file": "extensions/pi-autoresearch/index.ts",
          "lines": "645-676",
          "sha": "22bd30b1",
          "url": "https://github.com/nicobailon/pi-autoresearch/blob/22bd30b19482f2be5936031b2c6b149115779f16/extensions/pi-autoresearch/index.ts#L645-L676"
        }
      ],
      "repo": "pi-autoresearch",
      "repoUrl": "https://github.com/nicobailon/pi-autoresearch",
      "title": "Render to the available width and bound vertical output"
    },
    {
      "example": "width-aware-lines",
      "moreRefs": 0,
      "refs": [
        {
          "file": "todo-widget.ts",
          "lines": "5-8",
          "sha": "92b4c9c3",
          "url": "https://github.com/nicobailon/pi-memory-workbench/blob/92b4c9c3ad07841418d77118bf8bd02ad204f7c4/todo-widget.ts#L5-L8"
        }
      ],
      "repo": "pi-memory-workbench",
      "repoUrl": "https://github.com/nicobailon/pi-memory-workbench",
      "title": "Render to the available width and bound vertical output"
    },
    {
      "example": "width-aware-lines",
      "moreRefs": 0,
      "refs": [
        {
          "file": "index.ts",
          "lines": "1108-1150",
          "sha": "859dee67",
          "url": "https://github.com/nicobailon/pi-powerline-footer/blob/859dee671b633fb533b07ceba3e6c1ab1c43360a/index.ts#L1108-L1150"
        }
      ],
      "repo": "pi-powerline-footer",
      "repoUrl": "https://github.com/nicobailon/pi-powerline-footer",
      "title": "Render to the available width and bound vertical output"
    }
  ],
  "linkedFrom": [
    {
      "how": "supplies fitted rows",
      "id": "column-gauge",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/column-gauge.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/column-gauge.md",
      "name": "Column Gauge",
      "url": "https://pi-tui.ratstack.sh/patterns/column-gauge/"
    },
    {
      "how": "chooses the arrangement",
      "id": "section-loom",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/section-loom.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/section-loom.md",
      "name": "Section Loom",
      "url": "https://pi-tui.ratstack.sh/patterns/section-loom/"
    },
    {
      "how": "adapts content within those bounds",
      "id": "elastic-overlay",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/elastic-overlay.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/elastic-overlay.md",
      "name": "Elastic Overlay",
      "url": "https://pi-tui.ratstack.sh/patterns/elastic-overlay/"
    },
    {
      "how": "uses the same width-driven rearrangement",
      "id": "hinge-diff",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/hinge-diff.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/hinge-diff.md",
      "name": "Hinge Diff",
      "url": "https://pi-tui.ratstack.sh/patterns/hinge-diff/"
    }
  ],
  "links": {
    "agentGuide": "https://pi-tui.ratstack.sh/llms.txt",
    "index": "https://pi-tui.ratstack.sh/patterns.md",
    "skill": "https://pi-tui.ratstack.sh/skills/build-pi-tui-component.md"
  },
  "mdUrl": "https://pi-tui.ratstack.sh/patterns/hinge-panel.md",
  "motivation": "The MCP adapter's panel needs list and detail content in terminals too narrow for side-by-side panes.",
  "name": "Hinge Panel",
  "participants": [
    {
      "name": "Component",
      "role": "Renders width-bounded lines and invalidates cached output.",
      "url": "https://github.com/earendil-works/pi/blob/v1.0.3/packages/coding-agent/docs/tui.md#understand-the-component-model"
    },
    {
      "name": "truncateToWidth",
      "role": "Clips text to its allotted columns and can pad the result.",
      "url": "https://github.com/earendil-works/pi/blob/v1.0.3/packages/coding-agent/docs/tui.md#understand-the-component-model"
    },
    {
      "name": "visibleWidth",
      "role": "Measures rendered terminal columns rather than string length.",
      "url": "https://github.com/earendil-works/pi/blob/v1.0.3/packages/coding-agent/docs/tui.md#understand-the-component-model"
    },
    {
      "name": "Layout decision",
      "role": "Chooses side-by-side or stacked content from available space.",
      "url": null
    }
  ],
  "pi": "1.0.3",
  "related": [
    {
      "how": "fits each composed row",
      "id": "column-gauge",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/column-gauge.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/column-gauge.md",
      "name": "Column Gauge",
      "url": "https://pi-tui.ratstack.sh/patterns/column-gauge/"
    }
  ],
  "sampleCode": {
    "code": "// Hinge Panel: switch from paired sections to a stack when their budgets do not fit.\nimport { truncateToWidth, visibleWidth, type Component } from \"@earendil-works/pi-tui\";\nimport type { PatternStory } from \"../../../src/pattern.ts\";\n\nexport const story: PatternStory = {\n  id: \"hinge-panel\", title: \"Hinge Panel\", kind: \"component\",\n  apis: [\"Component\", \"truncateToWidth\", \"visibleWidth\"], rows: 14,\n  states: [\n    { id: \"wide\", label: \"Wide layout where space permits\" },\n    { id: \"narrow\", label: \"Stacked sections\", steps: [{ type: \"action\", name: \"stack\" }] },\n    { id: \"dont-fixed-width\", label: \"Don't: fixed 124-column frame\",\n      steps: [{ type: \"action\", name: \"fixed\" }], expectFail: [\"width\"] },\n  ],\n  setup({ theme, action, tui }) {\n    let mode: \"responsive\" | \"stacked\" | \"fixed\" = \"responsive\";\n    action(\"stack\", () => { mode = \"stacked\"; tui.requestRender(); });\n    action(\"fixed\", () => { mode = \"fixed\"; tui.requestRender(); });\n    const list = [\"TASKS\", \"> Render preview\", \"  Check width\", \"  Publish sample\"];\n    const detail = [\"RENDER PREVIEW\", \"State: ready\", \"File: src/preview.ts\", \"Next: inspect both themes\"];\n    const section = (lines: string[], width: number) => lines.map((line, i) =>\n      theme.fg(i === 0 ? \"accent\" : \"text\", truncateToWidth(line, width, \"…\", true)));\n    const component: Component = {\n      invalidate() {},\n      render(width) {\n        const layoutWidth = mode === \"fixed\" ? 124 : width;\n        const gap = theme.fg(\"border\", \" │ \");\n        const listWidth = Math.max(24, ...list.map(visibleWidth));\n        const detailMinimum = Math.max(...detail.map(visibleWidth));\n        const paired = mode !== \"stacked\" && listWidth + visibleWidth(gap) + detailMinimum <= layoutWidth;\n        const body = paired\n          ? section(list, listWidth).map((line, i) => line + gap +\n              section(detail, layoutWidth - listWidth - visibleWidth(gap))[i]!)\n          : [...section(list, layoutWidth), \"\", ...section(detail, layoutWidth)];\n        // The composer, not each section, owns the physical-row budget.\n        const bodyRows = tui.terminal.rows - 4;\n        return [\n          theme.fg(\"accent\", truncateToWidth(\"Hinge Panel · \" + (paired ? \"paired\" : \"stacked\"), width)),\n          theme.fg(\"border\", \"─\".repeat(layoutWidth)),\n          ...body.slice(0, bodyRows),\n          theme.fg(\"border\", \"─\".repeat(layoutWidth)),\n          theme.fg(\"muted\", truncateToWidth(\n            mode === \"fixed\" ? \"Don't: layout ignores render(width)\" : \"Same tasks · one width and row budget\", width)),\n        ];\n      },\n    };\n    return component;\n  },\n};\n",
    "lang": "ts",
    "path": "stories/patterns/structural/hinge-panel.ts"
  },
  "states": [
    {
      "dont": false,
      "expectFail": [],
      "frames": [
        {
          "alt": "Hinge Panel, Wide layout state, 40 columns, dark theme, 13 rows",
          "animated": false,
          "animation": null,
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 572,
          "rows": 13,
          "still": "https://pi-tui.ratstack.sh/frames/hinge-panel/wide-40-dark.b68e044395bf.webp",
          "theme": "dark",
          "w": 800,
          "width": 40
        },
        {
          "alt": "Hinge Panel, Wide layout state, 40 columns, light theme, 13 rows",
          "animated": false,
          "animation": null,
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 572,
          "rows": 13,
          "still": "https://pi-tui.ratstack.sh/frames/hinge-panel/wide-40-light.b782c003cb3c.webp",
          "theme": "light",
          "w": 800,
          "width": 40
        },
        {
          "alt": "Hinge Panel, Wide layout state, 60 columns, dark theme, 13 rows",
          "animated": false,
          "animation": null,
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 572,
          "rows": 13,
          "still": "https://pi-tui.ratstack.sh/frames/hinge-panel/wide-60-dark.d9f9c86fd909.webp",
          "theme": "dark",
          "w": 1200,
          "width": 60
        },
        {
          "alt": "Hinge Panel, Wide layout state, 60 columns, light theme, 13 rows",
          "animated": false,
          "animation": null,
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 572,
          "rows": 13,
          "still": "https://pi-tui.ratstack.sh/frames/hinge-panel/wide-60-light.27572fbb1cf0.webp",
          "theme": "light",
          "w": 1200,
          "width": 60
        },
        {
          "alt": "Hinge Panel, Wide layout state, 80 columns, dark theme, 13 rows",
          "animated": false,
          "animation": null,
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 572,
          "rows": 13,
          "still": "https://pi-tui.ratstack.sh/frames/hinge-panel/wide-80-dark.61a1e7f1548d.webp",
          "theme": "dark",
          "w": 1600,
          "width": 80
        },
        {
          "alt": "Hinge Panel, Wide layout state, 80 columns, light theme, 13 rows",
          "animated": false,
          "animation": null,
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 572,
          "rows": 13,
          "still": "https://pi-tui.ratstack.sh/frames/hinge-panel/wide-80-light.5818c5e9c4c4.webp",
          "theme": "light",
          "w": 1600,
          "width": 80
        },
        {
          "alt": "Hinge Panel, Wide layout state, 120 columns, dark theme, 13 rows",
          "animated": false,
          "animation": null,
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 572,
          "rows": 13,
          "still": "https://pi-tui.ratstack.sh/frames/hinge-panel/wide-120-dark.15ebc1cf68f2.webp",
          "theme": "dark",
          "w": 2400,
          "width": 120
        },
        {
          "alt": "Hinge Panel, Wide layout state, 120 columns, light theme, 13 rows",
          "animated": false,
          "animation": null,
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 572,
          "rows": 13,
          "still": "https://pi-tui.ratstack.sh/frames/hinge-panel/wide-120-light.98f790763dc6.webp",
          "theme": "light",
          "w": 2400,
          "width": 120
        }
      ],
      "how": "Show list and detail beside each other where their measured widths fit.",
      "id": "wide",
      "label": "Wide layout",
      "problems": []
    },
    {
      "dont": false,
      "expectFail": [],
      "frames": [
        {
          "alt": "Hinge Panel, Narrow layout state, 40 columns, dark theme, 13 rows",
          "animated": false,
          "animation": null,
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 572,
          "rows": 13,
          "still": "https://pi-tui.ratstack.sh/frames/hinge-panel/narrow-40-dark.b68e044395bf.webp",
          "theme": "dark",
          "w": 800,
          "width": 40
        },
        {
          "alt": "Hinge Panel, Narrow layout state, 40 columns, light theme, 13 rows",
          "animated": false,
          "animation": null,
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 572,
          "rows": 13,
          "still": "https://pi-tui.ratstack.sh/frames/hinge-panel/narrow-40-light.b782c003cb3c.webp",
          "theme": "light",
          "w": 800,
          "width": 40
        },
        {
          "alt": "Hinge Panel, Narrow layout state, 60 columns, dark theme, 13 rows",
          "animated": false,
          "animation": null,
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 572,
          "rows": 13,
          "still": "https://pi-tui.ratstack.sh/frames/hinge-panel/narrow-60-dark.8ceb6a16a4b1.webp",
          "theme": "dark",
          "w": 1200,
          "width": 60
        },
        {
          "alt": "Hinge Panel, Narrow layout state, 60 columns, light theme, 13 rows",
          "animated": false,
          "animation": null,
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 572,
          "rows": 13,
          "still": "https://pi-tui.ratstack.sh/frames/hinge-panel/narrow-60-light.0c5a2be49d0b.webp",
          "theme": "light",
          "w": 1200,
          "width": 60
        },
        {
          "alt": "Hinge Panel, Narrow layout state, 80 columns, dark theme, 13 rows",
          "animated": false,
          "animation": null,
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 572,
          "rows": 13,
          "still": "https://pi-tui.ratstack.sh/frames/hinge-panel/narrow-80-dark.a7487c90fa03.webp",
          "theme": "dark",
          "w": 1600,
          "width": 80
        },
        {
          "alt": "Hinge Panel, Narrow layout state, 80 columns, light theme, 13 rows",
          "animated": false,
          "animation": null,
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 572,
          "rows": 13,
          "still": "https://pi-tui.ratstack.sh/frames/hinge-panel/narrow-80-light.613c49e5a51b.webp",
          "theme": "light",
          "w": 1600,
          "width": 80
        },
        {
          "alt": "Hinge Panel, Narrow layout state, 120 columns, dark theme, 13 rows",
          "animated": false,
          "animation": null,
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 572,
          "rows": 13,
          "still": "https://pi-tui.ratstack.sh/frames/hinge-panel/narrow-120-dark.22247b0469f3.webp",
          "theme": "dark",
          "w": 2400,
          "width": 120
        },
        {
          "alt": "Hinge Panel, Narrow layout state, 120 columns, light theme, 13 rows",
          "animated": false,
          "animation": null,
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 572,
          "rows": 13,
          "still": "https://pi-tui.ratstack.sh/frames/hinge-panel/narrow-120-light.a2feff72a359.webp",
          "theme": "light",
          "w": 2400,
          "width": 120
        }
      ],
      "how": "Stack the same sections and cap body rows.",
      "id": "narrow",
      "label": "Narrow layout",
      "problems": []
    },
    {
      "dont": true,
      "expectFail": [
        "width"
      ],
      "frames": [
        {
          "alt": "Hinge Panel, Don't: fixed width state, 40 columns, dark theme, 26 rows",
          "animated": false,
          "animation": null,
          "checks": [
            {
              "evidence": [
                "line 2, column 41: frame 0: visibleWidth=124, limit=40",
                "line 3, column 41: frame 0: visibleWidth=124, limit=40",
                "line 4, column 41: frame 0: visibleWidth=124, limit=40",
                "line 5, column 41: frame 0: visibleWidth=124, limit=40",
                "line 6, column 41: frame 0: visibleWidth=124, limit=40",
                "line 7, column 41: frame 0: visibleWidth=124, limit=40",
                "line 3, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 4, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 5, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 7, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 8, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 9, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 11, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 12, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 13, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 15, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 16, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 17, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 19, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 20, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 21, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 23, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 24, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 25, column 1: frame 0: headless terminal row is wrapped (physical row)"
              ],
              "name": "width",
              "status": "fail",
              "verdict": "expected-fail"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 1144,
          "rows": 26,
          "still": "https://pi-tui.ratstack.sh/frames/hinge-panel/dont-fixed-width-40-dark.94674e53a2a0.webp",
          "theme": "dark",
          "w": 800,
          "width": 40
        },
        {
          "alt": "Hinge Panel, Don't: fixed width state, 40 columns, light theme, 26 rows",
          "animated": false,
          "animation": null,
          "checks": [
            {
              "evidence": [
                "line 2, column 41: frame 0: visibleWidth=124, limit=40",
                "line 3, column 41: frame 0: visibleWidth=124, limit=40",
                "line 4, column 41: frame 0: visibleWidth=124, limit=40",
                "line 5, column 41: frame 0: visibleWidth=124, limit=40",
                "line 6, column 41: frame 0: visibleWidth=124, limit=40",
                "line 7, column 41: frame 0: visibleWidth=124, limit=40",
                "line 3, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 4, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 5, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 7, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 8, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 9, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 11, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 12, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 13, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 15, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 16, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 17, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 19, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 20, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 21, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 23, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 24, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 25, column 1: frame 0: headless terminal row is wrapped (physical row)"
              ],
              "name": "width",
              "status": "fail",
              "verdict": "expected-fail"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 1144,
          "rows": 26,
          "still": "https://pi-tui.ratstack.sh/frames/hinge-panel/dont-fixed-width-40-light.4e99282ccbf3.webp",
          "theme": "light",
          "w": 800,
          "width": 40
        },
        {
          "alt": "Hinge Panel, Don't: fixed width state, 60 columns, dark theme, 26 rows",
          "animated": false,
          "animation": null,
          "checks": [
            {
              "evidence": [
                "line 2, column 61: frame 0: visibleWidth=124, limit=60",
                "line 3, column 61: frame 0: visibleWidth=124, limit=60",
                "line 4, column 61: frame 0: visibleWidth=124, limit=60",
                "line 5, column 61: frame 0: visibleWidth=124, limit=60",
                "line 6, column 61: frame 0: visibleWidth=124, limit=60",
                "line 7, column 61: frame 0: visibleWidth=124, limit=60",
                "line 3, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 4, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 6, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 7, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 9, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 10, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 12, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 13, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 15, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 16, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 18, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 19, column 1: frame 0: headless terminal row is wrapped (physical row)"
              ],
              "name": "width",
              "status": "fail",
              "verdict": "expected-fail"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 1144,
          "rows": 26,
          "still": "https://pi-tui.ratstack.sh/frames/hinge-panel/dont-fixed-width-60-dark.f00b3371bb4d.webp",
          "theme": "dark",
          "w": 1200,
          "width": 60
        },
        {
          "alt": "Hinge Panel, Don't: fixed width state, 60 columns, light theme, 26 rows",
          "animated": false,
          "animation": null,
          "checks": [
            {
              "evidence": [
                "line 2, column 61: frame 0: visibleWidth=124, limit=60",
                "line 3, column 61: frame 0: visibleWidth=124, limit=60",
                "line 4, column 61: frame 0: visibleWidth=124, limit=60",
                "line 5, column 61: frame 0: visibleWidth=124, limit=60",
                "line 6, column 61: frame 0: visibleWidth=124, limit=60",
                "line 7, column 61: frame 0: visibleWidth=124, limit=60",
                "line 3, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 4, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 6, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 7, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 9, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 10, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 12, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 13, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 15, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 16, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 18, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 19, column 1: frame 0: headless terminal row is wrapped (physical row)"
              ],
              "name": "width",
              "status": "fail",
              "verdict": "expected-fail"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 1144,
          "rows": 26,
          "still": "https://pi-tui.ratstack.sh/frames/hinge-panel/dont-fixed-width-60-light.27c304a1c096.webp",
          "theme": "light",
          "w": 1200,
          "width": 60
        },
        {
          "alt": "Hinge Panel, Don't: fixed width state, 80 columns, dark theme, 26 rows",
          "animated": false,
          "animation": null,
          "checks": [
            {
              "evidence": [
                "line 2, column 81: frame 0: visibleWidth=124, limit=80",
                "line 3, column 81: frame 0: visibleWidth=124, limit=80",
                "line 4, column 81: frame 0: visibleWidth=124, limit=80",
                "line 5, column 81: frame 0: visibleWidth=124, limit=80",
                "line 6, column 81: frame 0: visibleWidth=124, limit=80",
                "line 7, column 81: frame 0: visibleWidth=124, limit=80",
                "line 3, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 5, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 7, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 9, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 11, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 13, column 1: frame 0: headless terminal row is wrapped (physical row)"
              ],
              "name": "width",
              "status": "fail",
              "verdict": "expected-fail"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 1144,
          "rows": 26,
          "still": "https://pi-tui.ratstack.sh/frames/hinge-panel/dont-fixed-width-80-dark.a03a2cef4c8e.webp",
          "theme": "dark",
          "w": 1600,
          "width": 80
        },
        {
          "alt": "Hinge Panel, Don't: fixed width state, 80 columns, light theme, 26 rows",
          "animated": false,
          "animation": null,
          "checks": [
            {
              "evidence": [
                "line 2, column 81: frame 0: visibleWidth=124, limit=80",
                "line 3, column 81: frame 0: visibleWidth=124, limit=80",
                "line 4, column 81: frame 0: visibleWidth=124, limit=80",
                "line 5, column 81: frame 0: visibleWidth=124, limit=80",
                "line 6, column 81: frame 0: visibleWidth=124, limit=80",
                "line 7, column 81: frame 0: visibleWidth=124, limit=80",
                "line 3, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 5, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 7, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 9, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 11, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 13, column 1: frame 0: headless terminal row is wrapped (physical row)"
              ],
              "name": "width",
              "status": "fail",
              "verdict": "expected-fail"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 1144,
          "rows": 26,
          "still": "https://pi-tui.ratstack.sh/frames/hinge-panel/dont-fixed-width-80-light.d8224fa1867f.webp",
          "theme": "light",
          "w": 1600,
          "width": 80
        },
        {
          "alt": "Hinge Panel, Don't: fixed width state, 120 columns, dark theme, 26 rows",
          "animated": false,
          "animation": null,
          "checks": [
            {
              "evidence": [
                "line 2, column 121: frame 0: visibleWidth=124, limit=120",
                "line 3, column 121: frame 0: visibleWidth=124, limit=120",
                "line 4, column 121: frame 0: visibleWidth=124, limit=120",
                "line 5, column 121: frame 0: visibleWidth=124, limit=120",
                "line 6, column 121: frame 0: visibleWidth=124, limit=120",
                "line 7, column 121: frame 0: visibleWidth=124, limit=120",
                "line 3, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 5, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 7, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 9, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 11, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 13, column 1: frame 0: headless terminal row is wrapped (physical row)"
              ],
              "name": "width",
              "status": "fail",
              "verdict": "expected-fail"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 1144,
          "rows": 26,
          "still": "https://pi-tui.ratstack.sh/frames/hinge-panel/dont-fixed-width-120-dark.da9a91658e03.webp",
          "theme": "dark",
          "w": 2400,
          "width": 120
        },
        {
          "alt": "Hinge Panel, Don't: fixed width state, 120 columns, light theme, 26 rows",
          "animated": false,
          "animation": null,
          "checks": [
            {
              "evidence": [
                "line 2, column 121: frame 0: visibleWidth=124, limit=120",
                "line 3, column 121: frame 0: visibleWidth=124, limit=120",
                "line 4, column 121: frame 0: visibleWidth=124, limit=120",
                "line 5, column 121: frame 0: visibleWidth=124, limit=120",
                "line 6, column 121: frame 0: visibleWidth=124, limit=120",
                "line 7, column 121: frame 0: visibleWidth=124, limit=120",
                "line 3, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 5, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 7, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 9, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 11, column 1: frame 0: headless terminal row is wrapped (physical row)",
                "line 13, column 1: frame 0: headless terminal row is wrapped (physical row)"
              ],
              "name": "width",
              "status": "fail",
              "verdict": "expected-fail"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 1144,
          "rows": 26,
          "still": "https://pi-tui.ratstack.sh/frames/hinge-panel/dont-fixed-width-120-light.f2ab5e0f4ab4.webp",
          "theme": "light",
          "w": 2400,
          "width": 120
        }
      ],
      "how": "Return a fixed 74-column frame at narrower widths.",
      "id": "dont-fixed-width",
      "label": "Don't: fixed width",
      "problems": []
    }
  ],
  "structure": "width + rows -> layout\n  wide -> list | detail\nnarrow -> list / detail",
  "thumbnails": {
    "dark": {
      "animation": null,
      "src": "https://pi-tui.ratstack.sh/thumbs/hinge-panel/dark.13e441eacfd5.webp"
    },
    "light": {
      "animation": null,
      "src": "https://pi-tui.ratstack.sh/thumbs/hinge-panel/light.a356f6dbe5e7.webp"
    }
  },
  "url": "https://pi-tui.ratstack.sh/patterns/hinge-panel/",
  "widths": [
    40,
    60,
    80,
    120
  ]
}
