Inline and Sortable Blocks
Compose inline block editors and sortable block lists.
Inline editing uses a list wrapper plus per-block shells.
Sortable List Wrapper
SortableBlocks owns the dnd-kit context, sensors, default vertical strategy,
and default parent/vertical modifiers.
<SortableBlocks
data={blocks}
queryKey={blocksQueryOptions.queryKey}
variables={({ activeBlock, toIndex }) => ({
pageId,
id: activeBlock.id,
toIndex,
})}
mutation={moveBlockMutation}
>
<RenderBlocks data={blocks} components={inlineComponents} />
</SortableBlocks>When queryKey is provided, the package applies an optimistic cache move with
moveBlock before dispatching the mutation.
Manual Move Mode
If an app wants to own all side effects, use onMove instead of variables and mutation.
<SortableBlocks
data={blocks}
onMove={({ activeBlock, toIndex }) => {
moveBlockMutation.mutate({ id: activeBlock.id, toIndex });
}}
>
<RenderBlocks data={blocks} components={inlineComponents} />
</SortableBlocks>Inline Block Shell
Each inline component owns its fields, labels, commands, and mutation variables. The package provides the shared collapsible block shell.
export function HeroInlineBlock({ block }: BlockComponentProps<typeof heroBlock>) {
return (
<InlineBlockSortable id={block.id}>
<InlineBlock>
<InlineBlockHeader>
<InlineBlockDragHandle>
<GripIcon className="size-4" />
<span className="sr-only">Move block</span>
</InlineBlockDragHandle>
<InlineBlockTrigger>{heroBlock.label}</InlineBlockTrigger>
{/* app-owned command menu */}
</InlineBlockHeader>
<InlineBlockContent>
{/* app-owned inline fields */}
</InlineBlockContent>
</InlineBlock>
</InlineBlockSortable>
);
}InlineBlockSortable
InlineBlockSortable connects one block item to the nearest SortableBlocks
context and shares refs, attributes, listeners, drag state, and transform style
with child primitives.
If InlineBlockDragHandle is rendered without a sortable context, it returns
null, so the same shell can be used in non-sortable contexts.
Recommended Split
Keep this in the package:
- sortable list mechanics
- item refs and drag handle wiring
- collapsible inline shell primitives
Keep this in the app:
- concrete inline fields
- command menus
- permissions and mutation options
- labels and localized copy