SettingsDialog ​

A dialog for app settings, with a sidebar of grouped tabs on the left and the selected tab's content on the right.

vue
<script setup lang="ts">
import { markRaw, ref } from 'vue'
import {
  Avatar,
  Button,
  SettingsContent,
  SettingsDialog,
  SettingsNavGroup,
  SettingsNavItem,
  SettingsPanel,
  SettingsSidebar,
} from 'frappe-ui'
import ProfilePanel from './panels/ProfilePanel.vue'
import PreferencesPanel from './panels/PreferencesPanel.vue'
import NotificationsPanel from './panels/NotificationsPanel.vue'
import UsersPanel from './panels/UsersPanel.vue'
import GeneralPanel from './panels/GeneralPanel.vue'
import IntegrationsPanel from './panels/IntegrationsPanel.vue'
import PlanPanel from './panels/PlanPanel.vue'
import InvoicesPanel from './panels/InvoicesPanel.vue'

const open = ref(false)

// Modeled on Gameplan's settings: grouped tabs, an avatar on the Profile tab,
// and panels that range from simple forms to a long, searchable user table.
const groups = [
  {
    label: 'User settings',
    tabs: [
      {
        label: 'Profile',
        value: 'profile',
        avatar: true,
        component: markRaw(ProfilePanel),
      },
      {
        label: 'Preferences',
        value: 'preferences',
        icon: 'lucide-sliders-horizontal',
        component: markRaw(PreferencesPanel),
      },
      {
        label: 'Notifications',
        value: 'notifications',
        icon: 'lucide-bell',
        component: markRaw(NotificationsPanel),
      },
    ],
  },
  {
    label: 'Workspace',
    tabs: [
      {
        label: 'General',
        value: 'general',
        icon: 'lucide-building-2',
        component: markRaw(GeneralPanel),
      },
      {
        label: 'Users',
        value: 'users',
        icon: 'lucide-users',
        component: markRaw(UsersPanel),
      },
      {
        label: 'Integrations',
        value: 'integrations',
        icon: 'lucide-blocks',
        component: markRaw(IntegrationsPanel),
      },
    ],
  },
  {
    label: 'Billing',
    tabs: [
      {
        label: 'Plan',
        value: 'plan',
        icon: 'lucide-credit-card',
        component: markRaw(PlanPanel),
      },
      {
        label: 'Invoices',
        value: 'invoices',
        icon: 'lucide-receipt',
        component: markRaw(InvoicesPanel),
      },
    ],
  },
]

const tabs = groups.flatMap((group) => group.tabs)
const activeTab = ref(tabs[0].value)
</script>

<template>
  <Button @click="open = true">Open settings</Button>
  <SettingsDialog v-model:open="open" v-model:tab="activeTab">
    <SettingsSidebar>
      <SettingsNavGroup
        v-for="group in groups"
        :key="group.label"
        :label="group.label"
      >
        <SettingsNavItem
          v-for="tab in group.tabs"
          :key="tab.value"
          :value="tab.value"
        >
          <template #prefix>
            <Avatar
              v-if="tab.avatar"
              size="xs"
              label="Alex Rivera"
              class="shrink-0"
            />
            <span
              v-else
              :class="[tab.icon, 'size-4 shrink-0 text-ink-gray-6']"
            />
          </template>
          {{ tab.label }}
        </SettingsNavItem>
      </SettingsNavGroup>
    </SettingsSidebar>
    <SettingsContent>
      <SettingsPanel v-for="tab in tabs" :key="tab.value" :value="tab.value">
        <component :is="tab.component" />
      </SettingsPanel>
    </SettingsContent>
  </SettingsDialog>
</template>

Anatomy ​

SettingsDialog is built on Dialog and is made of small parts rather than a config object. Give each nav item and its panel the same value.

vue
<SettingsDialog v-model:open="open" v-model:tab="tab">
  <SettingsSidebar>
    <SettingsNavGroup label="User settings">
      <SettingsNavItem value="profile">
        <template #prefix><Avatar size="xs" label="Alex Rivera" /></template>
        Profile
      </SettingsNavItem>
      <SettingsNavItem value="notifications">Notifications</SettingsNavItem>
    </SettingsNavGroup>
  </SettingsSidebar>

  <SettingsContent>
    <SettingsPanel value="profile">…</SettingsPanel>
    <SettingsPanel value="notifications">
      <SettingsHeader title="Notifications" />
      <SettingsBody>
        <SettingsRow title="Email digests" description="A summary of missed activity.">
          <Switch v-model="digest" />
        </SettingsRow>
      </SettingsBody>
    </SettingsPanel>
  </SettingsContent>
</SettingsDialog>
  • SettingsDialog holds the open state (v-model:open), the selected tab (v-model:tab) and the keyboard shortcut.
  • SettingsSidebar, SettingsNavGroup and SettingsNavItem are the navigation. A nav item takes #prefix and #suffix.
  • SettingsContent and SettingsPanel are the right side, with one panel per tab.
  • SettingsHeader, SettingsBody and SettingsRow lay out a panel.

Examples ​

Notification settings ​

A panel with a SettingsHeader that stays in place, a SettingsBody that scrolls, and one SettingsRow per setting.

Notifications

Enable email digests
Send a summary of missed activity.
Digest frequency
Choose how often you receive your digest.
vue
<script setup lang="ts">
import { ref } from 'vue'
import { TabsRoot } from 'reka-ui'
import {
  Select,
  SettingsBody,
  SettingsHeader,
  SettingsPanel,
  SettingsRow,
  Switch,
} from 'frappe-ui'

const digestEnabled = ref(true)
const frequency = ref('Weekly')
const frequencyOptions = [
  { label: 'Weekly', value: 'Weekly' },
  { label: 'Fortnightly', value: 'Fortnightly' },
  { label: 'Monthly', value: 'Monthly' },
]
</script>

<template>
  <!--
    SettingsPanel is a reka-ui tabpanel, so it needs a TabsRoot ancestor. In the
    full dialog SettingsDialog provides it; here we add a minimal one to show a
    single panel in isolation.
  -->
  <div class="h-96 w-full overflow-hidden rounded-4 border border-outline-gray-2">
    <TabsRoot default-value="notifications" class="flex h-full">
      <SettingsPanel value="notifications">
        <SettingsHeader title="Notifications" />
        <SettingsBody>
          <div class="divide-y divide-outline-gray-1">
            <SettingsRow
              title="Enable email digests"
              description="Send a summary of missed activity."
            >
              <Switch v-model="digestEnabled" />
            </SettingsRow>
            <SettingsRow
              v-if="digestEnabled"
              title="Digest frequency"
              description="Choose how often you receive your digest."
            >
              <Select :options="frequencyOptions" v-model="frequency" />
            </SettingsRow>
          </div>
        </SettingsBody>
      </SettingsPanel>
    </TabsRoot>
  </div>
</template>

Behavior ​

Selected tab ​

The selected tab is the value of a nav item, not an active flag. v-model:tab is optional. Bind it to drive the selection yourself, for example from a /settings/:tab URL. Left unbound, the dialog tracks the selection itself.

Keeping panels mounted ​

A panel's content is unmounted when its tab is not selected. Set :unmount-on-hide="false" to keep visited panels mounted, so they keep their state and scroll position across tab switches.

Keyboard shortcut ​

Cmd+Shift+, (Ctrl+Shift+, on Windows and Linux) opens and closes the dialog, even while focus is in an input. Pass another combo to keyboardShortcut to change it, or false to turn it off.

Size and mobile layout ​

The dialog fills the screen on mobile, with the sidebar above the content. On desktop it is a centered panel. size sets its maximum width and takes the same values as Dialog's size.

Panel header and body ​

Put a SettingsHeader and a SettingsBody in each SettingsPanel. The header stays in place and the body scrolls, so titles, search inputs and column headers never scroll away. SettingsHeader takes title, description and an #actions slot, or any content in its default slot.

Setting rows ​

SettingsRow shows a setting's title and description on the left and its control on the right. When the control is a frappe-ui control such as Switch, the title becomes its <label>, with no label-for needed. Set labelFor to point the label at another element's id.

Accessibility ​

The dialog is a tab set: the sidebar has the tablist role, each nav item the tab role, and each panel the tabpanel role.

KeysAction
ArrowDown / ArrowUpMove focus to the next or previous tab
Enter / SpaceSelect the focused tab
Cmd+Shift+, / Ctrl+Shift+,Open or close the dialog

Arrow keys move focus without selecting a tab, so a dialog that drives its tab from the route does not navigate on every key press.

The dialog has a visually hidden title, "Settings", and a hidden description. Replace them with the #title and #description slots.

API Reference ​

SettingsDialog ​

Show types
typescript
import type { DialogSize } from '../Dialog/types'
import type { KeyboardShortcutCombo } from '../../composables/useKeyboardShortcut'

export interface SettingsDialogProps {
  /** Max-width size of the dialog. */
  size?: DialogSize

  /** Shortcut that toggles the dialog. Pass `false` to disable it. */
  keyboardShortcut?: KeyboardShortcutCombo | 'Mod+Shift+,' | false

  /**
   * Unmount a panel's content when its tab is inactive (reka-ui default: true).
   * Set false to keep visited panels mounted (hidden) — preserves their state
   * and scroll position across tab switches at the cost of memory.
   */
  unmountOnHide?: boolean
}

export interface SettingsDialogEmits {
  /** Fired when the dialog is opened or closed. */
  'update:open': [value: boolean]
}

/**
 * Shared with `ScrollArea` (imperative-api.md §2.5) once that component's own
 * sweep types its `defineExpose`. Kept local to this family until then.
 */
export interface SettingsBodyExposed {
  /** The element that actually scrolls. `null` before mount. */
  viewportElement: HTMLElement | null
}
size
= "4xl"
DialogSize

Max-width size of the dialog.

keyboardShortcut
= "Mod+Shift+,"
KeyboardShortcutKey | "Shift+P" | "Shift+B" | "Shift+D" | "Shift+C" | "Shift+M" | "Shift+F1" | "Shift+F2" | "Shift+F3" | "Shift+F4" | "Shift+F5" | "Shift+F6" | "Shift+F7" | "Shift+F8" | "Shift+F9" | "Shift+F10" | "Shift+F11" | "Shift+F12" | "Shift+Escape" | "Shift+Enter" | "Shift+Tab" | "Shift+Backspace" | "Shift+Delete" | "Shift+Insert" | "Shift+ArrowUp" | "Shift+ArrowDown" | "Shift+ArrowLeft" | "Shift+ArrowRight" | "Shift+Home" | "Shift+End" | "Shift+PageUp" | "Shift+PageDown" | "Shift+A" | "Shift+E" | "Shift+F" | "Shift+G" | "Shift+H" | "Shift+I" | "Shift+J" | "Shift+K" | "Shift+L" | "Shift+N" | "Shift+O" | "Shift+Q" | "Shift+R" | "Shift+S" | "Shift+T" | "Shift+U" | "Shift+V" | "Shift+W" | "Shift+X" | "Shift+Y" | "Shift+Z" | "Shift+Space" | "Shift+Digit0" | "Shift+Digit1" | "Shift+Digit2" | "Shift+Digit3" | "Shift+Digit4" | "Shift+Digit5" | "Shift+Digit6" | "Shift+Digit7" | "Shift+Digit8" | "Shift+Digit9" | "Shift+Minus" | "Shift+Equal" | "Shift+Slash" | "Shift+Backslash" | "Shift+Comma" | "Shift+Period" | "Shift+Semicolon" | "Shift+Quote" | "Shift+BracketLeft" | "Shift+BracketRight" | "Shift+Plus" | "Shift+Backtick" | "Alt+P" | "Alt+B" | "Alt+D" | "Alt+C" | "Alt+M" | "Alt+F1" | "Alt+F2" | "Alt+F3" | "Alt+F4" | "Alt+F5" | "Alt+F6" | "Alt+F7" | "Alt+F8" | "Alt+F9" | "Alt+F10" | "Alt+F11" | "Alt+F12" | "Alt+Escape" | "Alt+Enter" | "Alt+Tab" | "Alt+Backspace" | "Alt+Delete" | "Alt+Insert" | "Alt+ArrowUp" | "Alt+ArrowDown" | "Alt+ArrowLeft" | "Alt+ArrowRight" | "Alt+Home" | "Alt+End" | "Alt+PageUp" | "Alt+PageDown" | "Alt+A" | "Alt+E" | "Alt+F" | "Alt+G" | "Alt+H" | "Alt+I" | "Alt+J" | "Alt+K" | "Alt+L" | "Alt+N" | "Alt+O" | "Alt+Q" | "Alt+R" | "Alt+S" | "Alt+T" | "Alt+U" | "Alt+V" | "Alt+W" | "Alt+X" | "Alt+Y" | "Alt+Z" | "Alt+Space" | "Alt+Digit0" | "Alt+Digit1" | "Alt+Digit2" | "Alt+Digit3" | "Alt+Digit4" | "Alt+Digit5" | "Alt+Digit6" | "Alt+Digit7" | "Alt+Digit8" | "Alt+Digit9" | "Alt+Minus" | "Alt+Equal" | "Alt+Slash" | "Alt+Backslash" | "Alt+Comma" | "Alt+Period" | "Alt+Semicolon" | "Alt+Quote" | "Alt+BracketLeft" | "Alt+BracketRight" | "Alt+Plus" | "Alt+Backtick" | "Alt+Shift+P" | "Alt+Shift+B" | "Alt+Shift+D" | "Alt+Shift+C" | "Alt+Shift+M" | "Alt+Shift+F1" | "Alt+Shift+F2" | "Alt+Shift+F3" | "Alt+Shift+F4" | "Alt+Shift+F5" | "Alt+Shift+F6" | "Alt+Shift+F7" | "Alt+Shift+F8" | "Alt+Shift+F9" | "Alt+Shift+F10" | "Alt+Shift+F11" | "Alt+Shift+F12" | "Alt+Shift+Escape" | "Alt+Shift+Enter" | "Alt+Shift+Tab" | "Alt+Shift+Backspace" | "Alt+Shift+Delete" | "Alt+Shift+Insert" | "Alt+Shift+ArrowUp" | "Alt+Shift+ArrowDown" | "Alt+Shift+ArrowLeft" | "Alt+Shift+ArrowRight" | "Alt+Shift+Home" | "Alt+Shift+End" | "Alt+Shift+PageUp" | "Alt+Shift+PageDown" | "Alt+Shift+A" | "Alt+Shift+E" | "Alt+Shift+F" | "Alt+Shift+G" | "Alt+Shift+H" | "Alt+Shift+I" | "Alt+Shift+J" | "Alt+Shift+K" | "Alt+Shift+L" | "Alt+Shift+N" | "Alt+Shift+O" | "Alt+Shift+Q" | "Alt+Shift+R" | "Alt+Shift+S" | "Alt+Shift+T" | "Alt+Shift+U" | "Alt+Shift+V" | "Alt+Shift+W" | "Alt+Shift+X" | "Alt+Shift+Y" | "Alt+Shift+Z" | "Alt+Shift+Space" | "Alt+Shift+Digit0" | "Alt+Shift+Digit1" | "Alt+Shift+Digit2" | "Alt+Shift+Digit3" | "Alt+Shift+Digit4" | "Alt+Shift+Digit5" | "Alt+Shift+Digit6" | "Alt+Shift+Digit7" | "Alt+Shift+Digit8" | "Alt+Shift+Digit9" | "Alt+Shift+Minus" | "Alt+Shift+Equal" | "Alt+Shift+Slash" | "Alt+Shift+Backslash" | "Alt+Shift+Comma" | "Alt+Shift+Period" | "Alt+Shift+Semicolon" | "Alt+Shift+Quote" | "Alt+Shift+BracketLeft" | "Alt+Shift+BracketRight" | "Alt+Shift+Plus" | "Alt+Shift+Backtick" | "Ctrl+P" | "Ctrl+B" | "Ctrl+D" | "Ctrl+C" | "Ctrl+M" | "Ctrl+F1" | "Ctrl+F2" | "Ctrl+F3" | "Ctrl+F4" | "Ctrl+F5" | "Ctrl+F6" | "Ctrl+F7" | "Ctrl+F8" | "Ctrl+F9" | "Ctrl+F10" | "Ctrl+F11" | "Ctrl+F12" | "Ctrl+Escape" | "Ctrl+Enter" | "Ctrl+Tab" | "Ctrl+Backspace" | "Ctrl+Delete" | "Ctrl+Insert" | "Ctrl+ArrowUp" | "Ctrl+ArrowDown" | "Ctrl+ArrowLeft" | "Ctrl+ArrowRight" | "Ctrl+Home" | "Ctrl+End" | "Ctrl+PageUp" | "Ctrl+PageDown" | "Ctrl+A" | "Ctrl+E" | "Ctrl+F" | "Ctrl+G" | "Ctrl+H" | "Ctrl+I" | "Ctrl+J" | "Ctrl+K" | "Ctrl+L" | "Ctrl+N" | "Ctrl+O" | "Ctrl+Q" | "Ctrl+R" | "Ctrl+S" | "Ctrl+T" | "Ctrl+U" | "Ctrl+V" | "Ctrl+W" | "Ctrl+X" | "Ctrl+Y" | "Ctrl+Z" | "Ctrl+Space" | "Ctrl+Digit0" | "Ctrl+Digit1" | "Ctrl+Digit2" | "Ctrl+Digit3" | "Ctrl+Digit4" | "Ctrl+Digit5" | "Ctrl+Digit6" | "Ctrl+Digit7" | "Ctrl+Digit8" | "Ctrl+Digit9" | "Ctrl+Minus" | "Ctrl+Equal" | "Ctrl+Slash" | "Ctrl+Backslash" | "Ctrl+Comma" | "Ctrl+Period" | "Ctrl+Semicolon" | "Ctrl+Quote" | "Ctrl+BracketLeft" | "Ctrl+BracketRight" | "Ctrl+Plus" | "Ctrl+Backtick" | "Ctrl+Shift+P" | "Ctrl+Shift+B" | "Ctrl+Shift+D" | "Ctrl+Shift+C" | "Ctrl+Shift+M" | "Ctrl+Shift+F1" | "Ctrl+Shift+F2" | "Ctrl+Shift+F3" | "Ctrl+Shift+F4" | "Ctrl+Shift+F5" | "Ctrl+Shift+F6" | "Ctrl+Shift+F7" | "Ctrl+Shift+F8" | "Ctrl+Shift+F9" | "Ctrl+Shift+F10" | "Ctrl+Shift+F11" | "Ctrl+Shift+F12" | "Ctrl+Shift+Escape" | "Ctrl+Shift+Enter" | "Ctrl+Shift+Tab" | "Ctrl+Shift+Backspace" | "Ctrl+Shift+Delete" | "Ctrl+Shift+Insert" | "Ctrl+Shift+ArrowUp" | "Ctrl+Shift+ArrowDown" | "Ctrl+Shift+ArrowLeft" | "Ctrl+Shift+ArrowRight" | "Ctrl+Shift+Home" | "Ctrl+Shift+End" | "Ctrl+Shift+PageUp" | "Ctrl+Shift+PageDown" | "Ctrl+Shift+A" | "Ctrl+Shift+E" | "Ctrl+Shift+F" | "Ctrl+Shift+G" | "Ctrl+Shift+H" | "Ctrl+Shift+I" | "Ctrl+Shift+J" | "Ctrl+Shift+K" | "Ctrl+Shift+L" | "Ctrl+Shift+N" | "Ctrl+Shift+O" | "Ctrl+Shift+Q" | "Ctrl+Shift+R" | "Ctrl+Shift+S" | "Ctrl+Shift+T" | "Ctrl+Shift+U" | "Ctrl+Shift+V" | "Ctrl+Shift+W" | "Ctrl+Shift+X" | "Ctrl+Shift+Y" | "Ctrl+Shift+Z" | "Ctrl+Shift+Space" | "Ctrl+Shift+Digit0" | "Ctrl+Shift+Digit1" | "Ctrl+Shift+Digit2" | "Ctrl+Shift+Digit3" | "Ctrl+Shift+Digit4" | "Ctrl+Shift+Digit5" | "Ctrl+Shift+Digit6" | "Ctrl+Shift+Digit7" | "Ctrl+Shift+Digit8" | "Ctrl+Shift+Digit9" | "Ctrl+Shift+Minus" | "Ctrl+Shift+Equal" | "Ctrl+Shift+Slash" | "Ctrl+Shift+Backslash" | "Ctrl+Shift+Comma" | "Ctrl+Shift+Period" | "Ctrl+Shift+Semicolon" | "Ctrl+Shift+Quote" | "Ctrl+Shift+BracketLeft" | "Ctrl+Shift+BracketRight" | "Ctrl+Shift+Plus" | "Ctrl+Shift+Backtick" | "Ctrl+Alt+P" | "Ctrl+Alt+B" | "Ctrl+Alt+D" | "Ctrl+Alt+C" | "Ctrl+Alt+M" | "Ctrl+Alt+F1" | "Ctrl+Alt+F2" | "Ctrl+Alt+F3" | "Ctrl+Alt+F4" | "Ctrl+Alt+F5" | "Ctrl+Alt+F6" | "Ctrl+Alt+F7" | "Ctrl+Alt+F8" | "Ctrl+Alt+F9" | "Ctrl+Alt+F10" | "Ctrl+Alt+F11" | "Ctrl+Alt+F12" | "Ctrl+Alt+Escape" | "Ctrl+Alt+Enter" | "Ctrl+Alt+Tab" | "Ctrl+Alt+Backspace" | "Ctrl+Alt+Delete" | "Ctrl+Alt+Insert" | "Ctrl+Alt+ArrowUp" | "Ctrl+Alt+ArrowDown" | "Ctrl+Alt+ArrowLeft" | "Ctrl+Alt+ArrowRight" | "Ctrl+Alt+Home" | "Ctrl+Alt+End" | "Ctrl+Alt+PageUp" | "Ctrl+Alt+PageDown" | "Ctrl+Alt+A" | "Ctrl+Alt+E" | "Ctrl+Alt+F" | "Ctrl+Alt+G" | "Ctrl+Alt+H" | "Ctrl+Alt+I" | "Ctrl+Alt+J" | "Ctrl+Alt+K" | "Ctrl+Alt+L" | "Ctrl+Alt+N" | "Ctrl+Alt+O" | "Ctrl+Alt+Q" | "Ctrl+Alt+R" | "Ctrl+Alt+S" | "Ctrl+Alt+T" | "Ctrl+Alt+U" | "Ctrl+Alt+V" | "Ctrl+Alt+W" | "Ctrl+Alt+X" | "Ctrl+Alt+Y" | "Ctrl+Alt+Z" | "Ctrl+Alt+Space" | "Ctrl+Alt+Digit0" | "Ctrl+Alt+Digit1" | "Ctrl+Alt+Digit2" | "Ctrl+Alt+Digit3" | "Ctrl+Alt+Digit4" | "Ctrl+Alt+Digit5" | "Ctrl+Alt+Digit6" | "Ctrl+Alt+Digit7" | "Ctrl+Alt+Digit8" | "Ctrl+Alt+Digit9" | "Ctrl+Alt+Minus" | "Ctrl+Alt+Equal" | "Ctrl+Alt+Slash" | "Ctrl+Alt+Backslash" | "Ctrl+Alt+Comma" | "Ctrl+Alt+Period" | "Ctrl+Alt+Semicolon" | "Ctrl+Alt+Quote" | "Ctrl+Alt+BracketLeft" | "Ctrl+Alt+BracketRight" | "Ctrl+Alt+Plus" | "Ctrl+Alt+Backtick" | "Ctrl+Alt+Shift+P" | "Ctrl+Alt+Shift+B" | "Ctrl+Alt+Shift+D" | "Ctrl+Alt+Shift+C" | "Ctrl+Alt+Shift+M" | "Ctrl+Alt+Shift+F1" | "Ctrl+Alt+Shift+F2" | "Ctrl+Alt+Shift+F3" | "Ctrl+Alt+Shift+F4" | "Ctrl+Alt+Shift+F5" | "Ctrl+Alt+Shift+F6" | "Ctrl+Alt+Shift+F7" | "Ctrl+Alt+Shift+F8" | "Ctrl+Alt+Shift+F9" | "Ctrl+Alt+Shift+F10" | "Ctrl+Alt+Shift+F11" | "Ctrl+Alt+Shift+F12" | "Ctrl+Alt+Shift+Escape" | "Ctrl+Alt+Shift+Enter" | "Ctrl+Alt+Shift+Tab" | "Ctrl+Alt+Shift+Backspace" | "Ctrl+Alt+Shift+Delete" | "Ctrl+Alt+Shift+Insert" | "Ctrl+Alt+Shift+ArrowUp" | "Ctrl+Alt+Shift+ArrowDown" | "Ctrl+Alt+Shift+ArrowLeft" | "Ctrl+Alt+Shift+ArrowRight" | "Ctrl+Alt+Shift+Home" | "Ctrl+Alt+Shift+End" | "Ctrl+Alt+Shift+PageUp" | "Ctrl+Alt+Shift+PageDown" | "Ctrl+Alt+Shift+A" | "Ctrl+Alt+Shift+E" | "Ctrl+Alt+Shift+F" | "Ctrl+Alt+Shift+G" | "Ctrl+Alt+Shift+H" | "Ctrl+Alt+Shift+I" | "Ctrl+Alt+Shift+J" | "Ctrl+Alt+Shift+K" | "Ctrl+Alt+Shift+L" | "Ctrl+Alt+Shift+N" | "Ctrl+Alt+Shift+O" | "Ctrl+Alt+Shift+Q" | "Ctrl+Alt+Shift+R" | "Ctrl+Alt+Shift+S" | "Ctrl+Alt+Shift+T" | "Ctrl+Alt+Shift+U" | "Ctrl+Alt+Shift+V" | "Ctrl+Alt+Shift+W" | "Ctrl+Alt+Shift+X" | "Ctrl+Alt+Shift+Y" | "Ctrl+Alt+Shift+Z" | "Ctrl+Alt+Shift+Space" | "Ctrl+Alt+Shift+Digit0" | "Ctrl+Alt+Shift+Digit1" | "Ctrl+Alt+Shift+Digit2" | "Ctrl+Alt+Shift+Digit3" | "Ctrl+Alt+Shift+Digit4" | "Ctrl+Alt+Shift+Digit5" | "Ctrl+Alt+Shift+Digit6" | "Ctrl+Alt+Shift+Digit7" | "Ctrl+Alt+Shift+Digit8" | "Ctrl+Alt+Shift+Digit9" | "Ctrl+Alt+Shift+Minus" | "Ctrl+Alt+Shift+Equal" | "Ctrl+Alt+Shift+Slash" | "Ctrl+Alt+Shift+Backslash" | "Ctrl+Alt+Shift+Comma" | "Ctrl+Alt+Shift+Period" | "Ctrl+Alt+Shift+Semicolon" | "Ctrl+Alt+Shift+Quote" | "Ctrl+Alt+Shift+BracketLeft" | "Ctrl+Alt+Shift+BracketRight" | "Ctrl+Alt+Shift+Plus" | "Ctrl+Alt+Shift+Backtick" | "Mod+P" | "Mod+B" | "Mod+D" | "Mod+C" | "Mod+M" | "Mod+F1" | "Mod+F2" | "Mod+F3" | "Mod+F4" | "Mod+F5" | "Mod+F6" | "Mod+F7" | "Mod+F8" | "Mod+F9" | "Mod+F10" | "Mod+F11" | "Mod+F12" | "Mod+Escape" | "Mod+Enter" | "Mod+Tab" | "Mod+Backspace" | "Mod+Delete" | "Mod+Insert" | "Mod+ArrowUp" | "Mod+ArrowDown" | "Mod+ArrowLeft" | "Mod+ArrowRight" | "Mod+Home" | "Mod+End" | "Mod+PageUp" | "Mod+PageDown" | "Mod+A" | "Mod+E" | "Mod+F" | "Mod+G" | "Mod+H" | "Mod+I" | "Mod+J" | "Mod+K" | "Mod+L" | "Mod+N" | "Mod+O" | "Mod+Q" | "Mod+R" | "Mod+S" | "Mod+T" | "Mod+U" | "Mod+V" | "Mod+W" | "Mod+X" | "Mod+Y" | "Mod+Z" | "Mod+Space" | "Mod+Digit0" | "Mod+Digit1" | "Mod+Digit2" | "Mod+Digit3" | "Mod+Digit4" | "Mod+Digit5" | "Mod+Digit6" | "Mod+Digit7" | "Mod+Digit8" | "Mod+Digit9" | "Mod+Minus" | "Mod+Equal" | "Mod+Slash" | "Mod+Backslash" | "Mod+Comma" | "Mod+Period" | "Mod+Semicolon" | "Mod+Quote" | "Mod+BracketLeft" | "Mod+BracketRight" | "Mod+Plus" | "Mod+Backtick" | "Mod+Shift+P" | "Mod+Shift+B" | "Mod+Shift+D" | "Mod+Shift+C" | "Mod+Shift+M" | "Mod+Shift+F1" | "Mod+Shift+F2" | "Mod+Shift+F3" | "Mod+Shift+F4" | "Mod+Shift+F5" | "Mod+Shift+F6" | "Mod+Shift+F7" | "Mod+Shift+F8" | "Mod+Shift+F9" | "Mod+Shift+F10" | "Mod+Shift+F11" | "Mod+Shift+F12" | "Mod+Shift+Escape" | "Mod+Shift+Enter" | "Mod+Shift+Tab" | "Mod+Shift+Backspace" | "Mod+Shift+Delete" | "Mod+Shift+Insert" | "Mod+Shift+ArrowUp" | "Mod+Shift+ArrowDown" | "Mod+Shift+ArrowLeft" | "Mod+Shift+ArrowRight" | "Mod+Shift+Home" | "Mod+Shift+End" | "Mod+Shift+PageUp" | "Mod+Shift+PageDown" | "Mod+Shift+A" | "Mod+Shift+E" | "Mod+Shift+F" | "Mod+Shift+G" | "Mod+Shift+H" | "Mod+Shift+I" | "Mod+Shift+J" | "Mod+Shift+K" | "Mod+Shift+L" | "Mod+Shift+N" | "Mod+Shift+O" | "Mod+Shift+Q" | "Mod+Shift+R" | "Mod+Shift+S" | "Mod+Shift+T" | "Mod+Shift+U" | "Mod+Shift+V" | "Mod+Shift+W" | "Mod+Shift+X" | "Mod+Shift+Y" | "Mod+Shift+Z" | "Mod+Shift+Space" | "Mod+Shift+Digit0" | "Mod+Shift+Digit1" | "Mod+Shift+Digit2" | "Mod+Shift+Digit3" | "Mod+Shift+Digit4" | "Mod+Shift+Digit5" | "Mod+Shift+Digit6" | "Mod+Shift+Digit7" | "Mod+Shift+Digit8" | "Mod+Shift+Digit9" | "Mod+Shift+Minus" | "Mod+Shift+Equal" | "Mod+Shift+Slash" | "Mod+Shift+Backslash" | "Mod+Shift+Comma" | "Mod+Shift+Period" | "Mod+Shift+Semicolon" | "Mod+Shift+Quote" | "Mod+Shift+BracketLeft" | "Mod+Shift+BracketRight" | "Mod+Shift+Plus" | "Mod+Shift+Backtick" | "Mod+Alt+P" | "Mod+Alt+B" | "Mod+Alt+D" | "Mod+Alt+C" | "Mod+Alt+M" | "Mod+Alt+F1" | "Mod+Alt+F2" | "Mod+Alt+F3" | "Mod+Alt+F4" | "Mod+Alt+F5" | "Mod+Alt+F6" | "Mod+Alt+F7" | "Mod+Alt+F8" | "Mod+Alt+F9" | "Mod+Alt+F10" | "Mod+Alt+F11" | "Mod+Alt+F12" | "Mod+Alt+Escape" | "Mod+Alt+Enter" | "Mod+Alt+Tab" | "Mod+Alt+Backspace" | "Mod+Alt+Delete" | "Mod+Alt+Insert" | "Mod+Alt+ArrowUp" | "Mod+Alt+ArrowDown" | "Mod+Alt+ArrowLeft" | "Mod+Alt+ArrowRight" | "Mod+Alt+Home" | "Mod+Alt+End" | "Mod+Alt+PageUp" | "Mod+Alt+PageDown" | "Mod+Alt+A" | "Mod+Alt+E" | "Mod+Alt+F" | "Mod+Alt+G" | "Mod+Alt+H" | "Mod+Alt+I" | "Mod+Alt+J" | "Mod+Alt+K" | "Mod+Alt+L" | "Mod+Alt+N" | "Mod+Alt+O" | "Mod+Alt+Q" | "Mod+Alt+R" | "Mod+Alt+S" | "Mod+Alt+T" | "Mod+Alt+U" | "Mod+Alt+V" | "Mod+Alt+W" | "Mod+Alt+X" | "Mod+Alt+Y" | "Mod+Alt+Z" | "Mod+Alt+Space" | "Mod+Alt+Digit0" | "Mod+Alt+Digit1" | "Mod+Alt+Digit2" | "Mod+Alt+Digit3" | "Mod+Alt+Digit4" | "Mod+Alt+Digit5" | "Mod+Alt+Digit6" | "Mod+Alt+Digit7" | "Mod+Alt+Digit8" | "Mod+Alt+Digit9" | "Mod+Alt+Minus" | "Mod+Alt+Equal" | "Mod+Alt+Slash" | "Mod+Alt+Backslash" | "Mod+Alt+Comma" | "Mod+Alt+Period" | "Mod+Alt+Semicolon" | "Mod+Alt+Quote" | "Mod+Alt+BracketLeft" | "Mod+Alt+BracketRight" | "Mod+Alt+Plus" | "Mod+Alt+Backtick" | "Mod+Alt+Shift+P" | "Mod+Alt+Shift+B" | "Mod+Alt+Shift+D" | "Mod+Alt+Shift+C" | "Mod+Alt+Shift+M" | "Mod+Alt+Shift+F1" | "Mod+Alt+Shift+F2" | "Mod+Alt+Shift+F3" | "Mod+Alt+Shift+F4" | "Mod+Alt+Shift+F5" | "Mod+Alt+Shift+F6" | "Mod+Alt+Shift+F7" | "Mod+Alt+Shift+F8" | "Mod+Alt+Shift+F9" | "Mod+Alt+Shift+F10" | "Mod+Alt+Shift+F11" | "Mod+Alt+Shift+F12" | "Mod+Alt+Shift+Escape" | "Mod+Alt+Shift+Enter" | "Mod+Alt+Shift+Tab" | "Mod+Alt+Shift+Backspace" | "Mod+Alt+Shift+Delete" | "Mod+Alt+Shift+Insert" | "Mod+Alt+Shift+ArrowUp" | "Mod+Alt+Shift+ArrowDown" | "Mod+Alt+Shift+ArrowLeft" | "Mod+Alt+Shift+ArrowRight" | "Mod+Alt+Shift+Home" | "Mod+Alt+Shift+End" | "Mod+Alt+Shift+PageUp" | "Mod+Alt+Shift+PageDown" | "Mod+Alt+Shift+A" | "Mod+Alt+Shift+E" | "Mod+Alt+Shift+F" | "Mod+Alt+Shift+G" | "Mod+Alt+Shift+H" | "Mod+Alt+Shift+I" | "Mod+Alt+Shift+J" | "Mod+Alt+Shift+K" | "Mod+Alt+Shift+L" | "Mod+Alt+Shift+N" | "Mod+Alt+Shift+O" | "Mod+Alt+Shift+Q" | "Mod+Alt+Shift+R" | "Mod+Alt+Shift+S" | "Mod+Alt+Shift+T" | "Mod+Alt+Shift+U" | "Mod+Alt+Shift+V" | "Mod+Alt+Shift+W" | "Mod+Alt+Shift+X" | "Mod+Alt+Shift+Y" | "Mod+Alt+Shift+Z" | "Mod+Alt+Shift+Space" | "Mod+Alt+Shift+Digit0" | "Mod+Alt+Shift+Digit1" | "Mod+Alt+Shift+Digit2" | "Mod+Alt+Shift+Digit3" | "Mod+Alt+Shift+Digit4" | "Mod+Alt+Shift+Digit5" | "Mod+Alt+Shift+Digit6" | "Mod+Alt+Shift+Digit7" | "Mod+Alt+Shift+Digit8" | "Mod+Alt+Shift+Digit9" | "Mod+Alt+Shift+Minus" | "Mod+Alt+Shift+Equal" | "Mod+Alt+Shift+Slash" | "Mod+Alt+Shift+Backslash" | "Mod+Alt+Shift+Comma" | "Mod+Alt+Shift+Period" | "Mod+Alt+Shift+Semicolon" | "Mod+Alt+Shift+Quote" | "Mod+Alt+Shift+BracketLeft" | "Mod+Alt+Shift+BracketRight" | "Mod+Alt+Shift+Plus" | "Mod+Alt+Shift+Backtick" | "Mod+Ctrl+P" | "Mod+Ctrl+B" | "Mod+Ctrl+D" | "Mod+Ctrl+C" | "Mod+Ctrl+M" | "Mod+Ctrl+F1" | "Mod+Ctrl+F2" | "Mod+Ctrl+F3" | "Mod+Ctrl+F4" | "Mod+Ctrl+F5" | "Mod+Ctrl+F6" | "Mod+Ctrl+F7" | "Mod+Ctrl+F8" | "Mod+Ctrl+F9" | "Mod+Ctrl+F10" | "Mod+Ctrl+F11" | "Mod+Ctrl+F12" | "Mod+Ctrl+Escape" | "Mod+Ctrl+Enter" | "Mod+Ctrl+Tab" | "Mod+Ctrl+Backspace" | "Mod+Ctrl+Delete" | "Mod+Ctrl+Insert" | "Mod+Ctrl+ArrowUp" | "Mod+Ctrl+ArrowDown" | "Mod+Ctrl+ArrowLeft" | "Mod+Ctrl+ArrowRight" | "Mod+Ctrl+Home" | "Mod+Ctrl+End" | "Mod+Ctrl+PageUp" | "Mod+Ctrl+PageDown" | "Mod+Ctrl+A" | "Mod+Ctrl+E" | "Mod+Ctrl+F" | "Mod+Ctrl+G" | "Mod+Ctrl+H" | "Mod+Ctrl+I" | "Mod+Ctrl+J" | "Mod+Ctrl+K" | "Mod+Ctrl+L" | "Mod+Ctrl+N" | "Mod+Ctrl+O" | "Mod+Ctrl+Q" | "Mod+Ctrl+R" | "Mod+Ctrl+S" | "Mod+Ctrl+T" | "Mod+Ctrl+U" | "Mod+Ctrl+V" | "Mod+Ctrl+W" | "Mod+Ctrl+X" | "Mod+Ctrl+Y" | "Mod+Ctrl+Z" | "Mod+Ctrl+Space" | "Mod+Ctrl+Digit0" | "Mod+Ctrl+Digit1" | "Mod+Ctrl+Digit2" | "Mod+Ctrl+Digit3" | "Mod+Ctrl+Digit4" | "Mod+Ctrl+Digit5" | "Mod+Ctrl+Digit6" | "Mod+Ctrl+Digit7" | "Mod+Ctrl+Digit8" | "Mod+Ctrl+Digit9" | "Mod+Ctrl+Minus" | "Mod+Ctrl+Equal" | "Mod+Ctrl+Slash" | "Mod+Ctrl+Backslash" | "Mod+Ctrl+Comma" | "Mod+Ctrl+Period" | "Mod+Ctrl+Semicolon" | "Mod+Ctrl+Quote" | "Mod+Ctrl+BracketLeft" | "Mod+Ctrl+BracketRight" | "Mod+Ctrl+Plus" | "Mod+Ctrl+Backtick" | "Mod+Ctrl+Shift+P" | "Mod+Ctrl+Shift+B" | "Mod+Ctrl+Shift+D" | "Mod+Ctrl+Shift+C" | "Mod+Ctrl+Shift+M" | "Mod+Ctrl+Shift+F1" | "Mod+Ctrl+Shift+F2" | "Mod+Ctrl+Shift+F3" | "Mod+Ctrl+Shift+F4" | "Mod+Ctrl+Shift+F5" | "Mod+Ctrl+Shift+F6" | "Mod+Ctrl+Shift+F7" | "Mod+Ctrl+Shift+F8" | "Mod+Ctrl+Shift+F9" | "Mod+Ctrl+Shift+F10" | "Mod+Ctrl+Shift+F11" | "Mod+Ctrl+Shift+F12" | "Mod+Ctrl+Shift+Escape" | "Mod+Ctrl+Shift+Enter" | "Mod+Ctrl+Shift+Tab" | "Mod+Ctrl+Shift+Backspace" | "Mod+Ctrl+Shift+Delete" | "Mod+Ctrl+Shift+Insert" | "Mod+Ctrl+Shift+ArrowUp" | "Mod+Ctrl+Shift+ArrowDown" | "Mod+Ctrl+Shift+ArrowLeft" | "Mod+Ctrl+Shift+ArrowRight" | "Mod+Ctrl+Shift+Home" | "Mod+Ctrl+Shift+End" | "Mod+Ctrl+Shift+PageUp" | "Mod+Ctrl+Shift+PageDown" | "Mod+Ctrl+Shift+A" | "Mod+Ctrl+Shift+E" | "Mod+Ctrl+Shift+F" | "Mod+Ctrl+Shift+G" | "Mod+Ctrl+Shift+H" | "Mod+Ctrl+Shift+I" | "Mod+Ctrl+Shift+J" | "Mod+Ctrl+Shift+K" | "Mod+Ctrl+Shift+L" | "Mod+Ctrl+Shift+N" | "Mod+Ctrl+Shift+O" | "Mod+Ctrl+Shift+Q" | "Mod+Ctrl+Shift+R" | "Mod+Ctrl+Shift+S" | "Mod+Ctrl+Shift+T" | "Mod+Ctrl+Shift+U" | "Mod+Ctrl+Shift+V" | "Mod+Ctrl+Shift+W" | "Mod+Ctrl+Shift+X" | "Mod+Ctrl+Shift+Y" | "Mod+Ctrl+Shift+Z" | "Mod+Ctrl+Shift+Space" | "Mod+Ctrl+Shift+Digit0" | "Mod+Ctrl+Shift+Digit1" | "Mod+Ctrl+Shift+Digit2" | "Mod+Ctrl+Shift+Digit3" | "Mod+Ctrl+Shift+Digit4" | "Mod+Ctrl+Shift+Digit5" | "Mod+Ctrl+Shift+Digit6" | "Mod+Ctrl+Shift+Digit7" | "Mod+Ctrl+Shift+Digit8" | "Mod+Ctrl+Shift+Digit9" | "Mod+Ctrl+Shift+Minus" | "Mod+Ctrl+Shift+Equal" | "Mod+Ctrl+Shift+Slash" | "Mod+Ctrl+Shift+Backslash" | "Mod+Ctrl+Shift+Comma" | "Mod+Ctrl+Shift+Period" | "Mod+Ctrl+Shift+Semicolon" | "Mod+Ctrl+Shift+Quote" | "Mod+Ctrl+Shift+BracketLeft" | "Mod+Ctrl+Shift+BracketRight" | "Mod+Ctrl+Shift+Plus" | "Mod+Ctrl+Shift+Backtick" | "Mod+Ctrl+Alt+P" | "Mod+Ctrl+Alt+B" | "Mod+Ctrl+Alt+D" | "Mod+Ctrl+Alt+C" | "Mod+Ctrl+Alt+M" | "Mod+Ctrl+Alt+F1" | "Mod+Ctrl+Alt+F2" | "Mod+Ctrl+Alt+F3" | "Mod+Ctrl+Alt+F4" | "Mod+Ctrl+Alt+F5" | "Mod+Ctrl+Alt+F6" | "Mod+Ctrl+Alt+F7" | "Mod+Ctrl+Alt+F8" | "Mod+Ctrl+Alt+F9" | "Mod+Ctrl+Alt+F10" | "Mod+Ctrl+Alt+F11" | "Mod+Ctrl+Alt+F12" | "Mod+Ctrl+Alt+Escape" | "Mod+Ctrl+Alt+Enter" | "Mod+Ctrl+Alt+Tab" | "Mod+Ctrl+Alt+Backspace" | "Mod+Ctrl+Alt+Delete" | "Mod+Ctrl+Alt+Insert" | "Mod+Ctrl+Alt+ArrowUp" | "Mod+Ctrl+Alt+ArrowDown" | "Mod+Ctrl+Alt+ArrowLeft" | "Mod+Ctrl+Alt+ArrowRight" | "Mod+Ctrl+Alt+Home" | "Mod+Ctrl+Alt+End" | "Mod+Ctrl+Alt+PageUp" | "Mod+Ctrl+Alt+PageDown" | "Mod+Ctrl+Alt+A" | "Mod+Ctrl+Alt+E" | "Mod+Ctrl+Alt+F" | "Mod+Ctrl+Alt+G" | "Mod+Ctrl+Alt+H" | "Mod+Ctrl+Alt+I" | "Mod+Ctrl+Alt+J" | "Mod+Ctrl+Alt+K" | "Mod+Ctrl+Alt+L" | "Mod+Ctrl+Alt+N" | "Mod+Ctrl+Alt+O" | "Mod+Ctrl+Alt+Q" | "Mod+Ctrl+Alt+R" | "Mod+Ctrl+Alt+S" | "Mod+Ctrl+Alt+T" | "Mod+Ctrl+Alt+U" | "Mod+Ctrl+Alt+V" | "Mod+Ctrl+Alt+W" | "Mod+Ctrl+Alt+X" | "Mod+Ctrl+Alt+Y" | "Mod+Ctrl+Alt+Z" | "Mod+Ctrl+Alt+Space" | "Mod+Ctrl+Alt+Digit0" | "Mod+Ctrl+Alt+Digit1" | "Mod+Ctrl+Alt+Digit2" | "Mod+Ctrl+Alt+Digit3" | "Mod+Ctrl+Alt+Digit4" | "Mod+Ctrl+Alt+Digit5" | "Mod+Ctrl+Alt+Digit6" | "Mod+Ctrl+Alt+Digit7" | "Mod+Ctrl+Alt+Digit8" | "Mod+Ctrl+Alt+Digit9" | "Mod+Ctrl+Alt+Minus" | "Mod+Ctrl+Alt+Equal" | "Mod+Ctrl+Alt+Slash" | "Mod+Ctrl+Alt+Backslash" | "Mod+Ctrl+Alt+Comma" | "Mod+Ctrl+Alt+Period" | "Mod+Ctrl+Alt+Semicolon" | "Mod+Ctrl+Alt+Quote" | "Mod+Ctrl+Alt+BracketLeft" | "Mod+Ctrl+Alt+BracketRight" | "Mod+Ctrl+Alt+Plus" | "Mod+Ctrl+Alt+Backtick" | "Mod+Ctrl+Alt+Shift+P" | "Mod+Ctrl+Alt+Shift+B" | "Mod+Ctrl+Alt+Shift+D" | "Mod+Ctrl+Alt+Shift+C" | "Mod+Ctrl+Alt+Shift+M" | "Mod+Ctrl+Alt+Shift+F1" | "Mod+Ctrl+Alt+Shift+F2" | "Mod+Ctrl+Alt+Shift+F3" | "Mod+Ctrl+Alt+Shift+F4" | "Mod+Ctrl+Alt+Shift+F5" | "Mod+Ctrl+Alt+Shift+F6" | "Mod+Ctrl+Alt+Shift+F7" | "Mod+Ctrl+Alt+Shift+F8" | "Mod+Ctrl+Alt+Shift+F9" | "Mod+Ctrl+Alt+Shift+F10" | "Mod+Ctrl+Alt+Shift+F11" | "Mod+Ctrl+Alt+Shift+F12" | "Mod+Ctrl+Alt+Shift+Escape" | "Mod+Ctrl+Alt+Shift+Enter" | "Mod+Ctrl+Alt+Shift+Tab" | "Mod+Ctrl+Alt+Shift+Backspace" | "Mod+Ctrl+Alt+Shift+Delete" | "Mod+Ctrl+Alt+Shift+Insert" | "Mod+Ctrl+Alt+Shift+ArrowUp" | "Mod+Ctrl+Alt+Shift+ArrowDown" | "Mod+Ctrl+Alt+Shift+ArrowLeft" | "Mod+Ctrl+Alt+Shift+ArrowRight" | "Mod+Ctrl+Alt+Shift+Home" | "Mod+Ctrl+Alt+Shift+End" | "Mod+Ctrl+Alt+Shift+PageUp" | "Mod+Ctrl+Alt+Shift+PageDown" | "Mod+Ctrl+Alt+Shift+A" | "Mod+Ctrl+Alt+Shift+E" | "Mod+Ctrl+Alt+Shift+F" | "Mod+Ctrl+Alt+Shift+G" | "Mod+Ctrl+Alt+Shift+H" | "Mod+Ctrl+Alt+Shift+I" | "Mod+Ctrl+Alt+Shift+J" | "Mod+Ctrl+Alt+Shift+K" | "Mod+Ctrl+Alt+Shift+L" | "Mod+Ctrl+Alt+Shift+N" | "Mod+Ctrl+Alt+Shift+O" | "Mod+Ctrl+Alt+Shift+Q" | "Mod+Ctrl+Alt+Shift+R" | "Mod+Ctrl+Alt+Shift+S" | "Mod+Ctrl+Alt+Shift+T" | "Mod+Ctrl+Alt+Shift+U" | "Mod+Ctrl+Alt+Shift+V" | "Mod+Ctrl+Alt+Shift+W" | "Mod+Ctrl+Alt+Shift+X" | "Mod+Ctrl+Alt+Shift+Y" | "Mod+Ctrl+Alt+Shift+Z" | "Mod+Ctrl+Alt+Shift+Space" | "Mod+Ctrl+Alt+Shift+Digit0" | "Mod+Ctrl+Alt+Shift+Digit1" | "Mod+Ctrl+Alt+Shift+Digit2" | "Mod+Ctrl+Alt+Shift+Digit3" | "Mod+Ctrl+Alt+Shift+Digit4" | "Mod+Ctrl+Alt+Shift+Digit5" | "Mod+Ctrl+Alt+Shift+Digit6" | "Mod+Ctrl+Alt+Shift+Digit7" | "Mod+Ctrl+Alt+Shift+Digit8" | "Mod+Ctrl+Alt+Shift+Digit9" | "Mod+Ctrl+Alt+Shift+Minus" | "Mod+Ctrl+Alt+Shift+Equal" | "Mod+Ctrl+Alt+Shift+Slash" | "Mod+Ctrl+Alt+Shift+Backslash" | "Mod+Ctrl+Alt+Shift+Comma" | "Mod+Ctrl+Alt+Shift+Period" | "Mod+Ctrl+Alt+Shift+Semicolon" | "Mod+Ctrl+Alt+Shift+Quote" | "Mod+Ctrl+Alt+Shift+BracketLeft" | "Mod+Ctrl+Alt+Shift+BracketRight" | "Mod+Ctrl+Alt+Shift+Plus" | "Mod+Ctrl+Alt+Shift+Backtick" | "Mod+Shift+," | false

Shortcut that toggles the dialog. Pass `false` to disable it.

unmountOnHide
= true
boolean

Unmount a panel's content when its tab is inactive (reka-ui default: true). Set false to keep visited panels mounted (hidden) — preserves their state and scroll position across tab switches at the cost of memory.

open
= false
boolean

Controls whether the dialog is open.

tab
string | number

The selected tab — pairs with SettingsNavItem `:value` and SettingsPanel `:value`. Optional: leave unbound to let reka-ui manage selection internally, or bind `v-model:tab` to drive it (e.g. from the route).

title
—

Accessible dialog title (visually hidden). Defaults to "Settings".

description
—

Accessible dialog description (visually hidden, for aria-describedby).

default
—

Sidebar + content panes (compose SettingsSidebar and SettingsContent).

update:open
[value: boolean]

Fired when the open state changes.

update:tab
[value: string | number | undefined]

Fired when the tab changes.

SettingsSidebar ​

default
{}

SettingsNavGroup ​

Show types
typescript
import type { DialogSize } from '../Dialog/types'
import type { KeyboardShortcutCombo } from '../../composables/useKeyboardShortcut'

export interface SettingsDialogProps {
  /** Max-width size of the dialog. */
  size?: DialogSize

  /** Shortcut that toggles the dialog. Pass `false` to disable it. */
  keyboardShortcut?: KeyboardShortcutCombo | 'Mod+Shift+,' | false

  /**
   * Unmount a panel's content when its tab is inactive (reka-ui default: true).
   * Set false to keep visited panels mounted (hidden) — preserves their state
   * and scroll position across tab switches at the cost of memory.
   */
  unmountOnHide?: boolean
}

export interface SettingsDialogEmits {
  /** Fired when the dialog is opened or closed. */
  'update:open': [value: boolean]
}

/**
 * Shared with `ScrollArea` (imperative-api.md §2.5) once that component's own
 * sweep types its `defineExpose`. Kept local to this family until then.
 */
export interface SettingsBodyExposed {
  /** The element that actually scrolls. `null` before mount. */
  viewportElement: HTMLElement | null
}
label
string

Group heading shown above its items.

label
{}
default
{}

SettingsNavItem ​

Show types
typescript
import type { DialogSize } from '../Dialog/types'
import type { KeyboardShortcutCombo } from '../../composables/useKeyboardShortcut'

export interface SettingsDialogProps {
  /** Max-width size of the dialog. */
  size?: DialogSize

  /** Shortcut that toggles the dialog. Pass `false` to disable it. */
  keyboardShortcut?: KeyboardShortcutCombo | 'Mod+Shift+,' | false

  /**
   * Unmount a panel's content when its tab is inactive (reka-ui default: true).
   * Set false to keep visited panels mounted (hidden) — preserves their state
   * and scroll position across tab switches at the cost of memory.
   */
  unmountOnHide?: boolean
}

export interface SettingsDialogEmits {
  /** Fired when the dialog is opened or closed. */
  'update:open': [value: boolean]
}

/**
 * Shared with `ScrollArea` (imperative-api.md §2.5) once that component's own
 * sweep types its `defineExpose`. Kept local to this family until then.
 */
export interface SettingsBodyExposed {
  /** The element that actually scrolls. `null` before mount. */
  viewportElement: HTMLElement | null
}
value*
string | number

Unique tab id — must match the SettingsPanel `value` it controls.

default
—

Item label.

prefix
—

Leading icon or avatar.

suffix
—

Trailing badge / count.

SettingsContent ​

default
{}

SettingsPanel ​

Show types
typescript
import type { DialogSize } from '../Dialog/types'
import type { KeyboardShortcutCombo } from '../../composables/useKeyboardShortcut'

export interface SettingsDialogProps {
  /** Max-width size of the dialog. */
  size?: DialogSize

  /** Shortcut that toggles the dialog. Pass `false` to disable it. */
  keyboardShortcut?: KeyboardShortcutCombo | 'Mod+Shift+,' | false

  /**
   * Unmount a panel's content when its tab is inactive (reka-ui default: true).
   * Set false to keep visited panels mounted (hidden) — preserves their state
   * and scroll position across tab switches at the cost of memory.
   */
  unmountOnHide?: boolean
}

export interface SettingsDialogEmits {
  /** Fired when the dialog is opened or closed. */
  'update:open': [value: boolean]
}

/**
 * Shared with `ScrollArea` (imperative-api.md §2.5) once that component's own
 * sweep types its `defineExpose`. Kept local to this family until then.
 */
export interface SettingsBodyExposed {
  /** The element that actually scrolls. `null` before mount. */
  viewportElement: HTMLElement | null
}
value*
string | number

Unique tab id — must match the SettingsNavItem `value` that controls it.

default
{}

SettingsHeader ​

Show types
typescript
import type { DialogSize } from '../Dialog/types'
import type { KeyboardShortcutCombo } from '../../composables/useKeyboardShortcut'

export interface SettingsDialogProps {
  /** Max-width size of the dialog. */
  size?: DialogSize

  /** Shortcut that toggles the dialog. Pass `false` to disable it. */
  keyboardShortcut?: KeyboardShortcutCombo | 'Mod+Shift+,' | false

  /**
   * Unmount a panel's content when its tab is inactive (reka-ui default: true).
   * Set false to keep visited panels mounted (hidden) — preserves their state
   * and scroll position across tab switches at the cost of memory.
   */
  unmountOnHide?: boolean
}

export interface SettingsDialogEmits {
  /** Fired when the dialog is opened or closed. */
  'update:open': [value: boolean]
}

/**
 * Shared with `ScrollArea` (imperative-api.md §2.5) once that component's own
 * sweep types its `defineExpose`. Kept local to this family until then.
 */
export interface SettingsBodyExposed {
  /** The element that actually scrolls. `null` before mount. */
  viewportElement: HTMLElement | null
}
title
string

Convenience heading. Omit and use the default slot for a custom header.

description
string

Optional sub-heading under the title.

default
—

Replaces the entire header (title/description/actions) with custom content.

actions
—

Actions on the right of the default title header.

SettingsBody ​

default
{}
viewportElement
HTMLElement | null

The element that actually scrolls. `null` before mount.

SettingsRow ​

Show types
typescript
import type { DialogSize } from '../Dialog/types'
import type { KeyboardShortcutCombo } from '../../composables/useKeyboardShortcut'

export interface SettingsDialogProps {
  /** Max-width size of the dialog. */
  size?: DialogSize

  /** Shortcut that toggles the dialog. Pass `false` to disable it. */
  keyboardShortcut?: KeyboardShortcutCombo | 'Mod+Shift+,' | false

  /**
   * Unmount a panel's content when its tab is inactive (reka-ui default: true).
   * Set false to keep visited panels mounted (hidden) — preserves their state
   * and scroll position across tab switches at the cost of memory.
   */
  unmountOnHide?: boolean
}

export interface SettingsDialogEmits {
  /** Fired when the dialog is opened or closed. */
  'update:open': [value: boolean]
}

/**
 * Shared with `ScrollArea` (imperative-api.md §2.5) once that component's own
 * sweep types its `defineExpose`. Kept local to this family until then.
 */
export interface SettingsBodyExposed {
  /** The element that actually scrolls. `null` before mount. */
  viewportElement: HTMLElement | null
}
title*
string

Setting name, rendered on the left.

description
string

Optional helper text under the title.

labelFor
string

Explicit id to associate the title label with. Overrides auto-detection.

default
{}