Skip to content

Commit 8c3348c

Browse files
authored
Implement checkbox and radio group components (#625)
* chore: update pnpm approved builds * chore: bump discord.js version for checkbox support * feat: implement checkbox and radio group components * feat: add checkbox and radio exports to component index * feat: add documentation for Checkbox and Radio components * chore: revert pnpm approved builds * feat: add descriptions to CheckboxGroupOption in documentation * feat: add descriptions to RadioGroupOption in documentation and update default selection example to be less weird
1 parent e561108 commit 8c3348c

7 files changed

Lines changed: 689 additions & 45 deletions

File tree

Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,253 @@
1+
---
2+
title: Checkbox
3+
---
4+
5+
CommandKit provides `Checkbox`, `CheckboxGroup`, and `CheckboxGroupOption`
6+
for building checkbox inputs using Discord's component builders.
7+
8+
## Basic usage
9+
10+
Use `CheckboxGroup` when you want the user to pick one or more items from a
11+
list of options:
12+
13+
```tsx title="src/app/commands/checkbox-group.tsx"
14+
import {
15+
type ChatInputCommand,
16+
type OnModalKitSubmit,
17+
Modal,
18+
Label,
19+
CheckboxGroup,
20+
CheckboxGroupOption,
21+
} from 'commandkit';
22+
import { MessageFlags } from 'discord.js';
23+
24+
const handleSubmit: OnModalKitSubmit = async (interaction, context) => {
25+
// returns a string[] of all selected checkbox values
26+
const preferences = interaction.fields.getCheckboxGroup('notifications');
27+
28+
await interaction.reply({
29+
content: 'Thanks! Preferences saved.',
30+
flags: MessageFlags.Ephemeral,
31+
});
32+
33+
// Clean up the modal context
34+
context.dispose();
35+
};
36+
37+
export const chatInput: ChatInputCommand = async ({ interaction }) => {
38+
const modal = (
39+
<Modal title="Preferences" onSubmit={handleSubmit}>
40+
<Label
41+
label="Notifications"
42+
description="Select all notifications you want to receive"
43+
>
44+
<CheckboxGroup customId="notifications" required>
45+
<CheckboxGroupOption
46+
label="Releases"
47+
value="releases"
48+
description="New CommandKit releases"
49+
/>
50+
<CheckboxGroupOption
51+
label="Incidents"
52+
value="incidents"
53+
description="Service disruptions"
54+
/>
55+
<CheckboxGroupOption
56+
label="Tips"
57+
value="tips"
58+
description="Occasional usage tips"
59+
/>
60+
</CheckboxGroup>
61+
</Label>
62+
</Modal>
63+
);
64+
65+
await interaction.showModal(modal);
66+
};
67+
```
68+
69+
## Descriptions
70+
To provide more context about the options, you can add descriptions to `CheckboxGroupOption`:
71+
72+
```tsx title="src/app/commands/checkbox-descriptions.tsx"
73+
import {
74+
type ChatInputCommand,
75+
type OnModalKitSubmit,
76+
Modal,
77+
Label,
78+
CheckboxGroup,
79+
CheckboxGroupOption,
80+
} from 'commandkit';
81+
import { MessageFlags } from 'discord.js';
82+
83+
const handleSubmit: OnModalKitSubmit = async (interaction, context) => {
84+
const preferences = interaction.fields.getCheckboxGroup('features');
85+
86+
await interaction.reply({
87+
content: 'Saved!',
88+
flags: MessageFlags.Ephemeral,
89+
});
90+
91+
context.dispose();
92+
};
93+
94+
export const chatInput: ChatInputCommand = async ({ interaction }) => {
95+
const modal = (
96+
<Modal title="Feature Feedback" onSubmit={handleSubmit}>
97+
<Label
98+
label="Features"
99+
description="Which features do you use the most?"
100+
>
101+
<CheckboxGroup customId="features">
102+
<CheckboxGroupOption
103+
label="Modals"
104+
value="modals"
105+
description="For collecting structured input"
106+
/>
107+
<CheckboxGroupOption
108+
label="Select Menus"
109+
value="selects"
110+
description="For picking from a list of options"
111+
/>
112+
<CheckboxGroupOption
113+
label="Buttons"
114+
value="buttons"
115+
description="For quick actions and confirmations"
116+
/>
117+
</CheckboxGroup>
118+
</Label>
119+
</Modal>
120+
);
121+
122+
await interaction.showModal(modal);
123+
};
124+
```
125+
126+
## Default selections
127+
128+
Use `default` on `CheckboxGroupOption` to pre-select options:
129+
130+
```tsx title="src/app/commands/default-checkboxes.tsx"
131+
import {
132+
type ChatInputCommand,
133+
type OnModalKitSubmit,
134+
Modal,
135+
Label,
136+
CheckboxGroup,
137+
CheckboxGroupOption,
138+
} from 'commandkit';
139+
import { MessageFlags } from 'discord.js';
140+
141+
const handleSubmit: OnModalKitSubmit = async (interaction, context) => {
142+
const preferences = interaction.fields.getCheckboxGroup('topics');
143+
144+
await interaction.reply({
145+
content: 'Saved!',
146+
flags: MessageFlags.Ephemeral,
147+
});
148+
149+
context.dispose();
150+
};
151+
152+
export const chatInput: ChatInputCommand = async ({ interaction }) => {
153+
const modal = (
154+
<Modal title="Newsletter" onSubmit={handleSubmit}>
155+
<Label label="Topics" description="Uncheck anything you're not into">
156+
<CheckboxGroup customId="topics">
157+
<CheckboxGroupOption label="Announcements" value="news" default />
158+
<CheckboxGroupOption label="Tutorials" value="tutorials" default />
159+
<CheckboxGroupOption label="Community" value="community" />
160+
</CheckboxGroup>
161+
</Label>
162+
</Modal>
163+
);
164+
165+
await interaction.showModal(modal);
166+
};
167+
```
168+
169+
## Min/max values
170+
171+
You can enforce how many options the user must pick via `minValues` and
172+
`maxValues`:
173+
174+
```tsx title="src/app/commands/checkbox-limits.tsx"
175+
import {
176+
type ChatInputCommand,
177+
type OnModalKitSubmit,
178+
Modal,
179+
Label,
180+
CheckboxGroup,
181+
CheckboxGroupOption,
182+
} from 'commandkit';
183+
import { MessageFlags } from 'discord.js';
184+
185+
const handleSubmit: OnModalKitSubmit = async (interaction, context) => {
186+
const preferences = interaction.fields.getCheckboxGroup('topics');
187+
188+
await interaction.reply({
189+
content: 'Saved!',
190+
flags: MessageFlags.Ephemeral,
191+
});
192+
193+
context.dispose();
194+
};
195+
196+
export const chatInput: ChatInputCommand = async ({ interaction }) => {
197+
const modal = (
198+
<Modal title="Project Setup" onSubmit={handleSubmit}>
199+
<Label label="Tools" description="Pick 2 to 4 tools">
200+
<CheckboxGroup customId="tools" minValues={2} maxValues={4}>
201+
<CheckboxGroupOption label="TypeScript" value="ts" />
202+
<CheckboxGroupOption label="ESLint" value="eslint" />
203+
<CheckboxGroupOption label="Prettier" value="prettier" />
204+
<CheckboxGroupOption label="Vitest" value="vitest" />
205+
<CheckboxGroupOption label="Playwright" value="playwright" />
206+
</CheckboxGroup>
207+
</Label>
208+
</Modal>
209+
);
210+
211+
await interaction.showModal(modal);
212+
};
213+
```
214+
215+
## Single checkbox
216+
217+
Use `Checkbox` for a single boolean input. It can be useful when you want a
218+
simple "yes/no" toggle:
219+
220+
```tsx title="src/app/commands/single-checkbox.tsx"
221+
import {
222+
type ChatInputCommand,
223+
type OnModalKitSubmit,
224+
Modal,
225+
Label,
226+
Checkbox,
227+
} from 'commandkit';
228+
import { MessageFlags } from 'discord.js';
229+
230+
const handleSubmit: OnModalKitSubmit = async (interaction, context) => {
231+
// returns a boolean indicating whether the checkbox is checked
232+
const agree = interaction.fields.getCheckbox('agree');
233+
234+
await interaction.reply({
235+
content: 'Saved!',
236+
flags: MessageFlags.Ephemeral,
237+
});
238+
239+
context.dispose();
240+
};
241+
242+
export const chatInput: ChatInputCommand = async ({ interaction }) => {
243+
const modal = (
244+
<Modal title="Rules" onSubmit={handleSubmit}>
245+
<Label label="I agree to the rules">
246+
<Checkbox customId="agree" />
247+
</Label>
248+
</Modal>
249+
);
250+
251+
await interaction.showModal(modal);
252+
};
253+
```

0 commit comments

Comments
 (0)