ui: simplify adaptive sign-in choices
This commit is contained in:
parent
807b48bafc
commit
53380a99e1
3 changed files with 41 additions and 8 deletions
|
|
@ -66,7 +66,7 @@ export const LoginDialog: React.FC<LoginDialogProps> = ({ isOpen, onClose, onLog
|
||||||
const isAndroid = /Android/i.test(navigator.userAgent);
|
const isAndroid = /Android/i.test(navigator.userAgent);
|
||||||
// Which login method panel is showing. The three method cards below switch it.
|
// Which login method panel is showing. The three method cards below switch it.
|
||||||
const [loginTab, setLoginTab] = useState<'amber' | 'bunker' | 'nsec' | 'extension' | 'connect'>(
|
const [loginTab, setLoginTab] = useState<'amber' | 'bunker' | 'nsec' | 'extension' | 'connect'>(
|
||||||
isAndroid ? 'amber' : 'bunker',
|
isAndroid ? 'amber' : 'connect',
|
||||||
);
|
);
|
||||||
|
|
||||||
// Step 1: open Amber
|
// Step 1: open Amber
|
||||||
|
|
@ -360,18 +360,19 @@ export const LoginDialog: React.FC<LoginDialogProps> = ({ isOpen, onClose, onLog
|
||||||
<Tabs value={loginTab} onValueChange={(v) => setLoginTab(v as typeof loginTab)} className="w-full">
|
<Tabs value={loginTab} onValueChange={(v) => setLoginTab(v as typeof loginTab)} className="w-full">
|
||||||
{/* Method cards — plain-language labels; protocol names move to a
|
{/* Method cards — plain-language labels; protocol names move to a
|
||||||
tiny hint so newcomers aren't met with "NIP-46" as the main word. */}
|
tiny hint so newcomers aren't met with "NIP-46" as the main word. */}
|
||||||
<div className="mb-3 grid grid-cols-3 gap-2">
|
<div className="mb-3 grid grid-cols-2 gap-2">
|
||||||
{([
|
{([
|
||||||
{ id: 'extension', Icon: Shield, label: t('settingsUi.loginDialog.extensionCard'), hint: 'NIP-07' },
|
{ id: 'extension', Icon: Shield, label: t('settingsUi.loginDialog.extensionCard'), hint: 'NIP-07' },
|
||||||
{ id: isAndroid ? 'amber' : 'bunker', Icon: isAndroid ? Smartphone : Cloud, label: t('settingsUi.loginDialog.signerCard'), hint: isAndroid ? 'NIP-55' : 'NIP-46' },
|
isAndroid
|
||||||
{ id: 'connect', Icon: QrCode, label: t('settingsUi.loginDialog.signInWithPhone'), hint: 'NIP-46' },
|
? { id: 'amber', Icon: Smartphone, label: t('settingsUi.loginDialog.amberCard'), hint: 'NIP-55' }
|
||||||
|
: { id: 'connect', Icon: QrCode, label: t('settingsUi.loginDialog.pairSignerCard'), hint: 'NIP-46' },
|
||||||
] as const).map(({ id, Icon, label, hint }) => {
|
] as const).map(({ id, Icon, label, hint }) => {
|
||||||
const active = loginTab === id;
|
const active = loginTab === id || (id === 'connect' && loginTab === 'bunker');
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
key={id}
|
key={id}
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => setLoginTab(id)}
|
onClick={() => setLoginTab(id as typeof loginTab)}
|
||||||
className={cn(
|
className={cn(
|
||||||
'flex min-h-0 flex-col items-center gap-1 rounded-xl border p-2.5 text-center transition-colors',
|
'flex min-h-0 flex-col items-center gap-1 rounded-xl border p-2.5 text-center transition-colors',
|
||||||
active
|
active
|
||||||
|
|
@ -425,6 +426,13 @@ export const LoginDialog: React.FC<LoginDialogProps> = ({ isOpen, onClose, onLog
|
||||||
>
|
>
|
||||||
{t('settingsUi.loginDialog.noAmberGetIt')}
|
{t('settingsUi.loginDialog.noAmberGetIt')}
|
||||||
</a>
|
</a>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => setLoginTab('connect')}
|
||||||
|
className="text-[11px] text-gray-500 underline underline-offset-2 hover:text-gray-300"
|
||||||
|
>
|
||||||
|
{t('settingsUi.loginDialog.useAnotherSigner')}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
@ -566,6 +574,14 @@ export const LoginDialog: React.FC<LoginDialogProps> = ({ isOpen, onClose, onLog
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<button
|
||||||
|
type='button'
|
||||||
|
onClick={() => setLoginTab('bunker')}
|
||||||
|
className='w-full text-[11px] text-gray-500 underline underline-offset-2 hover:text-gray-300'
|
||||||
|
>
|
||||||
|
{t('settingsUi.loginDialog.pasteBunker')}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
|
|
||||||
|
|
@ -581,6 +597,13 @@ export const LoginDialog: React.FC<LoginDialogProps> = ({ isOpen, onClose, onLog
|
||||||
<Button className='w-full rounded-full py-2.5 bg-blue-500 hover:bg-blue-600 text-white font-bold uppercase' disabled={isLoading || !bunkerUri.trim()} onClick={handleBunkerLogin}>
|
<Button className='w-full rounded-full py-2.5 bg-blue-500 hover:bg-blue-600 text-white font-bold uppercase' disabled={isLoading || !bunkerUri.trim()} onClick={handleBunkerLogin}>
|
||||||
{isLoading ? <Loader2 className='w-4 h-4 animate-spin mr-2' /> : <Cloud className='w-4 h-4 mr-2' />}{t('settingsUi.loginDialog.connect')}
|
{isLoading ? <Loader2 className='w-4 h-4 animate-spin mr-2' /> : <Cloud className='w-4 h-4 mr-2' />}{t('settingsUi.loginDialog.connect')}
|
||||||
</Button>
|
</Button>
|
||||||
|
<button
|
||||||
|
type='button'
|
||||||
|
onClick={() => setLoginTab('connect')}
|
||||||
|
className='w-full text-[11px] text-gray-500 underline underline-offset-2 hover:text-gray-300'
|
||||||
|
>
|
||||||
|
{t('settingsUi.loginDialog.backToQR')}
|
||||||
|
</button>
|
||||||
{/* Instructions collapse: the default state is just input + Connect. */}
|
{/* Instructions collapse: the default state is just input + Connect. */}
|
||||||
<details>
|
<details>
|
||||||
<summary className='cursor-pointer text-[11px] text-gray-500 hover:text-gray-300'>
|
<summary className='cursor-pointer text-[11px] text-gray-500 hover:text-gray-300'>
|
||||||
|
|
|
||||||
|
|
@ -4590,6 +4590,11 @@ settingsUi: {
|
||||||
welcomeSubtitle: 'Sign up or log in to continue',
|
welcomeSubtitle: 'Sign up or log in to continue',
|
||||||
welcomeSubtitleBrowse: 'Sign up or log in — or keep browsing.',
|
welcomeSubtitleBrowse: 'Sign up or log in — or keep browsing.',
|
||||||
extensionCard: 'Browser extension',
|
extensionCard: 'Browser extension',
|
||||||
|
amberCard: 'Amber',
|
||||||
|
pairSignerCard: 'Pair a signer',
|
||||||
|
useAnotherSigner: 'Use another signer (QR)',
|
||||||
|
pasteBunker: 'Paste a bunker URI instead',
|
||||||
|
backToQR: '← Back to QR pairing',
|
||||||
signerCard: 'Signer app',
|
signerCard: 'Signer app',
|
||||||
secretKeyLink: 'Use a secret key instead',
|
secretKeyLink: 'Use a secret key instead',
|
||||||
whereBunker: 'Where do I get a bunker?',
|
whereBunker: 'Where do I get a bunker?',
|
||||||
|
|
@ -4632,7 +4637,7 @@ settingsUi: {
|
||||||
connect: 'Connect',
|
connect: 'Connect',
|
||||||
back: '← Back',
|
back: '← Back',
|
||||||
signInWithPhone: 'Sign in with your phone',
|
signInWithPhone: 'Sign in with your phone',
|
||||||
signInWithPhoneDesc: 'Scan with a signer app (Amber, nsec.app). Your key never leaves your phone.',
|
signInWithPhoneDesc: 'Scan with a NIP-46 signer such as nsec.app or Nostrum. On Android, Amber is the one-tap option above.',
|
||||||
showPairingCode: 'Show pairing code',
|
showPairingCode: 'Show pairing code',
|
||||||
waitingSigner: 'Waiting for your signer…',
|
waitingSigner: 'Waiting for your signer…',
|
||||||
copyLink: 'Copy link',
|
copyLink: 'Copy link',
|
||||||
|
|
|
||||||
|
|
@ -4590,6 +4590,11 @@ settingsUi: {
|
||||||
welcomeSubtitle: 'Regístrate o inicia sesión para continuar',
|
welcomeSubtitle: 'Regístrate o inicia sesión para continuar',
|
||||||
welcomeSubtitleBrowse: 'Regístrate o inicia sesión, o sigue explorando.',
|
welcomeSubtitleBrowse: 'Regístrate o inicia sesión, o sigue explorando.',
|
||||||
extensionCard: 'Extensión del navegador',
|
extensionCard: 'Extensión del navegador',
|
||||||
|
amberCard: 'Amber',
|
||||||
|
pairSignerCard: 'Emparejar un firmador',
|
||||||
|
useAnotherSigner: 'Usar otro firmador (QR)',
|
||||||
|
pasteBunker: 'Pegar una URI de bunker',
|
||||||
|
backToQR: '← Volver al emparejamiento QR',
|
||||||
signerCard: 'App firmante',
|
signerCard: 'App firmante',
|
||||||
secretKeyLink: 'Usar una clave secreta',
|
secretKeyLink: 'Usar una clave secreta',
|
||||||
whereBunker: '¿Dónde consigo un bunker?',
|
whereBunker: '¿Dónde consigo un bunker?',
|
||||||
|
|
@ -4632,7 +4637,7 @@ settingsUi: {
|
||||||
connect: 'Conectar',
|
connect: 'Conectar',
|
||||||
back: '← Atrás',
|
back: '← Atrás',
|
||||||
signInWithPhone: 'Inicia sesión con tu teléfono',
|
signInWithPhone: 'Inicia sesión con tu teléfono',
|
||||||
signInWithPhoneDesc: 'Escanea con una app firmadora (Amber, nsec.app). Tu clave nunca sale de tu teléfono.',
|
signInWithPhoneDesc: 'Escanea con un firmador NIP-46 como nsec.app o Nostrum. En Android, Amber es la opción de un toque de arriba.',
|
||||||
showPairingCode: 'Mostrar código de emparejamiento',
|
showPairingCode: 'Mostrar código de emparejamiento',
|
||||||
waitingSigner: 'Esperando a tu firmador…',
|
waitingSigner: 'Esperando a tu firmador…',
|
||||||
copyLink: 'Copiar enlace',
|
copyLink: 'Copiar enlace',
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue