Skip to content

Hub pages 2/4: {card-group}, {link-card}, and {explore} - #3826

Draft
florent-leborgne wants to merge 5 commits into
feature/hub-layout-herofrom
feature/hub-card-explore
Draft

Hub pages 2/4: {card-group}, {link-card}, and {explore}#3826
florent-leborgne wants to merge 5 commits into
feature/hub-layout-herofrom
feature/hub-card-explore

Conversation

@florent-leborgne

@florent-leborgne florent-leborgne commented Aug 10, 2026

Copy link
Copy Markdown
Member

Part 2 of 4, based on #3825. Implements elastic/docs-content-internal#1384 ({card-group}), #1385 ({link-card}) and #1549 ({explore}).

Demo: https://docs-v3-preview.elastic.dev/elastic/docs-builder/pull/3826/examples/products/docs-builder

The three ship together because {explore} is what switches the other two into their second rendering mode. Split apart, this would add a mode switch nothing can trigger.

The mode switch

Nesting decides it. There is no option.

Directive Standalone Inside {explore}
{card-group} Heading and an auto-filling card grid One collapsible accordion in a stack
{link-card} Bordered card with a description and a link list Titled link column, description dropped

Driving this from the ancestor rather than a per-directive option means every card grid elsewhere on the site keeps working unchanged. An author wraps existing groups in {explore} and the rendering follows.

The first accordion in a stack is expanded and the rest are collapsed. Toggling uses native <details> and <summary>, so it works without JavaScript.

Implementation choices

HubDirectiveViewModel. Hub links come from directive options and YAML bodies, so they never reach Markdig's link renderer. {link-card} alone has six anchors, and each view was repeating the external, anchor and preload rules by hand. This centralises them into one LinkAttributes call. {hero} moves onto it too.

Heading levels. An accordion title renders as <h3> and a column title as <h4>, so an Explore stack keeps a complete outline: section h2, accordion h3, column h4. A <span> would leave the accordion group missing from the page outline.

Machine-readable output. The LLM export keeps the whole structure, because the curated grouping of links is what a hub page is for. The search body deliberately gets nothing from these three: section, card and link titles are the tokens that would let a hub outrank the pages it links to.

From the designs

  • Card links and column links share one treatment: bulleted, blue, underlined. The prototype styled columns as a quiet dark index.
  • The prototype's aside, a second list of links inside a card, is dropped. A card held two kinds of link, which meant two treatments for the same thing in one card. A second group of links is now a second card. elastic/docs-content-internal#1385 and Clarify mandatory link text #1549 are updated.
  • Only a card that carries its own link lifts on hover, and that card is clickable across its whole surface.
  • Accordions open independently. Expanding one does not collapse the others.

Example page

docs/examples/products/docs-builder.md grows from a hero into a full hub, exercising every mode: a standalone highlight grid, a :variant: solutions grid with icons and accent variants, and a three-accordion {explore} stack of link columns.

Its solution cards use docs-content:// cross-links to the published Elastic documentation, which also covers the cross-link form.

Testing

./build.sh unit-test passes. dotnet format and npm run fmt:check are clean. A full docs build reports 0 errors and 0 warnings.

tests/authoring/Blocks/Hub/CardsAndExplore.fs covers both rendering modes, the solutions variant, the first-accordion-open rule, the dropped description, the heading levels, icon and variant accents, and four failure paths.

Screenshots to add or update

None attached. The accordion stack and the two card layouts are worth checking on the preview.

@florent-leborgne
florent-leborgne force-pushed the feature/hub-card-explore branch from ba2cdd4 to 72fb5a2 Compare August 11, 2026 07:56
@florent-leborgne
florent-leborgne force-pushed the feature/hub-card-explore branch from 72fb5a2 to b5e2d23 Compare August 11, 2026 08:46
@florent-leborgne
florent-leborgne force-pushed the feature/hub-card-explore branch from b5e2d23 to 47c33d0 Compare August 11, 2026 13:31
@florent-leborgne
florent-leborgne force-pushed the feature/hub-card-explore branch from 47c33d0 to a8a4319 Compare August 11, 2026 15:15
@florent-leborgne
florent-leborgne force-pushed the feature/hub-card-explore branch from a8a4319 to bc28c12 Compare August 11, 2026 15:48
@florent-leborgne
florent-leborgne force-pushed the feature/hub-card-explore branch from bc28c12 to 1ba5e1d Compare August 11, 2026 16:51
florent-leborgne added a commit that referenced this pull request Aug 12, 2026
Martijn's review on #3826.

- Card link lists and column link lists take the site's standard link
  affordance: a bullet, blue, underlined. The leading chevron is gone. An
  arrow now means a control that behaves like a button, such as a hero
  action, rather than an entry in a link index.
- The aside cluster takes the {button} directive's secondary treatment in a
  new small size, because those are buttons rather than cards. The size
  modifier composes with either button type and is available to any caller.
- Only a card that carries its own link lifts on hover, and that card now
  has a whole-card target. A card holding several links and no link of its
  own no longer promises a click it cannot answer.
- Card and explore type moves onto the site's scale.
- Explore accordions no longer share a `name`, so a reader can hold several
  open and compare them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@florent-leborgne
florent-leborgne force-pushed the feature/hub-card-explore branch from 1ba5e1d to 526ee02 Compare August 12, 2026 18:53
florent-leborgne added a commit that referenced this pull request Aug 12, 2026
Martijn's review on #3826.

- Card link lists and column link lists take the site's standard link
  affordance: a bullet, blue, underlined. The leading chevron is gone. An
  arrow now means a control that behaves like a button, such as a hero
  action, rather than an entry in a link index.
- The aside cluster takes the {button} directive's secondary treatment in a
  new small size, because those are buttons rather than cards. The size
  modifier composes with either button type and is available to any caller.
- Only a card that carries its own link lifts on hover, and that card now
  has a whole-card target. A card holding several links and no link of its
  own no longer promises a click it cannot answer.
- Card and explore type moves onto the site's scale.
- Explore accordions no longer share a `name`, so a reader can hold several
  open and compare them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@florent-leborgne
florent-leborgne force-pushed the feature/hub-card-explore branch from 526ee02 to a31286a Compare August 12, 2026 19:03
florent-leborgne added a commit that referenced this pull request Aug 13, 2026
Martijn's review on #3826.

- Card link lists and column link lists take the site's standard link
  affordance: a bullet, blue, underlined. The leading chevron is gone. An
  arrow now means a control that behaves like a button, such as a hero
  action, rather than an entry in a link index.
- The aside cluster takes the {button} directive's secondary treatment in a
  new small size, because those are buttons rather than cards. The size
  modifier composes with either button type and is available to any caller.
- Only a card that carries its own link lifts on hover, and that card now
  has a whole-card target. A card holding several links and no link of its
  own no longer promises a click it cannot answer.
- Card and explore type moves onto the site's scale.
- Explore accordions no longer share a `name`, so a reader can hold several
  open and compare them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@florent-leborgne
florent-leborgne force-pushed the feature/hub-card-explore branch from a31286a to 5db6d7e Compare August 13, 2026 07:58
@florent-leborgne
florent-leborgne force-pushed the feature/hub-card-explore branch from 5db6d7e to 3021075 Compare August 13, 2026 08:34
florent-leborgne and others added 4 commits August 13, 2026 11:35
These three ship together because {explore} is what switches the other two into
their second rendering mode. A reviewer cannot judge the mechanism from any one
of them alone.

{card-group} is a section heading and a card grid. {link-card} is one card, with
a title, a description, a primary link list, and an optional aside. Its body is a
fixed YAML schema rather than markdown, so a missing title or invalid YAML fails
the build. {explore} wraps card groups into a stack of collapsible accordions.

Nesting drives the mode switch, not an option. Inside {explore} a card group
renders as an accordion and a link card renders as a titled link column, with the
description dropped and the aside rendered as a badge cluster under its own
authored label. Driving this from the ancestor rather than a per-directive option
means every card grid elsewhere on the site keeps working unchanged.

Adds HubDirectiveViewModel, which centralises the attributes a hub link needs.
Hub links come from options and YAML bodies, so they never pass through Markdig's
link renderer and each view was repeating the external, anchor, and preload rules
by hand. {hero} moves onto it too.

The LLM export keeps the whole structure. The curated grouping of links is what a
hub page is for, and the nav tree in llms.txt is neither ordered nor curated, so
it is not a substitute. The search body deliberately gets nothing from these three
directives: section, card, and link titles are the tokens that would let a hub
outrank the pages it links to on a specific query.

Adds doesNotContainHtml to the authoring assertions, for content a directive
drops on purpose.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Martijn's review on #3826.

- Card link lists and column link lists take the site's standard link
  affordance: a bullet, blue, underlined. The leading chevron is gone. An
  arrow now means a control that behaves like a button, such as a hero
  action, rather than an entry in a link index.
- The aside cluster takes the {button} directive's secondary treatment in a
  new small size, because those are buttons rather than cards. The size
  modifier composes with either button type and is available to any caller.
- Only a card that carries its own link lifts on hover, and that card now
  has a whole-card target. A card holding several links and no link of its
  own no longer promises a click it cannot answer.
- Card and explore type moves onto the site's scale.
- Explore accordions no longer share a `name`, so a reader can hold several
  open and compare them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Martijn's point about tiny fonts applies to every piece of hub text. Card
descriptions, column descriptions, and aside links now read at the body
size. The two cluster labels sit one step down, so they stay distinct from
the column headings beside them, and nothing renders below 14px.

The aside buttons keep 14px. They support the column links above them, so
they must not outweigh them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The flag only ever drove the arrow, and the shared link attributes do their
own anchor check for preloading.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A link card held two kinds of link: a primary list and an aside that
rendered as a badge cluster in a column, or as inline dot-separated links in
a card. That is two visual languages for the same thing, in one card.

The aside also could not express what it promised. It said "these are
secondary", and the only signal was its label. At 12px that label was too
small to read, and at 14px it was indistinguishable from the column heading
beside it. There is no size that reads as subordinate but legible.

A second group of links now becomes a second card. One shape, one
treatment, everywhere.

This removes the `aside` field, both of its renderings, the badge styling,
and the small button size added for it, which nothing else used. It also
removes the label sizing question and the sub-24px target on the badges.

Follow-ups: elastic/docs-content-internal#1385 and #1549 both specify
`aside` and need updating.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants