Skip to main content
Version: 1.x

Checkbox

CommandKit provides Checkbox, CheckboxGroup, and CheckboxGroupOption for building checkbox inputs using Discord's component builders.

Basic usage

Use CheckboxGroup when you want the user to pick one or more items from a list of options:

src/app/commands/checkbox-group.tsx
import {
type ChatInputCommand,
type OnModalKitSubmit,
Modal,
Label,
CheckboxGroup,
CheckboxGroupOption,
} from 'commandkit';
import { MessageFlags } from 'discord.js';

const handleSubmit: OnModalKitSubmit = async (interaction, context) => {
// returns a string[] of all selected checkbox values
const preferences = interaction.fields.getCheckboxGroup('notifications');

await interaction.reply({
content: 'Thanks! Preferences saved.',
flags: MessageFlags.Ephemeral,
});

// Clean up the modal context
context.dispose();
};

export const chatInput: ChatInputCommand = async ({ interaction }) => {
const modal = (
<Modal title="Preferences" onSubmit={handleSubmit}>
<Label
label="Notifications"
description="Select all notifications you want to receive"
>
<CheckboxGroup customId="notifications" required>
<CheckboxGroupOption
label="Releases"
value="releases"
description="New CommandKit releases"
/>
<CheckboxGroupOption
label="Incidents"
value="incidents"
description="Service disruptions"
/>
<CheckboxGroupOption
label="Tips"
value="tips"
description="Occasional usage tips"
/>
</CheckboxGroup>
</Label>
</Modal>
);

await interaction.showModal(modal);
};

Descriptions

To provide more context about the options, you can add descriptions to CheckboxGroupOption:

src/app/commands/checkbox-descriptions.tsx
import {
type ChatInputCommand,
type OnModalKitSubmit,
Modal,
Label,
CheckboxGroup,
CheckboxGroupOption,
} from 'commandkit';
import { MessageFlags } from 'discord.js';

const handleSubmit: OnModalKitSubmit = async (interaction, context) => {
const preferences = interaction.fields.getCheckboxGroup('features');

await interaction.reply({
content: 'Saved!',
flags: MessageFlags.Ephemeral,
});

context.dispose();
};

export const chatInput: ChatInputCommand = async ({ interaction }) => {
const modal = (
<Modal title="Feature Feedback" onSubmit={handleSubmit}>
<Label label="Features" description="Which features do you use the most?">
<CheckboxGroup customId="features">
<CheckboxGroupOption
label="Modals"
value="modals"
description="For collecting structured input"
/>
<CheckboxGroupOption
label="Select Menus"
value="selects"
description="For picking from a list of options"
/>
<CheckboxGroupOption
label="Buttons"
value="buttons"
description="For quick actions and confirmations"
/>
</CheckboxGroup>
</Label>
</Modal>
);

await interaction.showModal(modal);
};

Default selections

Use default on CheckboxGroupOption to pre-select options:

src/app/commands/default-checkboxes.tsx
import {
type ChatInputCommand,
type OnModalKitSubmit,
Modal,
Label,
CheckboxGroup,
CheckboxGroupOption,
} from 'commandkit';
import { MessageFlags } from 'discord.js';

const handleSubmit: OnModalKitSubmit = async (interaction, context) => {
const preferences = interaction.fields.getCheckboxGroup('topics');

await interaction.reply({
content: 'Saved!',
flags: MessageFlags.Ephemeral,
});

context.dispose();
};

export const chatInput: ChatInputCommand = async ({ interaction }) => {
const modal = (
<Modal title="Newsletter" onSubmit={handleSubmit}>
<Label label="Topics" description="Uncheck anything you're not into">
<CheckboxGroup customId="topics">
<CheckboxGroupOption label="Announcements" value="news" default />
<CheckboxGroupOption label="Tutorials" value="tutorials" default />
<CheckboxGroupOption label="Community" value="community" />
</CheckboxGroup>
</Label>
</Modal>
);

await interaction.showModal(modal);
};

Min/max values

You can enforce how many options the user must pick via minValues and maxValues:

src/app/commands/checkbox-limits.tsx
import {
type ChatInputCommand,
type OnModalKitSubmit,
Modal,
Label,
CheckboxGroup,
CheckboxGroupOption,
} from 'commandkit';
import { MessageFlags } from 'discord.js';

const handleSubmit: OnModalKitSubmit = async (interaction, context) => {
const preferences = interaction.fields.getCheckboxGroup('topics');

await interaction.reply({
content: 'Saved!',
flags: MessageFlags.Ephemeral,
});

context.dispose();
};

export const chatInput: ChatInputCommand = async ({ interaction }) => {
const modal = (
<Modal title="Project Setup" onSubmit={handleSubmit}>
<Label label="Tools" description="Pick 2 to 4 tools">
<CheckboxGroup customId="tools" minValues={2} maxValues={4}>
<CheckboxGroupOption label="TypeScript" value="ts" />
<CheckboxGroupOption label="ESLint" value="eslint" />
<CheckboxGroupOption label="Prettier" value="prettier" />
<CheckboxGroupOption label="Vitest" value="vitest" />
<CheckboxGroupOption label="Playwright" value="playwright" />
</CheckboxGroup>
</Label>
</Modal>
);

await interaction.showModal(modal);
};

Single checkbox

Use Checkbox for a single boolean input. It can be useful when you want a simple "yes/no" toggle:

src/app/commands/single-checkbox.tsx
import {
type ChatInputCommand,
type OnModalKitSubmit,
Modal,
Label,
Checkbox,
} from 'commandkit';
import { MessageFlags } from 'discord.js';

const handleSubmit: OnModalKitSubmit = async (interaction, context) => {
// returns a boolean indicating whether the checkbox is checked
const agree = interaction.fields.getCheckbox('agree');

await interaction.reply({
content: 'Saved!',
flags: MessageFlags.Ephemeral,
});

context.dispose();
};

export const chatInput: ChatInputCommand = async ({ interaction }) => {
const modal = (
<Modal title="Rules" onSubmit={handleSubmit}>
<Label label="I agree to the rules">
<Checkbox customId="agree" />
</Label>
</Modal>
);

await interaction.showModal(modal);
};