{
  "name": "SplitPane",
  "source": "src/components/SplitPane.tsx",
  "propsType": "SplitPaneProps",
  "description": "SplitPane — two panes and a divider between them that a person moves.\n\nTHE WINDOW-SPLITTER PATTERN\n\nThe divider is a focusable `separator` whose value is the first pane's\nshare, 0 to 100, bounded by `minSize` and `maxSize`, and it controls that\npane (`aria-controls`). The arrow keys along its axis move it, Shift for\na bigger step; Home and End go to the bounds; a double-click, or Enter,\nputs it back where it started. The same handle Table's column resize is.\n\nPERCENT, NOT PIXELS\n\nThe share survives the window being resized, and the value a screen\nreader announces means something without knowing the width.\n\nONE COLUMN ON A PHONE\n\nSide by side, two panes on a phone are two unreadable strips. At the\n`collapse` breakpoint they stack and the divider is removed — from the\ntab order too, since `display: none` takes it out.",
  "import": "import { SplitPane } from 'ionbase-ui';",
  "status": "stable",
  "summary": "Two panes and a divider between them that a person moves — by dragging, or with the arrow keys — for two views read across, where which one needs the room depends on the reader.",
  "useWhen": [
    "two views of one thing are read across and both have long lines — a request and its response, a source and its preview, a log and its detail",
    "the right split depends on the content and on the reader, so it is theirs to set"
  ],
  "useInstead": [
    {
      "when": "detail that opens beside a list when something is picked, and closes",
      "use": "SidePanel",
      "why": "a SidePanel, in SidePanelLayout, is a region that comes and goes, with a title, a close button and a Drawer on a phone; a split is two panes that are always there"
    },
    {
      "when": "columns that are simply laid out — a main column and an aside",
      "use": "Grid",
      "why": "a layout nobody needs to change should not offer a control that changes it; every divider is one more tab stop"
    },
    {
      "when": "one table column is too narrow",
      "use": "TableCell",
      "why": "its `resize`, from useTableColumns, is the column's own handle in its header; a split around a table resizes the table, not the column"
    }
  ],
  "composition": {
    "order": [
      "SplitPane"
    ],
    "note": "`start` and `end` are the panes; `label` names the divider by what it resizes — \"Resize the API request\". The value is the first pane's share in percent: `defaultSize`, or `size` with `onSizeChange` to keep it (in the browser, say). Bound it with `minSize` and `maxSize`. Side by side it stacks at `collapse` (mobile by default); a vertical split needs a height from its container.",
    "example": "<SplitPane label=\"Resize the API request\" defaultSize={55} minSize={30} maxSize={70} collapse=\"tablet\" start={<CodeSnippet type=\"multi\" …>{request}</CodeSnippet>} end={<CodeSnippet type=\"multi\" …>{response}</CodeSnippet>} />"
  },
  "slots": {
    "start": {
      "accepts": "any",
      "note": "the first pane — start side, or top — whose share the divider sets; it scrolls on its own"
    },
    "end": {
      "accepts": "any",
      "note": "the second pane, taking the rest; it scrolls on its own"
    }
  },
  "a11y": {
    "requires": [
      "a `label` naming what the divider resizes: it is the control's only name"
    ],
    "guarantees": [
      "the divider is a focusable `separator` (the ARIA window-splitter pattern) with the first pane's share as `aria-valuenow`, `minSize` and `maxSize` as its bounds, and `aria-controls` pointing at the first pane",
      "the arrow keys along its axis move it 2%, with Shift 10%; Home and End go to the bounds; Enter and a double-click put it back at `defaultSize`",
      "the arrow moves the divider the way it points: side by side in a right-to-left page the first pane is on the right, so → shrinks it",
      "a drag moves it, with the pointer held, and selects no text on the way",
      "each pane scrolls on its own, and its content cannot widen it",
      "at the collapse breakpoint the panes stack and the divider is removed, from the tab order too",
      "a grip at the divider's middle marks it movable at 3:1; focused or dragged, the line and the grip turn to border/focus, and in forced colours to Highlight"
    ],
    "notes": [
      "The share is percent, not pixels: it survives a window resize, and the value announced means something without knowing the width.",
      "Nothing is kept between visits; keep `size` yourself, from `onSizeChange`, when it should be."
    ]
  },
  "antiPatterns": [
    {
      "dont": "a SplitPane for a main column and an aside nobody needs to resize",
      "do": "<Grid columns={[2, 1]} collapse=\"tablet\">",
      "why": "a divider is a control and a tab stop; offered where nothing is gained, it is one more thing to tab past"
    },
    {
      "dont": "a SplitPane whose end pane is a detail that opens and closes",
      "do": "SidePanelLayout with a SidePanel",
      "why": "the panel's title, close button and Drawer fallback are SidePanel's; an empty pane behind a divider is a layout with a hole in it"
    },
    {
      "dont": "`collapse=\"never\"` for a side-by-side split",
      "do": "the default, `mobile`",
      "why": "two panes side by side on a phone are two strips too narrow to read"
    }
  ],
  "stylesheet": "src/styles/split-pane.css",
  "tokens": [
    "--border-default",
    "--border-focus",
    "--border-strong",
    "--border-width-default",
    "--border-width-thick",
    "--icon-secondary",
    "--ion-duration-base",
    "--ion-ease-out",
    "--ion-split-pane-size",
    "--radius-full",
    "--ring-focus",
    "--spacing-12",
    "--spacing-16",
    "--spacing-24",
    "--spacing-4",
    "--spacing-8"
  ],
  "props": {
    "start": {
      "type": "React.ReactNode",
      "required": true,
      "origin": "own",
      "description": "The first pane: the start side, or the top. Its size is the value."
    },
    "end": {
      "type": "React.ReactNode",
      "required": true,
      "origin": "own",
      "description": "The second pane, which takes the rest."
    },
    "orientation": {
      "type": "SplitPaneOrientation | undefined",
      "required": false,
      "origin": "own",
      "description": "`horizontal` puts the panes side by side with a vertical divider;\n`vertical` stacks them with a horizontal one. A vertical split needs a\nheight from its container.",
      "values": [
        "vertical",
        "horizontal"
      ]
    },
    "label": {
      "type": "string",
      "required": true,
      "origin": "own",
      "description": "The divider's name, and so the resize control's: \"Resize the run list\".\nIt names what moving it changes — the first pane."
    },
    "defaultSize": {
      "type": "number | undefined",
      "required": false,
      "origin": "own",
      "description": "The first pane's share, in percent, for an uncontrolled split. Default 50."
    },
    "size": {
      "type": "number | undefined",
      "required": false,
      "origin": "own",
      "description": "The first pane's share, in percent, controlled. Pair with `onSizeChange`."
    },
    "onSizeChange": {
      "type": "((size: number) => void) | undefined",
      "required": false,
      "origin": "own",
      "description": "Fires with the new share, in percent, rounded to a whole number."
    },
    "minSize": {
      "type": "number | undefined",
      "required": false,
      "origin": "own",
      "description": "The smallest share the first pane can be given. Default 20."
    },
    "maxSize": {
      "type": "number | undefined",
      "required": false,
      "origin": "own",
      "description": "The largest share. Default 80."
    },
    "collapse": {
      "type": "SplitPaneCollapse | undefined",
      "required": false,
      "origin": "own",
      "description": "The breakpoint at and below which a side-by-side split stacks, and the\ndivider goes: `mobile` (767px) by default, `tablet` (1023px), or\n`never`. Grid's breakpoints. A vertical split never collapses.",
      "values": [
        "tablet",
        "mobile",
        "never"
      ]
    },
    "className": {
      "type": "string | undefined",
      "required": false,
      "origin": "own"
    },
    "style": {
      "type": "React.CSSProperties | undefined",
      "required": false,
      "origin": "own"
    }
  },
  "propCounts": {
    "own": 12,
    "aria": 0,
    "dom": 0,
    "other": 0
  }
}
