Skip to content

Lay out the account page as sections, not stacked cards #324

Closed

Description

@ryota-murakami

Context

A signed-in user opens /account to see who they are, how many boards and cards they have, and the Danger Zone. The page is three Card stacks with two more bordered tiles inside Account Data. Nothing on the page is compared side by side in a way that needs cards. FINDING-022 of the 2026-10-12 design review called this AI slop.

Who: the signed-in owner on /account. Not the signed-out landing page. Not Sign Out. Not account deletion.

Current State

Verified 2026-10-18 on main at df9e36b.

Surface File What it is now
Page root src/app/account/AccountClient.tsx:64-73 max-w-2xl column, then space-y-6 of three Cards
Profile src/app/account/AccountClient.tsx:75-112 Card + CardHeader + avatar row + "Linked since"
Account Data src/app/account/AccountClient.tsx:115-140 Card wrapping a two-cell grid of rounded-lg border p-4 tiles
Danger Zone src/app/account/AccountClient.tsx:143-169 Card with border-destructive, inner notice box, Delete Account
Actions src/app/account/AccountClient.tsx:172-187 Back to Boards, Sign Out. Keep as they are
Skeleton src/app/account/loading.tsx:26-83 Mirrors the three Cards and the two bordered tiles
E2E tiles e2e/logged-in/account-profile.spec.ts:61-84 Asserts the two tiles sit in one row and are equally wide
Stories src/app/account/AccountClient.stories.tsx Default / NoAvatar / EmptyStats / HighStats. They read the numbers, not the Card chrome

Below about 434px the live label "Repository Cards" wraps to two lines and the skeleton label is one h-4 w-20 line (src/app/account/loading.tsx:62). The two tiles grow when data arrives.

src/app/settings/SettingsClient.tsx still uses Card. That page is a later TODO. Do not change it here.

Proposed Change

One PR. Keep every string, every count, every action. Remove the Card chrome. Show Profile, Account Data, and Danger Zone as sections of one page. Show the two numbers without a bordered tile each. Make the skeleton match so the page does not jump.

Implementation Details

  1. AccountClient.tsx (same file, same memo + areServerRenderedPropsEqual).

    • Drop imports of Card, CardContent, CardDescription, CardHeader, CardTitle from @/components/ui/card.
    • Keep the page header (h1 Account, the subtitle).
    • Replace the three Cards with three <section> siblings in one space-y-8 column. Each section has an h2 (Profile, Account Data, Danger Zone) and the same description sentence that CardDescription holds today. Do not invent new copy.
    • Profile: avatar, @userName, "Connected via GitHub", "Linked since" stay. A border-t may sit above "Linked since". No Card.
    • Account Data: a two-column grid grid-cols-2 gap-4. Each cell is a vertical stack: icon, then the number (text-2xl font-bold), then the label. Same order as today. Classes on the cell: flex flex-col items-start (left-aligned). No border, no rounded-lg, no p-4, no items-center. Keep the LayoutDashboard and FileText icons at h-6 w-6. Put data-testid="account-stat-boards" on the Boards cell and data-testid="account-stat-cards" on the Repository Cards cell.
    • Reserve two lines for each Account Data label with min-h-[2lh] text-sm leading-5. Both live labels and both skeleton labels use that exact trio. That is the "page does not jump" rule. Do not add a pixel-shift E2E (MSW hides the skeleton). A 375-wide E2E only needs both labels visible.
    • Danger Zone: h2 stays text-destructive. Keep the inner notice box (border-destructive/20 bg-destructive/5) and the Delete Account button (data-testid="delete-account-button"). No outer Card. A border-t border-destructive on the section is enough to mark the zone.
    • Back to Boards and Sign Out stay after the sections, same labels, same forgetAccountOnThisBrowser + signOut path. Do not change Sign Out copy in this PR (the ellipsis TODO is next).
  2. loading.tsx (same file, same role="status" / "Loading account").

    • Drop Card imports. Mirror the three <section> blocks and the two borderless stat cells. Each label skeleton uses min-h-[2lh] text-sm leading-5 (same trio as the live labels).
    • Header, avatar circle, two text lines, Linked-since line, two numbers, Danger Zone notice, Delete button, Back / Sign Out skeletons stay in the same order and approximate sizes as today.
  3. Tests (same PR).

    • Unit / story: AccountClient.stories.tsx Default play asserts the three h2 names (Profile, Account Data, Danger Zone) and that the Boards / Repository Cards number cells have no border class. Keep NoAvatar, EmptyStats (0 twice), HighStats (42 and 1234).
    • E2E e2e/logged-in/account-profile.spec.ts (--project=logged-in):
      • Keep the profile test (@testuser, Connected via GitHub).
      • Keep the stats test: two text-2xl font-bold numbers in main.
      • Replace shows the Boards and Repository Cards tiles side by side, equally wide with: the two test-id cells sit in one row (same y, second x to the right, equal width) AND each cell's className does not match /(?:^|\s)border(?:-|\s|$)/. Name the test from the new behavior.
      • Keep open / cancel of Delete Account. Do not confirm deletion.
      • Add: main has three section elements. h2 Profile, Account Data, Danger Zone are visible.
    • A source lock (unit or the story) fails if AccountClient.tsx or loading.tsx still import from @/components/ui/card.
  4. Do not touch page.tsx data loading, DeleteAccountDialog, signOut, AccountLayoutClient, or /settings.

Acceptance Criteria

  • /account shows Profile, Account Data, and Danger Zone as section + h2, not as Card.
  • The Boards and Repository Cards numbers have no bordered tile.
  • The loading skeleton uses the same section layout and a two-line label reserve, so the two numbers do not grow when data arrives at a narrow width.
  • Delete Account still opens the dialog; Cancel still closes it. Confirm is never sent in this PR.
  • Sign Out and Back to Boards still sit under the sections.
  • e2e/logged-in/account-profile.spec.ts and AccountClient.stories.tsx pass.
  • Local check as ryota-murakami on /account (local app, port 3008): sidebar says Ryota Murakami; the three sections and two numbers are visible; Delete Account is not confirmed; Sign Out is not pressed.
  • Production check as ryota-murakami on https://gitbox-laststance.vercel.app/account after deploy: same. Do not Sign Out. Do not delete the account. Do not open, rename, move, or delete the boards Laststance, Hobby, Complete, or Practice.

Out of Scope

  • Sign Out copy ("Signing out..."), the ellipsis TODO.
  • Theme tokens, muted/primary contrast, settings page Cards.
  • Account deletion on ryota-murakami.
  • Sidebar, /boards, /board/[id].

Reality Receipts

  • src/app/account/AccountClient.tsx:75 Profile Card
  • src/app/account/AccountClient.tsx:122 bordered Account Data tile
  • src/app/account/AccountClient.tsx:143 Danger Zone Card
  • src/app/account/loading.tsx:26 Profile skeleton Card
  • e2e/logged-in/account-profile.spec.ts:61 tile side-by-side test

Rollback

Revert the PR. The old Card layout returns. No migration.

Activity

  1. ryota-murakami commented on Oct 18, 2026

    @ryota-murakami
    ContributorAuthor

    Shipped in v0.7.17.0 via #325

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions