Audio UI

repository·main·Indexed 41 days ago

https://github.com/ouestlabs/audio-ui

A collection of React UI primitives and utility functions designed for building audio-centric applications. It provides specialized components such as Faders, Knobs, XYPads, and ChannelStrips, and is compatible with the shadcn/ui ecosystem. The library includes @audio-ui/utils for shared logic and a PlaybackEngine interface for managing audio playback, including a native HTML audio implementation ($htmlAudio).

Tokens
24K
Snippets
62
Records
123
Agent score
50%

What's inside Audio UI

  1. Overview of audio/ui capabilities

    main

    audio/ui is a component library designed for building audio interfaces in React applications. It is built on top of shadcn/ui and provides accessible, composable components that can be copied, pasted, and customized.

    Available Features

    Components

    • Audio Player: A composable player featuring queue management, shuffle, repeat modes, and volume control.
    • Controls: Low-level primitives including Knob, Fader, XY Pad, and Transport controls.
    • Channel Strip: Layout patterns for mixer-style columns that integrate controls, labels, and readouts.

    Library Core

    • Audio Store: A state management solution powered by Zustand for audio playback, which includes localStorage persistence.
    • HTML Audio: A core singleton used for loading and controlling HTML5 audio, featuring built-in retry logic and event handling.

    Blocks

    • Pre-assembled Patterns: Ready-to-use combinations of components, such as complete audio player or channel strip patterns, available in the component catalog.
  2. Important considerations for Sortable List

    main

    When using the Sortable List component, keep the following in mind:

    • Item IDs: Each item must have a unique id property. The id type must match between the item object and the SortableItem component.
    • Custom Component: This component is custom to this project for drag-and-drop audio queue reordering and is not part of the default shadcn/ui registry.
    • Built with dnd-kit: The component uses @dnd-kit, which includes keyboard-friendly drag-and-drop behavior.
    • Drag Handle: SortableDragHandle uses the project Button primitive.
  3. Understand the audio/ui philosophy

    main

    Unlike traditional NPM component libraries, audio/ui is not a package you install and import. Instead, it is a collection of accessible and composable components built on top of shadcn/ui.

    Key characteristics:

    • Ownership: You copy and paste the actual component code into your project, giving you full control over the implementation.
    • Customization: Because you own the code, you can modify any part of a component to fit your specific design system or functionality requirements without fighting library overrides.
    • Composition: Components share a common interface and are designed to be used as either low-level primitives or high-level, copy-ready blocks/layouts.
    • AI-Ready: The open-code nature and consistent APIs make it easy for LLMs to read, understand, and generate new components for your specific needs.
  4. How the Audio Player works

    main

    The Audio Player is built on three core architectural principles:

    1. Composable UI: AudioPlayer acts as a container. Every control (seek bar, volume, queue, playback speed) is an independent component that can be placed anywhere.
    2. Centralized State: All playback state (current track, progress, queue, shuffle, repeat) is managed in a Zustand store. Components interact with this store directly, avoiding prop drilling.
    3. Separated Engine: The AudioProvider manages the connection between the HTML audio element and the Zustand store (handling event listeners, retries, preloading, and state restoration), while UI components remain purely presentational, reading state and calling store actions.
  5. Fader Interactions (Pointer, Keyboard, and Wheel)

    main

    The Fader component supports multiple input methods for accessibility and ease of use.

    Pointer

    • Track click / drag: Clicking or dragging on the track updates the value based on pointer position.
    • Thumb drag: Dragging the thumb adjusts the value continuously, clamped between min and max.
    • Commit event: onValueCommit fires when the drag interaction ends.

    Keyboard

    When the thumb is focused, use the following keys:

    • ArrowUp / ArrowRight: Increase by step.
    • ArrowDown / ArrowLeft: Decrease by step.
    • PageUp: Increase by step * 10.
    • PageDown: Decrease by step * 10.
    • Home: Set to min.
    • End: Set to max.

    Wheel

    • When focused, mouse wheel input nudges the value by step.
  6. Understand the Audio Store architecture

    main

    The Audio Store is built using Zustand and follows this data flow:

    1. React Components use useAudioStore selectors to subscribe to state.
    2. AudioStore (Zustand) manages the state and triggers updates to components.
    3. Actions in the store interact with a $audio Singleton.
    4. The $audio Singleton controls the HTMLAudioElement via the Browser Audio API.
    5. State is persisted to localStorage and restored on initialization.

    SSR Warning: The store uses canUseDOM() internally. When working in Server-Side Rendering (SSR) environments, ensure you check for DOM availability before calling store methods that interact with browser APIs.

  7. Knob interaction models: Pointer, Keyboard, and Wheel

    main

    The Knob supports multiple input methods for adjusting values:

    Pointer Interactions

    • Circular Drag (Default): Tracks rotation around the center. Controlled by dragSensitivity.
    • Vertical Fader Drag: Enable via dragOptions={{ verticalPanEnabled: true }}. Allows vertical movement to act like a fader after a small threshold.
    • Double-tap / Double-click: Two quick releases (within ~320ms and ≤ ~12px movement) resets the value to defaultValue (or the midpoint of min...max if defaultValue is missing). This triggers onValueCommit.

    Keyboard Navigation

    When focused, use the following keys:

    • ArrowUp / ArrowRight: Increase by step
    • ArrowDown / ArrowLeft: Decrease by step
    • PageUp: Increase by step × 10
    • PageDown: Decrease by step × 10
    • Home: Set to min
    • End: Set to max

    Mouse Wheel

    When focused, vertical wheel deltas adjust the value using the same logic as keyboard nudging.

  8. XY Pad interaction models

    main

    The XYPad supports several input methods:

    Pointer

    • Click / drag: Maps pointer position directly to X/Y coordinates within the configured bounds.
    • Clamping: Values are automatically clamped to the minX/maxX and minY/maxY ranges.
    • Commit event: The onValueCommit callback fires specifically when a drag interaction ends (on release).

    Keyboard (when focused)

    • ArrowLeft / ArrowRight: Decrease / increase X by stepX.
    • ArrowUp / ArrowDown: Increase / decrease Y by stepY.
    • PageUp / PageDown: Increase / decrease Y by stepY * 10.
    • Home: Jump to top-left corner (x = minX, y = maxY).
    • End: Jump to bottom-right corner (x = maxX, y = minY).

    Wheel (when focused)

    • Wheel deltas nudge both axes based on pad dimensions and axis ranges, quantized by stepX and stepY.
  9. How Channel Strip layout and composition works

    main

    The ChannelStrip is a layout shell designed for mixer-style columns. It groups labels, controls, and value readouts.

    Mental Model

    • Interaction: The strip itself is a layout container and does not handle pointer, wheel, or keyboard input. Interaction logic is delegated to the controls (like Fader or Knob) you place inside ChannelStripSection.
    • Layout: It supports vertical (default) and horizontal orientations. When using a ChannelStripFooter, the root uses a responsive grid on wide screens to keep the header and footer in distinct areas.
    • Composition: Use one ChannelStripSection per control line. A section typically contains a ChannelStripLabel, a control slot, and a ChannelStripValue.
    • Accessibility: The root renders as a section. ChannelStripHeader and ChannelStripFooter provide landmark regions. ChannelStripValue renders as an output element with aria-live="polite" to announce value changes.
  10. Use extended semantic color tokens in audio/ui

    main

    audio/ui extends the standard shadcn/ui theming system with additional semantic tokens designed for precise, context-aware UI states like alerts, badges, and status indicators. While standard shadcn/ui themes work, using these extended tokens ensures consistent contrast across different component states.

    To use these in your CSS, you can map the semantic variables to the @theme block. The library provides specific tokens for info, success, warning, invert, and destructive-foreground states.