Preferences Panel

Compact settings panel with staged changes.

Receive updates via email

Mobile and desktop alerts

Summary of activity every Monday

<PreferencesPanel  sections={[      {          "items": [              {                  "id": "email-notifications",                  "label": "Email Notifications",                  "description": "Receive updates via email",                  "type": "switch",                  "defaultChecked": true              },              {                  "id": "push-notifications",                  "label": "Push Notifications",                  "description": "Mobile and desktop alerts",                  "type": "switch",                  "defaultChecked": false              },              {                  "id": "weekly-digest",                  "label": "Weekly Digest",                  "description": "Summary of activity every Monday",                  "type": "switch",                  "defaultChecked": true              }          ]      }  ]}  onSave={(values) => {    console.log("Saved:", values);  }}  onCancel={() => {    console.log("Cancelled");  }}/>

Getting Started

Run this once from your project root.

npx shadcn@latest add @tool-ui/preferences-panel

Render PreferencesPanel in your UI with tool-compatible props.

import { PreferencesPanel } from "@/components/tool-ui/preferences-panel";export function Example() {  return (    <PreferencesPanel      id="preferences-panel-example"      sections={[        {          items: [            {              id: "notifications",              label: "Notifications",              description: "Receive push notifications",              type: "switch",              defaultChecked: true,            },            {              id: "theme",              label: "Theme",              description: "Choose your appearance",              type: "toggle",              options: [                { value: "light", label: "Light" },                { value: "dark", label: "Dark" },                { value: "auto", label: "Auto" },              ],              defaultValue: "auto",            },            {              id: "analytics",              label: "Analytics",              description: "Help improve the product",              type: "switch",              defaultChecked: false,            },          ],        },      ]}    />  );}

Register this renderer so tool results display as PreferencesPanel.

"use client";import { type Toolkit } from "@assistant-ui/react";import { PreferencesPanel } from "@/components/tool-ui/preferences-panel";import {  safeParseSerializablePreferencesPanel,  SerializablePreferencesPanelSchema,} from "@/components/tool-ui/preferences-panel/schema";import { createArgsToolRenderer } from "@/components/tool-ui/shared";export const toolkit: Toolkit = {  show_preferences_panel: {    description: "Display user preference settings with staged changes",    parameters: SerializablePreferencesPanelSchema,    render: createArgsToolRenderer({      safeParse: safeParseSerializablePreferencesPanel,      idPrefix: "preferences-panel",      render: (parsedArgs, { addResult }) => (          <PreferencesPanel            {...parsedArgs}            onSave={async (values) => {              await addResult({ choice: values });            }}            onCancel={() => {              addResult({ choice: {} });            }}          />      ),    }),  },};

These snippets use assistant-ui for end-to-end wiring, but the PreferencesPanel component itself is framework-agnostic at the UI layer: you can use it in any React codebase with any LLM SDK or tool-calling interface that can provide compatible props.

Key Features

Three control types

Switch for binary choices, toggle for 2-4 options, select for 5+ options

Staged changes

Explicit Save/Cancel actions prevent accidental changes

Receipt state

Use PreferencesPanel.Receipt for confirmed selections with success indicators

Organized sections

Group related settings with optional section headings

Receipt Example

import { PreferencesPanel } from "@/components/tool-ui/preferences-panel";<PreferencesPanel.Receipt  id="preferences-panel-receipt"  title="Privacy Settings"  sections={sections}  choice={{    "profile-visibility": "private",    "activity-status": false,  }}  error={{    "activity-status": "Requires premium plan",  }}/>;

Props

Prop

Type

PreferencesPanel.Receipt

Use the receipt variant to display confirmed preferences or validation errors.

Prop

Type

PreferenceSection

Prop

Type

PreferenceItem

Prop

Type

PreferencesValue

Prop

Type

Limits

  • Sections: 2 maximum per panel
  • Items per section: 3 maximum
  • Total items: 5 maximum across all sections
  • Toggle options: 2-4 choices (use select for more)
  • Select options: 5+ choices (use toggle for fewer)

Accessibility

  • Full keyboard navigation support for all control types
  • Labels properly associated with controls using htmlFor and id attributes
  • Save button disabled when no changes exist to prevent unnecessary actions
  • Receipt state uses role="status" for screen reader announcements
  • All animations respect prefers-reduced-motion user preference
  • Sufficient color contrast meets WCAG AA standards
  • Focus indicators visible on all interactive elements