diff --git a/app/onboarding.tsx b/app/onboarding.tsx
index 98c4ec5ab..45935cf71 100644
--- a/app/onboarding.tsx
+++ b/app/onboarding.tsx
@@ -21,6 +21,7 @@ import {
OnboardingPage,
OnboardingPagination,
} from '@/components/Onboarding';
+import PasskeyFaqModal from '@/components/PasskeyFaqModal';
import { Button } from '@/components/ui/button';
import { Text } from '@/components/ui/text';
import { path } from '@/constants/path';
@@ -47,13 +48,15 @@ export default function Onboarding() {
const { width: screenWidth, height: screenHeight } = useWindowDimensions();
const [currentIndex, setCurrentIndex] = useState(0);
const [showRecoveryLink, setShowRecoveryLink] = useState(false);
+ const [showPasskeyFaq, setShowPasskeyFaq] = useState(false);
const scrollX = useSharedValue(0);
// Responsive layout for small screens (iPhone SE)
const isSmallScreen = screenHeight < 700;
// Fixed button area height - content area uses flex: 1 to fill remaining space.
- // Grows to fit the account-recovery prompt that appears after a failed login.
- const buttonAreaHeight = (isSmallScreen ? 200 : 240) + (showRecoveryLink ? 44 : 0);
+ // Grows to fit the help prompt (Passkey FAQs / account recovery) shown after a failed login,
+ // which can wrap onto two lines on smaller screens.
+ const buttonAreaHeight = (isSmallScreen ? 200 : 240) + (showRecoveryLink ? 64 : 0);
// Track screen width as shared value for use in worklets
const widthSV = useSharedValue(screenWidth);
@@ -125,10 +128,15 @@ export default function Onboarding() {
const filteredOnboardingData = ONBOARDING_DATA.filter(slide => slide?.platform !== false);
// Surfaced below the Login button after a failed login attempt so users who
- // can't authenticate (e.g. lost passkey) can start account recovery.
+ // can't authenticate (e.g. lost passkey) can read the Passkey FAQs or start
+ // account recovery.
const recoveryLink = showRecoveryLink ? (
- Have trouble logging in?
+ Have trouble logging in? See our
+ setShowPasskeyFaq(true)} className="web:hover:opacity-70">
+ Passkey FAQs
+
+ or
+
+
);
}
@@ -330,6 +340,8 @@ export default function Onboarding() {
+
+
);
}
diff --git a/components/PasskeyFaqModal.tsx b/components/PasskeyFaqModal.tsx
new file mode 100644
index 000000000..55a0d5af2
--- /dev/null
+++ b/components/PasskeyFaqModal.tsx
@@ -0,0 +1,46 @@
+import { View } from 'react-native';
+import LottieView from 'lottie-react-native';
+
+import { FAQ } from '@/components/FAQ';
+import ResponsiveModal, { ModalState } from '@/components/ResponsiveModal';
+import { Text } from '@/components/ui/text';
+import passkeyFaqs from '@/constants/passkey-faqs';
+
+const MODAL_STATE: ModalState = { name: 'passkey-faq', number: 1 };
+const CLOSE_STATE: ModalState = { name: 'close', number: 0 };
+
+interface PasskeyFaqModalProps {
+ isOpen: boolean;
+ onOpenChange: (open: boolean) => void;
+}
+
+const PasskeyFaqModal = ({ isOpen, onOpenChange }: PasskeyFaqModalProps) => {
+ return (
+
+
+
+
+
+ Passkey FAQ
+
+
+
+ );
+};
+
+export default PasskeyFaqModal;
diff --git a/constants/passkey-faqs.tsx b/constants/passkey-faqs.tsx
new file mode 100644
index 000000000..17e953cf1
--- /dev/null
+++ b/constants/passkey-faqs.tsx
@@ -0,0 +1,26 @@
+import { Faq } from '@/lib/types';
+
+const passkeyFaqs: Faq[] = [
+ {
+ question: 'What is a passkey and why is it more secure than a password?',
+ answer:
+ "A passkey lets you log into Solid using your device's biometrics (Face ID, fingerprint) or PIN instead of a password. It's stored locally on your device (never with Solid's) and is phishing-resistant by design, making it significantly harder to steal or compromise than a traditional password.",
+ },
+ {
+ question: "Why can't I see the passkey option when logging in?",
+ answer:
+ "Passkeys require a compatible device and browser, make sure you're on a recent version of iOS, Android, Chrome, or Safari.",
+ },
+ {
+ question: 'Can I use my passkey across multiple devices?',
+ answer:
+ "Yes, if you use a password manager that supports passkeys (like iCloud Keychain or Google Password Manager), your passkey syncs across your devices automatically. Otherwise, you'll need to create a separate passkey on each new device.",
+ },
+ {
+ question: 'What happens if I lose my device?',
+ answer:
+ "Your passkey is tied to your device, not your account. If you lose access to your phone, visit the Passkey Recovery link on the login screen, enter your email, and we'll send you a verification code to regain access. Once in, you can set up a new passkey on your new device.",
+ },
+];
+
+export default passkeyFaqs;