SoroPass
Components

Recover

Headless-first recover screen that discovers the Stellar smart accounts a passkey controls on a new device — no seed phrase, with a full APG listbox keyboard pattern.

Return on a new device and find the accounts a passkey controls — no seed phrase. A proper listbox with a full keyboard pattern, handling the one-account and many-accounts cases.

Overview

Six states. The resolved list is a real role="listbox" with roving focus. This is discover-only — to enroll a new credential, see Add backup passkey.

discovering shows the calm OS-sheet wait. On resolved, focus lands on the first account row.

Use cases

  • Signing in on a new device — A returning user installs your wallet on a new phone. Recover finds the smart accounts their passkey already controls — no seed phrase, no manual import.
  • Restoring after cleared storage — Local data is gone but the passkey lives in the platform keychain. Recover re-discovers the user's accounts from the credential alone.
  • Choosing between multiple accounts — When one passkey controls several accounts, the resolved listbox lets the user pick the right one with a full keyboard pattern.

Features

  • Real listbox semanticsrole=listbox with roving focus — Up/Down wrap, Home/End jump, Enter/Space select. Built to the APG pattern, not a styled div.
  • 1 and many, gracefully — A single account skips straight to selected; multiple accounts render a scannable, selectable list.
  • Self-describing rows — Each row pairs a deterministic identicon with a middle-truncated address and an optional meta line you supply.
  • Helpful empty state — When nothing is found, the none state routes the user to create a brand-new passkey instead.
  • Calm OS-sheet waitdiscovering shows the opaque scrim + pulsing glyph while the native sheet resolves the credential.
  • One error layout — Cancelled, unsupported, and network failures share the single error view, copy swapped by KitError code.

Preview & code

Interactive recover preview

The real component runs in mock mode on the demo. Open the demo →

mountRecoverScreen(root, { flow, onContinue });
const accounts = await recover({ rpId, indexer });

Installation

pnpm add @soropass/ui @soropass/core

Usage

Mount on the new device's sign-in surface; supply a per-row meta line and handle the chosen account.

import { mountRecoverScreen } from '@soropass/ui/styled';

const handle = mountRecoverScreen(document.querySelector('#signin'), {
  flow,
  accountMeta: (account) => `Last used ${account.lastUsed}`,
  onContinue(account) {
    session.use(account.address);
    handle.unmount();
  },
  onCreateNew() { router.push('/create'); },
});

States

The screen exposes six states: idle, discovering, resolved, selected, none, and error.

Interactive recover preview

The real component runs in mock mode on the demo. Open the demo →

none is the empty state — "No accounts found" + a "Create a new passkey instead" call-to-action.

Props

PropTypeDefaultDescription
flow REQRecoverFlowHeadless discovery controller.
copyPartial<RecoverCopy>DEFAULT_RECOVER_COPYi18n / brand voice.
accountMeta(a, i) => stringundefinedSecondary line per row.
onContinue(a: Account) => voidundefinedSelected account confirmed.
onCreateNew() => voidundefinedEmpty-state CTA.

Copy (i18n)

KeyDefault string
idleTitleFind your account
recoverLabelRecover
manyTitle(count){count} accounts found — a function
noneTitleNo accounts found

Accessibility

The resolved list is an APG-pattern listbox.

KeyAction
↑ / ↓Move active option (wraps)
Home / EndFirst / last option
Enter / SpaceChoose the active option
TabRoving tabindex — only the active row is in the tab order
  • aria-selected + check on the chosen row; visible focus ring on the active row.
  • On resolved, focus lands on the first account; on error, the status paragraph.
  • RTL via logical properties; reduced-motion variant included.

Theming hooks

AreaTokens
listbox row--pk-color-surface, --pk-color-border, --pk-radius-md
selected row--pk-color-brand, --pk-color-brand-soft
focus ring--pk-focus-color / -width / -offset / -halo
discovering--pk-scrim, --pk-busy-opacity

In Stellar Wallets Kit

// Recover seam → RecoverFlow
const accounts = await recover({ rpId, indexer });

On this page