← Platform Docs
Mobile · Onboarding v2

The Auth Login Surface

The OAuth entry screen for the Ambasdr mobile app — an atmospheric Skia gradient, four brand-aligned OAuth pills, and a stubbed handoff to Gerald’s Auth0 wiring. First screen in the onboarding v2 redesign.

01

At a glance

Three layered atoms compose one screen.

Background

AuthGradientBackground

Single Skia canvas: charcoal→forest linear gradient + three slowly drifting Gaussian-blurred blobs + a 4% film-grain Turbulence overlay. One GPU pass per frame. Respects prefers-reduced-motion.

Buttons

OAuthButton × 4

Frost-fill pills with brand-colored Ionicons left-anchored via absolute positioning so the label dead-centers. LinkedIn / Google / Instagram / TikTok.

Screen

Login route

At app/(auth)/login.tsx. Composes the gradient, a frost-tinted three-plane Logomark, a Bebas Neue billboard headline, the OAuth pill stack, and an interactive legal fine-print block.

02

File map

Eight new files plus a route-redirect tweak. All under mobile/.

Path Role
app/(auth)/_layout.tsx Headerless Stack for the auth flow.
app/(auth)/login.tsx The login screen itself. Composes the three atoms.
app/index.tsx Root redirect: //(auth)/login.
components/auth/AuthGradientBackground.tsx Atmospheric Skia gradient with stage palette.
components/auth/OAuthButton.tsx Frost-fill OAuth pill atom.
stories/auth/*.stories.tsx Storybook stories: Auth/Login, Auth/AuthGradientBackground, Auth/OAuthButton.
__tests__/auth/*.test.tsx 39 unit tests covering rendering, interaction, accessibility, reduced motion, and brand-color regression.
03

AuthGradientBackground

Three layers, one Skia canvas, one GPU pass per frame.

Layer 1 — Base gradient

Diagonal LinearGradient from colors.ink (#1C1C1C charcoal) to colors.sage500 (#1F3D34 deep forest). Anchors top-left to bottom-right at viewport dimensions.

Layer 2 — Three blurred blobs

Each blob is a Circle with a BlurMask (Gaussian, style="normal"). The three blobs sit at distinct base positions and drift in slow circular orbits while breathing in opacity.

Layer 3 — Film grain

Turbulence shader with freqX/freqY=0.8, octaves=2, tileWidth/tileHeight=4, blended at 4% multiply opacity. Static (no animation) so it reads as material texture, not flicker.

Welcome stage palette

The auth surface uses the welcome stage from STAGE_PALETTES: inksage500 base + three blobs in sage400 (upper-right emerald glow), sage300 (lower-left mint haze), and frost (center breathing point). The StagePalette type is shaped so later onboarding steps can brighten as the user progresses.

Blob choreography

Each blob has its own drift period, breath period, and phase offset. All four numbers are coprime so the composition never repeats identically.

Blob Base position Radius / Blur Drift / Breath Opacity range
Upper-right emerald (0.75, 0.28) 220 / 80 32s / 18s 0.50–0.75
Lower-left sage haze (0.18, 0.78) 240 / 90 40s / 24s 0.40–0.60
Center frost breath (0.50, 0.50) 180 / 100 28s / 14s 0.15–0.28

A single master clock loops 0 → 1 over 120 seconds. Each blob derives its drift angle and breath phase from that clock modulo its own period. The Y delta on every orbit uses width (not height) as the radius scalar — gives a circular orbit in screen-px instead of an aspect-stretched ellipse, which reads as subtle drift rather than obvious vertical motion on a tall viewport.

Reduced motion

When useReducedMotion() is true, the master clock pins at zero. Blobs hold their base positions and mid-breath opacity. The gradient stays on screen; only the animation is suppressed.

04

OAuthButton

One atom, four providers, brand-colored icons.

Frost-fill pill, 56pt tall, full pill-radius. The icon sits in an absolutely positioned View at left: 24 so the label can dead-center across the full pill width — matching the AllTrails / Auth0 SDK convention rather than a flow-laid icon+label row.

Provider Ionicon Icon color Label
LinkedIn logo-linkedin #0A66C2 (LinkedIn blue) Continue with LinkedIn
Google logo-google colors.ink (single-glyph fallback) Continue with Google
Instagram logo-instagram #E1306C (Instagram pink) Continue with Instagram
TikTok logo-tiktok #000000 (TikTok black) Continue with TikTok
Why Google renders in ink

The Google “G” brand color is a four-color sweep (red / yellow / green / blue). A single-glyph icon font like Ionicons can’t render multi-color. We pick colors.ink over a single-stop approximation so we don’t misrepresent the brand.

Accessibility & interaction

05

Login screen

The three atoms composed into one route at app/(auth)/login.tsx.

Hero

Mark + headline

72pt Logomark with a frost-tinted three-plane hierarchy (#FAF8F3 / rgba(250,248,243,0.85) / rgba(250,248,243,0.55)). Below it, a Bebas Neue billboard headline: “Sign up or log into your ambasdr.” at 40pt / lineHeight 42 / letterSpacing 0.6, matching StepHeader.tsx’s rhythm per the project typography canon.

Bottom block

Pills + fine print

Four OAuthButton rows in a 12pt-gap column. Below them, a 11pt fine-print block with three inline legal links rendered as Text onPress with accessibilityRole="link". Underlined affordance, real onPress handlers, stubbed routes for now.

Fine-print copy (verbatim)

“By continuing to use Ambasdr, you agree to our Terms of Service and Privacy Policy. Personal data added to Ambasdr is public by default — refer to our Privacy FAQ to make changes.”

The wording is ported verbatim from the AllTrails reference screenshot Lennox shared, with every “AllTrails” replaced by “Ambasdr”. The three links use testIDs legal-link-terms, legal-link-privacy, and legal-link-privacy-faq.

06

Stubs and the Auth0 handoff

All interactive handlers on this screen are UI-only logs. Real auth wiring is Gerald’s lane.

Search for [oauth-stub] and [legal-stub]

Every tappable surface logs its intended action and either advances the route or no-ops. None of them touch tokens, sessions, or backend APIs yet.

OAuth handlers

// On press of any OAuth button:
console.log(`[oauth-stub] provider=${provider}`);
router.replace("/(onboarding)/username");

The route forward to /(onboarding)/username is temporary — it’s the current name-collection step. When the onboarding v2 single-field name step lands, the redirect target moves with it.

Legal-link handlers

// On press of any legal link span:
console.log(`[legal-stub] route=/legal/${route}`);
// no navigation — pure log until pages are ported

What Gerald owns next

07

Test coverage

39 unit tests across three files. Full suite stays green at 199 tests.

File Count Coverage
__tests__/auth/OAuthButton.test.tsx 17 Per-provider rendering & copy, a11y role + label, brand-color regression, disabled state behavior + a11y exposure, custom testID override.
__tests__/auth/AuthGradientBackground.test.tsx 8 Default + explicit stage rendering, style override, reduced-motion path, STAGE_PALETTES.welcome value assertions.
__tests__/auth/login.test.tsx 14 All 4 OAuth providers render & advance, headline + accessibilityRole="header", fine-print copy with Ambasdr substitution, 3 legal links with role=link, legal-stub press logs route & does NOT navigate, OAuth-stub press logs provider trace, reduced-motion path.
Skia + Reanimated test mocks

Skia primitives are aliased to bare RN Views; react-native-reanimated uses the package’s shipped mock entry. useReducedMotion is mocked at the suite level so reduced-motion paths can be flipped per-test. The mock pattern matches MeshGradientBackground.test.tsx from the shimmer animation PR.

08

Branch & merge trail

How this work landed on staging-mobile.

Net change at merge: 14 files, +899 / −160 lines, including the deletion of app/(onboarding)/welcome.tsx + its test and story (the onboarding v2 design drops the welcome interstitial).

09

What this unlocks

First screen in the onboarding v2 redesign sequence. Stacked PRs from here flesh out the form steps.

Next

Atoms PR

New ProgressBar (N/7 denominator), FooterButton, SageCurveBackground, OAuthButton refinements, FileContextSheet (bottom sheet for the Knowledge step). Storybook-first.

Then

Form steps PRs

Steps 1–4 (Name → Role → Handle → Photo), then Steps 5–6 (Socials with bubble pattern + Knowledge with bottom-sheet file context), then end-of-flow (Generating → Preview → Published → Notifications).

Once the full flow lands on staging-mobile, it ships to main as a single squashed PR — one logical “Onboarding v2 redesign” unit on the production history.