WebberUI

Vanish Input

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

Loading preview…
npx shadcn@latest add https://webberui.com/r/vanish-input.json

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
<VanishInput />

Installation

npx shadcn@latest add https://webberui.com/r/vanish-input.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[]"輸入訊息⋯"Placeholder text; passing an array rotates through them in order
valuestringControlled value (controlled mode)
defaultValuestring""Default value in uncontrolled mode
onChange(value: string) => voidFires when the content changes
onSubmit(value: string) => voidFires 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
classNamestringStyles 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="送出".
  • The form is carried by a native <form> with Enter submission and keyboard operation; the caret stays visible.

On this page