mdxui

Settings

Application settings and preferences view component

Settings

The Settings view provides a centralized interface for managing application configuration, user preferences, account settings, and integrations. It organizes settings into logical sections with sidebar navigation.

Type Signature

interface SettingsViewProps {
  /** Page title */
  title?: string
  /** Page description */
  description?: string
  /** View layout mode */
  layout?: 'single' | 'column' | 'canvas' | 'vibe'
  /** Settings sections */
  sections?: Array<{
    id: string
    label: string
    icon?: string
    content: React.ReactNode
  }>
  /** Active section */
  activeSection?: string
  /** Show navigation sidebar */
  showSidebar?: boolean
  /** Allow reset to defaults */
  allowReset?: boolean
  /** Page-level action buttons */
  actions?: Array<{
    id: string
    label: string
    icon?: string
    onClick?: () => void
    variant?: 'default' | 'primary' | 'destructive'
  }>
  /** Child content */
  children?: React.ReactNode
}

Usage

<App name="Acme Dashboard">
  <Shell>
    <SettingsView
      title="Settings"
      showSidebar={true}
      allowReset={true}
      sections={[
        {
          id: 'general',
          label: 'General',
          icon: 'Settings',
          content: <GeneralSettings />
        },
        {
          id: 'account',
          label: 'Account',
          icon: 'User',
          content: <AccountSettings />
        },
        {
          id: 'billing',
          label: 'Billing',
          icon: 'CreditCard',
          content: <BillingSettings />
        }
      ]}
    />
  </Shell>
</App>

Props

title

The page title displayed in the header. Defaults to "Settings".

<SettingsView title="Preferences">

description

Optional page description.

<SettingsView
  title="Settings"
  description="Manage your account and application preferences"
>

layout

Layout mode for the settings content. Defaults to 'single'.

// Single column layout with sidebar (default)
<SettingsView layout="single">

// Multi-column layout
<SettingsView layout="column">

sections

Array of settings sections with their content.

<SettingsView
  sections={[
    {
      id: 'profile',
      label: 'Profile',
      icon: 'User',
      content: <ProfileSettings />
    },
    {
      id: 'security',
      label: 'Security',
      icon: 'Lock',
      content: <SecuritySettings />
    },
    {
      id: 'notifications',
      label: 'Notifications',
      icon: 'Bell',
      content: <NotificationSettings />
    },
    {
      id: 'integrations',
      label: 'Integrations',
      icon: 'Puzzle',
      content: <IntegrationSettings />
    }
  ]}
/>

activeSection

The currently selected section ID. Used for controlled navigation.

const [section, setSection] = useState('profile')

<SettingsView
  activeSection={section}
  onSectionChange={setSection}
  sections={sections}
/>

showSidebar

Controls whether the settings navigation sidebar is rendered. Defaults to true.

// Show sidebar (default)
<SettingsView showSidebar={true}>

// Hide sidebar (single section)
<SettingsView showSidebar={false}>
  <GeneralSettings />
</SettingsView>

allowReset

Enable "Reset to Defaults" functionality. Defaults to true.

<SettingsView allowReset={true}>
  {/* Shows reset button in each section */}
</SettingsView>

actions

Page-level action buttons displayed in the header.

<SettingsView
  actions={[
    {
      id: 'save',
      label: 'Save Changes',
      variant: 'primary',
      onClick: () => saveSettings()
    },
    {
      id: 'cancel',
      label: 'Cancel',
      onClick: () => resetForm()
    }
  ]}
>

Layout Structure

The Settings view uses a sidebar navigation pattern:

┌─────────────────────────────────────┐
│            Settings                 │
├──────────┬──────────────────────────┤
│ General  │                          │
│ Account  │    General Settings      │
│ Security │                          │
│ Billing  │    [Form fields...]      │
│          │                          │
└──────────┴──────────────────────────┘

Without Sidebar

For single-section settings:

┌─────────────────────────────────────┐
│            Settings                 │
├─────────────────────────────────────┤
│                                     │
│       General Settings              │
│                                     │
│       [Form fields...]              │
│                                     │
└─────────────────────────────────────┘

Common Settings Sections

General Settings

Application-wide preferences:

<SettingsView
  sections={[
    {
      id: 'general',
      label: 'General',
      icon: 'Settings',
      content: (
        <>
          <FormField label="App Name" name="name" />
          <FormField label="Language" name="language" type="select" />
          <FormField label="Timezone" name="timezone" type="select" />
          <FormField label="Date Format" name="dateFormat" type="select" />
        </>
      )
    }
  ]}
/>

Account Settings

User account management:

{
  id: 'account',
  label: 'Account',
  icon: 'User',
  content: (
    <>
      <FormField label="Email" name="email" type="email" />
      <FormField label="Display Name" name="displayName" />
      <FormField label="Avatar" name="avatar" type="file" />
      <FormField label="Bio" name="bio" type="textarea" />
    </>
  )
}

Security Settings

Password and authentication:

{
  id: 'security',
  label: 'Security',
  icon: 'Lock',
  content: (
    <>
      <FormField label="Current Password" name="currentPassword" type="password" />
      <FormField label="New Password" name="newPassword" type="password" />
      <FormField label="Confirm Password" name="confirmPassword" type="password" />
      <Switch label="Two-Factor Authentication" name="twoFactor" />
      <Button variant="destructive">Revoke All Sessions</Button>
    </>
  )
}

Notification Settings

Email and push notification preferences:

{
  id: 'notifications',
  label: 'Notifications',
  icon: 'Bell',
  content: (
    <>
      <Switch label="Email Notifications" name="emailNotifications" />
      <Switch label="Push Notifications" name="pushNotifications" />
      <CheckboxGroup
        label="Notification Types"
        options={[
          { value: 'updates', label: 'Product Updates' },
          { value: 'marketing', label: 'Marketing Emails' },
          { value: 'security', label: 'Security Alerts' }
        ]}
      />
    </>
  )
}

Billing Settings

Subscription and payment information:

{
  id: 'billing',
  label: 'Billing',
  icon: 'CreditCard',
  content: (
    <>
      <PlanCard current={currentPlan} />
      <PaymentMethodCard card={paymentMethod} />
      <InvoiceHistory invoices={invoices} />
      <Button variant="destructive">Cancel Subscription</Button>
    </>
  )
}

Integration Settings

Third-party service connections:

{
  id: 'integrations',
  label: 'Integrations',
  icon: 'Puzzle',
  content: (
    <>
      <IntegrationCard
        name="Slack"
        connected={true}
        onDisconnect={() => {}}
      />
      <IntegrationCard
        name="GitHub"
        connected={false}
        onConnect={() => {}}
      />
      <IntegrationCard
        name="Google"
        connected={true}
        onDisconnect={() => {}}
      />
    </>
  )
}

App Type Specializations

Different app types include different settings:

DeveloperApp Settings

<SettingsView
  sections={[
    { id: 'general', label: 'General', content: <GeneralSettings /> },
    { id: 'api', label: 'API', content: <APISettings /> },
    { id: 'webhooks', label: 'Webhooks', content: <WebhookSettings /> },
    { id: 'security', label: 'Security', content: <SecuritySettings /> }
  ]}
/>

AdminApp Settings

<SettingsView
  sections={[
    { id: 'general', label: 'General', content: <GeneralSettings /> },
    { id: 'users', label: 'Users', content: <UserSettings /> },
    { id: 'roles', label: 'Roles', content: <RoleSettings /> },
    { id: 'system', label: 'System', content: <SystemSettings /> },
    { id: 'audit', label: 'Audit Logs', content: <AuditSettings /> }
  ]}
/>

SaaSApp Settings

<SettingsView
  sections={[
    { id: 'profile', label: 'Profile', content: <ProfileSettings /> },
    { id: 'team', label: 'Team', content: <TeamSettings /> },
    { id: 'billing', label: 'Billing', content: <BillingSettings /> },
    { id: 'integrations', label: 'Integrations', content: <IntegrationSettings /> },
    { id: 'notifications', label: 'Notifications', content: <NotificationSettings /> }
  ]}
/>

Form Handling

Settings views typically contain forms:

const handleSave = async (values: SettingsFormValues) => {
  await updateSettings(values)
  toast.success('Settings saved')
}

<SettingsView
  sections={[
    {
      id: 'general',
      label: 'General',
      content: (
        <Form onSubmit={handleSave}>
          <FormField label="App Name" name="name" />
          <FormField label="Description" name="description" />
          <FormActions>
            <Button type="submit">Save Changes</Button>
            <Button variant="ghost" onClick={resetForm}>Cancel</Button>
          </FormActions>
        </Form>
      )
    }
  ]}
/>

Validation

Validate settings before saving:

const schema = z.object({
  email: z.string().email(),
  name: z.string().min(2),
  timezone: z.string()
})

<SettingsView>
  <Form schema={schema} onSubmit={handleSave}>
    {/* Form fields */}
  </Form>
</SettingsView>

Responsive Behavior

Settings adapt to screen size:

Desktop (≥1024px)

┌────────────────────────────────────┐
│          Settings                  │
├──────────┬─────────────────────────┤
│ General  │                         │
│ Account  │   Form Fields           │
│ Security │                         │
│ Billing  │   [Settings content]    │
└──────────┴─────────────────────────┘
Sidebar + content

Mobile (under 1024px)

┌────────────────────────────────────┐
│          Settings                  │
├────────────────────────────────────┤
│ [Section Dropdown]                 │
├────────────────────────────────────┤
│                                    │
│        Form Fields                 │
│                                    │
│        [Settings content]          │
└────────────────────────────────────┘
Dropdown navigation + content

Auto-Save

Implement auto-save for better UX:

const [settings, setSettings] = useState(initialSettings)

useEffect(() => {
  const timer = setTimeout(() => {
    saveSettings(settings)
  }, 1000)

  return () => clearTimeout(timer)
}, [settings])

<SettingsView>
  <FormField
    value={settings.name}
    onChange={(value) => setSettings({ ...settings, name: value })}
  />
  <SaveIndicator status="saved" />
</SettingsView>

Reset to Defaults

Allow users to reset settings:

<SettingsView
  allowReset={true}
  sections={[
    {
      id: 'general',
      label: 'General',
      content: (
        <>
          <FormFields />
          <Button
            variant="destructive"
            onClick={() => resetToDefaults('general')}
          >
            Reset to Defaults
          </Button>
        </>
      )
    }
  ]}
/>

Integration with Payload CMS

Settings can auto-wire to Payload collections:

// Auto-fetches from Payload 'settings' collection
<SettingsView collection="settings">
  <GeneralSettings />
</SettingsView>

Best Practices

Organize settings into logical sections:

// Good - clear organization
<SettingsView
  sections={[
    { id: 'profile', label: 'Profile', ... },
    { id: 'security', label: 'Security', ... },
    { id: 'notifications', label: 'Notifications', ... }
  ]}
/>

// Bad - flat list of unrelated settings
<SettingsView>
  <FormField label="Name" />
  <FormField label="Password" />
  <FormField label="Email Notifications" />
  {/* ... mixed settings */}
</SettingsView>

Provide Clear Labels

Use descriptive labels and help text:

<FormField
  label="API Rate Limit"
  name="rateLimit"
  description="Maximum requests per minute. Contact support to increase."
  placeholder="100"
/>

Show Unsaved Changes

Warn before leaving with unsaved changes:

const [hasChanges, setHasChanges] = useState(false)

useEffect(() => {
  const handler = (e: BeforeUnloadEvent) => {
    if (hasChanges) {
      e.preventDefault()
      e.returnValue = ''
    }
  }
  window.addEventListener('beforeunload', handler)
  return () => window.removeEventListener('beforeunload', handler)
}, [hasChanges])

Handle Errors Gracefully

Show validation errors clearly:

<SettingsView>
  <Form onSubmit={handleSave} onError={handleError}>
    <FormField
      label="Email"
      name="email"
      error={errors.email}
    />
  </Form>
</SettingsView>

Accessibility

Settings views implement accessibility features:

  • Keyboard navigation - Tab through form fields
  • Form labels - All inputs have associated labels
  • Error announcements - Screen readers announce validation errors
  • Focus management - Focus moves to first error on submit
<SettingsView aria-label="Application settings">
  <section aria-labelledby="general-heading">
    <h2 id="general-heading">General Settings</h2>
    <Form>
      <FormField
        label="App Name"
        name="name"
        required
        aria-describedby="name-description"
      />
      <span id="name-description" className="sr-only">
        The name displayed in the browser tab and app header
      </span>
    </Form>
  </section>
</SettingsView>

On this page