Skip to content

feat(fields): adopt <Card> primitive for FieldCard tile [Phase 2a]#627

Merged
barach6662001-bit merged 2 commits intomainfrom
replit/phase-2a-fieldcard-card
Apr 24, 2026
Merged

feat(fields): adopt <Card> primitive for FieldCard tile [Phase 2a]#627
barach6662001-bit merged 2 commits intomainfrom
replit/phase-2a-fieldcard-card

Conversation

@barach6662001-bit
Copy link
Copy Markdown
Owner

Summary

Phase 2a — outer container of FieldCard migrated from a hand-rolled <div className={s.card}> to the design-system <Card> primitive.

Migration

  • <div className={s.card} onClick={...}><Card as="div" radius="lg" p="0" gap="0" className={s.card} onClick={...}>
  • Card supplies background (subtle / --card-bg), 1 px --border, and var(--radius-lg) (12 px) — matching the legacy values from tokens.
  • p="0" / gap="0" because the tile composes its own internal layout (a polygon thumb that bleeds to the edges + an info block with its own padding).
  • onClick is forwarded by Surface via ...rest; behavior unchanged.

CSS module

Trimmed .card to only the affordances Card does not provide:

  • cursor: pointer
  • position: relative (anchor for the absolutely-positioned hover overlay)
  • overflow: hidden (so the bleed thumb clips against the rounded corners)
  • transition + :hover lift (translateY(-2px)) and box-shadow: var(--shadow-md)
  • the descendant rule .card:hover .hoverOverlay { opacity: 1 } that fades the CTA in on hover

The legacy border-color: var(--border-hover) hover change is dropped — Card's inline border can't be overridden by an :hover class rule. The dominant transform + shadow lift is preserved, matching the precedent set by Phase 1d–1f migrations.

All inner markup, navigation, badges, crop pill, ownership label, cadastral number and responsive behavior preserved verbatim.

Tests

Adds frontend/src/pages/Fields/components/__tests__/FieldCard.test.tsx — 4 focused tests:

  1. Renders field name, area badge, cadastral number and crop pill
  2. Omits cadastral when cadastralNumber is undefined
  3. Renders fields.notSeeded fallback when currentCrop is unset
  4. Navigates to /fields/{id} when the card surface is clicked

No existing Fields tests to update.

Scope

Touches only:

  • frontend/src/pages/Fields/components/FieldCard.tsx
  • frontend/src/pages/Fields/components/FieldCard.module.css
  • frontend/src/pages/Fields/components/__tests__/FieldCard.test.tsx (new)

FieldCard.module.css has only one consumer (FieldsList) — no other call-sites affected. Out of scope per Phase 2a brief: FieldDetail, OperationDetail, AppLayout, Sidebar, no Card highlight prop.

Validation

  • npx vitest run src/design-system src/pages/Fields → 62/62 passing (incl. 4 new FieldCard tests)
  • npx tsc --noEmit clean
  • npx eslint on touched files clean

Phase 2 progression

Phase 1a–1f (PRs #616, #620, #621, #622, #624, #625) covered the dashboard row. Phase 2a starts extending Card adoption beyond the dashboard, into list/grid tiles. FieldCard chosen as the lowest-risk drop-in target (classic tile pattern, no need to reopen the deferred Card highlight prop discussion).

  Outer container of FieldCard migrated from a hand-rolled
  `<div className={s.card}>` to the design-system <Card> primitive.
  Card supplies background (subtle/--card-bg), border and radius
  (radius="lg" preserves the legacy 12 px radius). Card's auto
  padding/gap are disabled (p="0", gap="0") because the tile composes
  its own internal layout — a polygon thumb that bleeds to the edges
  plus an info block with its own padding.

  The local CSS module retains only the tile-specific affordances
  that <Card> does not provide: cursor:pointer, position:relative
  (for the absolutely-positioned hover overlay), overflow:hidden
  (so the bleed thumb clips against the radius), the lift +
  shadow hover transition, and the descendant rule that fades the
  hover CTA in on hover.

  Behavior preserved verbatim from the legacy implementation,
  including the existing onClick on a non-button element. The
  `border-color: var(--border-hover)` change on hover is dropped
  in favor of the dominant transform + shadow lift, matching the
  precedent set by Phase 1d–1f migrations (the inline border on
  the primitive cannot be overridden by an :hover class rule).

  No other consumers of FieldCard.module.css exist; FieldsList is
  the only call-site and is unchanged.

  Tests: adds frontend/src/pages/Fields/components/__tests__/FieldCard.test.tsx
  (4 focused tests covering name/area/cadastral/crop-pill rendering,
  the not-seeded fallback, the cadastral-omit case, and click navigation).
  No existing Fields tests to update.

  Validation: focused vitest suite (62 tests across design-system
  + Fields) passes; tsc --noEmit clean; eslint clean.

  Phase 2a — pure-surface migration, no functional changes.
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f2c9779791

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +47 to +51
<Card
as="div"
radius="lg"
p="0"
gap="0"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Keep FieldCard hover shadow from being overridden

Switching this container to <Card> causes Surface to inject an inline boxShadow (elevation defaults to 0), and inline styles win over .card:hover { box-shadow: ... } in FieldCard.module.css. In practice, hovering a field tile now only translates it; the shadow lift no longer appears. This regression is introduced by the new Card wrapper in FieldCard and affects every hover interaction in the fields grid.

Useful? React with 👍 / 👎.

@barach6662001-bit barach6662001-bit merged commit 5d42976 into main Apr 24, 2026
3 checks passed
@barach6662001-bit barach6662001-bit deleted the replit/phase-2a-fieldcard-card branch April 24, 2026 12:26
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