Inputs

Vanish Input

An input that dissolves its text into pixel particles on submit, in sweep, scatter, or rise styles, with rotating placeholders.

Bring this into your project

Run this command in your project folder. The CLI adds the source and dependencies; then follow the usage example below.

npx webberui@latest add vanish-input.en

New project or installation trouble? Start here →

Playground

Tune the props live — the code snippet updates as you go, so you can dial in the look you want before copying it.

0.9
3000
Active edited usageDefault props
<VanishInput/>

The complete example includes the preview layout and data. Install the component first, then paste this file into your project.

Installation

npx webberui@latest add https://webberui.com/r/vanish-input.en.json

Or, once registries are configured in components.json, install it as @webberui/vanish-input.

Usage

import { VanishInput } from "@/components/ui/vanish-input";

<VanishInput
  placeholder="Type and press Enter⋯"
  onSubmit={(value) => console.log(value)}
/>

On submit (Enter or clicking the arrow on the right), the component paints the current text onto an offscreen canvas, samples it pixel by pixel into particles, then lets those particles drift away and fade out according to variant, clearing the input at the same time.

Controlled mode

const [value, setValue] = React.useState("");

<VanishInput
  value={value}
  onChange={setValue}
  onSubmit={(v) => {
    // clear the controlled value yourself after submitting
    setValue("");
  }}
/>

Rotating placeholders

<VanishInput
  placeholder={["Search the docs⋯", "or type a command", "Chinese and emoji supported 🎉"]}
  variant="scatter"
/>

Props

PropTypeDefaultDescription
placeholderstring | string[]"Enter message..."Placeholder text; passing an array rotates through them in order
valuestring—Controlled value (controlled mode)
defaultValuestring""Default value in uncontrolled mode
onChange(value: string) => void—Fires when the content changes
onSubmit(value: string) => void—Fires on submit with the submitted text
variant"sweep" | "scatter" | "rise""sweep"Dissolve style: swept away / scattered / drifting upward
durationnumber0.9Duration of the dissolve animation (seconds)
placeholderIntervalnumber3000Interval between rotating placeholders (ms)
aria-labelstringfirst placeholderAccessible name
disabledbooleanfalseDisables input and submit
classNamestring—Styles for the outer container

How it works

  • On submit, the text is sampled pixel by pixel through getImageData, and the particle colour comes directly from the current text colour, so light and dark themes both line up automatically.
  • The canvas scales by devicePixelRatio (capped at 2) to stay sharp, and a ResizeObserver recomputes its size to follow the input's width.
  • When the particle count exceeds the cap, particles are thinned out at even intervals to keep the glyph outlines while protecting performance; the requestAnimationFrame loop stops automatically once every particle has faded out, and is also cleared when the component unmounts.
  • The input is carried by a native <input>, so pressing Enter mid-composition only confirms the candidate and does not submit by accident.

Accessibility

  • When the user has "reduce motion" enabled at the system level, submitting simply clears the input with no particle animation, and the placeholders stop rotating.
  • The canvas is marked aria-hidden, the input carries an aria-label (defaulting to the first placeholder), and the submit button carries aria-label="Send".
  • The form is carried by a native <form> with Enter submission and keyboard operation; the caret stays visible.