From 9c6490f0f8cc653b423863cc9ba482d86d51825f Mon Sep 17 00:00:00 2001 From: Frank Lagendijk Date: Fri, 11 Sep 2026 12:04:32 +0200 Subject: [PATCH] refactor(merge-queue): take the hub's bespoke UI into components MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two things on the Merge Queue hub were built inline in the MDX, and between them they were the last content file on the site reaching for `--color-*` primitives directly. The headline figures. The homepage and the hub carry the same three numbers — 3-5×, 60-90%, 0 — and drew them differently: the homepage through `.home-metrics-strip` in index.css with semantic tokens, the hub through nested divs with inline styles, hardcoded padding, radius and font sizes, numerals at weight 700 where the type scale's 1.5rem step is 500, and teal pulled from a primitive. Being inline it could not pick up the dark-mode remap the way every other surface does, so the same claim read as a different kind of object depending which page you came from. Both pages now render , which owns the markup and the styles the homepage already had; the superseded rules leave index.css. The comparison marks. The yes/no marks in "Mergify vs GitHub Native Merge Queue" were two `export const` arrow functions inside the MDX, each with a hand-written inline and its color in a style attribute, duplicating marks already in the site's icon set. replaces them, drawing from astro-icon. Its color stays a product primitive rather than a --theme-* token, because yes and no are a semantic pair with no semantic token behind them and DESIGN.md allows a primitive inside a component for that; what changes is that the content file no longer carries one. merge-queue.mdx loses about 90 lines of inline markup and styling, and `src/content/docs/` is now free of `--color-*` entirely. The tables are untouched. Glossary and the symptom/cause/help table are genuinely tabular and read better as tables than as cards. Co-Authored-By: Claude Opus 5 Change-Id: Ida30f19564a144a12561edd3215e324bd049e9d7 Claude-Session-Id: 18413631-aa75-4182-9e79-4c1ce31bb683 --- src/components/MetricStrip.astro | 79 ++++++++++++++++++++++ src/components/Verdict.astro | 53 +++++++++++++++ src/content/docs/index.mdx | 23 +++---- src/content/docs/merge-queue.mdx | 109 ++++++------------------------- src/styles/index.css | 29 -------- 5 files changed, 160 insertions(+), 133 deletions(-) create mode 100644 src/components/MetricStrip.astro create mode 100644 src/components/Verdict.astro diff --git a/src/components/MetricStrip.astro b/src/components/MetricStrip.astro new file mode 100644 index 0000000000..aa51df0d69 --- /dev/null +++ b/src/components/MetricStrip.astro @@ -0,0 +1,79 @@ +--- +/** + * A row of headline figures — "3-5×, faster merge throughput". + * + * The homepage and the Merge Queue hub carry the same three numbers, and until + * this component they drew them two different ways: the homepage through + * `.home-metrics-strip` in `index.css`, the hub through nested `
`s with + * inline styles in the MDX itself. The inline copy hardcoded its padding, + * radius and font sizes, set its numerals at weight 700 where the type scale's + * 1.5rem step is 500, and reached for `--color-teal-*` primitives directly — + * the only content file on the site that did. Being inline, it also could not + * pick up the dark-mode remap the way every other surface does, so the same + * claim looked like a different kind of object depending on which page you + * came from. + * + * One component, semantic tokens, one treatment. + */ +interface Metric { + /** The figure itself: "3-5×", "60-90%", "0". */ + value: string; + /** What it measures, in lower case: "faster merge throughput". */ + label: string; +} + +interface Props { + metrics: Metric[]; + /** Names the group for screen readers, since the figures alone carry no context. */ + label?: string; +} + +const { metrics, label = 'Impact at a glance' } = Astro.props; +--- + +
+ { + metrics.map((m) => ( +
+
{m.value}
+
{m.label}
+
+ )) + } +
+ + diff --git a/src/components/Verdict.astro b/src/components/Verdict.astro new file mode 100644 index 0000000000..f1cbd8c228 --- /dev/null +++ b/src/components/Verdict.astro @@ -0,0 +1,53 @@ +--- +import { Icon } from 'astro-icon/components'; + +/** + * A yes/no mark with its text, for comparison tables. + * + * These were two `export const` arrow functions inside `merge-queue.mdx`, each + * with a hand-written inline `` and its colour set from a `--color-*` + * primitive in a `style` attribute. That made the hub the last content file + * reaching for primitives directly, and the icons duplicated marks the site + * already has in its icon set. + * + * The colour stays a product primitive rather than a `--theme-*` token: yes and + * no are a semantic pair with no semantic token behind them, and DESIGN.md + * allows a primitive inside a component for exactly this case. The point of + * moving it here is that the content file no longer carries it. + */ +interface Props { + /** `true` renders the affirmative mark, `false` the negative one. */ + yes: boolean; +} + +const { yes } = Astro.props; +--- + + + + + diff --git a/src/content/docs/index.mdx b/src/content/docs/index.mdx index 2e9875a507..3330e5583e 100644 --- a/src/content/docs/index.mdx +++ b/src/content/docs/index.mdx @@ -10,6 +10,7 @@ import CommunityButton from '~/components/CommunityButton.astro'; import Docset from '~/components/DocsetGrid/Docset.astro'; import DocsetGrid from '~/components/DocsetGrid/DocsetGrid.astro'; import mergeQueueHero from './images/merge-queue-hero.jpg'; +import MetricStrip from '~/components/MetricStrip.astro';
{/* ---------------- HERO ---------------- */} @@ -44,20 +45,14 @@ import mergeQueueHero from './images/merge-queue-hero.jpg'; {/* ---------------- METRICS STRIP ---------------- */} -
-
-
3-5×
-
faster merge throughput
-
-
-
60-90%
-
CI cost reduction
-
-
-
0
-
broken builds
-
-
+ {/* -------------- PROBLEM CARDS -------------- */} diff --git a/src/content/docs/merge-queue.mdx b/src/content/docs/merge-queue.mdx index f4a0a60cec..243bc93743 100644 --- a/src/content/docs/merge-queue.mdx +++ b/src/content/docs/merge-queue.mdx @@ -8,88 +8,17 @@ import Button from '~/components/Button.astro'; import AcademyCallout from '~/components/AcademyCallout.astro'; import DocsetGrid from '~/components/DocsetGrid/DocsetGrid.astro'; import Docset from '~/components/DocsetGrid/Docset.astro'; - -export const Yes = ({children}) => ( - - - {children} - -); - -export const No = ({children}) => ( - - - {children} - -); - -
-
-
3-5x
-
merge throughput
-
-
-
60-90%
-
CI cost reduction
-
-
-
Zero
-
broken builds
-
-
+import MetricStrip from '~/components/MetricStrip.astro'; +import Verdict from '~/components/Verdict.astro'; + + Stop wasting engineering time on merge conflicts and broken main branches. Mergify's merge queue tests every PR against the latest code before merging, @@ -190,14 +119,14 @@ which services a PR affects and only batches compatible changes together. | Capability | GitHub Native | Mergify | |------------|---------------|---------| -| Parallel speculative checks | Up to 100 | Up to 128 | -| Batch multiple PRs | | Configurable size + CI optimization | -| Priority queues | | Label or rule-based | -| Monorepo scopes | | Path-based queues + Bazel/Nx integration | -| Two-step CI | | Draft CI + merge CI | -| Pause/freeze queue | | API + dashboard | -| Cross-repo queues | | Coordinate dependent repos | -| Queue analytics | | Wait times, throughput, failures | +| Parallel speculative checks | Up to 100 | Up to 128 | +| Batch multiple PRs | | Configurable size + CI optimization | +| Priority queues | | Label or rule-based | +| Monorepo scopes | | Path-based queues + Bazel/Nx integration | +| Two-step CI | | Draft CI + merge CI | +| Pause/freeze queue | | API + dashboard | +| Cross-repo queues | | Coordinate dependent repos | +| Queue analytics | | Wait times, throughput, failures | ## Learn More diff --git a/src/styles/index.css b/src/styles/index.css index 743d0e5c17..6b4733321f 100644 --- a/src/styles/index.css +++ b/src/styles/index.css @@ -599,35 +599,6 @@ a.current-header-link { display: block; } -/* METRICS STRIP */ -.home-metrics-strip { - background: var(--theme-bg); - border: 1px solid var(--theme-border-subtle); - border-radius: 12px; - padding-block: 2rem; - padding-inline: var(--min-spacing-inline); - margin-bottom: 2rem; - display: grid; - grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); - gap: 1rem; -} -.home-metric { - text-align: center; - min-width: 8rem; -} -.home-metric-value { - font-size: 1.5rem; - font-weight: 500; - color: var(--theme-text); - line-height: 1.2; - letter-spacing: -0.02em; -} -.home-metric-label { - font-size: 0.875rem; - color: var(--theme-text-muted); - margin-top: 0.25rem; -} - /* PROBLEM CARDS */ .home-problems { padding-block: 3rem 2rem;