You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte-kit-vice/src/uix/eidos/components/float-panel
dev a32608dadd
feat(eidos): Lote A — float-panel-close composes IconButton
4 months ago
..
README.md feat(uix): FloatPanel — draggable/resizable floating panel 4 months ago
context.ts feat(uix): FloatPanel — draggable/resizable floating panel 4 months ago
float-panel-action.svelte feat(uix): FloatPanel — draggable/resizable floating panel 4 months ago
float-panel-body.svelte feat(uix): FloatPanel — draggable/resizable floating panel 4 months ago
float-panel-close.svelte feat(eidos): Lote A — float-panel-close composes IconButton 4 months ago
float-panel-content.svelte feat(uix): FloatPanel — draggable/resizable floating panel 4 months ago
float-panel-controls.svelte feat(uix): FloatPanel — draggable/resizable floating panel 4 months ago
float-panel-header.svelte feat(uix): FloatPanel — draggable/resizable floating panel 4 months ago
float-panel-resize-grip.svelte feat(uix): FloatPanel — draggable/resizable floating panel 4 months ago
float-panel-resize-handle.svelte feat(uix): FloatPanel — draggable/resizable floating panel 4 months ago
float-panel-stage-trigger.svelte feat(uix): FloatPanel — draggable/resizable floating panel 4 months ago
float-panel-title.svelte feat(uix): FloatPanel — draggable/resizable floating panel 4 months ago
float-panel-trigger.svelte feat(uix): FloatPanel — draggable/resizable floating panel 4 months ago
float-panel.css feat(eidos): Lote A — float-panel-close composes IconButton 4 months ago
float-panel.svelte feat(uix): FloatPanel — draggable/resizable floating panel 4 months ago
index.ts feat(uix): FloatPanel — draggable/resizable floating panel 4 months ago
types.ts feat(eidos): Lote A — float-panel-close composes IconButton 4 months ago

README.md

FloatPanel (eidos)

Visual wrapper over Soma's draggable/resizable panel. Adds only chrome — variant, color (propagated to Content via context) — and the recipe that styles the surface, the header drag-handle, the scrollable body and the resize handles. Drag, resize, stacking, dismissal, focus and positioning are Soma's.

<!-- Zero-config: <FloatPanel.Header> auto-renders a Close (closable, default true). -->
<FloatPanel bind:open anchor={el} resizable variant="surface" color="primary">
  <FloatPanel.Content>
    <FloatPanel.Header>
      <FloatPanel.Title>Inspector</FloatPanel.Title>
    </FloatPanel.Header>
    <FloatPanel.Body>…</FloatPanel.Body>
    <FloatPanel.ResizeHandle edge="se" />
  </FloatPanel.Content>
</FloatPanel>

<!-- Custom header buttons: set closable={false} and compose Controls. -->
<FloatPanel.Header closable={false}>
  <FloatPanel.Title>Properties</FloatPanel.Title>
  <FloatPanel.Controls>
    <FloatPanel.Action aria-label="Delete object" onclick={remove}>🗑</FloatPanel.Action>
    <FloatPanel.Close />
  </FloatPanel.Controls>
</FloatPanel.Header>

Controls is the right-aligned button group (Ark's control); Action is a generic header icon-button sharing Close's chrome, for consumer-wired actions. closable (default true) is the zero-config convenience; set it false when you compose your own Controls.

StageTrigger (min/max/restore) shares the same chrome and goes in Controls too — it takes a stage prop and toggles to it:

<FloatPanel.Controls>
  <FloatPanel.StageTrigger stage="minimized" aria-label="Minimize">–</FloatPanel.StageTrigger>
  <FloatPanel.StageTrigger stage="maximized" aria-label="Maximize">▢</FloatPanel.StageTrigger>
  <FloatPanel.Close />
</FloatPanel.Controls>

minimized collapses to the header, maximized fills bounds (corners squared, drag/resize off), default restores. See the soma README for the stage model.

<FloatPanel.ResizeGrip /> renders a focusable se-corner grip (the diagonal-line mark) inside Content next to the ResizeHandle parts — it's the keyboard resize affordance (Enter to grab, arrows to resize). The header is itself a focusable keyboard move-handle. Full grab-mode model + live-region announcements are in the soma README ("Keyboard move / resize"); the recipe only adds the :focus-visible rings and the data-grabbed styling.

Props (visual)

Prop Type Default
variant 'surface' | 'outline' | 'ghost' (canonical ControlVariant) 'surface'
color ColorRole (8 roles) 'neutral'

All Soma Provider props pass through (open, anchor, position, size, draggable, resizable, minWidth, …). There is intentionally no visual size prop — the panel's size is its width/height geometry.

<FloatPanel.Content> additionally takes motion?: MotionPresetName (default 'scale-fade', 'none' to disable) — the open/close presence preset, mirroring <Popover.Content motion>.

Recipe

Tokens live under the float-panel key in src/uix/eidos/lib/recipes/base.ts (--float-panel-*). The surface uses --color-surface-overlay + --shadow-4 (→ --shadow-5 when data-topmost); the header is the grab handle (cursor grab→grabbing on data-dragging); the body scrolls; resize handles position absolutely per data-resize-edge with edge-appropriate cursors.

Open/close motion comes from the motion system (uix.motion), not hand-rolled CSS: the Content wrapper writes data-animation-style (prop motion, default 'scale-fade') and the generated preset animates scale + opacity keyed on [data-state]; Soma's Presence waits for that animation before unmounting. scale-fade is chosen over the popover/menu default slide-fade precisely because it never animates translate — the panel's drag position is also translate, and the two must not fight. Timing is tuned per-component via --motion-duration-{enter,exit} (normal in / fast out). Reduced-motion degrades to opacity-only automatically (the preset's reduce policy). Position (translate) is never transitioned, so the drag stays 1:1. See eidos-motion.md.

Comparativa externa

Closest reference is Ark UI Floating Panel (draggable+resizable, stages, persist, grid-snap). UIX FloatPanel matches its core (drag, resize, bounds, min/max, stacking/topmost, anchored→free, stages min/max/restore, composable header buttons) and adds the perceptual layer (sound/haptic on grab/ release/resize) that no framework ships; persist/snap are deferred (see soma README Gaps). Radix/Chakra/ MUI have no draggable panel; Mantine FloatingWindow is drag-only; react-rnd matches drag/resize but lacks a11y/theming/perception.

Sources: Ark UI Floating Panel · react-rnd · Mantine FloatingWindow · WAI-ARIA Dialog.

Decisiones

  • variant/color via context (root is virtual, like toggle-group) — set on the root, applied on Content.
  • No visual size — would clash with the panel's geometric size.
  • Surface = overlay ladder + elevation shadow; data-topmost lifts it.

Gaps

Same v2 roadmap as the soma layer (stages, persistence, snap-grid, keyboard move/resize). A docked / fixed mode (answer to Figma's floating-panel-fatigue lesson) is a candidate v2 addition.

Powered by TurnKey Linux.