Show real flag image in registration phone field
Flag emojis don't render on Windows, so derive an ISO code from the emoji's regional indicators and load a flagcdn image in front of the country-code selector (Account + Verify steps). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -891,9 +891,6 @@
|
||||
.dash-root .tm .ds-btn.v-primary { background: rgba(253, 169, 19, 0.92); color: #fff; border-radius: 9.132px; box-shadow: 0 8px 20px -10px rgba(253, 169, 19, 0.75); }
|
||||
.dash-root .tm .ds-btn.v-primary svg { color: #fff; }
|
||||
.dash-root .tm .ds-btn.v-primary:not(:disabled):hover { background: rgba(253, 169, 19, 1); }
|
||||
|
||||
.dash-root .view-body { display: flex; flex-direction: column; gap: 14px; }
|
||||
|
||||
.dash-root .tm-toolbar { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
|
||||
.dash-root .tm-search { display: flex; align-items: center; gap: 8px; flex: 1; min-width: 220px; height: 44px; padding: 0 13px; border-radius: 13px; border: 1px solid var(--border-2); background: var(--panel-2); color: var(--muted); transition: 0.14s; }
|
||||
.dash-root .tm-search:focus-within { border-color: var(--orange); box-shadow: 0 0 0 3px var(--ring); color: var(--orange); }
|
||||
|
||||
@@ -508,8 +508,12 @@ select.input option { background: var(--ink); color: var(--text); }
|
||||
|
||||
/* ---- country code select ---- */
|
||||
.phone-row { display: flex; gap: 8px; }
|
||||
.cc-field { position: relative; flex: 0 0 118px; width: 118px; }
|
||||
.cc-field .cc-select { width: 100%; flex: none; padding-left: 40px; }
|
||||
.cc-flag-img { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); width: 22px; height: 16px; border-radius: 3px; object-fit: cover; pointer-events: none; box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.18); }
|
||||
.cc-flag-img.static { position: static; transform: none; }
|
||||
.cc-select { width: 110px; flex: 0 0 110px; }
|
||||
@media (max-width: 420px) { .cc-select { width: 96px; flex-basis: 96px; } }
|
||||
@media (max-width: 420px) { .cc-field { flex-basis: 104px; width: 104px; } .cc-select { width: 96px; flex-basis: 96px; } }
|
||||
|
||||
/* ---- misc login/register bits ---- */
|
||||
.tips { list-style: none; padding: 0; margin: 16px 0 0; display: flex; flex-direction: column; gap: 8px; }
|
||||
|
||||
@@ -191,9 +191,13 @@ function StepAccount(p: {
|
||||
<div className="field" style={{ marginTop: 14 }}>
|
||||
<label className="label">Mobile number</label>
|
||||
<div className="phone-row">
|
||||
<select className="input cc-select" value={p.cc} onChange={(e) => p.setCc(e.target.value)}>
|
||||
{countryCodes.map((c) => <option key={c.code} value={c.code}>{c.flag} {c.code}</option>)}
|
||||
</select>
|
||||
<div className="cc-field">
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img className="cc-flag-img" src={flagUrl(p.country.flag)} alt={p.country.name} width={22} height={16} />
|
||||
<select className="input cc-select" value={p.cc} onChange={(e) => p.setCc(e.target.value)}>
|
||||
{countryCodes.map((c) => <option key={c.code} value={c.code}>{c.code}</option>)}
|
||||
</select>
|
||||
</div>
|
||||
<input className="input grow" inputMode="numeric" value={p.phone} onChange={(e) => p.setPhone(e.target.value.replace(/\D/g, ""))} placeholder={p.country.example} />
|
||||
</div>
|
||||
{p.phone && !p.phoneOk && <span style={{ fontSize: 12, color: "#fca5a5" }}>Enter a valid {p.country.digits}-digit number.</span>}
|
||||
@@ -398,7 +402,11 @@ function VerifyChannel({ kind, initial, country, cc, initialPhone, verified, onV
|
||||
<input className="input" value={value} onChange={(e) => { setValue(e.target.value); setState("idle"); }} placeholder="you@example.com" />
|
||||
) : (
|
||||
<div className="phone-row">
|
||||
<span className="input cc-select" style={{ display: "flex", alignItems: "center", justifyContent: "center" }}>{country.flag} {cc}</span>
|
||||
<span className="input cc-select" style={{ display: "flex", alignItems: "center", justifyContent: "center", gap: 7 }}>
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img className="cc-flag-img static" src={flagUrl(country.flag)} alt={country.name} width={22} height={16} />
|
||||
{cc}
|
||||
</span>
|
||||
<input className="input grow" inputMode="numeric" value={value} onChange={(e) => { setValue(e.target.value.replace(/\D/g, "")); setState("idle"); }} placeholder={country.example} />
|
||||
</div>
|
||||
)}
|
||||
@@ -618,3 +626,14 @@ function Stepper({ current }: { current: number }) {
|
||||
}
|
||||
|
||||
function cap(s: string) { return s.charAt(0).toUpperCase() + s.slice(1); }
|
||||
|
||||
// Flag emojis don't render on Windows, so map the emoji's regional-indicator
|
||||
// code points to an ISO-2 code and use a flag image instead.
|
||||
function flagUrl(flag: string): string {
|
||||
const iso = Array.from(flag)
|
||||
.map((ch) => ch.codePointAt(0))
|
||||
.filter((cp): cp is number => cp != null && cp >= 0x1f1e6 && cp <= 0x1f1ff)
|
||||
.map((cp) => String.fromCharCode(cp - 0x1f1e6 + 97))
|
||||
.join("");
|
||||
return `https://flagcdn.com/w40/${iso}.png`;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user