{
  "$schema": "https://pi-tui.ratstack.sh/schema/pattern.schema.json",
  "aka": [
    "Responsive overlay"
  ],
  "animated": false,
  "apis": [
    {
      "name": "ctx.ui.custom",
      "url": "https://github.com/earendil-works/pi/blob/v1.0.3/packages/coding-agent/docs/tui.md#use-custom-screens-and-overlays"
    },
    {
      "name": "OverlayOptions",
      "url": "https://github.com/earendil-works/pi/blob/v1.0.3/packages/coding-agent/docs/tui.md#use-custom-screens-and-overlays"
    },
    {
      "name": "OverlayHandle.getBounds",
      "url": null
    },
    {
      "name": "Box",
      "url": null
    },
    {
      "name": "DynamicBorder",
      "url": null
    }
  ],
  "applicability": [
    "Use this when a temporary view must remain positioned through resize."
  ],
  "category": "lifecycle",
  "categoryLabel": "Lifecycle and mounting",
  "consequences": [
    "Anchors, margins and percentages adapt a view to the current terminal.",
    "The component must still fit each line inside its supplied width."
  ],
  "family": "structural",
  "familyLabel": "Structural",
  "id": "elastic-overlay",
  "implementation": [
    "Do not cache mount-time coordinates.",
    "Overlay sizing does not excuse lines exceeding render(width)."
  ],
  "intent": "Resolve overlay size and placement from current terminal dimensions.",
  "jsonUrl": "https://pi-tui.ratstack.sh/patterns/elastic-overlay.json",
  "kind": "screen",
  "knownUses": [
    {
      "example": "nico-overlay-options",
      "moreRefs": 0,
      "refs": [
        {
          "file": "packages/tui/src/tui.ts",
          "lines": "71-104",
          "sha": "0c0aac65",
          "url": "https://github.com/earendil-works/pi/blob/0c0aac65990decf95ad5f49886ff5fccf1c09540/packages/tui/src/tui.ts#L71-L104"
        },
        {
          "file": "packages/tui/src/tui.ts",
          "lines": "87-120",
          "sha": "a4ccff38",
          "url": "https://github.com/earendil-works/pi/blob/a4ccff382c465fd789a318a981526b0b883630da/packages/tui/src/tui.ts#L87-L120"
        }
      ],
      "repo": "earendil-works/pi",
      "repoUrl": "https://github.com/earendil-works/pi",
      "title": "Configurable overlay sizing and placement"
    },
    {
      "example": "nico-overlay-centering-resize",
      "moreRefs": 0,
      "refs": [
        {
          "file": "packages/tui/src/tui.ts",
          "lines": "262-280",
          "sha": "c565fa9a",
          "url": "https://github.com/earendil-works/pi/blob/c565fa9af8876b9f3db07d45ad99493fc4eb9d0b/packages/tui/src/tui.ts#L262-L280"
        }
      ],
      "repo": "earendil-works/pi",
      "repoUrl": "https://github.com/earendil-works/pi",
      "title": "Recenter overlays after terminal resize"
    },
    {
      "example": "shell-overlay-lifecycle",
      "moreRefs": 0,
      "refs": [
        {
          "file": "overlay-component.ts",
          "lines": "20-205",
          "sha": "77df9a81",
          "url": "https://github.com/nicobailon/pi-interactive-shell/blob/77df9a8142a2f731635a4c5a01d68feecb5cced4/overlay-component.ts#L20-L205"
        }
      ],
      "repo": "pi-interactive-shell",
      "repoUrl": "https://github.com/nicobailon/pi-interactive-shell",
      "title": "Interactive shell overlay lifecycle and terminal sizing"
    },
    {
      "example": "nico-overlay-options",
      "moreRefs": 0,
      "refs": [],
      "repo": "dot314",
      "repoUrl": "https://github.com/nicobailon/dot314",
      "title": "Configurable overlay sizing and placement"
    },
    {
      "example": "nico-overlay-options",
      "moreRefs": 0,
      "refs": [],
      "repo": "pi-autoresearch",
      "repoUrl": "https://github.com/nicobailon/pi-autoresearch",
      "title": "Configurable overlay sizing and placement"
    },
    {
      "example": "nico-overlay-options",
      "moreRefs": 0,
      "refs": [],
      "repo": "pi-interactive-shell",
      "repoUrl": "https://github.com/nicobailon/pi-interactive-shell",
      "title": "Configurable overlay sizing and placement"
    },
    {
      "example": "nico-overlay-options",
      "moreRefs": 0,
      "refs": [],
      "repo": "pi-intercom",
      "repoUrl": "https://github.com/nicobailon/pi-intercom",
      "title": "Configurable overlay sizing and placement"
    },
    {
      "example": "nico-overlay-options",
      "moreRefs": 0,
      "refs": [],
      "repo": "pi-mcp-adapter",
      "repoUrl": "https://github.com/nicobailon/pi-mcp-adapter",
      "title": "Configurable overlay sizing and placement"
    },
    {
      "example": "nico-overlay-options",
      "moreRefs": 0,
      "refs": [],
      "repo": "pi-memory-workbench",
      "repoUrl": "https://github.com/nicobailon/pi-memory-workbench",
      "title": "Configurable overlay sizing and placement"
    },
    {
      "example": "nico-overlay-options",
      "moreRefs": 0,
      "refs": [],
      "repo": "pi-powerline-footer",
      "repoUrl": "https://github.com/nicobailon/pi-powerline-footer",
      "title": "Configurable overlay sizing and placement"
    },
    {
      "example": "nico-overlay-options",
      "moreRefs": 0,
      "refs": [],
      "repo": "pi-side-chat",
      "repoUrl": "https://github.com/nicobailon/pi-side-chat",
      "title": "Configurable overlay sizing and placement"
    },
    {
      "example": "nico-overlay-options",
      "moreRefs": 0,
      "refs": [],
      "repo": "pi-skill-palette",
      "repoUrl": "https://github.com/nicobailon/pi-skill-palette",
      "title": "Configurable overlay sizing and placement"
    },
    {
      "example": "nico-overlay-options",
      "moreRefs": 0,
      "refs": [],
      "repo": "pi-subagents",
      "repoUrl": "https://github.com/nicobailon/pi-subagents",
      "title": "Configurable overlay sizing and placement"
    },
    {
      "example": "nico-overlay-options",
      "moreRefs": 0,
      "refs": [],
      "repo": "pi-tool-display",
      "repoUrl": "https://github.com/nicobailon/pi-tool-display",
      "title": "Configurable overlay sizing and placement"
    }
  ],
  "linkedFrom": [],
  "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/elastic-overlay.md",
  "motivation": "Nico's overlay positioning and recentering work prevents dialogs retaining stale mount-time coordinates after resize.",
  "name": "Elastic Overlay",
  "participants": [
    {
      "name": "ctx.ui.custom",
      "role": "Mounts one interaction and resolves through done.",
      "url": "https://github.com/earendil-works/pi/blob/v1.0.3/packages/coding-agent/docs/tui.md#use-custom-screens-and-overlays"
    },
    {
      "name": "OverlayOptions",
      "role": "Defines overlay dimensions, placement and focus behavior.",
      "url": "https://github.com/earendil-works/pi/blob/v1.0.3/packages/coding-agent/docs/tui.md#use-custom-screens-and-overlays"
    },
    {
      "name": "Current terminal bounds",
      "role": "Drive placement again after dimension changes.",
      "url": null
    }
  ],
  "pi": "1.0.3",
  "related": [
    {
      "how": "adapts content within those bounds",
      "id": "hinge-panel",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/hinge-panel.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/hinge-panel.md",
      "name": "Hinge Panel",
      "url": "https://pi-tui.ratstack.sh/patterns/hinge-panel/"
    }
  ],
  "sampleCode": {
    "code": "// Elastic Overlay: let Pi resolve bounds again from current terminal dimensions.\nimport { Box, Text, matchesKey, type OverlayHandle, type OverlayOptions } from \"@earendil-works/pi-tui\";\nimport { DynamicBorder } from \"@earendil-works/pi-coding-agent\";\nimport type { PatternStory } from \"../../../src/pattern.ts\";\n\nexport const story: PatternStory = {\n  id: \"elastic-overlay\", title: \"Elastic Overlay\", kind: \"screen\",\n  apis: [\"ctx.ui.custom\", \"OverlayOptions\", \"OverlayHandle.getBounds\", \"Box\", \"DynamicBorder\"],\n  rows: 24, // Full viewport is the point: prove centering before and after resize.\n  states: [\n    { id: \"centered\", label: \"Centered view\", steps: [\n      { type: \"wait\", ms: 0 }, { type: \"action\", name: \"assert-center\" },\n    ] },\n    { id: \"resized\", label: \"Recomputed bounds\", steps: [\n      { type: \"resize\", rows: 18 }, { type: \"action\", name: \"assert-center\" },\n    ] },\n    { id: \"anchored\", label: \"Anchored view\", steps: [{ type: \"action\", name: \"anchor\" }] },\n  ],\n  setup({ ui, theme, action, tui }) {\n    let handle: OverlayHandle | undefined;\n    let complete: (() => void) | undefined;\n    const openPanel = (title: string, options: OverlayOptions) => {\n      void ui.custom<void>((_tui, panelTheme, _keys, done) => {\n        complete = () => done();\n        const panel = new Box(1, 0, line => panelTheme.bg(\"customMessageBg\", line));\n        const border = () => new DynamicBorder(line => panelTheme.fg(\"borderAccent\", line));\n        panel.addChild(border());\n        panel.addChild(new Text(panelTheme.fg(\"accent\", title), 0, 0));\n        panel.addChild(new Text(panelTheme.fg(\"text\", \"Preview ready\\n3 tasks · 2 checks passed\"), 0, 0));\n        panel.addChild(new Text(panelTheme.fg(\"muted\", \"esc close\"), 0, 0));\n        panel.addChild(border());\n        return {\n          render: (width: number) => panel.render(width),\n          invalidate: () => panel.invalidate(),\n          handleInput: (data: string) => { if (matchesKey(data, \"escape\")) done(); },\n        };\n      }, { overlay: true, overlayOptions: options, onHandle: value => { handle = value; } });\n    };\n    ui.setEditorText(\"Review the task preview\");\n    ui.setWidget(\"bounds\", (_tui, widgetTheme) => ({\n      invalidate() {},\n      render(width) { return [widgetTheme.fg(\"muted\", \"Terminal: \" + width + \" × \" + tui.terminal.rows)]; },\n    }));\n    openPanel(\"Task preview\", { width: \"75%\", minWidth: 28, anchor: \"center\", margin: 1 });\n    action(\"assert-center\", () => {\n      tui.renderNow();\n      const bounds = handle?.getBounds();\n      if (!bounds || bounds.col !== Math.floor((tui.terminal.columns - bounds.width) / 2) ||\n          bounds.row !== Math.floor((tui.terminal.rows - bounds.height) / 2)) {\n        throw new Error(\"Overlay bounds mismatch: \" + JSON.stringify(bounds));\n      }\n    });\n    action(\"anchor\", () => {\n      complete?.();\n      openPanel(\"Task preview · docked\", {\n        width: \"55%\", minWidth: 28, anchor: \"top-right\", margin: { top: 1, right: 2, left: 1 },\n        visible: (columns, rows) => columns >= 44 && rows >= 16,\n      });\n      ui.setWidget(\"visibility\", [theme.fg(\"muted\",\n        tui.terminal.columns < 44 ? \"Docked preview hidden below 44 columns\" : \"Docked preview · right margin 2\")]);\n    });\n    return () => { complete?.(); ui.setWidget(\"bounds\", undefined); ui.setWidget(\"visibility\", undefined); };\n  },\n};\n",
    "lang": "ts",
    "path": "stories/patterns/structural/elastic-overlay.ts"
  },
  "states": [
    {
      "dont": false,
      "expectFail": [],
      "frames": [
        {
          "alt": "Elastic Overlay, Centered view state, 40 columns, dark theme, 24 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": 1056,
          "rows": 24,
          "still": "https://pi-tui.ratstack.sh/frames/elastic-overlay/centered-40-dark.15b295554d22.webp",
          "theme": "dark",
          "w": 800,
          "width": 40
        },
        {
          "alt": "Elastic Overlay, Centered view state, 40 columns, light theme, 24 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": 1056,
          "rows": 24,
          "still": "https://pi-tui.ratstack.sh/frames/elastic-overlay/centered-40-light.34fdbd9badca.webp",
          "theme": "light",
          "w": 800,
          "width": 40
        },
        {
          "alt": "Elastic Overlay, Centered view state, 60 columns, dark theme, 24 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": 1056,
          "rows": 24,
          "still": "https://pi-tui.ratstack.sh/frames/elastic-overlay/centered-60-dark.e41026a4e5b5.webp",
          "theme": "dark",
          "w": 1200,
          "width": 60
        },
        {
          "alt": "Elastic Overlay, Centered view state, 60 columns, light theme, 24 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": 1056,
          "rows": 24,
          "still": "https://pi-tui.ratstack.sh/frames/elastic-overlay/centered-60-light.0663d9fa5943.webp",
          "theme": "light",
          "w": 1200,
          "width": 60
        },
        {
          "alt": "Elastic Overlay, Centered view state, 80 columns, dark theme, 24 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": 1056,
          "rows": 24,
          "still": "https://pi-tui.ratstack.sh/frames/elastic-overlay/centered-80-dark.ad90f62d8cf2.webp",
          "theme": "dark",
          "w": 1600,
          "width": 80
        },
        {
          "alt": "Elastic Overlay, Centered view state, 80 columns, light theme, 24 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": 1056,
          "rows": 24,
          "still": "https://pi-tui.ratstack.sh/frames/elastic-overlay/centered-80-light.07e0760b372a.webp",
          "theme": "light",
          "w": 1600,
          "width": 80
        },
        {
          "alt": "Elastic Overlay, Centered view state, 120 columns, dark theme, 24 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": 1056,
          "rows": 24,
          "still": "https://pi-tui.ratstack.sh/frames/elastic-overlay/centered-120-dark.7fbbb32f4b4d.webp",
          "theme": "dark",
          "w": 2400,
          "width": 120
        },
        {
          "alt": "Elastic Overlay, Centered view state, 120 columns, light theme, 24 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": 1056,
          "rows": 24,
          "still": "https://pi-tui.ratstack.sh/frames/elastic-overlay/centered-120-light.d7cd4f34968d.webp",
          "theme": "light",
          "w": 2400,
          "width": 120
        }
      ],
      "how": "Show a synthetic centered dialog above host content.",
      "id": "centered",
      "label": "Centered view",
      "problems": []
    },
    {
      "dont": false,
      "expectFail": [],
      "frames": [
        {
          "alt": "Elastic Overlay, Recomputed bounds state, 40 columns, dark theme, 18 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": 792,
          "rows": 18,
          "still": "https://pi-tui.ratstack.sh/frames/elastic-overlay/resized-40-dark.a3009d3ed0cb.webp",
          "theme": "dark",
          "w": 800,
          "width": 40
        },
        {
          "alt": "Elastic Overlay, Recomputed bounds state, 40 columns, light theme, 18 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": 792,
          "rows": 18,
          "still": "https://pi-tui.ratstack.sh/frames/elastic-overlay/resized-40-light.008e564cdde5.webp",
          "theme": "light",
          "w": 800,
          "width": 40
        },
        {
          "alt": "Elastic Overlay, Recomputed bounds state, 60 columns, dark theme, 18 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": 792,
          "rows": 18,
          "still": "https://pi-tui.ratstack.sh/frames/elastic-overlay/resized-60-dark.bdfd83b64d70.webp",
          "theme": "dark",
          "w": 1200,
          "width": 60
        },
        {
          "alt": "Elastic Overlay, Recomputed bounds state, 60 columns, light theme, 18 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": 792,
          "rows": 18,
          "still": "https://pi-tui.ratstack.sh/frames/elastic-overlay/resized-60-light.52cd0bdc9b61.webp",
          "theme": "light",
          "w": 1200,
          "width": 60
        },
        {
          "alt": "Elastic Overlay, Recomputed bounds state, 80 columns, dark theme, 18 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": 792,
          "rows": 18,
          "still": "https://pi-tui.ratstack.sh/frames/elastic-overlay/resized-80-dark.0873d5136d3e.webp",
          "theme": "dark",
          "w": 1600,
          "width": 80
        },
        {
          "alt": "Elastic Overlay, Recomputed bounds state, 80 columns, light theme, 18 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": 792,
          "rows": 18,
          "still": "https://pi-tui.ratstack.sh/frames/elastic-overlay/resized-80-light.30486c0048cf.webp",
          "theme": "light",
          "w": 1600,
          "width": 80
        },
        {
          "alt": "Elastic Overlay, Recomputed bounds state, 120 columns, dark theme, 18 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": 792,
          "rows": 18,
          "still": "https://pi-tui.ratstack.sh/frames/elastic-overlay/resized-120-dark.4769e988f76c.webp",
          "theme": "dark",
          "w": 2400,
          "width": 120
        },
        {
          "alt": "Elastic Overlay, Recomputed bounds state, 120 columns, light theme, 18 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": 792,
          "rows": 18,
          "still": "https://pi-tui.ratstack.sh/frames/elastic-overlay/resized-120-light.f61f52c8b35a.webp",
          "theme": "light",
          "w": 2400,
          "width": 120
        }
      ],
      "how": "Resize the terminal and keep its bounds correctly centered.",
      "id": "resized",
      "label": "Recomputed bounds",
      "problems": []
    },
    {
      "dont": false,
      "expectFail": [],
      "frames": [
        {
          "alt": "Elastic Overlay, Anchored view state, 40 columns, dark theme, 18 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": 792,
          "rows": 18,
          "still": "https://pi-tui.ratstack.sh/frames/elastic-overlay/anchored-40-dark.eb03a6f90490.webp",
          "theme": "dark",
          "w": 800,
          "width": 40
        },
        {
          "alt": "Elastic Overlay, Anchored view state, 40 columns, light theme, 18 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": 792,
          "rows": 18,
          "still": "https://pi-tui.ratstack.sh/frames/elastic-overlay/anchored-40-light.2132277eb70a.webp",
          "theme": "light",
          "w": 800,
          "width": 40
        },
        {
          "alt": "Elastic Overlay, Anchored view state, 60 columns, dark theme, 18 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": 792,
          "rows": 18,
          "still": "https://pi-tui.ratstack.sh/frames/elastic-overlay/anchored-60-dark.9a54cf9f446a.webp",
          "theme": "dark",
          "w": 1200,
          "width": 60
        },
        {
          "alt": "Elastic Overlay, Anchored view state, 60 columns, light theme, 18 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": 792,
          "rows": 18,
          "still": "https://pi-tui.ratstack.sh/frames/elastic-overlay/anchored-60-light.cd11f1362895.webp",
          "theme": "light",
          "w": 1200,
          "width": 60
        },
        {
          "alt": "Elastic Overlay, Anchored view state, 80 columns, dark theme, 18 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": 792,
          "rows": 18,
          "still": "https://pi-tui.ratstack.sh/frames/elastic-overlay/anchored-80-dark.476b5cbc111f.webp",
          "theme": "dark",
          "w": 1600,
          "width": 80
        },
        {
          "alt": "Elastic Overlay, Anchored view state, 80 columns, light theme, 18 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": 792,
          "rows": 18,
          "still": "https://pi-tui.ratstack.sh/frames/elastic-overlay/anchored-80-light.d54dc43c56e4.webp",
          "theme": "light",
          "w": 1600,
          "width": 80
        },
        {
          "alt": "Elastic Overlay, Anchored view state, 120 columns, dark theme, 18 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": 792,
          "rows": 18,
          "still": "https://pi-tui.ratstack.sh/frames/elastic-overlay/anchored-120-dark.ee1d853cd101.webp",
          "theme": "dark",
          "w": 2400,
          "width": 120
        },
        {
          "alt": "Elastic Overlay, Anchored view state, 120 columns, light theme, 18 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": 792,
          "rows": 18,
          "still": "https://pi-tui.ratstack.sh/frames/elastic-overlay/anchored-120-light.83c7d36d25ec.webp",
          "theme": "light",
          "w": 2400,
          "width": 120
        }
      ],
      "how": "Show an edge-anchored panel with margins and responsive visibility.",
      "id": "anchored",
      "label": "Anchored view",
      "problems": []
    }
  ],
  "structure": "terminal size + options -> bounds\nbounds + component -> overlay",
  "thumbnails": {
    "dark": {
      "animation": null,
      "src": "https://pi-tui.ratstack.sh/thumbs/elastic-overlay/dark.65b0e42a0c60.webp"
    },
    "light": {
      "animation": null,
      "src": "https://pi-tui.ratstack.sh/thumbs/elastic-overlay/light.b820352c49d1.webp"
    }
  },
  "url": "https://pi-tui.ratstack.sh/patterns/elastic-overlay/",
  "widths": [
    40,
    60,
    80,
    120
  ]
}
