feat: cards grid element with hidden card items child #99

Merged
dominik.polakovics merged 1 commit from afk/92 into main 2026-07-18 03:11:20 +02:00

Adds the cards/card core element pair from the issue spec, replicating the established image/img items-collection pattern.

What ships

  • scaffold/editor/elements/cards.yaml — grid parent (items: {element: card}, cols select 2/3/4 default 3, allowedIn: [page])
  • scaffold/editor/elements/card.yaml — hidden child (allowedIn: [cards], summary: heading; optional image, required heading, textarea blurb, link)
  • scaffold/themes/deckle/layouts/shortcodes/cards.html + card.html — the parent-Scratch collection pattern (deckleCards key): children push dicts in document order, parent renders the grid; honors the reserved disabled flag (bare bool and quoted) and has the hand-authored standalone fallback, mirroring img.html
  • scaffold/themes/deckle/layouts/partials/ce/card.html — shared per-card renderer: with link the root is a single wrapping <a class="ce-card"> (no nested interactive elements), honoring the linkTarget companion with the byte-exact target="_blank" rel="noopener" pair; without link a plain <div class="ce-card">
  • theme.css.ce-cards grid reusing the .ce-images breakpoints (1 col mobile, 2 at 40em, cols max at 48em) and modest .ce-card styling from existing tokens only

No Go or web changes were needed: element discovery, embedding, the collection-rows editor UI (add, drag-reorder, collapse, heading summary), and picker/tree hiding are all schema-driven.

Acceptance criteria

  • Both sidecars + shortcodes ship; card is hidden: true so it never appears in picker or tree (generic allowedElements/flattenChildren filtering, covered by existing web tests)
  • Parent form edits cards as collection rows — schema-driven IRRE UI, per-row summary from summary: heading
  • Single wrapping anchor with link, none without — pinned by the new TestCardsInProduction
  • cols is a max, collapsing on narrow viewports like the image grid (same 40em/48em breakpoints)
  • Real Hugo build with 0, 1, and many cards — kitchen-sink fixtures cover all three through buildLibrarySite (TestCardsInProduction, TestProductionBuildHygiene, TestContentRoundTrip all green; the zero-cards element renders nothing at all)

Verification

  • go test ./... green with real hugo 0.164 on PATH (theme/publish integration tests ran, not skipped); gofmt/go vet clean
  • web: npm run build + vitest — 792/792 pass (no web changes; confirms no regression)
  • AGENTS.md drift test green; the manual documents the items pattern generically, so no doc change is needed

Closes #92

🤖 Generated with Claude Code

Adds the `cards`/`card` core element pair from the issue spec, replicating the established `image`/`img` items-collection pattern. ## What ships - `scaffold/editor/elements/cards.yaml` — grid parent (`items: {element: card}`, `cols` select 2/3/4 default 3, `allowedIn: [page]`) - `scaffold/editor/elements/card.yaml` — hidden child (`allowedIn: [cards]`, `summary: heading`; optional image, required heading, textarea blurb, link) - `scaffold/themes/deckle/layouts/shortcodes/cards.html` + `card.html` — the parent-Scratch collection pattern (`deckleCards` key): children push dicts in document order, parent renders the grid; honors the reserved `disabled` flag (bare bool and quoted) and has the hand-authored standalone fallback, mirroring `img.html` - `scaffold/themes/deckle/layouts/partials/ce/card.html` — shared per-card renderer: with `link` the root is a **single wrapping `<a class="ce-card">`** (no nested interactive elements), honoring the `linkTarget` companion with the byte-exact `target="_blank" rel="noopener"` pair; without link a plain `<div class="ce-card">` - `theme.css` — `.ce-cards` grid reusing the `.ce-images` breakpoints (1 col mobile, 2 at 40em, cols max at 48em) and modest `.ce-card` styling from existing tokens only No Go or web changes were needed: element discovery, embedding, the collection-rows editor UI (add, drag-reorder, collapse, heading summary), and picker/tree hiding are all schema-driven. ## Acceptance criteria - Both sidecars + shortcodes ship; `card` is `hidden: true` so it never appears in picker or tree (generic `allowedElements`/`flattenChildren` filtering, covered by existing web tests) - Parent form edits cards as collection rows — schema-driven IRRE UI, per-row summary from `summary: heading` - Single wrapping anchor with link, none without — pinned by the new `TestCardsInProduction` - `cols` is a max, collapsing on narrow viewports like the image grid (same 40em/48em breakpoints) - Real Hugo build with 0, 1, and many cards — kitchen-sink fixtures cover all three through `buildLibrarySite` (`TestCardsInProduction`, `TestProductionBuildHygiene`, `TestContentRoundTrip` all green; the zero-cards element renders nothing at all) ## Verification - `go test ./...` green with real hugo 0.164 on PATH (theme/publish integration tests ran, not skipped); `gofmt`/`go vet` clean - `web`: `npm run build` + `vitest` — 792/792 pass (no web changes; confirms no regression) - AGENTS.md drift test green; the manual documents the items pattern generically, so no doc change is needed Closes #92 🤖 Generated with [Claude Code](https://claude.com/claude-code)
feat(scaffold): cards grid element with hidden card items child
All checks were successful
ci / build-and-test (pull_request) Successful in 9m57s
e8593406f2
A new core element pair following the image/img items-collection
pattern: `cards` is a responsive grid (cols select 2-4, a visual max
that collapses on narrow viewports at the same 40em/48em breakpoints as
.ce-images) owning a collection of hidden `card` children edited as
rows in the parent form (summary: heading). A card holds an optional
image, required heading, plain-text blurb, and an optional link; when
the link is set the whole card renders as a single wrapping anchor
honoring the linkTarget companion, with no nested interactive elements.
Zero cards render nothing at all, and disabled rows contribute nothing,
matching the img contract.

No Go or web changes: sidecars and shortcode templates are discovered
and embedded automatically, and the editor's collection-rows UI is
fully schema-driven. AGENTS.md needs no update — it documents the items
pattern generically, not an element inventory.

Coverage: kitchen-sink fixtures exercise 0, 1, and many cards through
the real-Hugo library-site build (round-trip canonical, production
hygiene), and TestCardsInProduction pins the grid class + anchor id,
the single-anchor contract with and without linkTarget, the unlinked
div form, and the zero-cards-render-nothing rule.

Closes #92

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Author
Owner

This was generated by AI while landing a PR.

Landing review — verdict: PASS.

  • CI: ci / build-and-test green (9m57s); relied on as the verification signal, not re-run. Its go test ./... ran with real Hugo on PATH.
  • AFK contract: Closes #92 present.
  • Convention: Conventional Commits title ✓; AGENTS.md drift test green (no new schema vocabulary).
  • Mergeable: no conflict with main; purely additive (356 insertions, 0 deletions).
  • Diff vs issue #92: sidecars match the specified schema; shortcodes mirror the established img/image items-collection pattern (Scratch deckleCards, .Inner-first, disabled honored, standalone fallback); linked card renders a single wrapping <a class="ce-card"> with linkTargettarget="_blank" rel="noopener", unlinked renders a plain <div>. TestCardsInProduction pins the single-anchor span, exactly-2 anchors, and the zero-cards-renders-nothing contract.

No blockers found. Awaiting the maintainer's free-text go-ahead to merge.

> *This was generated by AI while landing a PR.* **Landing review — verdict: PASS.** - **CI**: `ci / build-and-test` green (9m57s); relied on as the verification signal, not re-run. Its `go test ./...` ran with real Hugo on PATH. - **AFK contract**: `Closes #92` present. - **Convention**: Conventional Commits title ✓; AGENTS.md drift test green (no new schema vocabulary). - **Mergeable**: no conflict with `main`; purely additive (356 insertions, 0 deletions). - **Diff vs issue #92**: sidecars match the specified schema; shortcodes mirror the established `img`/`image` items-collection pattern (Scratch `deckleCards`, `.Inner`-first, `disabled` honored, standalone fallback); linked card renders a single wrapping `<a class="ce-card">` with `linkTarget` → `target="_blank" rel="noopener"`, unlinked renders a plain `<div>`. `TestCardsInProduction` pins the single-anchor span, exactly-2 anchors, and the zero-cards-renders-nothing contract. No blockers found. Awaiting the maintainer's free-text go-ahead to merge.
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Cloonar/deckle!99
No description provided.