Overlays & Feedback
Floating Panel
A draggable, resizable panel that floats above the page. It ships with the Indoku theme applied.
Always give CloseTrigger and StageTrigger children (icons or text); they render only what you pass.
Import
import { FloatingPanel, useFloatingPanel } from "@indoku/ui"Anatomy
FloatingPanel.Root (or RootProvider)├─ FloatingPanel.Trigger└─ Portal └─ FloatingPanel.Positioner └─ FloatingPanel.Content ├─ FloatingPanel.Header │ ├─ FloatingPanel.DragTrigger › FloatingPanel.Title │ └─ FloatingPanel.Control › StageTrigger / CloseTrigger ├─ FloatingPanel.Body └─ FloatingPanel.ResizeTriggersExamples
Basic
Root, Positioner, Content, Header, Body and ResizeTriggers.
Floating panel
Drag the header to move it, pull an edge to resize.
Controlled open
Drive open and onOpenChange yourself.
Controlled
open = false
Stage triggers
minimized, maximized and default.
Stages
Minimize, maximize or restore the panel.
Store provider
Create the store with useFloatingPanel and pass it to RootProvider.
open: false
Store provider
Driven from outside via useFloatingPanel.
Boundary constraints
Keep the panel inside an element with getBoundaryEl.
The panel cannot leave this box.
Bounded
Try dragging me out.
Anchor positioning
Compute the starting position with getAnchorPosition.
Anchored
Positioned from the trigger rect.
Props
FloatingPanel.Root
| Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | – | Controlled open state. |
defaultOpen | boolean | false | Initial open state. |
onOpenChange | (details: { open: boolean }) => void | – | Called when the panel opens or closes. |
onStageChange | (details: { stage: 'minimized' | 'maximized' | 'default' }) => void | – | Called when the stage changes. |
defaultSize / size | { width: number; height: number } | – | Initial or controlled size. |
minSize / maxSize | { width: number; height: number } | – | Resize limits. |
defaultPosition / position | { x: number; y: number } | – | Initial or controlled position. |
getBoundaryEl | () => HTMLElement | null | – | Element the panel is constrained to. Defaults to the viewport. |
getAnchorPosition | (details: { triggerRect, boundaryRect }) => { x: number; y: number } | – | Computes the position when the panel opens. |
draggable / resizable | boolean | true | Turn dragging or resizing off. |
lockAspectRatio | boolean | false | Keep the aspect ratio while resizing. |
persistRect | boolean | false | Remember size and position between opens. |
FloatingPanel.StageTrigger
| Prop | Type | Default | Description |
|---|---|---|---|
stage* | 'minimized' | 'maximized' | 'default' | – | Stage this trigger switches to. |
useFloatingPanel (store)
| Prop | Type | Default | Description |
|---|---|---|---|
open / setOpen(open) | boolean / fn | – | Read or set the open state. |
minimize() / maximize() / restore() | () => void | – | Change the stage. |
setPosition(pos) / setSize(size) | fn | – | Move or resize programmatically. |
* required. Style props and HTML attributes are accepted as well.
Accessibility
- The title is wired to the content with
aria-labelledby. - Give icon-only triggers an
aria-label.
Notes
- Render
Positionerinside aPortalso the panel is not clipped by overflow containers. - With
getBoundaryEl, the boundary should beposition: relative.
Created by @indokudev