Skip to content

Styling ​

Components use Shadow DOM with ::part() selectors and BEM class names for styling flexibility.

Quick Start ​

Import the optional stylesheet, which styles every component (palette, cheatsheet, settings, context menus, radial menu):

js
import 'keybinds/styles/palette.css'

Its colors follow the page's color-scheme: with :root { color-scheme: light dark } it's light or dark along with the system.

Theme Variables ​

Every color and font in the stylesheet comes from a custom property. Set them on :root (or on one component) to match your page:

css
:root {
  --keybinds-bg: #fffaf3;
  --keybinds-fg: #2b2118;
  --keybinds-accent: #b4532a;
  --keybinds-font: 'Inter', sans-serif;
}
VariableUsed forDefault
--keybinds-bgDialog backgroundCanvas
--keybinds-fgTextCanvasText
--keybinds-mutedSecondary text60% of fg
--keybinds-borderBorders, dividers16% of fg
--keybinds-surfaceKey caps, buttons7% of fg over bg
--keybinds-accentMatches, recordingHighlight
--keybinds-accent-softActive row18% of accent
--keybinds-warnBinding conflicts#c2410c
--keybinds-backdropBehind dialogsblack at 45%
--keybinds-shadowDialog shadow
--keybinds-radiusDialog corners10px
--keybinds-font, --keybinds-monoText, key capssystem fonts

Selecting Components ​

Each component marks itself with data-keybinds="<kind>" when it's added to the page: command-palette, cheatsheet, settings, basic-context-menu, context-menu or radial-menu. Select by that rather than by tag name, so styles still apply if the component is registered under another name.

Custom Styles with ::part() ​

Target shadow DOM elements using CSS ::part():

css
[data-keybinds="command-palette"]::part(dialog) {
  background: #fff;
  border-radius: 12px;
}

[data-keybinds="command-palette"]::part(input) {
  font-size: 18px;
}

[data-keybinds="command-palette"]::part(item-active) {
  background: #0066cc;
  color: white;
}

Command Palette Parts ​

PartDescription
paletteRoot container
backdropOverlay behind dialog
dialogMain dialog box
inputSearch input field
listResults list (<ul>)
itemIndividual result (<li>)
item-activeCurrently selected item
item-disabledInactive command (failing when)
item-labelCommand label text
item-categoryCategory badge
item-keyKeyboard shortcut (<kbd>)
empty"No results" message

Cheatsheet Parts ​

PartDescription
cheatsheetRoot container
backdropOverlay behind dialog
dialogMain dialog box
groupCategory group container
group-titleCategory heading
listCommands list (<ul>)
itemIndividual command (<li>)
item-disabledInactive command
item-labelCommand label text
item-keysContainer for key badges
item-keyIndividual key (<kbd>)

Settings Parts ​

PartDescription
settingsRoot container
backdropOverlay behind dialog
dialogMain dialog box
headerHeader container
titleTitle text
reset-allReset All button
groupCategory group container
group-titleCategory heading
listCommands list (<ul>)
itemIndividual command (<li>)
item-labelCommand label text
item-bindingsContainer for all bindings
item-resetPer-command reset button
bindingIndividual binding span
binding-recordingBinding in recording state
binding-keysKey display container
binding-keyIndividual key (<kbd>)
binding-removeRemove (×) button
binding-releasePress/release switch on a binding (binding-release-on while it is a release)
item-addAdd binding container
add-keyAdd Key button
add-mouseAdd Mouse button
add-gamepadAdd Gamepad button (shown while a gamepad is connected)
add-axisAdd a source to an axis
recording-overlayRecording prompt text
recording-releaseRelease toggle in the recording prompt (recording-release-on while on)
conflictConflict warning message
conflict-acceptReplace button
conflict-cancelCancel button

Context Menu Parts ​

PartDescription
context-menuRoot container
backdropOverlay behind menu (covers viewport)
listMenu list (<ul>)
itemIndividual menu item (<li>)
item-activeCurrently highlighted item
item-disabledInactive command (failing when)
separatorCategory separator between groups
item-labelCommand label text
item-keysContainer for shortcut keys
item-keyIndividual key (<kbd>)

BEM Classes ​

Inside shadow DOM, elements have BEM class names matching their parts:

.palette
.palette__backdrop
.palette__dialog
.palette__input
.palette__list
.palette__item
.palette__item--active
.palette__item--disabled
...

These are useful if you're styling via JavaScript or inspecting elements.

Example: Light Theme ​

css
keybinds-command-palette::part(backdrop) {
  background: rgba(0, 0, 0, 0.3);
}

keybinds-command-palette::part(dialog) {
  background: #ffffff;
  border: 1px solid #e0e0e0;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
}

keybinds-command-palette::part(input) {
  color: #333;
  border-bottom: 1px solid #e0e0e0;
}

keybinds-command-palette::part(item) {
  color: #333;
}

keybinds-command-palette::part(item-active) {
  background: #f0f0f0;
}

keybinds-command-palette::part(item-key) {
  background: #f5f5f5;
  border-color: #ddd;
  color: #666;
}

Example: Glassmorphic ​

css
keybinds-command-palette::part(dialog) {
  background: rgba(255, 255, 255, 0.1);
  backdrop-filter: blur(20px);
  border: 1px solid rgba(255, 255, 255, 0.2);
}

Positioning ​

Override default positioning:

css
/* Center vertically */
keybinds-command-palette::part(dialog) {
  top: 50%;
  transform: translate(-50%, -50%);
}

/* Bottom sheet on mobile */
@media (max-width: 600px) {
  keybinds-command-palette::part(dialog) {
    top: auto;
    bottom: 0;
    left: 0;
    right: 0;
    transform: none;
    width: 100%;
    max-width: none;
    border-radius: 12px 12px 0 0;
  }
}