Skip to content
Native Animation
Command Palette animation preview

This preview uses fictional demo content. See the props below for the customization options available in this component.

npx nativeanimation add command-palette
Glass

Command Palette

A searchable action palette with sliding selection and configurable commands, placeholder, fonts, and accent color.

$9 for this animation

Add to your project

Copy the component and its assets into your app with the Native Animation CLI, or paste the agent prompt into Claude Code, Codex or Cursor once the MCP server is connected.

About this animation

A searchable action palette with sliding selection and configurable commands, placeholder, fonts, and accent color.

Why this one

Desktop command palettes usually become flat search lists on mobile. This one lets you drag the selection across commands, keeps matching letters connected to the search, and makes the selected action visibly execute. The panel contracts toward its launcher while a confirmation appears. The Nimbus demo changes the actual workspace theme, adds tasks and projects, switches destinations, prepares an invitation, previews CSV data, and archives completed tasks.

How it works

  1. onLayout measures the available container. The panel uses 92% of its width, capped at 520 pt, and starts at 14% of its height, with a 72 pt minimum clearance for viewer controls. Long lists scroll instead of shrinking touch targets.
  2. One opening shared value drives panel opacity, drop, scale, backdrop depth, and blur intensity. Android blur uses a shared BlurTargetView with the SDK 31+ method.
  3. A subsequence matcher scores word starts, adjacent letters, and short gaps. Results sort by relevance while spring-driven row positions follow their new layout. Optional keywords participate with a lower score.
  4. The selected row position is a shared value. Dragging updates it on the UI thread; tapping a command executes through Gesture Handler. Search updates React only when text changes.
  5. Matching letters draw their accent underline. A result digit rolls in a fixed, measured window; collections of ten or more use a plain result count.
  6. Executing lights the selected row, calls the host once, contracts the palette, and announces its confirmation. Reopening or closing cancels pending execution. All timers are cleared on unmount.

Install

Copy this folder without demo/ into your project.

npx expo install expo-blur expo-image expo-linear-gradient react-native-gesture-handler react-native-reanimated react-native-worklets

Wrap your app in GestureHandlerRootView. Configure Reanimated/worklets according to your Expo SDK. No images, network requests, or Skia initialization are required. Icons: Lucide (ISC), copied from the Native Animation kit and rendered as local SVG data with expo-image.

Usage

import { CommandPalette, type PaletteCommand } from './command-palette';

const commands: PaletteCommand[] = [
  { id: 'new-task', title: 'New task', group: 'Suggested', icon: 'plus', description: 'Capture something to do' },
  { id: 'inbox', title: 'Go to Inbox', group: 'Navigation', icon: 'inbox', description: 'See what needs your attention' },
];

export function Workspace() {
  return (
    <CommandPalette
      commands={commands}
      onExecute={(command) => {
        // Apply the action to your own workspace here.
        return `${command.title} complete`;
      }}
    >
      <YourWorkspace />
    </CommandPalette>
  );
}
const palette = useRef<CommandPaletteRef>(null);

<CommandPalette
  ref={palette}
  commands={commands}
  accentColor="#38BDF8"
  blurIntensity={40}
  springDamping={30}
  colorScheme="dark"
  fontFamily="YourInterfaceFont"
  monoFontFamily="YourMonoFont"
  launcherLabel="Quick actions"
  onOpenChange={(open) => trackSearchVisibility(open)}
/>

// External controls:
palette.current?.open();
palette.current?.search('task');
palette.current?.select('new-task');
palette.current?.execute();

The ref exports open(), close(), search(query), select(id), and execute(). Opening resets search. Methods never open the software keyboard automatically; tap the input to type. Pass unique command IDs and keep grouped commands contiguous for the unfiltered view. Keep mobile titles and descriptions concise. Description defaults to the command group when omitted. Keyboard hints are hidden, including from screen-reader row labels, unless showShortcuts={true} is explicitly supplied. Hosts with a hardware keyboard may continue passing optional shortcut values. Import ref types from the same folder.

Props

PropTypeDefaultPurpose
commandsreadonly PaletteCommand[]RequiredID, title, group, kit icon, optional description, shortcut, keywords, confirmation
childrenReactNode—Workspace rendered behind the palette
onExecute(command) => string | void—Apply an action and optionally return confirmation copy
onOpenChange(open: boolean) => void—Observe visibility changes
onInteraction() => void—Stop host autoplay on touch, drag, or typing
accentColorstring#38BDF8Match underlines, icons, selection border
colorScheme'light' | 'dark' | 'auto''auto'Surface treatment; auto follows the device
fontFamilystringSystemInterface font
monoFontFamilystringSystemSection headers and shortcuts
showShortcutsbooleanfalseOpt in to row, launcher, and close keyboard hints
placeholderstringSearch actions…Search hint
launcherLabelstringSearch actionsLauncher text and accessible label
blurIntensitynumber40Glass intensity, clamped to 0–100
springDampingnumber28Row/panel damping, minimum 28 to avoid excess bounce
styleStyleProp<ViewStyle>—Root container overrides
testIDstring—Test selector

PaletteCommand.icon accepts the kit names in icons.ts. The component imports no project theme; the demo supplies Geist and Geist Mono from the catalog's shared typography.

Compatibility

Targets Expo SDK 58, React Native 0.88.0, Reanimated 4.7.1, worklets 0.13.0, and Gesture Handler 3.3.0. Supports iOS, Android, and web APIs. Android 12+ uses native blur; older Android versions fall back to translucent material.

Accessibility

Interactive controls have button roles and labels. Rows support screen-reader activation as well as tap gestures; opening also has a launcher alternative to the downward pull. The input accepts Return to execute, Escape to close, and arrow keys to select. Optional shortcut chips require showShortcuts={true}; register global shortcuts in the host app. Visibility, result changes, and confirmations are announced. Background accessibility is hidden while the modal is open, and hidden palette views do not receive input. The search field remains a native accessible input; no forced keyboard focus interrupts autoplay.

Reduced motion removes blur, drop, scale, contraction, shaking, and digit rolling. Opening/closing, underline changes, rows, and toast use 200 ms fades. Touch targets are at least 48 pt; command rows are 64 pt with separate title and description lines. Dragging only selects, so releasing does not execute an accidental command; tap a command or submit the input to execute.

Demo timeline

The demo opens at 260 ms; types d, da, and dar at 910, 1160, and 1410 ms; selects dark mode at 1810 ms; and executes at 2210 ms. The selected row lights, the workspace changes theme, and the panel contracts toward the launcher before 3 seconds. The loop repeats every 4.7 seconds, alternating the actual theme. Any physical touch or typing permanently stops that mounted demo's autoplay. There is no autoplay logic in the reusable component.

Performance and limitations

Position, opening, selection, pressure, underline drawing, and digit motion run on the UI thread. Search uses React state per query and a small linear subsequence scorer; use a prefiltered command collection for large datasets. The drag selects within the currently visible scroll viewport; swipe the list to reveal more results. onExecute is synchronous; perform async work in the host and provide your own pending/error feedback. The CSV demo displays local preview data rather than writing a file. The demo's invitation action prepares a draft rather than contacting another person.

Layout

The mobile polish preserves fuzzy filtering, animated row positions, match underlines, drag selection, and the execution transition. Demo commands contain descriptions instead of desktop shortcuts. The workspace scrolls in short containers, and the panel keeps 72 pt of top clearance with a keyboard-aware scroll viewport.