Scale menu

A menu that picks a root and a scale and turns the scale on or off, in parts you place beside items of your own.

Audio UI

Installation

pnpm dlx shadcn@latest add @audio-ui/scale-menu

Anatomy

<ScaleMenu>
  <ScaleMenuTrigger />
  <ScaleMenuContent>
    <ScaleMenuToggle />
    <ScaleMenuRoot />
    <ScaleMenuName />
  </ScaleMenuContent>
</ScaleMenu>

Usage

import type { Scale } from "@audio-ui/core/pitch";
import {
  ScaleMenu,
  ScaleMenuContent,
  ScaleMenuName,
  ScaleMenuRoot,
  ScaleMenuToggle,
  ScaleMenuTrigger,
} from "@/components/audio-ui/scale-menu";
import { DropdownMenuSeparator } from "@/components/ui/dropdown-menu";

const [enabled, setEnabled] = useState(false);
const [scale, setScale] = useState<Scale>({ name: "major", root: 0 });

<ScaleMenu
  enabled={enabled}
  onEnabledChange={setEnabled}
  onScaleChange={setScale}
  scale={scale}
>
  <ScaleMenuTrigger />
  <ScaleMenuContent>
    <ScaleMenuToggle />
    <DropdownMenuSeparator />
    <ScaleMenuRoot />
    <ScaleMenuName />
  </ScaleMenuContent>
</ScaleMenu>;

A scale is { root, name }: root is a pitch class, 0 for C to 11 for B, and name one of the scales in SCALES from @audio-ui/core/pitch ("major", "minor", "dorian", "blues"…). The menu keeps the scale while it is off, so turning it back on brings back the last one; picking a root or a scale turns it on.

Pass enabled ? scale : null to whatever marks the scale: a Piano roll's scale marks its rows, and inScale(pitch, scale) from @audio-ui/core/pitch tells whether any pitch is in it.

Items of your own

ScaleMenuContent is a dropdown menu's content, so any item goes beside the parts. The piano roll block adds a checkbox that folds the roll onto the scale's rows, and shows each item's key:

<ScaleMenuContent>
  <ScaleMenuToggle>
    Mark the scale
    <DropdownMenuShortcut>K</DropdownMenuShortcut>
  </ScaleMenuToggle>
  <DropdownMenuCheckboxItem checked={folded} onCheckedChange={setFolded}>
    Only its rows
    <DropdownMenuShortcut>G</DropdownMenuShortcut>
  </DropdownMenuCheckboxItem>
  <DropdownMenuSeparator />
  <ScaleMenuRoot />
  <ScaleMenuName />
</ScaleMenuContent>

API reference

ScaleMenu

Props · 4

Parts

Components · 5

ScaleMenuTrigger
The button that opens the menu: filled and named after the scale ("D Dorian") when it is on, outlined and named "Scale" when off. Takes the button's props.
ScaleMenuContent
The menu. Aligned to the trigger's end unless given align.
ScaleMenuToggle
A checkbox item that turns the scale on or off. Its children are the label, "Mark the scale" when left out.
ScaleMenuRoot
A submenu of the twelve roots.
ScaleMenuName
A submenu of the scales.

The file also exports SCALE_LABELS, each scale's name as the menu writes it, and scaleLabel(scale), which writes a scale as "D Dorian".

Built by Ouest Labs, the source code is available on GitHub.
RSS