{"name":"floating-panel","title":"Floating Panel","description":"A draggable and resizable floating window with minimize, maximize and close controls.","installCommand":"bunx marko-ui add floating-panel -y","usageTags":"<FloatingPanel>","importSnippet":"import FloatingPanel from \"@/components/ui/floating-panel/floating-panel.marko\";","usageSnippet":"<FloatingPanel defaultPosition={ x: 320, y: 160 } defaultSize={ width: 360, height: 260 }>\n  <@trigger|props|>\n    <Button ...props>Open panel</Button>\n  </@trigger>\n  <@title>Layers</@title>\n  Panel content\n</FloatingPanel>","tags":["FloatingPanel"],"parts":[{"name":"title","description":"Header title content."},{"name":"trigger","param":"Record<string, unknown>","description":"Render-prop trigger: `<@trigger|props|><Button type=\"button\" ...props/></@trigger>`."}],"props":[{"name":"allowOverflow","type":"boolean | undefined","required":false,"default":"true","description":"Whether the panel should be strictly contained within the boundary when dragging"},{"name":"closeOnEscape","type":"boolean | undefined","required":false,"description":"Whether the panel should close when the escape key is pressed"},{"name":"defaultOpen","type":"boolean | undefined","required":false,"default":"false","description":"The initial open state of the panel when rendered.\nUse when you don't need to control the open state of the panel."},{"name":"defaultPosition","type":"Point | undefined","required":false,"description":"The initial position of the panel when rendered.\nUse when you don't need to control the position of the panel."},{"name":"defaultSize","type":"Size | undefined","required":false,"description":"The default size of the panel"},{"name":"dir","type":"'ltr' | 'rtl' | undefined","required":false,"default":"ltr","description":"The document's text/writing direction."},{"name":"disabled","type":"boolean | undefined","required":false,"description":"Whether the panel is disabled"},{"name":"draggable","type":"boolean | undefined","required":false,"default":"true","description":"Whether the panel is draggable"},{"name":"finalFocusEl","type":"(() => HTMLElement | null) | undefined","required":false,"description":"Element to receive focus when the panel is closed.\nBy default, the trigger element is focused."},{"name":"getAnchorPosition","type":"((details: AnchorPositionDetails) => Point) | undefined","required":false,"description":"Function that returns the initial position of the panel when it is opened.\nIf provided, will be used instead of the default position."},{"name":"getBoundaryEl","type":"(() => HTMLElement | null) | undefined","required":false,"description":"The boundary of the panel. Useful for recalculating the boundary rect when\nthe it is resized."},{"name":"getRootNode","type":"(() => ShadowRoot | Document | Node) | undefined","required":false,"description":"A root node to correctly resolve document in custom environments. E.x.: Iframes, Electron."},{"name":"gridSize","type":"number | undefined","required":false,"default":"1","description":"The snap grid for the panel"},{"name":"hideCloseTrigger","type":"boolean","required":false,"description":"Hide the close button."},{"name":"hideStageTriggers","type":"boolean","required":false,"description":"Hide the minimize/maximize/restore stage buttons."},{"name":"ids","type":"ElementIds | undefined","required":false,"description":"The ids of the elements in the floating panel. Useful for composition."},{"name":"initialFocusEl","type":"(() => HTMLElement | null) | undefined","required":false,"description":"Element to receive focus when the panel is opened.\nBy default, the first focusable element in the content is focused."},{"name":"lockAspectRatio","type":"boolean | undefined","required":false,"description":"Whether the panel is locked to its aspect ratio"},{"name":"maxSize","type":"Size | undefined","required":false,"description":"The maximum size of the panel"},{"name":"minSize","type":"Size | undefined","required":false,"description":"The minimum size of the panel"},{"name":"open","type":"boolean | undefined","required":false,"description":"The controlled open state of the panel"},{"name":"persistRect","type":"boolean | undefined","required":false,"description":"Whether the panel size and position should be preserved when it is closed"},{"name":"position","type":"Point | undefined","required":false,"description":"The controlled position of the panel"},{"name":"resizable","type":"boolean | undefined","required":false,"default":"true","description":"Whether the panel is resizable"},{"name":"restoreFocus","type":"boolean | undefined","required":false,"default":"true","description":"Whether to restore focus to the trigger when the panel is closed."},{"name":"size","type":"Size | undefined","required":false,"description":"The size of the panel"},{"name":"strategy","type":"'absolute' | 'fixed' | undefined","required":false,"default":"fixed","description":"The strategy to use for positioning"},{"name":"translations","type":"IntlTranslations | undefined","required":false,"description":"The translations for the floating panel."}],"events":[{"name":"onOpenChange","arg":"OpenChangeDetails","description":"Function called when the panel is opened or closed"},{"name":"onPositionChange","arg":"PositionChangeDetails","description":"Function called when the position of the panel changes via dragging"},{"name":"onPositionChangeEnd","arg":"PositionChangeDetails","description":"Function called when the position of the panel changes via dragging ends"},{"name":"onSizeChange","arg":"SizeChangeDetails","description":"Function called when the size of the panel changes via resizing"},{"name":"onSizeChangeEnd","arg":"SizeChangeDetails","description":"Function called when the size of the panel changes via resizing ends"},{"name":"onStageChange","arg":"StageChangeDetails","description":"Function called when the stage of the panel changes"},{"name":"openChange","arg":"boolean","description":"Sugar for onOpenChange — receives the plain boolean, enables `open:=state`."},{"name":"positionChange","arg":"floatingPanelMachine.Point","description":"Sugar for onPositionChange — receives the plain point."},{"name":"positionEndChange","arg":"floatingPanelMachine.Point","description":"Sugar for onPositionChangeEnd — receives the plain point."},{"name":"sizeChange","arg":"floatingPanelMachine.Size","description":"Sugar for onSizeChange — receives the plain size."},{"name":"sizeEndChange","arg":"floatingPanelMachine.Size","description":"Sugar for onSizeChangeEnd — receives the plain size."},{"name":"stageChange","arg":"floatingPanelMachine.Stage","description":"Sugar for onStageChange — receives the plain stage."}],"keyboard":[],"accessibilityNotes":[],"examples":[{"id":"floating-panel-demo","title":"Basic","source":"import FloatingPanel from \"@marko-ui/shadcn/ui/floating-panel/floating-panel.marko\";\nimport Button from \"@marko-ui/shadcn/ui/button/button.marko\";\n\n<FloatingPanel defaultPosition={ x: 380, y: 200 } defaultSize={ width: 360, height: 260 }>\n  <@trigger|props|>\n    <Button type=\"button\" ...props variant=\"outline\">Open panel</Button>\n  </@trigger>\n  <@title>Layers</@title>\n  <p class=\"text-muted-foreground\">\n    Drag the header to move this panel. Grab any edge or corner to resize\n    it. Use the header buttons to minimize, maximize or close.\n  </p>\n</FloatingPanel>","description":"Drag the header to move the panel. Grab any edge or corner to resize it. Use the header buttons to minimize, maximize or close."},{"id":"floating-panel-not-resizable","title":"Drag only","source":"import FloatingPanel from \"@marko-ui/shadcn/ui/floating-panel/floating-panel.marko\";\nimport Button from \"@marko-ui/shadcn/ui/button/button.marko\";\n\n<FloatingPanel\n  resizable=false\n  defaultPosition={ x: 380, y: 200 }\n  defaultSize={ width: 320, height: 200 }\n>\n  <@trigger|props|>\n    <Button type=\"button\" ...props variant=\"outline\">Open inspector</Button>\n  </@trigger>\n  <@title>Inspector</@title>\n  <div class=\"grid gap-2\">\n    <div class=\"flex items-center justify-between\">\n      <span class=\"text-muted-foreground\">Width</span>\n      <span class=\"font-medium\">320px</span>\n    </div>\n    <div class=\"flex items-center justify-between\">\n      <span class=\"text-muted-foreground\">Resizable</span>\n      <span class=\"font-medium\">No</span>\n    </div>\n  </div>\n</FloatingPanel>","description":"Pass `resizable=false` to disable the resize handles and keep dragging."},{"id":"floating-panel-constrained","title":"Size constraints","source":"import FloatingPanel from \"@marko-ui/shadcn/ui/floating-panel/floating-panel.marko\";\nimport Button from \"@marko-ui/shadcn/ui/button/button.marko\";\n\n<FloatingPanel\n  minSize={ width: 260, height: 180 }\n  maxSize={ width: 560, height: 480 }\n  defaultPosition={ x: 380, y: 200 }\n  defaultSize={ width: 340, height: 240 }\n>\n  <@trigger|props|>\n    <Button type=\"button\" ...props variant=\"secondary\">Open constrained panel</Button>\n  </@trigger>\n  <@title>Constrained</@title>\n  <p class=\"text-muted-foreground\">\n    This panel cannot be resized below 260×180 or above 560×480.\n  </p>\n</FloatingPanel>","description":"Pass `minSize` and `maxSize` to clamp how far the panel can be resized."},{"id":"floating-panel-controlled","title":"Controlled","source":"import FloatingPanel from \"@marko-ui/shadcn/ui/floating-panel/floating-panel.marko\";\nimport Button from \"@marko-ui/shadcn/ui/button/button.marko\";\n\n<let/panelOpen=false>\n<let/panelStage=\"default\">\n\n<div class=\"flex flex-col gap-3\">\n  <div class=\"flex items-center gap-2\">\n    <Button type=\"button\" variant=\"outline\" onClick() { panelOpen = !panelOpen }>\n      ${panelOpen ? \"Close\" : \"Open\"} controlled panel\n    </Button>\n    <span class=\"text-muted-foreground text-sm\">\n      open: ${String(panelOpen)} · stage: ${panelStage}\n    </span>\n  </div>\n  <FloatingPanel\n    open:=panelOpen\n    stageChange=(stage) => (panelStage = stage)\n    defaultPosition={ x: 380, y: 200 }\n    defaultSize={ width: 340, height: 220 }\n  >\n    <@title>Controlled panel</@title>\n    <p class=\"text-muted-foreground\">\n      The button above owns this panel's open state, and the stage is\n      mirrored back into the page.\n    </p>\n  </FloatingPanel>\n</div>","description":"Zag machines are controlled: an `open` prop without a change handler never moves. Pair it with `openChange`, or use Marko's bind shorthand `open:=state`.","essential":true}],"importInstallCommand":"bun add @marko-ui/shadcn marko-zag","requires":["button"],"body":{"description":"Panel body content."},"nativeAttributes":"div"}
