0
# Compound Components
1
2
The compound components provide granular control for building custom spotlight interfaces. Each component handles a specific aspect of the spotlight functionality and can be combined to create fully customized implementations.
3
4
## CSS Imports
5
6
When using individual compound components, you must import the required styles:
7
8
```css
9
/* Standard styles */
10
@import "@mantine/spotlight/styles.css";
11
12
/* Or layer styles (alternative) */
13
@import "@mantine/spotlight/styles.layer.css";
14
```
15
16
## Capabilities
17
18
### SpotlightRoot
19
20
Root container component that provides the modal overlay, keyboard handling, and context for child components.
21
22
```typescript { .api }
23
/**
24
* Root container component with modal functionality and keyboard handling
25
* @param props - Configuration props for the root component
26
* @returns JSX element containing the modal container and context provider
27
*/
28
function SpotlightRoot(props: SpotlightRootProps): JSX.Element;
29
30
interface SpotlightRootProps extends StylesApiProps<SpotlightRootFactory>, Omit<ModalProps, 'opened' | 'onClose' | 'withCloseButton'> {
31
/** Spotlight store, can be used to create multiple instances */
32
store?: SpotlightStore;
33
/** Controlled Spotlight search query */
34
query?: string;
35
/** Called when query changes */
36
onQueryChange?: (query: string) => void;
37
/** Determines whether the search query should be cleared when the spotlight is closed */
38
clearQueryOnClose?: boolean;
39
/** Keyboard shortcut or list of shortcuts to trigger spotlight */
40
shortcut?: string | string[] | null;
41
/** List of tags which when focused will be ignored by shortcut */
42
tagsToIgnore?: string[];
43
/** Determines whether shortcut should trigger based in contentEditable */
44
triggerOnContentEditable?: boolean;
45
/** If set, spotlight will not be rendered */
46
disabled?: boolean;
47
/** Called when spotlight opens */
48
onSpotlightOpen?: () => void;
49
/** Called when spotlight closes */
50
onSpotlightClose?: () => void;
51
/** Forces opened state, useful for tests */
52
forceOpened?: boolean;
53
/** Determines whether spotlight should be closed when one of the actions is triggered */
54
closeOnActionTrigger?: boolean;
55
/** Spotlight content max-height. Ignored unless scrollable prop is set */
56
maxHeight?: React.CSSProperties['maxHeight'];
57
/** Determines whether the actions list should be scrollable */
58
scrollable?: boolean;
59
}
60
```
61
62
### SpotlightSearch
63
64
Search input component with keyboard navigation support for arrow keys and Enter.
65
66
```typescript { .api }
67
/**
68
* Search input component with keyboard navigation
69
* @param props - Configuration props for the search input
70
* @returns JSX element containing the search input
71
*/
72
function SpotlightSearch(props: SpotlightSearchProps): JSX.Element;
73
74
interface SpotlightSearchProps extends BoxProps, Omit<InputProps, 'classNames' | 'styles' | 'vars' | 'variant'>, CompoundStylesApiProps<SpotlightSearchFactory>, ElementProps<'input', 'size'> {}
75
```
76
77
### SpotlightActionsList
78
79
Scrollable container component for displaying actions with auto-sizing and scroll area management.
80
81
```typescript { .api }
82
/**
83
* Scrollable container for actions with auto-sizing
84
* @param props - Configuration props for the actions list
85
* @returns JSX element containing the scrollable actions container
86
*/
87
function SpotlightActionsList(props: SpotlightActionsListProps): JSX.Element;
88
89
interface SpotlightActionsListProps extends BoxProps, CompoundStylesApiProps<SpotlightActionsListFactory>, ElementProps<'div'> {}
90
```
91
92
### SpotlightAction
93
94
Individual action button component with highlighting, sections, and click handling.
95
96
```typescript { .api }
97
/**
98
* Individual action button with highlighting and sections
99
* @param props - Configuration props for the action button
100
* @returns JSX element containing the action button
101
*/
102
function SpotlightAction(props: SpotlightActionProps): JSX.Element;
103
104
interface SpotlightActionProps extends BoxProps, CompoundStylesApiProps<SpotlightActionFactory>, ElementProps<'button'> {
105
/** Action label, pass string to use in default filter */
106
label?: string;
107
/** Action description, pass string to use in default filter */
108
description?: string;
109
/** Section displayed on the left side of the label, for example, icon */
110
leftSection?: React.ReactNode;
111
/** Section displayed on the right side of the label, for example, hotkey */
112
rightSection?: React.ReactNode;
113
/** Children override default action elements, if passed, label, description and sections are hidden */
114
children?: React.ReactNode;
115
/** Determines whether left and right sections should have dimmed styles */
116
dimmedSections?: boolean;
117
/** Determines whether search query should be highlighted in action label */
118
highlightQuery?: boolean;
119
/** Key of theme.colors of any valid CSS color that will be used to highlight search query */
120
highlightColor?: MantineColor;
121
/** Determines whether the spotlight should be closed when action is triggered, overrides closeOnActionTrigger prop set on Spotlight */
122
closeSpotlightOnTrigger?: boolean;
123
/** Keywords that are used for default filtering, not displayed anywhere, can be a string: "react,router,javascript" or an array: ['react', 'router', 'javascript'] */
124
keywords?: string | string[];
125
}
126
```
127
128
### SpotlightEmpty
129
130
Empty state component displayed when no actions match the current search query.
131
132
```typescript { .api }
133
/**
134
* Empty state component when no actions match
135
* @param props - Configuration props for the empty state
136
* @returns JSX element containing the empty state content
137
*/
138
function SpotlightEmpty(props: SpotlightEmptyProps): JSX.Element;
139
140
interface SpotlightEmptyProps extends BoxProps, CompoundStylesApiProps<SpotlightEmptyFactory>, ElementProps<'div'> {}
141
```
142
143
### SpotlightFooter
144
145
Footer area component for displaying additional information or controls.
146
147
```typescript { .api }
148
/**
149
* Footer area component
150
* @param props - Configuration props for the footer
151
* @returns JSX element containing the footer content
152
*/
153
function SpotlightFooter(props: SpotlightFooterProps): JSX.Element;
154
155
interface SpotlightFooterProps extends BoxProps, CompoundStylesApiProps<SpotlightFooterFactory>, ElementProps<'div'> {}
156
```
157
158
### SpotlightActionsGroup
159
160
Group container component for organizing related actions with a label.
161
162
```typescript { .api }
163
/**
164
* Group container for related actions with label
165
* @param props - Configuration props for the actions group
166
* @returns JSX element containing the grouped actions
167
*/
168
function SpotlightActionsGroup(props: SpotlightActionsGroupProps): JSX.Element;
169
170
interface SpotlightActionsGroupProps extends BoxProps, CompoundStylesApiProps<SpotlightActionsGroupFactory>, ElementProps<'div'> {
171
/** Spotlight.Action components */
172
children?: React.ReactNode;
173
/** Group label */
174
label?: string;
175
}
176
```
177
178
## Usage Examples
179
180
### Custom Spotlight Implementation
181
182
```typescript
183
import {
184
SpotlightRoot,
185
SpotlightSearch,
186
SpotlightActionsList,
187
SpotlightAction,
188
SpotlightEmpty,
189
SpotlightFooter,
190
createSpotlight
191
} from "@mantine/spotlight";
192
193
function CustomSpotlight() {
194
const [store, spotlight] = createSpotlight();
195
const actions = [
196
{ id: "1", label: "Home", description: "Go home" },
197
{ id: "2", label: "Settings", description: "Open settings" },
198
];
199
200
return (
201
<div>
202
<button onClick={spotlight.open}>Open Custom Spotlight</button>
203
204
<SpotlightRoot store={store} shortcut="ctrl + k">
205
<SpotlightSearch placeholder="Type to search..." />
206
207
<SpotlightActionsList>
208
{actions.map((action) => (
209
<SpotlightAction
210
key={action.id}
211
label={action.label}
212
description={action.description}
213
onClick={() => console.log(action.label)}
214
/>
215
))}
216
<SpotlightEmpty>No results found</SpotlightEmpty>
217
</SpotlightActionsList>
218
219
<SpotlightFooter>
220
Press ↵ to select, ↑↓ to navigate
221
</SpotlightFooter>
222
</SpotlightRoot>
223
</div>
224
);
225
}
226
```
227
228
### Actions with Sections
229
230
```typescript
231
import { SpotlightAction } from "@mantine/spotlight";
232
import { IconHome, IconKeyboard } from "@tabler/icons-react";
233
234
function ActionWithSections() {
235
return (
236
<SpotlightAction
237
label="Home"
238
description="Navigate to home page"
239
leftSection={<IconHome size={16} />}
240
rightSection={<IconKeyboard size={16} />}
241
keywords={["home", "main", "start"]}
242
highlightQuery
243
onClick={() => navigate("/")}
244
/>
245
);
246
}
247
```
248
249
### Grouped Actions
250
251
```typescript
252
import { SpotlightActionsGroup, SpotlightAction } from "@mantine/spotlight";
253
254
function GroupedActions() {
255
return (
256
<SpotlightActionsGroup label="Navigation">
257
<SpotlightAction
258
label="Home"
259
description="Go to home page"
260
onClick={() => navigate("/")}
261
/>
262
<SpotlightAction
263
label="Settings"
264
description="Open settings"
265
onClick={() => navigate("/settings")}
266
/>
267
</SpotlightActionsGroup>
268
);
269
}
270
```
271
272
## Default Props
273
274
```typescript { .api }
275
// SpotlightRoot defaults
276
const rootDefaults = {
277
size: 600,
278
yOffset: 80,
279
zIndex: getDefaultZIndex('max'),
280
overlayProps: { backgroundOpacity: 0.35, blur: 7 },
281
transitionProps: { duration: 200, transition: 'pop' },
282
clearQueryOnClose: true,
283
closeOnActionTrigger: true,
284
shortcut: 'mod + K',
285
maxHeight: 400,
286
};
287
288
// SpotlightSearch defaults
289
const searchDefaults = {
290
size: 'lg',
291
};
292
293
// SpotlightAction defaults
294
const actionDefaults = {
295
dimmedSections: true,
296
highlightQuery: false,
297
};
298
```