Skip to content

Hub pages 1/4: hub page layout and the {hero} directive - #3825

Merged
Mpdreamz merged 9 commits into
mainfrom
feature/hub-layout-hero
Aug 14, 2026
Merged

Hub pages 1/4: hub page layout and the {hero} directive#3825
Mpdreamz merged 9 commits into
mainfrom
feature/hub-layout-hero

Conversation

@florent-leborgne

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

Copy link
Copy Markdown
Member

Part 1 of 4. Implements elastic/docs-content-internal#1386 (layout: hub) and #1380 ({hero}), against the promotion bar in #1379.

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

Rebuilt on the current navigation implementation. The prototype branch is merged with nav-v2, which is out of scope, so nothing from nav-v2 ports.

What this adds

  • MarkdownPageLayout.Hub and the RenderHub branch. It drops the right-rail table of contents and the previous/next navigation, keeps the left sidebar, and gives the body the full content column.
  • Page-title detection falls back from a top-level H1, to an H1 nested in a directive, to {hero}'s :title:. A hub page has no authored H1.
  • {hero}: product icon, page title, description, and up to three optional actions.
  • A page with layout: hub and no {hero} fails the build. The layout removes the page H1, so the page would otherwise have no title.
  • docs/syntax/hub-pages.md, docs/syntax/hero.md, an example hub at docs/examples/products/docs-builder.md, and F# authoring tests.

Visual decisions

  • Hero actions use the {button} directive's neutral style from feat(button): add neutral variant to the button directive #3853. All three carry equal weight, so the option names set order, not prominence. A blue variant would make each action claim to be the call to action.
  • The eyebrow border moves to grey-70. feat(button): add neutral variant to the button directive #3853 flagged that this stack used border colours failing the 3:1 non-text contrast ratio, and the border is what identifies that control.
  • All hub text uses the site's size tokens. Body text is 16px and nothing renders below 14px.
  • An arrow marks only a link that sends the reader onward, never a button. One shared class draws it.
  • The hero adds no side padding of its own, so it lines up with every section on the page at any width.

Implementation choices

DirectiveLinkValidator. Directive links never reach Markdig's inline link parser, so every directive taking a URL had invented its own handling. This promotes the prototype's hub-only validator to a shared one and moves {page-card} onto it, deleting its hand-rolled copy. {page-card} keeps its contract: relative links resolve against the source file, and no file-existence check runs, because its links can target generated pages such as the CLI reference.

Parser guard. DirectiveBlockParser.TryContinue stops an ancestor directive consuming an option line once it has opened a nested directive child. Without it the ancestor takes every descendant's options and the last one wins.

The collision only fires when a parent and child read the same option name. Only the hub pair overlaps: {explore} and {card-group} both use :id: and :title:. Existing pairs split cleanly, so they were latently exposed but never broken.

Parent reads Child reads
{tab-set} group {tab-item} sync, selected
{applies-switch} group {applies-item} sync
{stepper} none {step} anchor
{dropdown} open {note} name

tests/authoring/Blocks/NestedDirectiveOptions.fs pins that each option still reaches the block that declared it, for all four pairs. Those tests pass with the guard removed, so they are guard-rails against breaking option routing rather than regression tests for the bug itself. The {explore} tests in #3826 are what catch the bug.

The guard changes exactly one pattern: an option line appearing after a nested child has opened. A scan of every markdown file in docs-builder and docs-content found zero occurrences.

Cross-links are not external. A cross-link resolves to a full URL but still points at documentation this site serves, so it does not open in a new tab. Inline links make the same distinction.

Machine-readable output. {hero} gets an LLM renderer and a plain-text renderer. The search body takes the hero title and description only. Indexing section and card titles would let a hub outrank the pages it links to.

Article id, not class. The article keeps id="markdown-content", which the copy button, syntax highlighter and smooth scroll select on. It does not take the class: typography.css is unlayered and hub.css sits in @layer components, so the class would override every hub rule.

Two prototype details do not port. The empty #toc-nav slot is dropped, because main replaced hx-select-oob with a whole-body swap. Hero links use preload rather than hx-boost="false", matching PageCardView.

Known gaps

  • No version switcher on a hub page. VersionDropdown renders from the table-of-contents rail this layout removes. The designs place it in the top bar, which belongs to the navigation work in elastic/docs-content-internal#1589.
  • :description: uses the default Markdig pipeline, because it is a directive option rather than a body block. Substitutions, roles and link validation do not apply inside it. Documented on the syntax page.

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.

Adds containsRawHtml and doesNotContainHtml to the authoring assertions. The pretty-printed comparison only matches a childless element or a snapshot taken from the outermost element of the directive output, so asserting an attribute on a container needs the raw form.

Screenshots to add or update

None attached. Check the rendered hero on the preview.

@theletterf theletterf left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nice! Two Qs:

  • How does a hub page render without a hero directive? Should it trigger an error if empty?
  • Related to the above, do we want to keep hero directives independent and available to all pages? Shouldn't the hero block, if mandatory for all hub pages, be part of the layout and not a separate directive?

@theletterf

Copy link
Copy Markdown
Member

I think we can roll with this one! I would just think of a warning in case a layout is missing what we consider mandatory directives (like hero).

florent-leborgne added a commit that referenced this pull request Aug 12, 2026
Martijn's review on #3825 and theletterf's questions.

- The hero no longer adds its own horizontal padding. The content column
  supplies the gutter, so the hero aligned with the sections below it only
  above the shared max-width. Below it the hero sat 24px further in.
- Hero type moves onto the site's scale. The root font size is 14px, so
  values written as 16px-root arithmetic rendered around 12% small. The
  description in particular used a size found nowhere else on the site.
- The three hero actions carry equal weight and take the secondary button
  treatment from the {button} directive, rather than a bespoke hero button.
  The option names set order, not weight.
- A page with `layout: hub` and no {hero} now fails the build. The layout
  removes the page H1, so without a hero the page has no title at all and
  falls back to its file path.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
florent-leborgne added a commit that referenced this pull request Aug 12, 2026
Martijn's review on #3825 covered the whole page, so the same rules apply
here.

- Get started type moves onto the site's scale. The values it carried were
  16px-root arithmetic against a 14px root, so every one rendered small.
- Step numbers move from grey-70 to ink-light. grey-70 reads at 3.31:1 on
  white, short of the 4.5:1 minimum, and ink-light carries the same quiet
  weight at 7.03:1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
florent-leborgne added a commit that referenced this pull request Aug 12, 2026
Martijn's review on #3825 covered the whole page, so the same rule applies
here. What's new type moves onto the site's scale. Every raw font size in
hub.css is now a scale token.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
florent-leborgne added a commit that referenced this pull request Aug 12, 2026
Martijn's review on #3825 covered the whole page, so the same rules apply
here.

- Get started type moves onto the site's scale. The values it carried were
  16px-root arithmetic against a 14px root, so every one rendered small.
- Step numbers move from grey-70 to ink-light. grey-70 reads at 3.31:1 on
  white, short of the 4.5:1 minimum, and ink-light carries the same quiet
  weight at 7.03:1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
florent-leborgne added a commit that referenced this pull request Aug 12, 2026
Martijn's review on #3825 covered the whole page, so the same rule applies
here. What's new type moves onto the site's scale. Every raw font size in
hub.css is now a scale token.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
florent-leborgne added a commit that referenced this pull request Aug 13, 2026
Martijn's review on #3825 covered the whole page, so the same rules apply
here.

- Get started type moves onto the site's scale. The values it carried were
  16px-root arithmetic against a 14px root, so every one rendered small.
- Step numbers move from grey-70 to ink-light. grey-70 reads at 3.31:1 on
  white, short of the 4.5:1 minimum, and ink-light carries the same quiet
  weight at 7.03:1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
florent-leborgne added a commit that referenced this pull request Aug 13, 2026
Martijn's review on #3825 covered the whole page, so the same rule applies
here. What's new type moves onto the site's scale. Every raw font size in
hub.css is now a scale token.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
florent-leborgne added a commit that referenced this pull request Aug 13, 2026
Martijn's review on #3825 covered the whole page, so the same rules apply
here.

- Get started type moves onto the site's scale. The values it carried were
  16px-root arithmetic against a 14px root, so every one rendered small.
- Step numbers move from grey-70 to ink-light. grey-70 reads at 3.31:1 on
  white, short of the 4.5:1 minimum, and ink-light carries the same quiet
  weight at 7.03:1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
florent-leborgne added a commit that referenced this pull request Aug 13, 2026
Martijn's review on #3825 covered the whole page, so the same rule applies
here. What's new type moves onto the site's scale. Every raw font size in
hub.css is now a scale token.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
florent-leborgne added a commit that referenced this pull request Aug 13, 2026
Martijn's review on #3825 covered the whole page, so the same rules apply
here.

- Get started type moves onto the site's scale. The values it carried were
  16px-root arithmetic against a 14px root, so every one rendered small.
- Step numbers move from grey-70 to ink-light. grey-70 reads at 3.31:1 on
  white, short of the 4.5:1 minimum, and ink-light carries the same quiet
  weight at 7.03:1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
florent-leborgne added a commit that referenced this pull request Aug 13, 2026
Martijn's review on #3825 covered the whole page, so the same rule applies
here. What's new type moves onto the site's scale. Every raw font size in
hub.css is now a scale token.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
florent-leborgne added a commit that referenced this pull request Aug 13, 2026
Martijn's review on #3825 covered the whole page, so the same rules apply
here.

- Get started type moves onto the site's scale. The values it carried were
  16px-root arithmetic against a 14px root, so every one rendered small.
- Step numbers move from grey-70 to ink-light. grey-70 reads at 3.31:1 on
  white, short of the 4.5:1 minimum, and ink-light carries the same quiet
  weight at 7.03:1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
florent-leborgne added a commit that referenced this pull request Aug 13, 2026
Martijn's review on #3825 covered the whole page, so the same rule applies
here. What's new type moves onto the site's scale. Every raw font size in
hub.css is now a scale token.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
florent-leborgne added a commit that referenced this pull request Aug 13, 2026
Martijn's review on #3825 covered the whole page, so the same rule applies
here. What's new type moves onto the site's scale. Every raw font size in
hub.css is now a scale token.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
florent-leborgne and others added 4 commits August 13, 2026 17:48
Adds the first two pieces of the hub page mechanism, rebuilt on the current
navigation implementation. The prototype branch is merged with nav-v2, which is
out of scope, so nothing from nav-v2 ports.

Adds `layout: hub`, which drops the right-rail table of contents and the
previous/next navigation, keeps the left sidebar, and gives the body the full
content column. Page-title detection gains two fallbacks, so a page composed
only of directives still resolves a title: an H1 nested in a directive, then the
first {hero} directive's :title: option.

Adds {hero}, the identity band. It carries a product icon, the page title, a
description, and up to three optional actions.

Promotes the prototype's hub-only link validator to a shared
DirectiveLinkValidator. Directive links never pass through Markdig's inline link
parser, so every directive that takes a URL had invented its own handling.
{page-card} moves onto the shared class and its hand-rolled copy goes. It keeps
its previous contract: relative links resolve against the source file, and no
file-existence check runs, because page-card links can target generated pages
that have no markdown file on disk.

Guards DirectiveBlockParser.TryContinue so an ancestor directive stops consuming
option lines once it has opened a nested directive child. Without the guard the
ancestor swallows every descendant's options and the last one wins. This affects
every nested directive, so it lands with regression tests over tab sets,
steppers, and dropdowns.

Adds LLM markdown and plain-text renderers for {hero}. A hub page has no body
prose, so without them it exports as an empty shell. The plain-text renderer
feeds the search index and emits the hero title and description only. Hub pages
answer generic "<product> docs" queries. Indexing section and card titles would
let a hub compete with the pages it links to on specific queries.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Three defects, all introduced in this branch rather than carried from the
prototype.

Suppress the page-level H1 and the applies-to badge on a hub page. The prototype
guards both in Index.cshtml and that guard was missed, so every hub page rendered
the page title twice: once from Index.cshtml, once from {hero}. This also
delivers the applies-to suppression that #1386 records but the code did not do.

Drop the markdown-content class from the hub article. The class was added to
reach the JS hooks, but those select on the markdown-content id, not the class.
typography.css is unlayered and hub.css sits in @layer components, so unlayered
rules win regardless of specificity. The class made typography.css restyle the
hero eyebrow as a blue underlined link and skew the icon alignment against the
heading. The id stays, so hljs, smooth-scroll and toc-nav keep working.

Give hero actions the same link treatment as inline links. An external action now
opens in a new tab with rel="noopener noreferrer" and no preload, and an anchor
action no longer preloads. Only an internal link preloads.

Fix an empty href for "/index.md". Stripping the whole "/index.md" segment left
an empty string rather than the site root.

The example page gains three actions, one internal and two external, to
demonstrate both forms.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The mark sat about 9px right of the eyebrow and the description below it. Two
insets stacked. Each icon's viewBox carried transparent padding around the glyph,
which cost 5px at the rendered size. The 48px chip then centred the 40px SVG
inside itself, which cost another 4px.

Crops every icon's viewBox to its glyph, so no transparent padding is left to
absorb, and lets the box hug the mark instead of forcing it into a fixed square.
Width now follows from the glyph's own aspect ratio.

The letter fallback keeps the chip. It has no glyph to align, and the chip's own
edge already lines up with the text column.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…tabs

The example page was an Elasticsearch hub whose links had all been repointed at
docs-builder pages, leaving an Elasticsearch name, icon, hero and headings on top
of docs-builder content. It is now a docs-builder hub throughout, renamed to
docs/examples/products/docs-builder.md.

Its hero demonstrates all three link forms: a site-absolute path, a docs-content
cross-link, and an in-page anchor. The unknown `docs-builder` icon key also
exercises the single-letter fallback.

Fixes a defect the cross-link uncovered. A cross-link resolves to a full URL, so
the hero treated it as external and opened it in a new tab. Inline links make the
opposite call, and deliberately so: a cross-link still points at documentation
this site serves. DirectiveLinkValidator now records the URLs it resolved from a
cross-link scheme, and the view model consults that rather than guessing from the
scheme.

Adds doesNotContainHtml to the authoring assertions.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
florent-leborgne and others added 5 commits August 13, 2026 17:48
Martijn's review on #3825 and theletterf's questions.

- The hero no longer adds its own horizontal padding. The content column
  supplies the gutter, so the hero aligned with the sections below it only
  above the shared max-width. Below it the hero sat 24px further in.
- Hero type moves onto the site's scale. The root font size is 14px, so
  values written as 16px-root arithmetic rendered around 12% small. The
  description in particular used a size found nowhere else on the site.
- The three hero actions carry equal weight and take the secondary button
  treatment from the {button} directive, rather than a bespoke hero button.
  The option names set order, not weight.
- A page with `layout: hub` and no {hero} now fails the build. The layout
  removes the page H1, so without a hero the page has no title at all and
  falls back to its file path.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Martijn's point about tiny fonts applies to every piece of hub text, not
only the ones in his screenshot. The eyebrow is a reading affordance, so it
takes the body size.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The site puts an arrow on two kinds of link: one that sends the reader
onward out of a section, such as "View all reference docs" on the landing
page, and a row that is itself the target, such as {page-card} or the
previous and next footer. It marks no ordinary link and no button.

The hero followed neither. Its actions are buttons, so they carried an
arrow the site gives no button, and only when the target was an in-page
anchor. Both are gone.

The eyebrow keeps its arrow, because it sends the reader onward to the docs
home. It now uses the site's glyph and hover slide through one shared
`.hub-arrow` class, rather than a second arrow drawn by hand.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
#3853 added `:type: neutral` to the {button} directive, a monochrome
outline for clusters where blue competes with the primary action. That is
exactly what the hero needs: three actions of equal rank, none of which
should claim to be the call to action.

#3853 also flagged that this stack used border colours failing the 3:1
non-text contrast ratio. The eyebrow pill moves from grey-20, which reads
at 1.32:1, to grey-70 at 3.31:1. The border is what identifies that
control, so it has to clear the threshold.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Hub heroes fall back to initials when a product key is missing from the
inline SVG map. Logstash hubs need the product mark.

Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Martijn Laarman <Mpdreamz@gmail.com>
@florent-leborgne
florent-leborgne force-pushed the feature/hub-layout-hero branch from d0395b2 to 87136e7 Compare August 13, 2026 15:54
florent-leborgne added a commit that referenced this pull request Aug 13, 2026
Martijn's review on #3825 covered the whole page, so the same rules apply
here.

- Get started type moves onto the site's scale. The values it carried were
  16px-root arithmetic against a 14px root, so every one rendered small.
- Step numbers move from grey-70 to ink-light. grey-70 reads at 3.31:1 on
  white, short of the 4.5:1 minimum, and ink-light carries the same quiet
  weight at 7.03:1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
florent-leborgne added a commit that referenced this pull request Aug 13, 2026
Martijn's review on #3825 covered the whole page, so the same rule applies
here. What's new type moves onto the site's scale. Every raw font size in
hub.css is now a scale token.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
florent-leborgne added a commit that referenced this pull request Aug 13, 2026
Martijn's review on #3825 covered the whole page, so the same rules apply
here.

- Get started type moves onto the site's scale. The values it carried were
  16px-root arithmetic against a 14px root, so every one rendered small.
- Step numbers move from grey-70 to ink-light. grey-70 reads at 3.31:1 on
  white, short of the 4.5:1 minimum, and ink-light carries the same quiet
  weight at 7.03:1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
florent-leborgne added a commit that referenced this pull request Aug 13, 2026
Martijn's review on #3825 covered the whole page, so the same rule applies
here. What's new type moves onto the site's scale. Every raw font size in
hub.css is now a scale token.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
florent-leborgne added a commit that referenced this pull request Aug 13, 2026
Martijn's review on #3825 covered the whole page, so the same rules apply
here.

- Get started type moves onto the site's scale. The values it carried were
  16px-root arithmetic against a 14px root, so every one rendered small.
- Step numbers move from grey-70 to ink-light. grey-70 reads at 3.31:1 on
  white, short of the 4.5:1 minimum, and ink-light carries the same quiet
  weight at 7.03:1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
florent-leborgne added a commit that referenced this pull request Aug 13, 2026
Martijn's review on #3825 covered the whole page, so the same rule applies
here. What's new type moves onto the site's scale. Every raw font size in
hub.css is now a scale token.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@florent-leborgne
florent-leborgne marked this pull request as ready for review August 14, 2026 09:10
@florent-leborgne
florent-leborgne requested review from a team as code owners August 14, 2026 09:10
@Mpdreamz
Mpdreamz merged commit dd63298 into main Aug 14, 2026
25 checks passed
@Mpdreamz
Mpdreamz deleted the feature/hub-layout-hero branch August 14, 2026 10:20
Mpdreamz added a commit that referenced this pull request Aug 14, 2026
* Add {get-started}

The onboarding section of a hub page. It gives a new reader one opinionated path
to a first success, before they face the full link list. The section is optional.

Keeps the top-level install and tutorial pair as first-class fields rather than
treating it as prototype back-compatibility. The designs use exactly that shape:
a copyable command beside a tutorial card, with numbered steps below.

The install snippet renders inside `.highlight pre` with a language class, which
is what the site's copy button and syntax highlighter already select on. Both
work with no extra wiring, because the hub layout kept the markdown-content id.

Steps take one of three shapes: plain, a whole-card link, or two or more equally
weighted options side by side. Numbering is automatic and sits before the title,
because the section describes a sequence and the number is what carries that.

Drops the prototype's per-step icon field. The icons restate the step title, the
number badge is already the visual anchor, and a schema field for decoration
makes every author pick icons that then drift between hubs.

The LLM export renders the steps as an ordered list with options as sub-items.
The search body gets nothing, for the same reason as the other hub directives.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* Apply review feedback to the get-started section

Martijn's review on #3825 covered the whole page, so the same rules apply
here.

- Get started type moves onto the site's scale. The values it carried were
  16px-root arithmetic against a 14px root, so every one rendered small.
- Step numbers move from grey-70 to ink-light. grey-70 reads at 3.31:1 on
  white, short of the 4.5:1 minimum, and ink-light carries the same quiet
  weight at 7.03:1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* Raise get-started text to body size

Martijn's point about tiny fonts applies to every piece of hub text. Step
descriptions, option labels, option descriptions, option buttons, and the
step links now read at the body size. The install command keeps 14px, which
is what every other code block on the site renders at.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* Use the shared arrow in get-started

Both links that carry an arrow here send the reader onward out of the card,
which is one of the two cases the site marks. They now use the same glyph
and hover slide as every other hub arrow. The option button carries none,
like every other button on the site.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* Let a get-started section run to any number of steps

Nothing in the schema limited the section to three steps. One CSS rule did:
when a step carried options, the grid locked to two tracks, which suits one
wide step and two others exactly. A fourth step left one card alone on a
half-width row.

The directive now counts the steps that flow in columns and sets the track
count. Three across when they divide by three, two when they are even, so
the last row is never short. A step carrying options still spans the full
row and takes no track. Below 640px of available width the steps stack.

The width is measured on the section rather than the viewport, because the
left sidebar narrows the body.

The example hub gains a fourth step, so the preview shows the new
arrangement.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* Give a linked step the shared card hover

The step card hovered to a blue border while the other two card types
hovered to grey. Blue also makes one step in a sequence look like the call
to action. It now uses grey-80, the same treatment as {page-card} and a
linked {link-card}.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Mpdreamz added a commit that referenced this pull request Aug 14, 2026
* Add {whats-new}

A recency panel for a hub page. A reader who bookmarks a hub wants a quick answer
to "what changed recently" without hunting through release notes.

The panel content moves out of the build tool. The prototype reads
config/whats-new.yml from docs-builder, which means a writer editing a highlight
card opens a pull request against the build tool and waits for a release. It now
reads hub-whats-new.yml from the root of the current documentation set, beside
changelog.yml and redirects.yml.

That makes the directive documentation-set scoped. It cannot render another
repository's panel, and this is a constraint rather than a syntax gap.
Cross-link resolution maps pages through the link index, and a YAML data file is
not a page. In an isolated build the other repository is not checked out, so
there would be no file to read. Every hub page lives in the same repository as
its content file, so the limit costs nothing today.

The common case stays one line, `:product: <key>`. Omitting it accepts the same
schema as an inline YAML body, for a one-off panel.

Adds containsRawHtml to the authoring assertions. The pretty-printed comparison
only matches a childless element or a snapshot taken from the outermost element
of the directive output, so asserting a class on a container previously meant
snapshotting its whole subtree.

Follow-up, not in this change: a skill in docs-content that updates
hub-whats-new.yml from the release notes of each product that has a hub page.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* Apply review feedback to the what's new section

Martijn's review on #3825 covered the whole page, so the same rule applies
here. What's new type moves onto the site's scale. Every raw font size in
hub.css is now a scale token.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* Raise what's new text to body size, and stop shouting the date

Martijn's point about tiny fonts applies to every piece of hub text. Card
descriptions, release note links, and the footer now read at the body size.
Card meta sits one step down at 14px. No hub text renders below 14px, and
nothing uses the smallest step of the scale.

The card date no longer forces uppercase. It is authored, so it keeps the
casing the writer chose. The example data and the syntax page now use
sentence case to match.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* Use the shared arrow in what's new

The card link and the upgrade link both send the reader onward, which is one
of the two cases the site marks with an arrow. They now use the same glyph
and hover slide as every other hub arrow. No hub directive draws its own
arrow any more.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* Give a what's new card the shared card hover

The card hovered to a pale blue border reading 2.12:1 against white, so the
state was barely visible. It now uses grey-80 at 4.15:1, the same treatment
as every other card on a hub page that is itself a link.

Every card that is a link now hovers the same way, and every state border
in the hub clears the 3:1 ratio.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

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.

4 participants