{"name":"resizable","title":"Resizable","description":"Accessible resizable panel groups and layouts with keyboard support.","installCommand":"bunx marko-ui add resizable -y","usageTags":"<Resizable>","importSnippet":"import Resizable from \"@/components/ui/resizable/resizable.marko\";","usageSnippet":"<Resizable|panel| panels=[{ id: \"one\", defaultSize: 50 }, { id: \"two\", defaultSize: 50 }]>\n  ${panel.id}\n</Resizable>","tags":["Resizable"],"parts":[],"props":[{"name":"panels","type":"ResizablePanel[]","required":true},{"name":"class","type":"string","required":false},{"name":"orientation","type":"'horizontal' | 'vertical'","required":false}],"events":[{"name":"collapseChange","arg":"string, size: number"},{"name":"expandChange","arg":"string, size: number"},{"name":"onCollapse","arg":"splitterMachine.ExpandCollapseDetails"},{"name":"onExpand","arg":"splitterMachine.ExpandCollapseDetails"},{"name":"onResize","arg":"splitterMachine.ResizeDetails"},{"name":"onResizeEnd","arg":"splitterMachine.ResizeEndDetails"},{"name":"onResizeStart"},{"name":"resizeChange","arg":"number[]"},{"name":"resizeEndChange","arg":"number[]"}],"keyboard":[{"keys":"Tab / Shift+Tab","description":"Moves focus to the next or previous resize handle."},{"keys":"ArrowLeft / ArrowRight","description":"Resizes a horizontal-orientation handle by 1% per press, or 10% while holding Shift."},{"keys":"ArrowUp / ArrowDown","description":"Resizes a vertical-orientation handle by 1% per press, or 10% while holding Shift."},{"keys":"Home","description":"Moves the handle to its minimum allowed position."},{"keys":"End","description":"Moves the handle to its maximum allowed position."},{"keys":"Enter","description":"Collapses or expands the adjacent panel."},{"keys":"F6","description":"Cycles focus to the next resize handle (Shift+F6 cycles to the previous one)."}],"accessibilityNotes":["Each resize handle is a focusable, keyboard-operable separator (`role=\"separator\"`) — no pointer is required to resize panels.","Real deviation from upstream: `@zag-js/splitter` accepts a `dir` prop that flips arrow-key semantics for RTL, but this component's `<zag>` doesn't forward it (only `orientation`, `panels`, and callback props are wired to the machine). A `dir=\"rtl\"` attribute on `Resizable` still mirrors the layout visually (it lands on the root `<div>` as a plain HTML attribute), but arrow-key direction is not RTL-aware."],"examples":[{"id":"resizable-demo","title":"Default","source":"import Resizable from \"@marko-ui/shadcn/ui/resizable/resizable.marko\";\n\nstatic const OUTER_PANELS = [\n  { id: \"one\", defaultSize: 50 },\n  { id: \"two\", defaultSize: 50 },\n];\n\nstatic const INNER_PANELS = [\n  { id: \"two-a\", defaultSize: 25 },\n  { id: \"two-b\", defaultSize: 75 },\n];\n\n<Resizable|panel| panels=OUTER_PANELS class=\"max-w-md rounded-lg border md:min-w-[450px]\">\n  <if=panel.id === \"one\">\n    <div class=\"flex h-[200px] items-center justify-center p-6\">\n      <span class=\"font-semibold\">One</span>\n    </div>\n  </if>\n  <else>\n    <Resizable|innerPanel| panels=INNER_PANELS orientation=\"vertical\">\n      <div class=\"flex h-full items-center justify-center p-6\">\n        <span class=\"font-semibold\">${innerPanel.id === \"two-a\" ? \"Two\" : \"Three\"}</span>\n      </div>\n    </Resizable>\n  </else>\n</Resizable>","description":"Nest a `Resizable` inside another panel's content to build a layout of more than two regions."},{"id":"resizable-vertical","title":"Vertical","source":"import Resizable from \"@marko-ui/shadcn/ui/resizable/resizable.marko\";\n\nstatic const PANELS = [\n  { id: \"header\", defaultSize: 25 },\n  { id: \"content\", defaultSize: 75 },\n];\n\n<Resizable|panel| panels=PANELS orientation=\"vertical\" class=\"min-h-[200px] max-w-md rounded-lg border md:min-w-[450px]\">\n  <div class=\"flex h-full items-center justify-center p-6\">\n    <span class=\"font-semibold\">${panel.id === \"header\" ? \"Header\" : \"Content\"}</span>\n  </div>\n</Resizable>","description":"Set `orientation=\"vertical\"` to stack panels top to bottom."},{"id":"resizable-handle","title":"Min and max sizes","source":"import Resizable from \"@marko-ui/shadcn/ui/resizable/resizable.marko\";\n\nstatic const PANELS = [\n  { id: \"sidebar\", defaultSize: 25, minSize: 15 },\n  { id: \"content\", defaultSize: 75, minSize: 30 },\n];\n\n<Resizable|panel| panels=PANELS class=\"min-h-[200px] max-w-md rounded-lg border md:min-w-[450px]\">\n  <div class=\"flex h-full items-center justify-center p-6\">\n    <span class=\"font-semibold\">${panel.id === \"sidebar\" ? \"Sidebar\" : \"Content\"}</span>\n  </div>\n</Resizable>","description":"Pass `minSize` and `maxSize` on a panel to constrain how far it can be dragged."},{"id":"resizable-rtl","title":"RTL","source":"import Resizable from \"@marko-ui/shadcn/ui/resizable/resizable.marko\";\n\nstatic const OUTER_PANELS = [\n  { id: \"one\", defaultSize: 50 },\n  { id: \"two\", defaultSize: 50 },\n];\n\nstatic const INNER_PANELS = [\n  { id: \"two-a\", defaultSize: 25 },\n  { id: \"two-b\", defaultSize: 75 },\n];\n\n<Resizable|panel| panels=OUTER_PANELS class=\"max-w-sm rounded-lg border\" dir=\"rtl\">\n  <if=panel.id === \"one\">\n    <div class=\"flex h-[200px] items-center justify-center p-6\">\n      <span class=\"font-semibold\">واحد</span>\n    </div>\n  </if>\n  <else>\n    <Resizable|innerPanel| panels=INNER_PANELS orientation=\"vertical\" dir=\"rtl\">\n      <div class=\"flex h-full items-center justify-center p-6\">\n        <span class=\"font-semibold\">${innerPanel.id === \"two-a\" ? \"اثنان\" : \"ثلاثة\"}</span>\n      </div>\n    </Resizable>\n  </else>\n</Resizable>","description":"Set `dir=\"rtl\"` on the `Resizable` (matching the surrounding document direction) to mirror the layout."},{"id":"resizable-controlled","title":"Controlled","source":"import Resizable from \"@marko-ui/shadcn/ui/resizable/resizable.marko\";\n\nstatic const PANELS = [\n  { id: \"one\", defaultSize: 50 },\n  { id: \"two\", defaultSize: 50 },\n];\n\n<let/sizes=[50, 50]/>\n\n<div class=\"flex flex-col gap-3\">\n  <Resizable|panel|\n    panels=PANELS\n    class=\"min-h-[200px] max-w-md rounded-lg border md:min-w-[450px]\"\n    resizeChange=(newSizes) => { sizes = newSizes; }\n  >\n    <div class=\"flex h-full items-center justify-center p-6\">\n      <span class=\"font-semibold\">${panel.id === \"one\" ? \"One\" : \"Two\"}</span>\n    </div>\n  </Resizable>\n  <span class=\"text-sm text-muted-foreground\">\n    sizes: ${sizes.map((size) => `${Math.round(size)}%`).join(\" / \")}\n  </span>\n</div>","description":"Listen for `resizeChange` to read the live size (in percent) of every panel as the handle is dragged."}],"importInstallCommand":"bun add @marko-ui/shadcn marko-zag","body":{"param":"ResizablePanel, number"},"nativeAttributes":"div","itemTypes":[{"prop":"panels","typeName":"ResizablePanel","fields":[{"name":"id","type":"string","required":true},{"name":"defaultSize","type":"number | string","required":false},{"name":"minSize","type":"number | string","required":false},{"name":"maxSize","type":"number | string","required":false}]}],"composition":"`Resizable` is a single component, not a three-part composition. Where upstream composes `ResizablePanelGroup` / `ResizablePanel` / `ResizableHandle` as separate importable components, this port folds all three into one `Resizable` tag:\n\n```text\nResizable\n├── (panel — one per entry in the `panels` prop, rendered via the tag's own body)\n└── (resize handle — generated automatically between each adjacent pair of panels)\n```\n\nThere is no separate `ResizablePanel` or `ResizableHandle` tag to import: pass an ordered `panels` array (`{ id, defaultSize?, minSize?, maxSize? }`) and render each panel's content through the tag's own body, taking the panel data and its index as default-body tag parameters (`<Resizable|panel, index|>`). A resize handle is inserted between every pair of adjacent panels for you — there is no `withHandle` toggle; the drag-handle icon is always shown."}
