Initial release: dreamknob library + showcase

React + TypeScript knob/fader library with a headless interaction core
(rotary, relative-drag and track modes, wheel, keyboard, a11y), SVG
primitives, nine prebuilt skins, seven-segment display engine, and a
Vite showcase with gallery, live playground and API docs.
This commit is contained in:
Dreamodus 2026-07-12 14:26:52 -07:00
commit 60a02cb1db
46 changed files with 6186 additions and 0 deletions

View file

@ -0,0 +1,149 @@
import React from 'react';
import {
Arc,
Fader,
FlatKnob,
Knob,
KnobValue,
LEDFader,
LEDKnob,
MetalKnob,
NeonKnob,
Pointer,
RubberKnob,
SegmentDisplay,
SteppedKnob,
Ticks,
VintageKnob,
logTaper,
} from 'dreamknob';
const Card: React.FC<{
title: string;
desc: string;
tag: string;
children: React.ReactNode;
}> = ({ title, desc, tag, children }) => (
<div className="card">
<h3>{title}</h3>
<div className="card-desc">{desc}</div>
<div className="demo">{children}</div>
<span className="tag">{tag}</span>
</div>
);
export const Gallery: React.FC = () => (
<section className="block" id="gallery">
<div className="container">
<div className="section-kicker">Gallery</div>
<h2 className="section-title">Every style in the studio</h2>
<p className="section-sub">
Nine prebuilt skins every color themeable per instance. All of them share the
same interaction core: rotary or drag adjustment, scroll-wheel nudge, keyboard,
fine control and double-click reset.
</p>
<div className="grid">
<Card title="Flat" desc="Clean 2D arc knob for modern plugin UIs." tag="<FlatKnob />">
<FlatKnob size={86} defaultValue={64} label="Level" aria-label="Flat demo" />
<FlatKnob size={86} defaultValue={0} min={-50} max={50} arcFrom="center" color="#3df2ad" label="Pan" aria-label="Pan demo" />
<FlatKnob size={86} defaultValue={30} color="#ffd23e" trackColor="rgba(255,210,62,0.15)" label="Send" aria-label="Send demo" />
</Card>
<Card title="Metal" desc="Brushed aluminum with a knurled rim — 3D hi-fi feel." tag="<MetalKnob />">
<MetalKnob size={92} defaultValue={40} label="Input" aria-label="Metal demo" />
<MetalKnob size={92} defaultValue={75} tone="dark" color="#ff9640" label="Drive" aria-label="Dark metal demo" />
</Card>
<Card title="Rubber" desc="Soft-touch synth knob with a glowing halo." tag="<RubberKnob />">
<RubberKnob size={92} defaultValue={72} label="Cutoff" aria-label="Rubber demo" />
<RubberKnob size={92} defaultValue={30} color="#4cc2ff" label="Res" aria-label="Rubber resonance demo" />
</Card>
<Card title="Vintage" desc="Chicken-head bakelite over a printed scale." tag="<VintageKnob />">
<VintageKnob size={96} defaultValue={7} min={0} max={10} step={0.5} label="Volume" scaleLabels={['0', '', '', '', '', '5', '', '', '', '', '10']} aria-label="Vintage demo" />
<VintageKnob size={96} defaultValue={4} min={0} max={10} bodyColor="#26221f" label="Tone" aria-label="Bakelite demo" />
</Card>
<Card title="LED" desc="Segmented ring + true seven-segment readout." tag="<LEDKnob />">
<LEDKnob size={96} defaultValue={120} min={40} max={240} step={1} label="BPM" aria-label="LED demo" />
<LEDKnob size={96} defaultValue={-12.5} min={-60} max={0} step={0.5} digits={4} color="#ff4d6b" label="Thresh" aria-label="Threshold demo" />
</Card>
<Card title="Neon" desc="A glowing arc for dark, futuristic interfaces." tag="<NeonKnob />">
<NeonKnob size={90} defaultValue={35} label="Space" aria-label="Neon demo" />
<NeonKnob size={90} defaultValue={80} color="#3df2ad" label="Shine" aria-label="Neon green demo" />
</Card>
<Card title="Stepped" desc="Detented selector with named or numeric positions." tag="<SteppedKnob />">
<SteppedKnob size={92} positions={['LP', 'BP', 'HP', 'NT']} defaultValue={0} label="Filter" aria-label="Filter type demo" />
<SteppedKnob size={92} min={-24} max={24} steps={9} color="#4cc2ff" defaultValue={0} label="Semi" aria-label="Semitones demo" />
</Card>
<Card title="Fader" desc="Absolute-position linear control, both orientations." tag="<Fader />">
<Fader length={130} defaultValue={-6} min={-60} max={12} step={0.5} unit=" dB" label="Main" aria-label="Fader demo" />
<Fader orientation="horizontal" length={150} defaultValue={35} step={1} color="#e44cff" label="X-Fade" aria-label="Crossfade demo" />
</Card>
<Card title="LED fader" desc="Segmented meter-style fader with color zones." tag="<LEDFader />">
<LEDFader
length={130}
defaultValue={70}
step={1}
zones={[
{ upTo: 0.6, color: '#3df2ad' },
{ upTo: 0.85, color: '#ffd23e' },
{ upTo: 1, color: '#ff4d6b' },
]}
label="Level"
aria-label="LED fader demo"
/>
<LEDFader
orientation="horizontal"
length={140}
defaultValue={40}
step={1}
color="#4cc2ff"
label="Pos"
aria-label="Horizontal LED fader demo"
/>
</Card>
<Card title="Segment display" desc="The seven-segment engine, standalone." tag="<SegmentDisplay />">
<div style={{ display: 'flex', flexDirection: 'column', gap: 10, alignItems: 'center' }}>
<SegmentDisplay value={128.5} digits={4} decimals={1} />
<SegmentDisplay value={-42} digits={4} color="#ff4d6b" />
</div>
</Card>
<Card title="Log taper" desc="Audio-true frequency sweep: equal ratios per turn." tag="taper={logTaper}">
<FlatKnob
size={92}
min={20}
max={20000}
defaultValue={632}
taper={logTaper}
decimals={0}
color="#3df2ad"
format={v => (v >= 1000 ? `${(v / 1000).toFixed(1)}k` : `${Math.round(v)}`)}
label="Freq"
aria-label="Frequency demo"
/>
</Card>
<Card title="Compose your own" desc="Primitives + headless core = any design you want." tag="<Knob> + primitives">
<Knob size={96} defaultValue={42} aria-label="Composed demo">
<Ticks count={28} radius={47} length={5} width={1.5} color="rgba(255,255,255,0.12)" activeColor="#ffd23e" />
<Arc radius={36} thickness={2.5} color="#ffd23e" trackColor="rgba(255,255,255,0.08)" cap="butt" />
<Pointer type="triangle" radius={33} length={9} width={8} color="#ffd23e" />
<KnobValue color="#fff" fontSize={15} />
</Knob>
</Card>
<Card title="Vertical-drag mode" desc="Prefer the up/down plugin feel? One prop." tag="interaction='vertical'">
<RubberKnob size={92} defaultValue={50} interaction="vertical" color="#3df2ad" label="Depth" showValue aria-label="Vertical drag demo" />
</Card>
</div>
</div>
</section>
);