Command center components for react and Mantine
npx @tessl/cli install tessl/npm-mantine--spotlight@8.2.0Mantine Spotlight provides command center components for React applications built with the Mantine design system. It enables developers to create keyboard-accessible search overlays that can be triggered with shortcuts (like Ctrl+K), allowing users to quickly find and execute actions within an application.
npm install @mantine/spotlight @mantine/core @mantine/hooksimport { Spotlight, spotlight } from "@mantine/spotlight";For individual components:
import {
SpotlightRoot,
SpotlightSearch,
SpotlightActionsList,
SpotlightAction,
createSpotlight
} from "@mantine/spotlight";CSS imports (required):
/* Standard styles */
@import "@mantine/spotlight/styles.css";
/* Layer styles (alternative) */
@import "@mantine/spotlight/styles.layer.css";import { Spotlight } from "@mantine/spotlight";
function App() {
const actions = [
{
id: "home",
label: "Home",
description: "Get to home page",
onClick: () => navigate("/"),
},
{
id: "dashboard",
label: "Dashboard",
description: "Get full information about current system status",
onClick: () => navigate("/dashboard"),
},
];
return (
<div>
<Spotlight
actions={actions}
nothingFound="Nothing found..."
highlightQuery
searchProps={{
placeholder: "Search...",
leftSection: <IconSearch size={16} />,
}}
/>
</div>
);
}Mantine Spotlight is built around several key components:
Spotlight provides a complete command center with search and actionsSpotlightRoot, SpotlightSearch, etc.)Complete spotlight interface with built-in search, action filtering, and keyboard navigation. Perfect for quick implementation of command centers.
function Spotlight(props: SpotlightProps): JSX.Element;
interface SpotlightProps extends SpotlightRootProps {
/** Props passed down to the Spotlight.Search */
searchProps?: SpotlightSearchProps;
/** Actions data, passed down to Spotlight.Action component */
actions: SpotlightActions[];
/** Function to filter actions data based on search query */
filter?: SpotlightFilterFunction;
/** Message displayed when none of the actions match given filter */
nothingFound?: React.ReactNode;
/** Determines whether search query should be highlighted in action label */
highlightQuery?: boolean;
/** Maximum number of actions displayed at a time */
limit?: number;
}
type SpotlightActions = SpotlightActionData | SpotlightActionGroupData;
interface SpotlightActionData extends SpotlightActionProps {
id: string;
group?: string;
}
interface SpotlightActionGroupData {
group: string;
actions: SpotlightActionData[];
}Individual components for building custom spotlight interfaces with full control over layout and behavior.
function SpotlightRoot(props: SpotlightRootProps): JSX.Element;
function SpotlightSearch(props: SpotlightSearchProps): JSX.Element;
function SpotlightActionsList(props: SpotlightActionsListProps): JSX.Element;
function SpotlightAction(props: SpotlightActionProps): JSX.Element;Store-based state management for controlling spotlight behavior programmatically, supporting both global and instance-based stores.
function createSpotlight(): readonly [SpotlightStore, SpotlightActions];
function createSpotlightStore(): SpotlightStore;
function useSpotlight(store: SpotlightStore): SpotlightState;
// Global instance
const spotlight: SpotlightActions;
function openSpotlight(): void;
function closeSpotlight(): void;
function toggleSpotlight(): void;
interface SpotlightState {
opened: boolean;
selected: number;
listId: string;
query: string;
empty: boolean;
registeredActions: Set<string>;
}
interface SpotlightActions {
open(): void;
close(): void;
toggle(): void;
}Helper functions for action filtering, grouping, and type checking.
function isActionsGroup(
item: SpotlightActionData | SpotlightActionGroupData
): item is SpotlightActionGroupData;
type SpotlightFilterFunction = (
query: string,
actions: SpotlightActions[]
) => SpotlightActions[];
const defaultSpotlightFilter: SpotlightFilterFunction;type SpotlightStore = MantineStore<SpotlightState>;
type SpotlightRootStylesNames =
| ModalStylesNames
| 'search'
| 'actionsList'
| 'action'
| 'empty'
| 'footer'
| 'actionBody'
| 'actionLabel'
| 'actionDescription'
| 'actionSection'
| 'actionsGroup';
type SpotlightFactory = Factory<{
props: SpotlightProps;
ref: HTMLDivElement;
stylesNames: SpotlightStylesNames;
staticComponents: {
Search: typeof SpotlightSearch;
ActionsList: typeof SpotlightActionsList;
Action: typeof SpotlightAction;
Empty: typeof SpotlightEmpty;
Footer: typeof SpotlightFooter;
ActionsGroup: typeof SpotlightActionsGroup;
Root: typeof SpotlightRoot;
open: typeof spotlight.open;
close: typeof spotlight.close;
toggle: typeof spotlight.toggle;
};
}>;
type SpotlightRootFactory = Factory<{
props: SpotlightRootProps;
ref: HTMLDivElement;
stylesNames: SpotlightRootStylesNames;
compound: true;
}>;
interface SpotlightActionProps extends BoxProps {
/** Action label, pass string to use in default filter */
label?: string;
/** Action description, pass string to use in default filter */
description?: string;
/** Section displayed on the left side of the label, for example, icon */
leftSection?: React.ReactNode;
/** Section displayed on the right side of the label, for example, hotkey */
rightSection?: React.ReactNode;
/** Children override default action elements */
children?: React.ReactNode;
/** Determines whether left and right sections should have dimmed styles */
dimmedSections?: boolean;
/** Determines whether search query should be highlighted in action label */
highlightQuery?: boolean;
/** Key of theme.colors for highlighting search query */
highlightColor?: MantineColor;
/** Determines whether the spotlight should be closed when action is triggered */
closeSpotlightOnTrigger?: boolean;
/** Keywords that are used for default filtering */
keywords?: string | string[];
}
interface SpotlightRootProps extends StylesApiProps<SpotlightRootFactory>, Omit<ModalProps, 'opened' | 'onClose' | 'withCloseButton'> {
/** Spotlight store, can be used to create multiple instances */
store?: SpotlightStore;
/** Controlled Spotlight search query */
query?: string;
/** Called when query changes */
onQueryChange?: (query: string) => void;
/** Determines whether the search query should be cleared when the spotlight is closed */
clearQueryOnClose?: boolean;
/** Keyboard shortcut or list of shortcuts to trigger spotlight */
shortcut?: string | string[] | null;
/** List of tags which when focused will be ignored by shortcut */
tagsToIgnore?: string[];
/** Determines whether shortcut should trigger based in contentEditable */
triggerOnContentEditable?: boolean;
/** If set, spotlight will not be rendered */
disabled?: boolean;
/** Called when spotlight opens */
onSpotlightOpen?: () => void;
/** Called when spotlight closes */
onSpotlightClose?: () => void;
/** Forces opened state, useful for tests */
forceOpened?: boolean;
/** Determines whether spotlight should be closed when one of the actions is triggered */
closeOnActionTrigger?: boolean;
/** Spotlight content max-height. Ignored unless scrollable prop is set */
maxHeight?: React.CSSProperties['maxHeight'];
/** Determines whether the actions list should be scrollable */
scrollable?: boolean;
}