Styling

Customize every aspect of the command palette's appearance using CSS classes, inline styles, or by going completely unstyled.

Three Approaches

🎨

CSS Classes

Use Tailwind, CSS modules, or any class-based styling. Best for design systems.

Inline Styles

Pass CSS properties directly. Great for dynamic theming based on state.

🔧

Unstyled Mode

Remove all defaults and build from scratch. Full control for custom designs.

Using Classes & Inline Styles

Mix and match classes and styles to achieve the look you want:

Basic Styling
<CommandPalette
  commands={actions}
  
  <!-- Use CSS classes (works with Tailwind!) -->
  inputClass="rounded-lg border-gray-200 focus:ring-2"
  resultContainerClass="hover:bg-gray-50"
  optionSelectedClass="bg-blue-50 border-l-2 border-blue-500"
  
  <!-- Or inline styles (CSS Properties) -->
  inputStyle={{ fontSize: '16px', padding: '1rem' }}
  overlayStyle={{ backdropFilter: 'blur(8px)' }}
/>

Dark Mode / Theming

Create theme objects and switch between them dynamically:

Dynamic Theming
<script>
  let isDark = $state(false);
  
  const darkTheme = {
    inputStyle: { background: '#1f2937', color: '#f9fafb' },
    paletteWrapperInnerStyle: { 
      background: '#1f2937',
      boxShadow: '0 25px 50px rgba(0,0,0,0.5)'
    },
    resultContainerStyle: { borderColor: '#374151' },
    optionSelectedStyle: { background: '#374151' }
  };
  
  const lightTheme = {
    inputStyle: { background: '#ffffff', color: '#111827' },
    paletteWrapperInnerStyle: { background: '#ffffff' },
    resultContainerStyle: { borderColor: '#e5e7eb' },
    optionSelectedStyle: { background: '#f3f4f6' }
  };
  
  const theme = $derived(isDark ? darkTheme : lightTheme);
</script>

<CommandPalette
  commands={actions}
  inputStyle={theme.inputStyle}
  paletteWrapperInnerStyle={theme.paletteWrapperInnerStyle}
  resultContainerStyle={theme.resultContainerStyle}
  optionSelectedStyle={theme.optionSelectedStyle}
/>

Going Unstyled

Set unstyled={true} to remove all default styles:

Unstyled Mode
<!-- Remove all default styles for full control -->
<CommandPalette
  commands={actions}
  unstyled={true}
  
  <!-- Now add your own classes -->
  overlayClass="fixed inset-0 bg-black/50 z-50"
  paletteWrapperInnerClass="max-w-xl mx-auto mt-20 bg-white rounded-xl shadow-2xl"
  inputClass="w-full px-4 py-3 text-lg border-b outline-none"
  resultsContainerClass="max-h-80 overflow-y-auto"
  resultContainerClass="px-4 py-3 cursor-pointer"
  optionSelectedClass="bg-blue-50"
/>
⚠️
Important: When using unstyled, you're responsible for all positioning, scrolling, and visual feedback. Make sure to handle the overlay, container dimensions, and scroll behavior.

CSS Class Reference

When not using unstyled mode, these classes are applied:

ClassElement
.cp-overlayFullscreen backdrop
.cp-wrapperCentered wrapper
.cp-containerMain palette box
.cp-input-wrapperInput container
.cp-inputSearch input
.cp-search-iconSearch icon
.cp-resultsResults list
.cp-group-headerGroup name header
.cp-resultIndividual result
.cp-result-activeActive result
.cp-result-iconResult icon container
.cp-result-titleResult title
.cp-result-subtitleResult subtitle
.cp-kbdKeyboard shortcut badge
.cp-emptyEmpty state container

Custom CSS Overrides

Override default styles using global CSS:

Custom Overrides
/* Override default styles with CSS */
:global(.cp-overlay) {
  background: rgba(0, 0, 0, 0.8);
  backdrop-filter: blur(12px);
}

:global(.cp-container) {
  background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 16px;
}

:global(.cp-input) {
  background: transparent;
  color: white;
  font-size: 18px;
}

:global(.cp-result) {
  border-radius: 8px;
  transition: all 0.15s ease;
}

:global(.cp-result-active) {
  background: rgba(99, 102, 241, 0.2);
  transform: translateX(4px);
}