Floating Panel / Window
Preview: Default
Non-modal, draggable and resizable panel (inspector, chat, notes). Drag the title bar or focus it and use arrow keys (Shift = 32px); drag the corner grip or use Alt+arrow keys on the title bar to resize. Both stay inside the parent when `bounds="parent"`. Minimize collapses to the title bar.
Import
import { FloatingPanel } from '@marbleui/ui'Props
<FloatingPanel>
| Prop | Type | Default | Description |
|---|---|---|---|
| children *required | ReactNode | — | |
| title *required | string | — | |
| bounds | 'none' | 'parent' | 'parent' | |
| className | string | — | |
| defaultPosition | { x: number; y: number; } | { x: 24, y: 24 } | |
| defaultSize | { w: number; h: number; } | { w: 320, h: 260 } | |
| onClose | () => void | — |
Usage notes
Non-modal panel over a canvas or workspace that can be dragged, resized and minimized: an inspector, notes, a chat. For a panel anchored to a trigger use Popover; for an edge panel use Sheet.
<div className="relative h-[32rem]">
<ArtboardView />
{open && <FloatingPanel title="Inspector" onClose={() => setOpen(false)}>…</FloatingPanel>}
</div>
- It’s absolutely positioned, so put it in a
relativecontainer. Withbounds="parent"(default) dragging stays inside that parent;"none"removes the limit. defaultPositionanddefaultSize(minimum 220×140) are starting values only. Position and size aren’t reported back and reset on remount. You decide when it renders;onCloseadds a close button.- Keyboard: Tab to the title bar and use the arrow keys (8 px, 32 px with Shift). Alt+arrow keys resize it, like the bottom-right grip does with a pointer; with
bounds="parent"both moving and resizing stay inside the parent. - It’s a
role="dialog"named bytitle, but opening doesn’t move focus into it and Escape doesn’t close it.
Example source · show· hide
import { useState } from 'react'
import { Button } from '../button'
import { FloatingPanel } from './floating-panel'
function Demo() {
const [open, setOpen] = useState(true)
return (
<div className="relative h-80 w-[34rem] overflow-hidden rounded-xl border border-border bg-[radial-gradient(var(--border)_1px,transparent_1px)] [background-size:16px_16px]">
{!open && <Button className="m-4" variant="outline" onPress={() => setOpen(true)}>Open inspector</Button>}
{open && <FloatingPanel title="Inspector" onClose={() => setOpen(false)}><dl className="grid grid-cols-2 gap-y-2 text-sm"><dt className="text-fg-muted">Width</dt><dd className="text-fg">320px</dd><dt className="text-fg-muted">Radius</dt><dd className="text-fg">12px</dd><dt className="text-fg-muted">Fill</dt><dd className="text-fg">surface</dd></dl><p className="mt-3 text-xs text-fg-muted">Drag the title bar, resize from the corner.</p></FloatingPanel>}
</div>
)
}
export const styles = { Default: Demo }Source: packages/ui/src/floating-panel/floating-panel.tsx
Catalog
- Category
- overlays
- Priority
- Extra
- Primitive
- custom
- React Aria
- useMove