KQ-1252 · MUTE/CONE
Mute Cone
A mute toggle drawn as a speaker cone with up to four waves and a five-pill level meter: muting folds the waves back into the cone outermost first, a cascade apart on the exit ease, then a pen draws the slash; unmuting lifts the pen and releases the waves one by one on the snap spring, each overshooting its own radius, while the meter refills to the kept level on the glide spring. The volume is a second value: a long press arms a scrub, a vertical drag follows the finger 1:1 and rubber-bands past either end, the waves follow the level band by band, and reaching 0 mutes. It is a button with aria-pressed and a constant name; Space and Enter mute, the arrow keys, Page keys, Home and End set the volume, and the change is announced politely.
Design review
Fernworks · 4 in the call
sound on · volume 60%
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/mute-cone
Props
- pressed / defaultPressed
- boolean
- default false
- Whether the sound is muted, controlled or initial.
- onPressedChange
- (pressed: boolean) => void
- default —
- Fires from the press, drag or key that muted or unmuted.
- level / defaultLevel
- number
- default 60
- The volume, 0 to 100, controlled or initial. Muting keeps it; 0 is silence.
- onLevelChange
- (level: number) => void
- default —
- Fires from the drag or key that changed the volume, as it changes.
- waves
- number
- default 4
- How many sound waves the cone can hold, 1 to 4; the level fills them in turn and the icon's width follows.
- slash
- "line" | "cross" | "none"
- default "line"
- The mark drawn once the waves have folded: a slash through the cone, a cross where the waves were, or none.
- step
- number
- default 10
- How far one arrow key moves the level.
- label
- string
- default "Sound on"
- The word while sound plays.
- pressedLabel
- string
- default "Muted"
- The word while muted, in the muted colour.
- name
- string
- default "Mute"
- The toggle's accessible name, the same in both states.
- formatLevel
- (level: number) => string
- default `${level}%`
- How the level is written while it is scrubbed, and spoken.
- holdDelay
- number
- default 420
- How long a press is held before it starts scrubbing the level, in ms.
- scrubDistance
- number
- default 120
- How far a vertical drag travels to cross the whole range, in px.
- stagger
- number
- default cascade of the wave count
- The beat between one wave and the next as they fold or release, in ms.
- compact
- boolean
- default false
- Icon only: the cone over a row of five dots, the words in its accessible name.
- size
- "sm" | "md" | "lg"
- default "md"
- 40, 48 or 56px tall.
- accent
- string
- default "var(--accent-bright)"
- The waves and the meter, any CSS colour.
- mutedColor
- string
- default "var(--danger)"
- The muted mark and word.
- sound
- boolean
- default false
- Play the fold and release, the slash, and the meter's detents; only ever for the visitor's own press, drag or key.
- disabled
- boolean
- default false
- Not pressable or draggable, drawn at half strength.
- className
- string
- default —
- Classes for the button.
| Prop | Type | Default | Description |
|---|---|---|---|
| pressed / defaultPressed | boolean | false | Whether the sound is muted, controlled or initial. |
| onPressedChange | (pressed: boolean) => void | — | Fires from the press, drag or key that muted or unmuted. |
| level / defaultLevel | number | 60 | The volume, 0 to 100, controlled or initial. Muting keeps it; 0 is silence. |
| onLevelChange | (level: number) => void | — | Fires from the drag or key that changed the volume, as it changes. |
| waves | number | 4 | How many sound waves the cone can hold, 1 to 4; the level fills them in turn and the icon's width follows. |
| slash | "line" | "cross" | "none" | "line" | The mark drawn once the waves have folded: a slash through the cone, a cross where the waves were, or none. |
| step | number | 10 | How far one arrow key moves the level. |
| label | string | "Sound on" | The word while sound plays. |
| pressedLabel | string | "Muted" | The word while muted, in the muted colour. |
| name | string | "Mute" | The toggle's accessible name, the same in both states. |
| formatLevel | (level: number) => string | `${level}%` | How the level is written while it is scrubbed, and spoken. |
| holdDelay | number | 420 | How long a press is held before it starts scrubbing the level, in ms. |
| scrubDistance | number | 120 | How far a vertical drag travels to cross the whole range, in px. |
| stagger | number | cascade of the wave count | The beat between one wave and the next as they fold or release, in ms. |
| compact | boolean | false | Icon only: the cone over a row of five dots, the words in its accessible name. |
| size | "sm" | "md" | "lg" | "md" | 40, 48 or 56px tall. |
| accent | string | "var(--accent-bright)" | The waves and the meter, any CSS colour. |
| mutedColor | string | "var(--danger)" | The muted mark and word. |
| sound | boolean | false | Play the fold and release, the slash, and the meter's detents; only ever for the visitor's own press, drag or key. |
| disabled | boolean | false | Not pressable or draggable, drawn at half strength. |
| className | string | — | Classes for the button. |