Skip to content

feat(auth): sign-up, sign-in and password-reset flow#8

Merged
0xdevcollins merged 5 commits into
mainfrom
feat/auth-flow
Jun 11, 2026
Merged

feat(auth): sign-up, sign-in and password-reset flow#8
0xdevcollins merged 5 commits into
mainfrom
feat/auth-flow

Conversation

@0xdevcollins

@0xdevcollins 0xdevcollins commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Summary

Implements the full authentication experience from the Figma designs as a feature-first set of routes under (auth), wired to the existing better-auth client. Replaces the previous basic /sign-in page.

Screens (8)

  • Sign up: choose path (email + Google / Apple / Github) -> with email -> verify code
  • Sign in: choose path -> email + password (forgot-password link, show/hide toggle) -> verify code
  • Reset password: request code -> verify code -> set new password

Shared shell & building blocks (src/features/auth/)

  • (auth)/layout.tsx reuses marketing's HeroBackground (star-field + bottom brand glow), centered BoundlessLogo, and a terms line pinned to the bottom.
  • AuthCard (plain + sectioned for OTP), AuthInput, OtpInput (6-digit, two connected groups, auto-advance / backspace / paste), SocialAuthButtons, OrDivider, AuthFooterPill, and the step forms.
  • All actions use the Button primitive; inputs use the Form/Input primitives and design tokens.

Auth wiring

  • Sign-up + verify -> emailOtp.sendVerificationOtp / signIn.emailOtp (passwordless, auto-creates).
  • Sign-in -> signIn.email; social -> signIn.social.
  • Reset -> emailOtp.sendVerificationOtp({ type: 'forget-password' }) then emailOtp.resetPassword.

Intentional deviations from Figma (flagged)

  1. Social buttons on the sign-in screen read "Sign in with ..." (Figma showed "Sign up with ..." on the log-in screen, a copy slip).
  2. Footer pill on /sign-up/email reads "Already have an account? Sign In" (Figma showed "Don't have an account? Sign up").
  3. The set-new-password screen (/reset-password/new) has no Figma frame yet, so it follows the existing auth design system. Worth a design review when the official mockup lands.

Verification

  • npm run typecheck, npm run lint (0 errors), npm run test (14/14) all pass.
  • All routes smoke-tested locally (200, correct content, no runtime errors).

Note: the get-started modal and other unrelated in-progress changes were intentionally left out of this branch to keep the PR focused on auth.

Summary by CodeRabbit

Release Notes

  • New Features

    • Complete authentication flows for sign-in, sign-up, and password reset with email and OTP verification
    • Social authentication buttons supporting Google, Apple, and GitHub
    • Enhanced input field component with validation states, labels, and helper text
    • New option card component for user selections
    • Get-started onboarding modal
  • Style

    • Improved input field styling with better visual hierarchy and icon support
    • Updated navigation bar with wallet and credits display formatting

Build the full authentication experience from the Figma designs as a
feature-first set of routes under (auth), backed by the existing
better-auth client.

Screens:
- Sign up: choose path (email + Google/Apple/Github), with email, verify code
- Sign in: choose path, email + password (forgot link, show/hide), verify code
- Reset password: request code, verify code, set new password

Adds a shared auth shell (star-field background + brand glow, centered logo,
terms footer) and reusable building blocks: AuthCard, AuthInput, OtpInput,
SocialAuthButtons, OrDivider, AuthFooterPill, and the step forms. Wires
emailOtp (passwordless sign-up + verification), signIn.email, signIn.social
and emailOtp.resetPassword. Replaces the previous basic sign-in page.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 11, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
boundless-v2 Ready Ready Preview, Comment Jun 11, 2026 9:33pm

@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@0xdevcollins, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 55 minutes and 7 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more credits in the billing tab to continue.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 67dda653-d163-466b-a16e-6e1a8e2481d3

📥 Commits

Reviewing files that changed from the base of the PR and between e841b76 and 766f523.

⛔ Files ignored due to path filters (1)
  • public/brand/Boundless-mark-card.svg is excluded by !**/*.svg
📒 Files selected for processing (23)
  • src/app/(auth)/reset-password/new/page.tsx
  • src/app/(auth)/reset-password/verify/page.tsx
  • src/app/(auth)/sign-in/page.tsx
  • src/app/(auth)/sign-in/verify/page.tsx
  • src/app/(auth)/sign-up/verify/page.tsx
  • src/app/input-preview/page.tsx
  • src/app/layout.tsx
  • src/components/layout/app-nav.tsx
  • src/components/ui/input.tsx
  • src/components/ui/option-card.tsx
  • src/features/auth/components/otp-input.tsx
  • src/features/auth/components/otp-verify-form.tsx
  • src/features/auth/components/reset-password-form.tsx
  • src/features/auth/components/reset-password-new-form.tsx
  • src/features/auth/components/sign-in-email-form.tsx
  • src/features/auth/components/sign-up-email-form.tsx
  • src/features/auth/components/social-auth-buttons.tsx
  • src/features/auth/index.ts
  • src/features/auth/lib/safe-redirect.ts
  • src/features/discover/components/filter-rail.tsx
  • src/features/marketing/components/get-started-modal.tsx
  • src/features/marketing/index.ts
  • src/lib/format.ts
📝 Walkthrough

Walkthrough

This PR introduces a complete authentication system with shared layout, reusable auth UI components, and three parallel email-based flows (sign-in with password fallback, sign-up with OTP, password reset with OTP). It includes social authentication buttons, OTP input/verification components, helper utilities for safe redirects and number formatting, and enhancements to existing UI components like Input and AppNav.

Changes

Authentication System Implementation

Layer / File(s) Summary
Shared Auth Page Layout
src/app/(auth)/layout.tsx
AuthLayout wraps all auth pages in a consistent shell with HeroBackground, centered BoundlessLogo/children, and pinned AuthTerms footer.
Reusable Auth UI Components
src/features/auth/components/auth-card.tsx, auth-footer-pill.tsx, auth-terms.tsx, or-divider.tsx, provider-icons.tsx
AuthCard (plain/sectioned variants), AuthFooterPill (pill navigation), AuthTerms (terms/privacy links), OrDivider, and provider SVG icons (Google, Apple, GitHub) form the foundational auth UI toolkit.
OTP Input and Verification
src/features/auth/components/otp-input.tsx, otp-verify-form.tsx
OtpInput renders two-segment digit entry with Backspace/paste handling and cross-input focus. OtpVerifyForm gates submission on completeness, handles sign-in/reset modes, calls authClient, and persists OTP in sessionStorage for password-reset flows.
Social Authentication Buttons
src/features/auth/components/social-auth-buttons.tsx
SocialAuthButtons renders Google/Apple/GitHub buttons, tracks pending provider state, calls signIn.social, and shows per-button loading and toast errors.
Sign-in Flow: Email and Social Routes
src/app/(auth)/sign-in/page.tsx, sign-in/email/page.tsx, sign-in/verify/page.tsx, src/features/auth/components/sign-in-email-form.tsx
Sign-in page refactored with email CTA and social buttons. SignInEmailForm validates email/password and redirects based on searchParams. SignInVerifyPage reads email and mounts OtpVerifyForm in sign-in mode.
Sign-up Flow: Email and Social Routes
src/app/(auth)/sign-up/page.tsx, sign-up/email/page.tsx, sign-up/verify/page.tsx, src/features/auth/components/sign-up-email-form.tsx
Sign-up page with email CTA and social buttons. SignUpEmailForm sends verification OTP via authClient and redirects to verify page. SignUpVerifyPage reads email and mounts OtpVerifyForm in sign-in mode.
Password Reset Flow: Email-based Recovery
src/app/(auth)/reset-password/page.tsx, reset-password/verify/page.tsx, reset-password/new/page.tsx, src/features/auth/components/reset-password-form.tsx, reset-password-new-form.tsx
ResetPasswordForm sends forget-password OTP. ResetPasswordVerifyPage reads email and stores verified OTP in sessionStorage. ResetPasswordNewForm reads OTP from sessionStorage, validates password match and minimum length, calls resetPassword, and clears sessionStorage.
Safe Redirect Utility
src/features/auth/lib/safe-redirect.ts
safeRedirect validates redirect destinations, rejecting non-same-origin and unsafe paths, returning default fallback on failure.
Input Component and Related UI Updates
src/components/ui/input.tsx, src/components/ui/option-card.tsx, src/components/layout/app-nav.tsx, src/lib/format.ts
Input component replaced with variant-driven styled implementation supporting labels, helper text, icons, and state variants. OptionCard adds selectable option cards with radio role. AppNav updated to numeric credits/wallet with formatCompact/formatNumber helpers. Formatting utilities added for compact/grouped number display.
Preview Pages and Layout Utilities
src/app/input-preview/page.tsx, src/features/marketing/components/get-started-modal.tsx, src/features/discover/components/filter-rail.tsx, src/app/layout.tsx
InputPreview demonstrates Input variants. GetStartedModal dialog component. FilterRail reward inputs use inputSize='small'. Root layout removes geistMono font variable.
Feature Barrel Exports
src/features/auth/index.ts, src/features/marketing/index.ts
Auth barrel exports all new auth components and safeRedirect; removes old SignInForm. Marketing barrel exports GetStartedModal.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • boundlessfi/boundless-platform#1: Both PRs modify src/app/layout.tsx's <html> className font-variable setup, with this PR removing geistMono.variable and the previous PR introducing font variable handling.

Poem

🐰 A bunny hops through auth gates secure,

Email paths and OTP pure,

Social buttons shine so bright,

Password resets set things right—

Sign up, sign in, recovery sure! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly describes the main feature added: a complete sign-up, sign-in, and password-reset authentication flow with multiple screens and components.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/auth-flow

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

🧹 Nitpick comments (2)
src/features/auth/components/otp-input.tsx (1)

80-99: ⚡ Quick win

Add accessible labeling for screen readers.

Individual digit inputs without labels can be confusing for assistive technology users. Consider adding aria-label to each input indicating its position (e.g., "Digit 1 of 6").

♿ Proposed accessibility improvement
              <input
                key={index}
                ref={el => {
                  refs.current[index] = el;
                }}
                type='text'
                inputMode='numeric'
                autoComplete='one-time-code'
                maxLength={1}
                disabled={disabled}
                autoFocus={autoFocus && index === 0}
                value={value[index] ?? ''}
                onChange={event => handleChange(event, index)}
                onKeyDown={event => handleKeyDown(event, index)}
                onPaste={handlePaste}
+               aria-label={`Digit ${index + 1} of ${length}`}
                className={cn(
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/auth/components/otp-input.tsx` around lines 80 - 99, Add an
accessible aria-label to each OTP input so screen readers can announce its
position: in the input JSX (the element that uses refs.current[index],
value[index], onChange -> handleChange, onKeyDown -> handleKeyDown, onPaste ->
handlePaste) add an aria-label prop like aria-label={`Digit ${index + 1} of
${totalDigits ?? value?.length ?? refs.current.length}`} (or derive totalDigits
from the prop that controls OTP length). Ensure the label updates per index and
keep existing handlers/props intact.
src/features/auth/components/otp-verify-form.tsx (1)

59-59: 💤 Low value

Encode OTP in URL for robustness.

While OTPs are typically numeric, for consistency and safety the OTP should also be URL-encoded.

🔧 Proposed fix
    router.push(
-     `/reset-password/new?email=${encodeURIComponent(email)}&otp=${otp}`
+     `/reset-password/new?email=${encodeURIComponent(email)}&otp=${encodeURIComponent(otp)}`
    );
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/auth/components/otp-verify-form.tsx` at line 59, The OTP is not
URL-encoded in the reset link generation in otp-verify-form.tsx; update the
template string that builds
`/reset-password/new?email=${encodeURIComponent(email)}&otp=${otp}` to encode
the OTP as well (use encodeURIComponent(otp)) so both email and otp are safely
escaped when constructing the URL in the component that generates the reset
link.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/app/`(auth)/reset-password/verify/page.tsx:
- Around line 12-30: The page currently defaults email to '' and renders the
verify UI even when no email is provided; add a guard that redirects to
'/reset-password' when email is missing. Import and call Next.js's redirect
(from 'next/navigation') or your app's router redirect function at the top of
the component (before rendering AuthCard/OtpVerifyForm) and perform if (!email)
redirect('/reset-password'); so OtpVerifyForm (mode='reset') is only rendered
when a valid email exists.

In `@src/app/`(auth)/sign-in/page.tsx:
- Around line 21-27: The sign-in redirect query param is being dropped: update
the Link to `/sign-in/email` to include the current `redirect` query value
(e.g., append `?redirect=${redirect}`) and propagate the same param into the
social sign-in branch by passing it into the SocialAuthButtons component (add a
prop such as `redirect` or `callbackUrl` and use it in SocialAuthButtons to set
the OAuth callback/next URL instead of the hardcoded `/dashboard`). Locate the
Link in page.tsx and the SocialAuthButtons usage and ensure they both read the
current search param (via useSearchParams or equivalent) and forward it so the
original redirect is preserved across both paths.

In `@src/app/`(auth)/sign-in/verify/page.tsx:
- Around line 12-30: The verify page currently defaults email to '' and always
renders OtpVerifyForm, which can never succeed without an email; update the page
component to guard when email is missing by checking the derived email (the
email variable from searchParams) before rendering OtpVerifyForm/AuthCard: if
email is falsy, either redirect back to '/sign-in/email' or render a friendly
message/UI prompting the user to provide an email (e.g., replace OtpVerifyForm
with a link/button to backHref); ensure the check happens before rendering
OtpVerifyForm (referencing the email variable and the OtpVerifyForm and AuthCard
components) so no verification is attempted with an empty email.

In `@src/app/`(auth)/sign-up/verify/page.tsx:
- Around line 12-30: The page currently defaults email to '' and renders
OtpVerifyForm which will call authClient.signIn.emailOtp with an empty email;
update the component that uses searchParams and the email constant to
validate/guard the email before rendering OtpVerifyForm (e.g., check that email
is non-empty and a valid email format), and if the guard fails, redirect back to
the email entry route or render a friendly message/CTA (e.g., link to
'/sign-up/email') instead of rendering OtpVerifyForm; ensure the guard lives in
the verify page where email is read (the email variable derived from
searchParams) so OtpVerifyForm only receives a guaranteed valid email.

In `@src/features/auth/components/auth-input.tsx`:
- Around line 22-30: Replace the raw <input> in the AuthInput component with the
shared Input primitive: import the Input component and use <Input ref={ref}
{...props} className={cn('h-14 w-full rounded-md border ...
aria-invalid:border-error-500', hasAdornment && 'pr-12', className)} /> so you
preserve ref forwarding, {...props} forwarding, the cn class merge, and the
hasAdornment/pr-12 behavior; ensure the component still exposes the same props
and aria-invalid styling and remove the old native <input> element.

In `@src/features/auth/components/otp-input.tsx`:
- Around line 26-30: setDigit currently does value.split('') then assigns
next[index], which creates sparse arrays when index >= next.length; fix by
creating a fully populated array of the expected length before assigning: build
next as an array of length `length` filled with empty strings and copy existing
characters from `value` into it (or push empty strings until next.length ===
length), then set next[index] = digit and call onChange(next.join('').slice(0,
length)); reference the setDigit function and the variables value, length, next,
and onChange.

In `@src/features/auth/components/otp-verify-form.tsx`:
- Around line 56-60: The current router.push call that navigates in the reset
flow (the branch where mode === 'reset') leaks the OTP via URL
(`router.push(`/reset-password/new?email=${encodeURIComponent(email)}&otp=${otp}`)`);
change this to persist the OTP in a short-lived client-side or server-side state
(e.g., sessionStorage key like "resetOtp:<email>" or set a secure, short-lived
cookie) and navigate without the otp query param (only include the encoded email
or a state token), then read and immediately remove the OTP in the next
component before calling emailOtp.resetPassword; update the logic around
router.push, the reset-password/new component, and any emailOtp.resetPassword
invocation to use the stored OTP instead of the URL.

In `@src/features/auth/components/sign-in-email-form.tsx`:
- Around line 35-55: The redirect value read into redirectTo from searchParams
must be validated before calling router.push to prevent open redirects; update
the onSubmit flow to validate the redirect (the variable redirectTo derived from
searchParams.get('redirect')) and only navigate if it is a safe internal
path—e.g., allow only strings that begin with a single '/' and not '//' or full
URLs (or parse with the URL constructor and ensure same-origin), otherwise fall
back to '/dashboard'; make this validation check immediately before router.push
in the onSubmit handler (or compute a safeRedirect helper used by onSubmit) so
signIn.email and router.push use a sanitized path.

In `@src/features/auth/components/social-auth-buttons.tsx`:
- Around line 33-42: The handleSocial function sets pending then awaits
signIn.social but lacks error handling, so if signIn.social throws the pending
state never resets; wrap the await in try/catch/finally: call
setPending(provider) before trying, in catch handle thrown errors by calling
toast.error with the error message (falling back to the existing message), and
ensure setPending(null) runs in finally so buttons are re-enabled; refer to
handleSocial, setPending, signIn.social, and toast.error to locate and update
the code.

---

Nitpick comments:
In `@src/features/auth/components/otp-input.tsx`:
- Around line 80-99: Add an accessible aria-label to each OTP input so screen
readers can announce its position: in the input JSX (the element that uses
refs.current[index], value[index], onChange -> handleChange, onKeyDown ->
handleKeyDown, onPaste -> handlePaste) add an aria-label prop like
aria-label={`Digit ${index + 1} of ${totalDigits ?? value?.length ??
refs.current.length}`} (or derive totalDigits from the prop that controls OTP
length). Ensure the label updates per index and keep existing handlers/props
intact.

In `@src/features/auth/components/otp-verify-form.tsx`:
- Line 59: The OTP is not URL-encoded in the reset link generation in
otp-verify-form.tsx; update the template string that builds
`/reset-password/new?email=${encodeURIComponent(email)}&otp=${otp}` to encode
the OTP as well (use encodeURIComponent(otp)) so both email and otp are safely
escaped when constructing the URL in the component that generates the reset
link.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: aaa4ee73-52ad-42cb-a2e9-39365fbf6a65

📥 Commits

Reviewing files that changed from the base of the PR and between a9df20c and e841b76.

📒 Files selected for processing (25)
  • src/app/(auth)/layout.tsx
  • src/app/(auth)/reset-password/new/page.tsx
  • src/app/(auth)/reset-password/page.tsx
  • src/app/(auth)/reset-password/verify/page.tsx
  • src/app/(auth)/sign-in/email/page.tsx
  • src/app/(auth)/sign-in/page.tsx
  • src/app/(auth)/sign-in/verify/page.tsx
  • src/app/(auth)/sign-up/email/page.tsx
  • src/app/(auth)/sign-up/page.tsx
  • src/app/(auth)/sign-up/verify/page.tsx
  • src/features/auth/components/auth-card.tsx
  • src/features/auth/components/auth-footer-pill.tsx
  • src/features/auth/components/auth-input.tsx
  • src/features/auth/components/auth-terms.tsx
  • src/features/auth/components/or-divider.tsx
  • src/features/auth/components/otp-input.tsx
  • src/features/auth/components/otp-verify-form.tsx
  • src/features/auth/components/provider-icons.tsx
  • src/features/auth/components/reset-password-form.tsx
  • src/features/auth/components/reset-password-new-form.tsx
  • src/features/auth/components/sign-in-email-form.tsx
  • src/features/auth/components/sign-in-form.tsx
  • src/features/auth/components/sign-up-email-form.tsx
  • src/features/auth/components/social-auth-buttons.tsx
  • src/features/auth/index.ts
💤 Files with no reviewable changes (1)
  • src/features/auth/components/sign-in-form.tsx

Comment thread src/app/(auth)/reset-password/verify/page.tsx
Comment thread src/app/(auth)/sign-in/page.tsx Outdated
Comment thread src/app/(auth)/sign-in/verify/page.tsx
Comment thread src/app/(auth)/sign-up/verify/page.tsx
Comment thread src/features/auth/components/auth-input.tsx Outdated
Comment thread src/features/auth/components/otp-input.tsx
Comment thread src/features/auth/components/otp-verify-form.tsx Outdated
Comment thread src/features/auth/components/sign-in-email-form.tsx Outdated
Comment thread src/features/auth/components/social-auth-buttons.tsx
Rebuild components/ui/input.tsx as the full Figma Input component:
label + bordered frame (leading icon, control, trailing add-on / icon) +
helper text, composed via inputSize (small | large), shape (rounded | pill)
and state (default | success | error). Hover, active/typing and filled are
handled by CSS (:hover, :focus-within, value); read-only and disabled by the
native attributes. Covers the 32-variant matrix.

Adopt it across the auth forms (sign-up, sign-in, reset, set-new-password),
removing the bespoke AuthInput. Update the one other consumer (filter-rail)
to inputSize=small and add an /input-preview matrix page.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Guard the verify and set-password pages: redirect to the entry route when
  the email query param is missing, so OTP verification is never attempted
  with an empty email.
- Preserve the `redirect` param across the sign-in choose-path: forward it to
  the email link and as the social callbackURL.
- Validate `redirect` with a safeRedirect helper (reject //, /\ and absolute
  URLs) to prevent open redirects.
- Stop leaking the reset OTP in the URL: carry it via sessionStorage and clear
  it after use.
- Fix OtpInput sparse-array write on non-sequential entry; add per-digit
  aria-labels.
- Handle thrown errors in social sign-in so the pending state always resets.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Validate auth forms on touch (mode: 'onTouched') so the input error state
  triggers on blur and updates live as the user types, instead of only on
  submit.
- Add micro-interactions to the Input: eased multi-property transitions, a
  focus glow ring tinted per state (primary / success / error), smooth icon
  color transitions, and a fade/zoom entrance for the success/error status
  icon (motion-reduce safe).
- Apply the same polish to the OTP boxes: transitions, primary caret, focus
  tint, and a group border highlight on focus.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@0xdevcollins 0xdevcollins merged commit f4fa1ce into main Jun 11, 2026
3 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant