Skip to main content
Manages the dynamic button tree with localStorage persistence.

Import

import { useDynamicUI } from "modifywithai"

Usage

const dynamicUI = useDynamicUI({
    storageKey: "my-app-buttons-user-123",
})

Options

OptionTypeRequiredDescription
storageKeystringYeslocalStorage key for persistence

Return Value

State

PropertyTypeDescription
treeDynamicUITree | nullCurrent button tree
isLoadingbooleanLoading from storage

Methods

MethodTypeDescription
addButton(button: DynamicButton) => voidAdd a button
removeButton(id: string) => voidRemove a button
updateButton(id: string, updates: Partial<DynamicButton>) => voidUpdate a button
addGroup(group: DynamicButtonGroup) => voidAdd a button group
removeGroup(id: string) => voidRemove a group
clearAll() => voidRemove all buttons

Types

DynamicButton

interface DynamicButton {
    id: string
    label: string
    icon?: string           // Lucide icon name
    variant?: "default" | "destructive" | "outline" | "secondary" | "ghost"
    actions: ToolAction[]   // Actions to execute on click
}

DynamicButtonGroup

interface DynamicButtonGroup {
    id: string
    label?: string
    direction?: "horizontal" | "vertical"
}

DynamicUITree

interface DynamicUITree {
    root: string                              // Root element key
    elements: Record<string, DynamicUIElement>
}

interface DynamicUIElement {
    key: string
    type: "DynamicButton" | "DynamicButtonGroup"
    props: Record<string, unknown>
    children?: string[]
    parentKey?: string
}

Example

function ButtonManager() {
    const dynamicUI = useDynamicUI({
        storageKey: "my-app-buttons",
    })

    const addQuickCreate = () => {
        dynamicUI.addButton({
            id: "quick-create",
            label: "Quick Create",
            icon: "plus",
            variant: "default",
            actions: [{ name: "createItem", options: {} }],
        })
    }

    if (dynamicUI.isLoading) return null

    return (
        <div>
            <button onClick={addQuickCreate}>Add Button</button>
            <button onClick={() => dynamicUI.removeButton("quick-create")}>
                Remove
            </button>
            <button onClick={dynamicUI.clearAll}>Clear All</button>
        </div>
    )
}

With AssistantProvider

The DynamicUI component handles this automatically when used inside AssistantProvider:
import { AssistantProvider, DynamicUI } from "modifywithai"

function App() {
    return (
        <AssistantProvider
            availableActions={availableActions}
            onAction={handleAction}
            getContext={() => ({ currentPage: "home" })}
        >
            <DynamicUI className="my-buttons" />
            <ChatInterface />
        </AssistantProvider>
    )
}

Storage Key

Use a unique key per user to keep buttons separate:
const dynamicUI = useDynamicUI({
    storageKey: `app-buttons-${user.id}`,
})