Skip to content

Comments

feat(auth): add pw signup flow MVP#1473

Draft
tyler-dane wants to merge 2 commits intomainfrom
feat/1452-form
Draft

feat(auth): add pw signup flow MVP#1473
tyler-dane wants to merge 2 commits intomainfrom
feat/1452-form

Conversation

@tyler-dane
Copy link
Contributor

@tyler-dane tyler-dane commented Feb 21, 2026

Related to #1452

  • Added AuthModal component to manage user authentication flows, including sign in, sign up, and password recovery.
  • Introduced AccountIcon for triggering the authentication modal.
  • Created forms for sign in, sign up, and forgot password, utilizing Zod for validation.
  • Implemented tab navigation between sign in and sign up views.
  • Integrated Google OAuth sign-in functionality.
  • Established context and hooks for managing modal state and feature flags.
  • Added comprehensive tests for modal behavior and form validation.

PW-PLAN.md

… forgot password functionality

- Added `AuthModal` component to manage user authentication flows, including sign in, sign up, and password recovery.
- Introduced `AccountIcon` for triggering the authentication modal.
- Created forms for sign in, sign up, and forgot password, utilizing Zod for validation.
- Implemented tab navigation between sign in and sign up views.
- Integrated Google OAuth sign-in functionality.
- Established context and hooks for managing modal state and feature flags.
- Added comprehensive tests for modal behavior and form validation.
Copilot AI review requested due to automatic review settings February 21, 2026 03:45
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds an MVP email/password authentication UI shell to the web app by introducing an auth modal (sign in / sign up / forgot password) and a header entry point via an account icon, plus Zod validation and tests.

Changes:

  • Render a new AccountIcon in Day/Week/Now headers and mount AuthModal via CompassProvider.
  • Add AuthModal state management (context + hooks) and auth forms with Zod-based validation schemas.
  • Add unit/integration-style tests for modal behavior and schema validation.

Reviewed changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated 13 comments.

Show a summary per file
File Description
packages/web/src/views/Day/components/Header/Header.tsx Adds AccountIcon to Day/Now header.
packages/web/src/views/Calendar/components/Header/Header.tsx Adds AccountIcon to Week header.
packages/web/src/components/CompassProvider/CompassProvider.tsx Mounts AuthModalProvider + AuthModal around app content.
packages/web/src/components/AuthModal/index.ts New barrel re-export for auth modal modules.
packages/web/src/components/AuthModal/hooks/useAuthModal.ts Adds modal state + view switching hook/context.
packages/web/src/components/AuthModal/hooks/useAuthFeatureFlag.ts Adds URL-param-based gating for auth UI.
packages/web/src/components/AuthModal/forms/SignUpForm.tsx Adds validated sign-up form UI.
packages/web/src/components/AuthModal/forms/SignInForm.tsx Adds validated sign-in form UI + forgot-password link.
packages/web/src/components/AuthModal/forms/ForgotPasswordForm.tsx Adds validated forgot-password request form + generic success state.
packages/web/src/components/AuthModal/components/AuthTabs.tsx Adds tab UI to switch sign-in/sign-up.
packages/web/src/components/AuthModal/components/AuthInput.tsx Adds styled input with error messaging/ARIA.
packages/web/src/components/AuthModal/components/AuthButton.tsx Adds styled auth button variants.
packages/web/src/components/AuthModal/AuthModalProvider.tsx Provides auth modal context to the tree.
packages/web/src/components/AuthModal/AuthModal.tsx Implements modal content + Google button + form routing.
packages/web/src/components/AuthModal/AuthModal.test.tsx Adds modal/account icon behavior tests.
packages/web/src/components/AuthModal/AccountIcon.tsx Adds phosphor-based icon trigger for opening modal.
packages/web/src/auth/schemas/auth.schemas.ts Adds Zod schemas + inferred types for auth forms.
packages/web/src/auth/schemas/auth.schemas.test.ts Adds schema unit tests.

Comment on lines 40 to 55
className={clsx(
"bg-bg-secondary border-border-primary h-10 rounded-md border px-3 text-base transition-colors",
"text-text-lighter placeholder:text-text-darkPlaceholder",
"focus:border-accent-primary focus:outline-none",
{
"border-red-500 focus:border-red-500": showError,
},
)}
aria-invalid={showError ? true : undefined}
aria-describedby={showError ? errorId : undefined}
{...inputProps}
/>
{showError && (
<span id={errorId} className="text-sm text-red-400" role="alert">
{error}
</span>
Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

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

These error styles use raw Tailwind colors (border-red-500, text-red-400), but the web codebase defines semantic tokens (e.g. --color-status-error) and AGENTS.md asks to avoid raw Tailwind colors. Please switch to semantic classes (e.g. border-status-error, text-status-error) so the UI stays consistent with theming.

Copilot uses AI. Check for mistakes.
Comment on lines 128 to 134
// Click on backdrop (the presentation div)
const backdrop = document.querySelector('[role="presentation"]');
expect(backdrop).toBeInTheDocument();

await user.click(backdrop!);

await waitFor(() => {
Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

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

Tests here rely heavily on data-testid and a CSS selector (document.querySelector('[role="presentation"]')). AGENTS.md asks tests to prefer semantic queries (roles/labels/text) and avoid data- attributes/selectors. Consider rewriting these to use getByRole/getByLabelText and user interactions on accessible elements.

Copilot uses AI. Check for mistakes.
Comment on lines 1 to 5
export { AccountIcon } from "./AccountIcon";
export { AuthModal } from "./AuthModal";
export { AuthModalProvider } from "./AuthModalProvider";
export { useAuthModal, type AuthView } from "./hooks/useAuthModal";
export { useAuthFeatureFlag } from "./hooks/useAuthFeatureFlag";
Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

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

This introduces a barrel index.ts in components/AuthModal, but AGENTS.md explicitly says to avoid barrel files. Please remove this index and update imports to target the specific modules (e.g. @web/components/AuthModal/AccountIcon).

Suggested change
export { AccountIcon } from "./AccountIcon";
export { AuthModal } from "./AuthModal";
export { AuthModalProvider } from "./AuthModalProvider";
export { useAuthModal, type AuthView } from "./hooks/useAuthModal";
export { useAuthFeatureFlag } from "./hooks/useAuthFeatureFlag";

Copilot uses AI. Check for mistakes.
Comment on lines 69 to 72
const renderWithProviders = (
component: React.ReactElement,
initialRoute: string = "/day",
) => {
Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

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

renderWithProviders annotates component as React.ReactElement, but this test file doesn't import the React namespace. Import React (type-only) or use ReactElement from react to avoid TS compile errors.

Copilot uses AI. Check for mistakes.
Comment on lines 67 to 71
const handleChange = useCallback(
(field: keyof FormState) => (e: React.ChangeEvent<HTMLInputElement>) => {
const value = e.target.value;
setFormState((prev) => ({ ...prev, [field]: value }));

Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

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

handleChange references React.ChangeEvent but this file doesn't import the React namespace. With jsx: react-jsx (and no allowUmdGlobalAccess), this will fail type-checking. Import React as a type/value, or switch the annotation to ChangeEvent<HTMLInputElement> imported from react.

Copilot uses AI. Check for mistakes.
Comment on lines 44 to 55
jest.mock("@web/components/Tooltip/TooltipWrapper", () => ({
TooltipWrapper: ({
children,
onClick,
}: {
children: React.ReactNode;
onClick?: () => void;
description?: string;
}) => (
<div onClick={onClick} data-testid="tooltip-wrapper">
{children}
</div>
Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

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

This file uses React.ReactNode in the TooltipWrapper mock props but doesn't import the React namespace, which will fail TS compilation in this repo (most files that use React.* types import React). Import React (type-only is fine) or switch to ReactNode imported from react.

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +17
import { useSearchParams } from "react-router-dom";

/**
* Feature flag hook for email/password authentication UI
*
* Checks for the URL parameter `?enableAuth=true` to conditionally
* show the auth modal and related UI elements.
*
* @returns boolean - true if auth feature is enabled via URL param
*
* @example
* // Navigate to /day?enableAuth=true to enable
* const isAuthEnabled = useAuthFeatureFlag();
*/
export function useAuthFeatureFlag(): boolean {
const [searchParams] = useSearchParams();
return searchParams.get("enableAuth") === "true";
Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

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

The rollout gate in issue #1452 requires showing the account icon only for unauthenticated users whose last-known email deterministically matches foo@bar.com. This implementation gates via a user-controlled URL param (?enableAuth=true), which doesn't meet the rollout requirement and can be trivially enabled by anyone. Please implement the specified deterministic signal + email check (and keep it hidden by default when unknown).

Suggested change
import { useSearchParams } from "react-router-dom";
/**
* Feature flag hook for email/password authentication UI
*
* Checks for the URL parameter `?enableAuth=true` to conditionally
* show the auth modal and related UI elements.
*
* @returns boolean - true if auth feature is enabled via URL param
*
* @example
* // Navigate to /day?enableAuth=true to enable
* const isAuthEnabled = useAuthFeatureFlag();
*/
export function useAuthFeatureFlag(): boolean {
const [searchParams] = useSearchParams();
return searchParams.get("enableAuth") === "true";
const ROLLOUT_EMAIL = "foo@bar.com";
/**
* Feature flag hook for email/password authentication UI
*
* Enables the auth modal and related UI elements only for
* unauthenticated users whose last-known email deterministically
* matches the rollout email.
*
* The last-known email is read from a deterministic client-side
* signal (e.g. localStorage) and the feature remains disabled
* when the email is unknown or cannot be read.
*
* @returns boolean - true if auth feature is enabled for the rollout email
*/
export function useAuthFeatureFlag(): boolean {
// Default: feature is hidden when the deterministic signal is unavailable
if (typeof window === "undefined" || !window.localStorage) {
return false;
}
try {
const lastKnownEmail = window.localStorage.getItem("lastKnownEmail");
if (!lastKnownEmail) {
return false;
}
return lastKnownEmail === ROLLOUT_EMAIL;
} catch {
// On any storage access error, keep the feature disabled.
return false;
}

Copilot uses AI. Check for mistakes.
…st coverage

- Renamed `User` icon to `UserIcon` for clarity in `AccountIcon`.
- Enhanced `AuthModal` and its forms with consistent button labels and improved comments for future implementation.
- Updated test cases to use semantic queries and ensure consistent button labels across tabs.
- Refactored `AuthInput` error handling styles for better clarity.
- Removed unused `index.ts` file from `AuthModal` directory to streamline imports.
- Adjusted import paths in various components to reflect the new structure.
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