Documentation Index
Fetch the complete documentation index at: https://mintlify.com/betterdiscord/betterdiscord/llms.txt
Use this file to discover all available pages before exploring further.
BetterDiscord provides a comprehensive settings system with pre-built React components for common input types.
Basic settings panel
Implement getSettingsPanel() in your plugin to return a settings UI:
getSettingsPanel() {
return BdApi.UI.buildSettingsPanel({
settings: [
{
type: "switch",
id: "enabled",
name: "Enable Feature",
note: "Toggle the main feature on or off",
value: this.settings.enabled,
onChange: (value) => {
this.settings.enabled = value;
this.saveSettings();
}
}
]
});
}
Setting types
BetterDiscord supports multiple setting component types:
Switch
Boolean toggle switch:
{
type: "switch",
id: "enableNotifications",
name: "Enable Notifications",
note: "Show notifications when events occur",
value: this.settings.enableNotifications,
onChange: (value) => {
this.settings.enableNotifications = value;
this.saveSettings();
}
}
Text input
Single-line text input:
{
type: "text",
id: "username",
name: "Username",
note: "Enter your username",
value: this.settings.username,
placeholder: "Enter username...",
onChange: (value) => {
this.settings.username = value;
this.saveSettings();
}
}
Numeric input with optional min/max:
{
type: "number",
id: "maxItems",
name: "Maximum Items",
note: "Maximum number of items to display",
value: this.settings.maxItems,
min: 1,
max: 100,
onChange: (value) => {
this.settings.maxItems = value;
this.saveSettings();
}
}
Slider
Range slider with visual feedback:
{
type: "slider",
id: "volume",
name: "Volume",
note: "Adjust the volume level",
value: this.settings.volume,
min: 0,
max: 100,
step: 5,
units: "%",
markers: [0, 25, 50, 75, 100],
onChange: (value) => {
this.settings.volume = value;
this.saveSettings();
}
}
Array of numbers or marker objects: {value: number, label: string}
Dropdown
Select from a list of options:
{
type: "dropdown",
id: "theme",
name: "Theme",
note: "Choose your preferred theme",
value: this.settings.theme,
options: [
{label: "Light", value: "light"},
{label: "Dark", value: "dark"},
{label: "Auto", value: "auto"}
],
onChange: (value) => {
this.settings.theme = value;
this.saveSettings();
}
}
Exclusive selection with descriptions:
{
type: "radio",
id: "displayMode",
name: "Display Mode",
note: "Choose how to display content",
value: this.settings.displayMode,
options: [
{
name: "Compact",
value: "compact",
description: "Show minimal information"
},
{
name: "Cozy",
value: "cozy",
description: "Balanced view"
},
{
name: "Expanded",
value: "expanded",
description: "Show all details",
color: "#5865F2"
}
],
onChange: (value) => {
this.settings.displayMode = value;
this.saveSettings();
}
}
Color picker
Color selection with swatches:
{
type: "color",
id: "accentColor",
name: "Accent Color",
note: "Choose your accent color",
value: this.settings.accentColor,
defaultValue: "#5865F2",
onChange: (value) => {
this.settings.accentColor = value;
this.saveSettings();
}
}
Value can be a hex string ("#5865F2") or integer (5793522).
Keybind
Keyboard shortcut recorder:
{
type: "keybind",
id: "toggleShortcut",
name: "Toggle Shortcut",
note: "Press keys to set shortcut",
value: this.settings.toggleShortcut,
max: 3,
clearable: true,
onChange: (value) => {
this.settings.toggleShortcut = value;
this.saveSettings();
}
}
Value is an array of key names: ["Control", "Shift", "K"]
Organizing settings
Group related settings using categories:
getSettingsPanel() {
return BdApi.UI.buildSettingsPanel({
settings: [
{
type: "category",
id: "appearance",
name: "Appearance",
collapsible: true,
shown: true,
settings: [
{
type: "color",
id: "accentColor",
name: "Accent Color",
value: this.settings.accentColor,
onChange: (value) => this.updateSetting("accentColor", value)
},
{
type: "slider",
id: "opacity",
name: "Opacity",
value: this.settings.opacity,
min: 0,
max: 100,
onChange: (value) => this.updateSetting("opacity", value)
}
]
},
{
type: "category",
id: "behavior",
name: "Behavior",
collapsible: true,
shown: false,
settings: [
{
type: "switch",
id: "autoStart",
name: "Auto Start",
value: this.settings.autoStart,
onChange: (value) => this.updateSetting("autoStart", value)
}
]
}
],
onChange: (category, id, value) => {
this.api.Logger.info(`Setting changed: ${category}/${id} = ${value}`);
}
});
}
Persisting settings
Save and load settings using BdApi.Data:
module.exports = class MyPlugin {
constructor() {
this.api = new BdApi("MyPlugin");
this.defaultSettings = {
enabled: true,
theme: "dark",
volume: 50
};
}
start() {
this.loadSettings();
}
loadSettings() {
this.settings = this.api.Data.load("settings");
// Merge with defaults for any missing keys
if (!this.settings) {
this.settings = {...this.defaultSettings};
} else {
this.settings = {...this.defaultSettings, ...this.settings};
}
}
saveSettings() {
this.api.Data.save("settings", this.settings);
}
updateSetting(key, value) {
this.settings[key] = value;
this.saveSettings();
// Apply setting immediately
this.applySetting(key, value);
}
applySetting(key, value) {
switch(key) {
case "theme":
this.applyTheme(value);
break;
case "volume":
this.setVolume(value);
break;
}
}
};
Advanced: Custom components
For complex settings, use custom React components:
getSettingsPanel() {
const {React} = BdApi;
const CustomSetting = () => {
const [value, setValue] = React.useState(this.settings.custom);
return React.createElement("div", {className: "custom-setting"},
React.createElement("h3", {}, "Custom Setting"),
React.createElement("input", {
type: "range",
min: 0,
max: 100,
value: value,
onChange: (e) => {
setValue(e.target.value);
this.updateSetting("custom", e.target.value);
}
}),
React.createElement("span", {}, value)
);
};
return BdApi.UI.buildSettingsPanel({
settings: [
{
type: "custom",
id: "customSetting",
name: "Advanced Setting",
note: "This is a custom component",
children: React.createElement(CustomSetting)
}
]
});
}
Using BdApi.Components
Access individual setting components directly:
getSettingsPanel() {
const {React, Components} = BdApi;
const {SettingItem, SwitchInput, SliderInput, SettingGroup} = Components;
return React.createElement(SettingGroup, {},
React.createElement(SettingItem, {
id: "enable-feature",
name: "Enable Feature",
note: "Toggle this feature"
},
React.createElement(SwitchInput, {
value: this.settings.enabled,
onChange: (value) => this.updateSetting("enabled", value)
})
),
React.createElement(SettingItem, {
id: "volume",
name: "Volume",
note: "Adjust volume level"
},
React.createElement(SliderInput, {
value: this.settings.volume,
min: 0,
max: 100,
units: "%",
onChange: (value) => this.updateSetting("volume", value)
})
)
);
}
Component props reference
All setting components accept these common props:
Current value of the setting
Callback when value changes: (newValue) => void
Whether the input is disabled (default: false)
See the type definitions in the source for component-specific props:
- SwitchInput:
~/workspace/source/src/betterdiscord/ui/settings/components/switch.tsx:7-13
- SliderInput:
~/workspace/source/src/betterdiscord/ui/settings/components/slider.tsx:13-22
- TextInput:
~/workspace/source/src/betterdiscord/ui/settings/components/textbox.tsx:8-15
- DropdownInput:
~/workspace/source/src/betterdiscord/ui/settings/components/dropdown.tsx:9-21
- RadioInput:
~/workspace/source/src/betterdiscord/ui/settings/components/radio.tsx:18-24
- ColorInput:
~/workspace/source/src/betterdiscord/ui/settings/components/color.tsx:50-56
- KeybindInput:
~/workspace/source/src/betterdiscord/ui/settings/components/keybind.tsx:11-17