import type { WordInfo } from '../../api/client'
import { speak, speechSupported } from '../../audio/speech'
import { usePack } from '../../i18n'
import { wordBand } from './wordband'
// WordCard is the right-click popover for any word: its dictionary definition(s)
// on top and tappable synonym pills below. Clicking a synonym replaces the word
// in place. Both datasets are offline, so this opens instantly and fills in as
// the (local) lookup returns. Labels are bilingual (zh-first, en subtitle) to
// match the rest of Petal's chrome β the writer uses Mandarin and English.
interface Props {
word: string
info: WordInfo | null
loading: boolean
// Whether the word is in the vocabulary garden (auto-saved on lookup). The
// heart toggles it; `onToggleSave` removes/re-adds it.
saved: boolean
onToggleSave: () => void
style: React.CSSProperties
onReplace: (synonym: string) => void
}
export function WordCard({ word, info, loading, saved, onToggleSave, style, onReplace }: Props) {
const t = usePack()
const definitions = info?.definitions ?? []
const synonyms = info?.synonyms ?? []
const gloss = info?.gloss ?? ''
const phonetic = info?.phonetic ?? ''
const etymology = info?.etymology ?? ''
// Null whenever the dictionary has no opinion β the chip then doesn't render.
const band = info ? wordBand(info.frequency ?? 0, info.difficulty ?? -1) : null
const empty = !loading && !gloss && definitions.length === 0 && synonyms.length === 0
return (
{/* How to say it, and how hard it is. The pronunciation aid pairs with the
π button above; the band answers the question a learner actually has
when she has found a word she likes β "can I use this?". Both are
quiet, muted lines: information she can take or leave, never a verdict
on her writing. */}
{(phonetic || band) && (