Skip to content
Template Empire
Browse components

Form Preference Center

A grouped preference center with native tri-state controls and controlled or local selection.

Notification preferences

Product updates

News about features and changes to the service.

Account security

Important messages about access to your account.

Billing notices

Receipts and account billing changes.

These settings update this example only; choose the notices you want to receive.

Customise

Code

import { useState } from "react";
const groups = [
  { id: "product-updates", label: "Product updates", preferences: [
    { id: "release-notes", label: "Release notes" },
    { id: "monthly-digest", label: "Monthly digest" },
  ] },
  { id: "billing", label: "Billing notices", preferences: [
    { id: "invoice-notices", label: "Invoice notices" },
  ] },
];
const [value, setValue] = useState({ "release-notes": true, "monthly-digest": false });

<FormPreferenceCenter
  title="Notification preferences"
  groups={groups}
  value={value}
  onValueChange={setValue}
/>

Form Preference Center lets people review independent account and notification choices by group. Each group control reports whether all, none, or some options are enabled, and a group change updates only that group's preferences.

Supply controlled values when the page owns the settings, or use defaultValue for local interaction. Missing option values start disabled. The component does not save, submit, or infer consent policy.

Install

Add the @te registry to your components.json once:

{
  "registries": {
    "@te": "https://templateempire.io/r/{name}.json"
  }
}

Then install the component:

npx shadcn@latest add @te/form-preference-center

Usage

import { FormPreferenceCenter } from "@/components/form-preference-center";

<FormPreferenceCenter
  title="Notification preferences"
  groups={[
    {
      id: "product",
      label: "Product updates",
      preferences: [
        { id: "release-notes", label: "Release notes" },
        { id: "monthly-digest", label: "Monthly digest" },
      ],
    },
  ]}
  defaultValue={{ "release-notes": true }}
/>

Props

PropTypeDefaultDescription
titlestringrequiredVisible section heading.
groupsFormPreferenceGroup[]requiredOrdered groups with unique IDs, labels, and at least one preference each.
valueRecord<string, boolean>undefinedControlled preference values; missing keys are false and unknown keys are ignored.
defaultValueRecord<string, boolean>undefinedInitial values for uncontrolled use; missing preferences start disabled.
onValueChange(next) => voidundefinedReceives the complete next map of known preference IDs after a user change.
classNamestringundefinedAdditional classes merged onto the section.

Customisation

Use groups to match the account or notification areas your product already has. Controlled values remain authoritative; group toggles only change the preferences in that group. The callback map includes every known preference ID once, so the page can store or submit it using its own policy.

<FormPreferenceCenter
  title="Workspace notices"
  groups={workspaceNoticeGroups}
  value={settings}
  onValueChange={setSettings}
/>

Frequently asked questions

What does a mixed group control do?
It shows a Mixed state when some, but not all, preferences in that group are enabled. Activating it enables the whole group; activating an already complete group disables it.
Does the component save preferences?
No. It emits a complete next value map, but persistence, consent rules, and form submission belong to the consuming page.
Are unknown value keys kept?
No. Rendering and emitted maps use only the preference IDs supplied in groups.

Related components

Want the full page this belongs to?Template Empire builds complete Next.js templates with considered account and settings experiences. Browse the paid templates that pair with these free components.Explore Template Empire templates