# Configuration

> Learn how to configure Flexiboards components.

Source: https://www.flexiboards.dev/docs/configuration

Framework: Svelte

Boards and targets take a `config` prop; widgets take their configuration as props. Configuration cascades from board to target to widget, and it is reactive, so a board can be locked with one state change:

Example: Lockable board

```svelte
<script lang="ts">
	import {
		FlexiBoard,
		FlexiTarget,
		FlexiWidget,
		type FlexiBoardConfiguration
	} from '@flexiboards/svelte';

	let editing = $state(true);

	const boardConfig: FlexiBoardConfiguration = $state({
		targetDefaults: { layout: { type: 'flow', flowAxis: 'row', placementStrategy: 'append' } },
		widgetDefaults: {
			draggability: 'full',
			className: (widget) => [
				'rounded-lg bg-primary px-4 py-2 text-primary-foreground',
				widget.isShadow && 'opacity-50'
			]
		}
	});

	$effect(() => {
		boardConfig.widgetDefaults!.draggability = editing ? 'full' : 'none';
	});
</script>

<div class="flex w-72 items-center gap-2 rounded-t-xl border border-b-0 px-4 py-3 lg:w-96">
	<button class="rounded-md border px-3 py-1 text-sm" onclick={() => (editing = !editing)}>
		{editing ? 'Lock' : 'Unlock'}
	</button>
	<span class="text-muted-foreground text-sm"
		>{editing ? 'Widgets are draggable' : 'Widgets are locked'}</span
	>
</div>

<FlexiBoard class="w-72 rounded-b-xl border p-6 lg:w-96" config={boardConfig}>
	<FlexiTarget class="gap-3">
		<FlexiWidget>One</FlexiWidget>
		<FlexiWidget>Two</FlexiWidget>
		<FlexiWidget>Three</FlexiWidget>
	</FlexiTarget>
</FlexiBoard>
```

Every widget picks up `draggability` from the board's `widgetDefaults`, so flipping one value locks them all. The rest of this page explains the cascade and which properties react to changes.

## Cascading configuration

On components that support children, the `config` prop carries a defaults property. Use it to set a default configuration for those children.

The following excerpts replace the opening `FlexiBoard` element in an existing board. Keep your targets and widgets inside it:

```svelte
<FlexiBoard
	config={{
		targetDefaults: {
			layout: {
				type: 'flow',
				flowAxis: 'row',
				placementStrategy: 'append'
			}
		}
	}}
>
	<!-- Existing targets and widgets. -->
</FlexiBoard>
```

A target that doesn't specify a layout now uses the one in `targetDefaults`.

The configuration cascades: following the hierarchy of FlexiBoard -> FlexiTarget -> FlexiWidget, the configuration applied is the nearest one that was specified.

For example, say the board's configuration has `widgetDefaults.className = 'a'` and the target's has `widgetDefaults.className = 'b'`.

- If we specify a class on a widget, `c`, then the widget will have class `c` only.
- If we don't specify a class on the widget, then the widget will have class `b`.
- If we don't specify a class on the widget, and we didn't specify `widgetDefaults.className = 'b'` on our widget's parent target, then the widget will have class `a`.

The widget's own configuration wins, and defaults fill in the properties it doesn't specify.

## Reactivity

Flexiboards' configuration system is reactive. If the configuration object you pass to the `config` prop changes, the board picks up the change for a number of the properties on that object.

For example, you can use this system to quickly change whether widgets are draggable on the board.

In Svelte, pass a configuration object declared with a rune, and mutate it:

```svelte
<script lang="ts">
	import { FlexiBoard, type FlexiBoardConfiguration } from '@flexiboards/svelte';

	let boardConfig: FlexiBoardConfiguration = $state({
		widgetDefaults: {
			draggability: 'full'
		}
	});
</script>

<FlexiBoard config={boardConfig}>
	<!-- Your targets and widgets would be inside here. -->
</FlexiBoard>
```

Here, we've set `widgetDefaults.draggability = 'full'` on our board's configuration, so all widgets (that haven't specified their own `draggability` prop) will be fully draggable. To lock the board, set `boardConfig.widgetDefaults.draggability = 'none'`. The board and its widgets update on their own.

Use these boundaries when changing an existing board:

| Configuration                                                                                                        | Update behavior                                                                                                        |
| -------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| Widget content, classes, `componentProps`, `metadata`, draggability, resizability, triggers, limits, and transitions | Prop changes update the existing widget. Defaults on the board or target apply where the widget has no explicit value. |
| Widget `id`, `type`, `x`, `y`, `width`, and `height`                                                                 | Read when the widget is created. Use `moveTo()` for a move; import a layout to replace positions or sizes.             |
| Target `layout.type`                                                                                                 | Chooses the grid implementation at creation. Recreate the target to switch between free and flow grids.                |
| Target identifier                                                                                                    | Set when the target is created. Keep it stable so stored layouts still identify the target.                            |
| `initialLayout` / `initialLayouts`                                                                                   | Seed the initial render. To load another saved layout after mount, call the appropriate controller's `importLayout()`. |
| `loadLayout` / `loadLayouts`                                                                                         | Called during client initialization. Replacing the callback does not request another load.                             |

Changes to size limits constrain later placements; they do not request an immediate resize. [Controller actions](https://www.flexiboards.dev/docs/controllers#changing-the-board-from-code) run placement rules and report their outcome.

## Deprecated and removed

- `simpleTransitionConfig()` is deprecated and retains its original 150ms easing. Use `cssTransitionConfig()` for the current CSS preset. See [Transitions](https://www.flexiboards.dev/docs/transitions).

Removed in v1.0: the `draggable` boolean (use `draggability`) and `width`/`height` in `widgetDefaults`. See [Migrating to v1.0](https://www.flexiboards.dev/docs/breaking-changes-to-10).

The generated tables on each component's API page also flag deprecated members.
