Spotlight
Command menu for search and application navigation.
Want to skip the docs? Try our MCP Server
#
Documentation
#
#
Usage
#
Use Spotlight for a global search or command palette. It opens with Cmd/Ctrl+K, and SpotlightTrigger renders a search button that opens it too.
Spotlight takes the same options as Menu: group them with group, navigate with href, or run an action with execute. Typing in the search input filters the options.
"use client";
import { type MenuOption, toaster } from "@optiaxiom/react";
import {
Spotlight,
SpotlightContent,
SpotlightTrigger,
} from "@optiaxiom/react/unstable";
import { useMemo } from "react";
const groups = {
actions: { label: "Actions" },
pages: { label: "Pages" },
} satisfies Record<string, MenuOption["group"]>;
export function App() {
return (
<Spotlight
options={useMemo<MenuOption[]>(
() => [
{ group: groups.pages, href: "../", label: "Components" },
{ group: groups.pages, href: "../../", label: "Home" },
{
execute: () => toaster.create("Created a project"),
group: groups.actions,
label: "Create project",
},
{
execute: () => toaster.create("Invited a member"),
group: groups.actions,
label: "Invite member",
},
],
[],
)}
>
<SpotlightTrigger>Search</SpotlightTrigger>
<SpotlightContent />
</Spotlight>
);
}#
Anatomy
#
import {
Spotlight,
SpotlightContent,
SpotlightTrigger,
} from "@optiaxiom/react/unstable";
export default () => (
<Spotlight>
<SpotlightTrigger />
<SpotlightContent />
</Spotlight>
);#
Recent items
#
Use the visible callback on options to show recent items while the search input is empty, and search results once the user types.
"use client";
import { type MenuOption, toaster } from "@optiaxiom/react";
import {
Spotlight,
SpotlightContent,
SpotlightTrigger,
} from "@optiaxiom/react/unstable";
import { useMemo } from "react";
const groups = {
projects: { label: "Projects" },
recent: { label: "Recent" },
} satisfies Record<string, MenuOption["group"]>;
const projects = ["Atlas", "Beacon", "Comet", "Delta", "Echo"];
const recent = ["Comet", "Atlas"];
export function App() {
return (
<Spotlight
options={useMemo(
() => [
...recent.map<MenuOption>((name) => ({
execute: () => toaster.create(`Opened ${name}`),
group: groups.recent,
key: `recent-${name}`,
label: name,
visible: ({ inputValue }) => !inputValue,
})),
...projects.map<MenuOption>((name) => ({
execute: () => toaster.create(`Opened ${name}`),
group: groups.projects,
key: `project-${name}`,
label: name,
visible: ({ inputValue }) =>
inputValue
? name.toLowerCase().includes(inputValue.toLowerCase())
: false,
})),
],
[],
)}
>
<SpotlightTrigger>Search projects</SpotlightTrigger>
<SpotlightContent />
</Spotlight>
);
}#
Responsive trigger
#
A Spotlight can have more than one SpotlightTrigger. Leave out children (and give it an aria-label) for an icon-only trigger, then use responsive display to show the icon on small screens and the full search button on larger ones. Resize the window to see the triggers swap.
"use client";
import { Kbd, type MenuOption } from "@optiaxiom/react";
import {
Spotlight,
SpotlightContent,
SpotlightTrigger,
} from "@optiaxiom/react/unstable";
import { useMemo } from "react";
export function App() {
return (
<Spotlight
options={useMemo<MenuOption[]>(
() => [
{ href: "../", label: "Components" },
{ href: "../../", label: "Home" },
],
[],
)}
>
<SpotlightTrigger aria-label="Search" display={["flex", "none"]} />
<SpotlightTrigger
addonAfter={
<Kbd color="fg.tertiary" ml="auto" modifiers="mod" variant="subtle">
K
</Kbd>
}
display={["none", "flex"]}
w="224"
>
Search
</SpotlightTrigger>
<SpotlightContent />
</Spotlight>
);
}#
Related
#
Menu
Dropdown menu for displaying actions.
#
Props
#
#
Spotlight
#
import { Spotlight } from "@optiaxiom/react/unstable";Doesn't render its own HTML element.
Prop |
|---|
children*
|
defaultOpenThe initial open state in uncontrolled mode.
|
disableHotkeyTurn off the Cmd/Ctrl+K hotkey, such as when another Spotlight on the page owns it.
|
emptyCustom empty state content.
|
inputValueThe input value in controlled mode.
|
loadingWhether to show loading spinner or skeleton items inside the menu.
|
onInputValueChangeHandler that is called when input value changes.
|
onOpenChangeHandler that is called when the open state changes.
|
openThe open state in controlled mode. A controlled menu doesn’t close when an item is picked: close it from
the item’s
|
options*The items we want to render.
|
placeholderThe placeholder for the search input. The default is translated for
the
Default: |
#
SpotlightTrigger
#
import { SpotlightTrigger } from "@optiaxiom/react/unstable";Supports all Box props in addition to its own. Renders a <div> element.
Prop |
|---|
addonAfterDisplay content inside the button after
|
addonBeforeDisplay content inside the button before
|
appearanceControl the appearance by selecting between the different button types.
|
asChildChange the default rendered element for the one passed as a child, merging their props and behavior. Read the Composition guide for more details.
|
children
|
className
|
disabledWhether the button is disabled.
|
iconDisplay an icon before or after the button content or omit
Default: |
iconPositionControl whether to show the icon before or after the button content.
|
loadingShow a loading spinner and mark the button
|
sizeControl the size of the button.
|
squareWhether button should have square shape (an icon-only button with no label).
|
typeThe default behavior of the button.
|
#
SpotlightContent
#
import { SpotlightContent } from "@optiaxiom/react/unstable";Supports all Box props in addition to its own. Renders a <div> element.
Prop |
|---|
align
|
alignOffset
|
asChildChange the default rendered element for the one passed as a child, merging their props and behavior. Read the Composition guide for more details.
|
children
|
className
|
onCloseAutoFocusEvent handler called when auto-focusing on close. Can be prevented.
|
onEscapeKeyDownEvent handler called when the escape key is down. Can be prevented.
|
onFocusOutsideEvent handler called when the focus moves outside of the
|
onInteractOutsideEvent handler called when an interaction happens outside the
|
onOpenAutoFocusEvent handler called when auto-focusing on open. Can be prevented.
|
onPointerDownOutsideEvent handler called when the a
|
side
|
sideOffset
|
#
Changelog
#
#
0.5.0
#
- Added component