Skip to content

feat: container-query cards, AVIF assets, heart hover fix - #85

Merged
fringe4life merged 2 commits into
mainfrom
feat/model-card-cq-avif
Aug 26, 2026
Merged

feat: container-query cards, AVIF assets, heart hover fix#85
fringe4life merged 2 commits into
mainfrom
feat/model-card-cq-avif

Conversation

@fringe4life

@fringe4life fringe4life commented Aug 26, 2026

Copy link
Copy Markdown
Owner

Summary

🎨 Container-query + subgrid model cards and detail layouts
⚡ Converted model/hero/placeholder images to AVIF, dropped duplicates
🐛 Locked heart hover when guests cannot like
🗑️ Removed unused src/assets images and heart-icon
📝 Synced README badges and project structure
📦 Bumped Next to 16.4.0-canary.8
🧪 Added model-card and model-detail component tests

Closes #84
Closes #83
Closes #82
Closes #22

Test plan

  • Guest heart button: no like-hover cue when unauthenticated
  • Listing cards: container-query split + subgrid align across title/description lengths
  • Model detail page layout still correct at narrow/wide containers
  • Images load as AVIF (hero, placeholder, model thumbs); no broken 404s for old jpg/png paths
  • bun run test:components
  • bun run check / bun run type

🎨 Container-query + subgrid model cards and detail layouts
⚡ Converted model/hero/placeholder images to AVIF, dropped duplicates
🐛 Locked heart hover when guests cannot like
🗑️ Removed unused src/assets images and heart-icon
📝 Synced README badges and project structure
📦 Bumped Next to 16.4.0-canary.8
🧪 Added model-card and model-detail component tests

Closes #84, #83, #82, #22
@fringe4life fringe4life self-assigned this Aug 26, 2026
@github-actions

github-actions Bot commented Aug 26, 2026

Copy link
Copy Markdown

React Doctor found no new issues. 🎉

Reviewed by React Doctor for commit 78f29e8.

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Add container-responsive model layouts and AVIF assets

✨ Enhancement 🐞 Bug fix 🧪 Tests 📝 Documentation ⚙️ Configuration changes 🕐 40+ Minutes

Grey Divider

AI Description

• Rebuilds model cards and detail views with container-responsive layouts and aligned content.
• Migrates model imagery to AVIF and centralizes public fallback paths.
• Prevents guest like-hover feedback and adds component regression coverage.
Diagram

graph TD
  CFG["Panda Config"] --> CS["Card Styles"] --> CARD["Model Cards"]
  CFG --> DS["Detail Styles"] --> DETAIL["Model Detail"]
  SEED["Seed Data"] --> ASSETS["AVIF Assets"] --> CARD
  ASSETS --> DETAIL
  PAGE["Detail Page"] --> DETAIL
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Retain viewport breakpoints
  • ➕ Requires fewer styling changes
  • ➕ Matches the previous responsive model
  • ➖ Components cannot adapt to their actual parent width
  • ➖ Nested cards and detail panels remain brittle
2. Use picture-based format fallbacks
  • ➕ Supports clients without AVIF decoding
  • ➕ Allows explicit AVIF and legacy source ordering
  • ➖ Adds markup and duplicate asset maintenance
  • ➖ Provides little value if supported browsers are modern-only

Recommendation: Keep the container-query approach because card and detail behavior should follow available component width rather than viewport width. The AVIF-only migration is also reasonable for a modern browser baseline; add format fallbacks only if compatibility requirements include clients without AVIF support.

Files changed (74) +795 / -376

Enhancement (64) +620 / -353
hero-image-square.avifAdd AVIF hero image +0/-0

Add AVIF hero image

• Adds the optimized square hero image in AVIF format for the shared hero source constant.

public/hero-image-square.avif

1.avifAdd AVIF thumbnail for model 1 +0/-0

Add AVIF thumbnail for model 1

• Adds the optimized AVIF replacement for model thumbnail 1.

public/img/models/1.avif

2.avifAdd AVIF thumbnail for model 2 +0/-0

Add AVIF thumbnail for model 2

• Adds the optimized AVIF replacement for model thumbnail 2.

public/img/models/2.avif

3.avifAdd AVIF thumbnail for model 3 +0/-0

Add AVIF thumbnail for model 3

• Adds the optimized AVIF replacement for model thumbnail 3.

public/img/models/3.avif

4.avifAdd AVIF thumbnail for model 4 +0/-0

Add AVIF thumbnail for model 4

• Adds the optimized AVIF replacement for model thumbnail 4.

public/img/models/4.avif

5.avifAdd AVIF thumbnail for model 5 +0/-0

Add AVIF thumbnail for model 5

• Adds the optimized AVIF replacement for model thumbnail 5.

public/img/models/5.avif

6.avifAdd AVIF thumbnail for model 6 +0/-0

Add AVIF thumbnail for model 6

• Adds the optimized AVIF replacement for model thumbnail 6.

public/img/models/6.avif

7.avifAdd AVIF thumbnail for model 7 +0/-0

Add AVIF thumbnail for model 7

• Adds the optimized AVIF replacement for model thumbnail 7.

public/img/models/7.avif

8.avifAdd AVIF thumbnail for model 8 +0/-0

Add AVIF thumbnail for model 8

• Adds the optimized AVIF replacement for model thumbnail 8.

public/img/models/8.avif

9.avifAdd AVIF thumbnail for model 9 +0/-0

Add AVIF thumbnail for model 9

• Adds the optimized AVIF replacement for model thumbnail 9.

public/img/models/9.avif

10.avifAdd AVIF thumbnail for model 10 +0/-0

Add AVIF thumbnail for model 10

• Adds the optimized AVIF replacement for model thumbnail 10.

public/img/models/10.avif

11.avifAdd AVIF thumbnail for model 11 +0/-0

Add AVIF thumbnail for model 11

• Adds the optimized AVIF replacement for model thumbnail 11.

public/img/models/11.avif

12.avifAdd AVIF thumbnail for model 12 +0/-0

Add AVIF thumbnail for model 12

• Adds the optimized AVIF replacement for model thumbnail 12.

public/img/models/12.avif

13.avifAdd AVIF thumbnail for model 13 +0/-0

Add AVIF thumbnail for model 13

• Adds the optimized AVIF replacement for model thumbnail 13.

public/img/models/13.avif

14.avifAdd AVIF thumbnail for model 14 +0/-0

Add AVIF thumbnail for model 14

• Adds the optimized AVIF replacement for model thumbnail 14.

public/img/models/14.avif

15.avifAdd AVIF thumbnail for model 15 +0/-0

Add AVIF thumbnail for model 15

• Adds the optimized AVIF replacement for model thumbnail 15.

public/img/models/15.avif

16.avifAdd AVIF thumbnail for model 16 +0/-0

Add AVIF thumbnail for model 16

• Adds the optimized AVIF replacement for model thumbnail 16.

public/img/models/16.avif

17.avifAdd AVIF thumbnail for model 17 +0/-0

Add AVIF thumbnail for model 17

• Adds the optimized AVIF replacement for model thumbnail 17.

public/img/models/17.avif

18.avifAdd AVIF thumbnail for model 18 +0/-0

Add AVIF thumbnail for model 18

• Adds the optimized AVIF replacement for model thumbnail 18.

public/img/models/18.avif

19.avifAdd AVIF thumbnail for model 19 +0/-0

Add AVIF thumbnail for model 19

• Adds the optimized AVIF replacement for model thumbnail 19.

public/img/models/19.avif

20.avifAdd AVIF thumbnail for model 20 +0/-0

Add AVIF thumbnail for model 20

• Adds the optimized AVIF replacement for model thumbnail 20.

public/img/models/20.avif

21.avifAdd AVIF thumbnail for model 21 +0/-0

Add AVIF thumbnail for model 21

• Adds the optimized AVIF replacement for model thumbnail 21.

public/img/models/21.avif

22.avifAdd AVIF thumbnail for model 22 +0/-0

Add AVIF thumbnail for model 22

• Adds the optimized AVIF replacement for model thumbnail 22.

public/img/models/22.avif

23.avifAdd AVIF thumbnail for model 23 +0/-0

Add AVIF thumbnail for model 23

• Adds the optimized AVIF replacement for model thumbnail 23.

public/img/models/23.avif

24.avifAdd AVIF thumbnail for model 24 +0/-0

Add AVIF thumbnail for model 24

• Adds the optimized AVIF replacement for model thumbnail 24.

public/img/models/24.avif

25.avifAdd AVIF thumbnail for model 25 +0/-0

Add AVIF thumbnail for model 25

• Adds the optimized AVIF replacement for model thumbnail 25.

public/img/models/25.avif

26.avifAdd AVIF thumbnail for model 26 +0/-0

Add AVIF thumbnail for model 26

• Adds the optimized AVIF replacement for model thumbnail 26.

public/img/models/26.avif

27.avifAdd AVIF thumbnail for model 27 +0/-0

Add AVIF thumbnail for model 27

• Adds the optimized AVIF replacement for model thumbnail 27.

public/img/models/27.avif

28.avifAdd AVIF thumbnail for model 28 +0/-0

Add AVIF thumbnail for model 28

• Adds the optimized AVIF replacement for model thumbnail 28.

public/img/models/28.avif

29.avifAdd AVIF thumbnail for model 29 +0/-0

Add AVIF thumbnail for model 29

• Adds the optimized AVIF replacement for model thumbnail 29.

public/img/models/29.avif

30.avifAdd AVIF thumbnail for model 30 +0/-0

Add AVIF thumbnail for model 30

• Adds the optimized AVIF replacement for model thumbnail 30.

public/img/models/30.avif

31.avifAdd AVIF thumbnail for model 31 +0/-0

Add AVIF thumbnail for model 31

• Adds the optimized AVIF replacement for model thumbnail 31.

public/img/models/31.avif

32.avifAdd AVIF thumbnail for model 32 +0/-0

Add AVIF thumbnail for model 32

• Adds the optimized AVIF replacement for model thumbnail 32.

public/img/models/32.avif

33.avifAdd AVIF thumbnail for model 33 +0/-0

Add AVIF thumbnail for model 33

• Adds the optimized AVIF replacement for model thumbnail 33.

public/img/models/33.avif

34.avifAdd AVIF thumbnail for model 34 +0/-0

Add AVIF thumbnail for model 34

• Adds the optimized AVIF replacement for model thumbnail 34.

public/img/models/34.avif

35.avifAdd AVIF thumbnail for model 35 +0/-0

Add AVIF thumbnail for model 35

• Adds the optimized AVIF replacement for model thumbnail 35.

public/img/models/35.avif

36.avifAdd AVIF thumbnail for model 36 +0/-0

Add AVIF thumbnail for model 36

• Adds the optimized AVIF replacement for model thumbnail 36.

public/img/models/36.avif

37.avifAdd AVIF thumbnail for model 37 +0/-0

Add AVIF thumbnail for model 37

• Adds the optimized AVIF replacement for model thumbnail 37.

public/img/models/37.avif

38.avifAdd AVIF thumbnail for model 38 +0/-0

Add AVIF thumbnail for model 38

• Adds the optimized AVIF replacement for model thumbnail 38.

public/img/models/38.avif

39.avifAdd AVIF thumbnail for model 39 +0/-0

Add AVIF thumbnail for model 39

• Adds the optimized AVIF replacement for model thumbnail 39.

public/img/models/39.avif

40.avifAdd AVIF thumbnail for model 40 +0/-0

Add AVIF thumbnail for model 40

• Adds the optimized AVIF replacement for model thumbnail 40.

public/img/models/40.avif

41.avifAdd AVIF thumbnail for model 41 +0/-0

Add AVIF thumbnail for model 41

• Adds the optimized AVIF replacement for model thumbnail 41.

public/img/models/41.avif

42.avifAdd AVIF thumbnail for model 42 +0/-0

Add AVIF thumbnail for model 42

• Adds the optimized AVIF replacement for model thumbnail 42.

public/img/models/42.avif

43.avifAdd AVIF thumbnail for model 43 +0/-0

Add AVIF thumbnail for model 43

• Adds the optimized AVIF replacement for model thumbnail 43.

public/img/models/43.avif

44.avifAdd AVIF thumbnail for model 44 +0/-0

Add AVIF thumbnail for model 44

• Adds the optimized AVIF replacement for model thumbnail 44.

public/img/models/44.avif

45.avifAdd AVIF thumbnail for model 45 +0/-0

Add AVIF thumbnail for model 45

• Adds the optimized AVIF replacement for model thumbnail 45.

public/img/models/45.avif

46.avifAdd AVIF thumbnail for model 46 +0/-0

Add AVIF thumbnail for model 46

• Adds the optimized AVIF replacement for model thumbnail 46.

public/img/models/46.avif

47.avifAdd AVIF thumbnail for model 47 +0/-0

Add AVIF thumbnail for model 47

• Adds the optimized AVIF replacement for model thumbnail 47.

public/img/models/47.avif

48.avifAdd AVIF thumbnail for model 48 +0/-0

Add AVIF thumbnail for model 48

• Adds the optimized AVIF replacement for model thumbnail 48.

public/img/models/48.avif

49.avifAdd AVIF thumbnail for model 49 +0/-0

Add AVIF thumbnail for model 49

• Adds the optimized AVIF replacement for model thumbnail 49.

public/img/models/49.avif

50.avifAdd AVIF thumbnail for model 50 +0/-0

Add AVIF thumbnail for model 50

• Adds the optimized AVIF replacement for model thumbnail 50.

public/img/models/50.avif

51.avifAdd AVIF thumbnail for model 51 +0/-0

Add AVIF thumbnail for model 51

• Adds the optimized AVIF replacement for model thumbnail 51.

public/img/models/51.avif

52.avifAdd AVIF thumbnail for model 52 +0/-0

Add AVIF thumbnail for model 52

• Adds the optimized AVIF replacement for model thumbnail 52.

public/img/models/52.avif

placeholder.avifAdd shared AVIF model placeholder +0/-0

Add shared AVIF model placeholder

• Adds the public AVIF fallback used by cards, detail views, metadata, and tests.

public/img/placeholder.avif

page.tsxUse shared AVIF fallback in detail metadata +5/-1

Use shared AVIF fallback in detail metadata

• Switches Open Graph metadata to the centralized placeholder source and explicitly disables instant navigation for the detail route.

src/app/3d-models/[slug]/page.tsx

styles.tsMake the model grid a named query container +10/-6

Make the model grid a named query container

• Wraps the listing grid in the 'models-grid' container, increases the minimum card track width, and removes row gaps so card subgrids control vertical spacing.

src/app/styles.ts

models.tsPoint seed models to AVIF and stress responsive copy +126/-86

Point seed models to AVIF and stress responsive copy

• Migrates all 52 model image paths from JPG to AVIF. Expands selected descriptions to varied lengths so clamping and subgrid alignment are exercised by representative content.

src/db/seed-data/models.ts

model-card-skeleton.tsxAlign card skeleton with responsive card tracks +48/-57

Align card skeleton with responsive card tracks

• Rebuilds the loading skeleton around the shared card container, media, title, description, metadata, category, and like-row styles.

src/features/models/components/model-card-skeleton.tsx

model-card.styles.tsAdd container-query and subgrid card styles +199/-0

Add container-query and subgrid card styles

• Introduces shared card and skeleton styles using named container thresholds, subgrid row alignment, split media layouts, responsive copy clamping, overlay links, and squircle surfaces.

src/features/models/components/model-card.styles.ts

model-card.tsxRecompose cards for responsive shared styling +57/-118

Recompose cards for responsive shared styling

• Moves presentation into the new card style module, adopts subgrid-compatible markup, centralizes the placeholder source, and preserves image/title view transitions and like controls.

src/features/models/components/model-card.tsx

model-detail.styles.tsAdd container-responsive detail styles +120/-0

Add container-responsive detail styles

• Introduces named-container styles for stacked and split detail layouts, fluid typography, squircle media surfaces, and a footer containing date and interaction controls.

src/features/models/components/model-detail.styles.ts

model-detail.tsxRecompose model details around container queries +51/-83

Recompose model details around container queries

• Uses the new detail style module and shared AVIF fallback, while moving projected like controls into the metadata footer and retaining image/title transitions.

src/features/models/components/model-detail.tsx

hero-image.tsPoint hero source to AVIF +2/-2

Point hero source to AVIF

• Changes the shared square hero image path and documentation from PNG to AVIF.

src/lib/hero-image.ts

placeholder-image.tsCentralize the AVIF placeholder path +2/-0

Centralize the AVIF placeholder path

• Adds a shared constant for the public model fallback image, eliminating duplicated and app-local placeholder imports.

src/lib/placeholder-image.ts

Bug fix (1) +49 / -2
heart-button-client.tsxLock disabled heart hover feedback +49/-2

Lock disabled heart hover feedback

• Inlines the heart icon and maps visual states to Panda '_icon' colors. Disabled guest buttons now override hover styling so they do not imply that liking is available.

src/features/models/likes/components/heart-button-client.tsx

Tests (4) +93 / -3
model-card.spec.tsxTest model card accessibility contracts +45/-0

Test model card accessibility contracts

• Adds component coverage for the detail link, image alternative text, category content, and unauthenticated like-button affordance.

tests/components/models/model-card.spec.tsx

model-detail.spec.tsxTest full model detail composition +45/-0

Test full model detail composition

• Adds component coverage for headings, full descriptions, image accessibility, category, header and child slots, and machine-readable dates.

tests/components/models/model-detail.spec.tsx

models-grid.spec.tsxUse the AVIF placeholder in grid tests +1/-1

Use the AVIF placeholder in grid tests

• Updates model-grid test data to reference the new public AVIF fallback path.

tests/components/models/models-grid.spec.tsx

db-test.tsSeed tests with AVIF placeholder paths +2/-2

Seed tests with AVIF placeholder paths

• Updates test database model fixtures to use the centralized public AVIF placeholder location.

tests/setup/db-test.ts

Documentation (2) +11 / -13
README.mdDocument responsive layouts and AVIF asset paths +9/-10

Document responsive layouts and AVIF asset paths

• Updates framework badges and architecture documentation for Next.js canary.8, AVIF thumbnails, new style modules, the shared placeholder helper, and inlined heart styling.

README.md

REACT_STINKY.mdDocument inlined heart visual-state styling +2/-3

Document inlined heart visual-state styling

• Revises the heart-state cleanup notes to reflect Panda '_icon' styling in the client button and removal of the separate icon component.

docs/REACT_STINKY.md

Other (3) +22 / -5
bun.lockLock Next.js canary.8 artifacts +3/-3

Lock Next.js canary.8 artifacts

• Refreshes the Next.js package, SWC binary, checksums, and transitive version references for 16.4.0-canary.8.

bun.lock

package.jsonBump application and Next.js versions +2/-2

Bump application and Next.js versions

• Advances the application version to 0.9.0 and Next.js to 16.4.0-canary.8.

package.json

panda.config.tsConfigure model container queries and corner shapes +17/-0

Configure model container queries and corner shapes

• Adds named model containers, card/detail query thresholds, and a custom 'cornerShape' utility supporting squircle and bevel values.

panda.config.ts

@qodo-code-review

qodo-code-review Bot commented Aug 26, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Remediation recommended

1. Card requests undersized images ✓ Resolved 🐞 Bug ≡ Correctness
Description
The card switches its sizes hint at a viewport width of 28rem, but the layout’s 1rem horizontal
padding means the models-grid container does not reach the 28rem split query until the viewport
reaches 30rem. Between 28rem and 30rem, the card remains a full-width stacked image while Next
requests only a 10rem candidate, producing visibly soft thumbnails.
Code

src/features/models/components/model-card.tsx[75]

+                sizes="(max-width: 28rem) calc(100vw - 2rem), 10rem"
Evidence
The card is stacked below the named container's 28rem card-split threshold and its media is
square/full-column in that state. The only runtime placement wraps the results section in 1rem (4)
padding, so at viewport widths just over 28rem the grid is still under 28rem, while the added
sizes expression has already fallen through to 10rem.

src/features/models/components/model-card.tsx[70-76]
src/features/models/components/model-card.styles.ts[12-20]
src/features/models/components/model-card.styles.ts[76-90]
panda.config.ts[110-115]
src/app/3d-models/layout.tsx[60-64]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The image `sizes` viewport breakpoint changes to `10rem` before the container query changes the card to its split layout, causing undersized image candidates between 28rem and 30rem viewport widths.

## Issue Context
The models section has 1rem padding on each side, while `card-split` is evaluated against the resulting `models-grid` container. Account for that padding in the viewport-based image hint (or otherwise provide a conservative hint that covers the stacked card).

## Fix Focus Areas
- src/features/models/components/model-card.tsx[70-76]
- src/features/models/components/model-card.styles.ts[12-20]
- src/app/3d-models/layout.tsx[60-64]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
✅ Compliance rules (platform): 8 rules
Review mode: ⚖️ Balanced

Grey Divider

Tip of the day
💡 Did you know, you can start a comment with 'qodo' or '@qodo' to chat about any finding

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread src/features/models/components/model-card.tsx Outdated
🎨 Named navbar CQ tokens for offline indicator (#86)
⚡ Align card/detail Image sizes with CQ split + layout padding
🧪 Assert model card and detail sizes contracts

Closes #86
@fringe4life

Copy link
Copy Markdown
Owner Author

Follow-up pushed (78f29e8):

  • Named navbar CQ tokens for offline indicator
  • Card/detail Image sizes aligned with CQ split + layout padding

Closes #86 (also in commit body). Image-sizes review fixes included.

@fringe4life
fringe4life merged commit 09dc557 into main Aug 26, 2026
2 checks passed
@fringe4life
fringe4life deleted the feat/model-card-cq-avif branch August 26, 2026 10:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant