FlexiBoard
The main container component of a board, managing the targets and widgets within it.
FlexiBoard (component)
| Name | Description |
|---|---|
controller Optional Bindable FlexiBoardController | undefined | The controller managing this component's state and behaviour. Bind to it to access the component's imperative API. |
onfirstcreate Optional ((instance: FlexiBoardController) => void) | undefined | Fires when the component's controller is first created. |
children Required Snippet | The child content of the board, which should contain the inner FlexiTarget and FlexiWidget components. |
config Optional FlexiBoardConfiguration<ClassValue> | The configuration object for the board. |
class Optional ClassValue | The class names to apply to the board's root element. |
suspense Optional Snippet<[FlexiBoardSuspenseReason]> | Fallback content shown while the board's server-rendered layout is provisional: a stored layout not yet imported, or an unconfirmed responsive breakpoint guess. It is server-rendered alongside the board and toggled by generated CSS, so it applies from the first paint. It unmounts once the layout is confirmed at hydration. |
<script lang="ts">
import { FlexiBoard, FlexiTarget } from '@flexiboards/svelte';
</script>
<FlexiBoard class="flex gap-4" config={{ widgetDefaults: { draggability: 'full' } }}>
<FlexiTarget key="main">
<!-- widgets go here -->
</FlexiTarget>
</FlexiBoard> FlexiBoardController
You can access the controller via binding to the controller prop or using the onfirstcreate callback.
<script lang="ts">
import { FlexiBoard, type FlexiBoardController } from '@flexiboards/svelte';
let board: FlexiBoardController | undefined = $state();
</script>
<FlexiBoard bind:controller={board}>
<!-- targets go here -->
</FlexiBoard> | Name | Description |
|---|---|
style string | The reactive styling to apply to the board's root element. |
ref HTMLElement | undefined | The reactive DOM reference to the board's root element. |
breakpoint Readonly string | The breakpoint that the board corresponds to, if the board is responsive. |
layoutPending Readonly boolean | Whether the board's rendered layout is provisional: a `loadLayout` (or `loadLayouts`) is configured but hasn't run yet. True throughout a server render and during hydration until the stored layout is imported. Adapters expose it in the markup (`data-flexi-pending="layout"`) so a skeleton or veil can cover the stand-in layout. |
breakpointPending Readonly string | null | The breakpoint this render is assuming without confirmation, or null once it's real. Non-null only for a board under a ResponsiveFlexiBoard during a server render, where the rendered breakpoint is a guess. Adapters emit it as `data-flexi-pending="<key>"` (unless layoutPending takes priority) so a stylesheet can veil the board only when the viewport doesn't match the guess. |
currentWidgetAction Readonly WidgetAction | null | The move or resize the user is in the middle of, or null when idle. Reactive: read it during render to react to a drag starting and ending. |
| Name | Description |
|---|---|
moveWidget (widget: FlexiWidgetController, from: FlexiTargetController | undefined, to: FlexiTargetController) => void | Moves an existing widget from one target to another. |
importLayout (layout: FlexiLayout | FlexiLayoutEnvelope) => void | Imports a widget layout into the board: a bare layout, or the `{ version, layout }` envelope that `exportLayoutEnvelope()` returns. |
exportLayout () => FlexiLayout | Exports the current widget layout of the board. |
exportLayoutEnvelope () => FlexiLayoutEnvelope | Exports the layout with its format version, the shape to persist so a later release can migrate it on import. |
clear () => void | Deletes every widget in every target of this board. Fires `onWidgetDelete` per widget and `onLayoutChange` once. |
FlexiBoardConfiguration
FlexiBoard accepts these options through config. See Configuration reactivity for update behavior and initialization-only options.
For reactivity, give the config prop a reactive source (a proxy).
| Name | Description |
|---|---|
widgetDefaults Optional FlexiWidgetDefaults<ClassValue> | undefined | The default configuration for widgets within this board. |
targetDefaults Optional FlexiTargetDefaults | undefined | The default configuration for targets within this board. |
breakpoint Optional string | undefined | Optional breakpoint override. When this board is inside a ResponsiveFlexiBoard, the breakpoint is automatically inferred from the responsive controller's `currentBreakpoint`. You typically don't need to set this manually. If set outside of a ResponsiveFlexiBoard context, a warning will be logged. |
registry Optional Record<string, FlexiRegistryEntry<ClassValue>> | undefined | A registry of widget types, mapping type keys to shared widget configuration. Widgets reference an entry via their `type`. |
initialLayout Optional FlexiLayout | undefined | A layout to render from instead of the widgets declared in markup, as a plain value keyed by target. Applied during the initial render pass on both the server and the client, so a layout fetched in a server request handler (e.g. from a database) server-renders at its final positions with no pending window. Requires a `registry` to resolve each entry's `type`. Targets without an entry here fall back to their declared widgets. A configured `loadLayout` still runs on the client and overrides this. |
loadLayout Optional (() =>
| FlexiLayout
| FlexiLayoutEnvelope
| FlexiWidgetLayoutEntry[]
| undefined) | undefined | Function to load an initial layout on mount. Called once when the board is ready. Not invoked during server rendering. Use `initialLayout` for layouts the server already has. |
onLayoutChange Optional ((layout: FlexiLayout) => void) | undefined | Callback fired when the board's layout changes (widget moved, resized, added, or removed), whether by the user or through the controller API. Receives the committed layout in a microtask, before drop animations settle. Synchronous changes are batched into one notification. |
onWidgetGrab Optional ((event: FlexiWidgetEvent) => void) | undefined | Called when the user picks a widget up (by pointer or keyboard). |
onWidgetDrop Optional ((event: FlexiWidgetDropEvent) => void) | undefined | Called when a widget the user was moving or resizing lands in a target. Fires after the placement is committed, so the widget's `x`, `y`, `width`, `height` and `target` are already final. |
onWidgetCancel Optional ((event: FlexiWidgetEvent) => void) | undefined | Called when the user cancels a move or resize (Escape, or releasing where nothing accepts the widget); the widget is back where it started. |
onWidgetDelete Optional ((event: FlexiWidgetEvent) => void) | undefined | Called when a widget is deleted, by dropping it on a FlexiDelete or by calling `widget.delete()`. |
onWidgetResize Optional ((event: FlexiWidgetEvent) => void) | undefined | Called when a resize the user was making commits. The widget's `width` and `height` are already final. |
onWidgetEnterTarget Optional ((event: FlexiWidgetEvent) => void) | undefined | Called when a widget being moved is carried over a target, which then shows a drop preview for it. |
onWidgetLeaveTarget Optional ((event: FlexiWidgetEvent) => void) | undefined | Called when a widget being moved leaves the target it was over. |
canDrop Optional ((check: FlexiDropCheck) => boolean) | undefined | Decides whether a widget may be placed at a position. Called while the user hovers (so the drop preview can show a rejection) and again on release. Return false to refuse: the widget stays where it was. Placement rules the grid already enforces (bounds, collisions) run regardless. |
portalDropFlights Optional boolean | undefined | Hosts drop flights in the fixed, viewport-level portal instead of flying them inside the board. Reach for this when drops are released outside the board's box and must fly in across its edge without clipping under the board's overflow lock (e.g. a small hero board mid-page). Leave it off for scrollable boards: a portalled flight escapes the scroll container's clip and paints above surrounding chrome for its duration. Default: |
autoScroll Optional boolean | undefined | Scrolls the board's scrollable ancestors (the page included) while a drag or resize hovers within 48px of their visible edge. Turn it off for boards that sit on a page where a drag should never move the viewport (e.g. a marketing hero). An unexpected page scroll mid-drag reads as the board jumping. Default: |
FlexiTargetDefaults
The default configuration for targets.
| Name | Description |
|---|---|
rowSizing Optional (string | (({ target, grid }: { target: FlexiTargetController; grid: FlexiGrid }) => string)) | The value inside the target's `grid-template-rows` `repeat()` function. |
columnSizing Optional (string | (({ target, grid }: { target: FlexiTargetController; grid: FlexiGrid }) => string)) | The value inside the target's `grid-template-columns` `repeat()` function. |
layout Optional TargetLayout | The layout algorithm and parameters to use for the target grid. |
Interaction callbacks
onWidgetGrab, onWidgetDrop, onWidgetResize, onWidgetCancel, onWidgetDelete, onWidgetEnterTarget and onWidgetLeaveTarget receive these events. canDrop receives a FlexiDropCheck and returns whether the placement is allowed; see Reacting to interactions for when each fires.
FlexiWidgetEvent
| Name | Description |
|---|---|
widget Required FlexiWidgetController | |
target Optional FlexiTargetController | The target the widget is in or over. Undefined when it is over none (e.g. a cancelled adder drag). |
FlexiWidgetDropEvent
| Name | Description |
|---|---|
widget Required FlexiWidgetController | |
sourceTarget Optional FlexiTargetController | The target the widget was picked up from. Undefined for a widget added through an adder. |
target Required FlexiTargetController | The target the widget landed in. |
FlexiDropCheck
| Name | Description |
|---|---|
widget Required FlexiWidgetController | |
target Required FlexiTargetController | |
x Required number | |
y Required number | |
width Required number | |
height Required number |
FlexiWidgetDefaults
The default configuration for widgets.
| Name | Description |
|---|---|
draggability Optional 'none' | 'movable' | 'full' | undefined | The draggability of the widget. Default: |
resizability Optional 'none' | 'horizontal' | 'vertical' | 'both' | undefined | The resizability of the widget. Default: |
snippet Optional (Snippet<[{ widget: FlexiWidgetController }]>) | The render function used for this widget's content. |
component Optional (Component) | The component that is rendered by this widget. |
componentProps Optional Record<string, any> | undefined | The props applied to the component rendered, if it has one. |
className Optional (ClassValue | ((widget: FlexiWidgetController) => ClassValue)) | undefined | The class names to apply to this widget. |
transition Optional FlexiWidgetTransitionConfiguration | undefined | The transition configuration for this widget. |
grabTrigger Optional FlexiWidgetTriggerConfiguration | undefined | The configuration for how pointer events should trigger a grab event on the widget. E.g. a long press. |
resizeTrigger Optional FlexiWidgetTriggerConfiguration | undefined | The configuration for how pointer events should trigger a resize event on the widget. E.g. a long press. |
minWidth Optional number | undefined | The minimum width of the widget in units. Defaults to 1, cannot be less than 1. |
minHeight Optional number | undefined | The minimum height of the widget in units. Defaults to 1, cannot be less than 1. |
maxWidth Optional number | undefined | The maximum width of the widget in units. Defaults to Infinity, cannot be less than 1. |
maxHeight Optional number | undefined | The maximum height of the widget in units. Defaults to Infinity, cannot be less than 1. |
FlexiLayout
The value returned by exportLayout() and accepted by importLayout(), initialLayout, and loadLayout. It maps each target’s key to an array of entries. See Exporting & Importing.
FlexiWidgetLayoutEntry
| Name | Description |
|---|---|
id Optional string | A stable identifier for this widget. Always present in an export: the id you gave the widget, or a generated one. Round-trips through import. |
type Optional string | The registry key that says how to render this widget. Exported even when absent, so no widget's position is lost; on import, entries without a type are skipped, since nothing says how to render them. |
x Required number | The column the widget starts at, zero-indexed. |
y Required number | The row the widget starts at, zero-indexed. |
width Required number | The width of the widget in grid units. |
height Required number | The height of the widget in grid units. |
metadata Optional Record<string, any> | Custom serialisable data attached to the widget, preserved through export and import. |
FlexiRegistryEntry
An entry in the board’s registry, keyed by widget type. Its properties are widget defaults applied to every widget of that type.
| Name | Description |
|---|---|
draggability Optional 'none' | 'movable' | 'full' | undefined | The draggability of the widget. Default: |
resizability Optional 'none' | 'horizontal' | 'vertical' | 'both' | undefined | The resizability of the widget. Default: |
snippet Optional (Snippet<[{ widget: FlexiWidgetController }]>) | The render function used for this widget's content. |
component Optional (Component) | The component that is rendered by this widget. |
componentProps Optional Record<string, any> | undefined | The props applied to the component rendered, if it has one. |
className Optional (ClassValue | ((widget: FlexiWidgetController) => ClassValue)) | undefined | The class names to apply to this widget. |
transition Optional FlexiWidgetTransitionConfiguration | undefined | The transition configuration for this widget. |
grabTrigger Optional FlexiWidgetTriggerConfiguration | undefined | The configuration for how pointer events should trigger a grab event on the widget. E.g. a long press. |
resizeTrigger Optional FlexiWidgetTriggerConfiguration | undefined | The configuration for how pointer events should trigger a resize event on the widget. E.g. a long press. |
minWidth Optional number | undefined | The minimum width of the widget in units. Defaults to 1, cannot be less than 1. |
minHeight Optional number | undefined | The minimum height of the widget in units. Defaults to 1, cannot be less than 1. |
maxWidth Optional number | undefined | The maximum width of the widget in units. Defaults to Infinity, cannot be less than 1. |
maxHeight Optional number | undefined | The maximum height of the widget in units. Defaults to Infinity, cannot be less than 1. |
Accessibility
The board renders as role="application", described by a visually hidden instructions element, and carries aria-busy while a layout is pending. It also hosts the aria-live announcer that reports grabs, resizes, releases, and rejected drops. See Accessibility.