Translate togglePro
A message in two languages that never jumps: switching crossfades in place, and the block is always as tall as the longer version.
On this page
Installation
Usage
import { TranslateToggle } from "@/components/ui/chatcn/pro/translate-toggle"
<TranslateToggle
original={text}
translation={translated}
from={{ code: "pt", name: "Portuguese" }}
to={{ code: "en", name: "English" }}
onTranslate={translate}
/>Both versions sit in the same grid cell, so the message takes the height of the longer one and switching moves nothing below it. The swap crossfades with a 2 px blur at the midpoint so it reads as one text changing. The line under the text says Translated from Portuguese with Show original, or the language with Translate to English; the button holds both labels in one cell, so its width never changes. With no translation yet, the first press calls onTranslate and shows Translating to English; the original stays readable meanwhile. Each version carries its lang, so screen readers switch voice.
Examples
States
Props
| Prop | Type | Notes |
|---|---|---|
original, translation | ReactNode | translation is missing until translated |
from, to | { code, name } | BCP 47 code and the language name |
view, defaultView, onViewChange | "original" | "translation" | |
status | "idle" | "translating" | "done" | "error" | Inferred when omitted |
onTranslate | () => void | Asked for when there is no translation yet |
disabled | boolean | |
labels | Partial<TranslateToggleLabels> | Every string, for translation |
Keyboard
| Key | Action |
|---|---|
| Enter or Space | Switch language |
Accessibility
- The toggle has
aria-pressedfor the translation; the hidden version isaria-hidden. - Status changes are a polite live region; a failure is an alert.
Motion
200 ms crossfade on opacity and filter. Reduced motion keeps the fade without the blur.