Language Pair Selector
A paired source/target language picker — From/To pill toggles with a swap button, or a compact {source} → {target} select. Feeds useTranslate.
Language Pair Selector
The Language Pair Selector is a paired source/target language picker. The pills variant renders From/To pill toggles (flag + name) with a swap-languages button; the compact variant renders a grouped {source} → {target} pair of selects. It is fully controlled via sourceCode / targetCode and the onSelectSource / onSelectTarget / onSwap callbacks.
It is presentational and portable — feed the selected codes to any translation backend. With LocalMode you can (optionally) drive useTranslate() from @localmode/react, composed with useDetectLanguage() to auto-fill the source.
When to use it: any translation surface that lets the user choose a language pair and swap direction.
Preview
Installation
pnpm dlx shadcn@latest add @localmode/ui/input-controls/language-pair-selectornpx shadcn@latest add @localmode/ui/input-controls/language-pair-selectoryarn dlx shadcn@latest add @localmode/ui/input-controls/language-pair-selectorbunx --bun shadcn@latest add @localmode/ui/input-controls/language-pair-selectorDependencies
- Data source: renders the selected codes you pass and emits
onSelectSource/onSelectTarget/onSwapcallbacks — works with any backend. Recommended LocalMode producer:useTranslate(optionally composed withuseDetectLanguage). lucide-react— the swap icon
Files installed
language-pair-selector.tsx— the componentlib/utils.ts— thecn()helper (if not already present)
Props
LanguagePairSelector
Prop
Type
Examples
Drive a translation
import { useState } from 'react';
import { useTranslate } from '@localmode/react';
import { transformers } from '@localmode/transformers';
import { LanguagePairSelector } from '@/components/language-pair-selector';
const LANGS = [
{ code: 'en', name: 'English', flag: '🇬🇧' },
{ code: 'fr', name: 'French', flag: '🇫🇷' },
];
export function Translator() {
const [src, setSrc] = useState('en');
const [tgt, setTgt] = useState('fr');
const { execute, data } = useTranslate({
model: transformers.translator(`Xenova/opus-mt-${src}-${tgt}`),
});
return (
<LanguagePairSelector
languages={LANGS}
sourceCode={src}
targetCode={tgt}
onSelectSource={setSrc}
onSelectTarget={setTgt}
onSwap={() => { setSrc(tgt); setTgt(src); }}
/>
);
}Compact variant
<LanguagePairSelector variant="compact" languages={LANGS} {...props} />Customization
flag is optional per language and renders before the name. The active pill uses bg-primary/10 text-primary; the compact variant uses native styled selects for a tight footprint. Everything is theme-driven via shadcn/ui CSS variables — edit the copied file to change the pill shape or wire the swap button to additional side effects.
Segmented Mode Picker
A pill toggle for 2–4 mutually-exclusive modes, plus a typed TabBar variant with disabledTabs gating.
Text Processing Panel
A two-column input→output NLP shell — labeled textarea + word count + optional Char Limit Indicator, a result pane with copy, and a run/cancel/clear toolbar.