diff --git a/src/components/pages/ChangelogPage.astro b/src/components/pages/ChangelogPage.astro index 03f68a8..0aee89b 100644 --- a/src/components/pages/ChangelogPage.astro +++ b/src/components/pages/ChangelogPage.astro @@ -33,9 +33,11 @@ const products = ["lite", "enterprise", "core"] as const; const count = (id: string) => (id === "all" ? entries.length : entries.filter((e) => e.product === id).length); const filters = [{ id: "all", label: c.all }, ...products.map((id) => ({ id, label: c.filters[id] }))]; +// The latest release of each product; its tile leads to its notes on this page when it has any. const latest = products .map((id) => entries.find((e) => e.product === id)) - .filter((e): e is ChangelogEntry => Boolean(e)); + .filter((e): e is ChangelogEntry => Boolean(e)) + .map((e) => ({ ...e, onPage: Boolean(e.notes || e.releaseNotes) || !e.url })); // Newest month first; releases keep their newest-first order inside it. const months: { key: string; label: string; items: ChangelogEntry[] }[] = []; @@ -62,12 +64,12 @@ for (const e of entries) {

{c.latest}

{latest.map((e) => ( - + {releaseProductName(e.product, lang)} {e.tag} - {e.url && {c.github} ↗} + {e.onPage ? `${c.readNotes} ↓` : `${c.github} ↗`} ))} @@ -92,38 +94,45 @@ for (const e of entries) { {m.items.map(async (entry) => { const name = releaseProductName(entry.product, lang); const notes = entry.notes; - const Content = notes ? (await render(notes)).Content : null; + const published = notes ? undefined : entry.releaseNotes; + const source = notes ?? published; + const Content = source ? (await render(source)).Content : null; + // Core and Enterprise publish their notes in English only + const english = lang === "zh-CN" && published?.data.lang === "en"; + // A release with notes opens in place to show them + const Wrap = Content ? "details" : "div"; + const Row = Content ? "summary" : "div"; return (
  • {/* The anchor the release had while the page listed Enterprise alone (#v0.4.0). */} {entry.legacyId && } -
    - - {name} - {entry.tag} - {entry.url ? ( - - {c.github} ↗ - - ) : } -
    - - {notes && ( -
    -

    {notes.data.title}

    - {notes.data.highlights && ( -
      - {notes.data.highlights.map((h) =>
    • {h}
    • )} -
    - )} - {Content && ( -
    - {c.readNotes} -
    -
    - )} -
    - )} + + + + {name} + + {entry.tag} + {english && EN} + + {entry.url ? ( + + {c.github} ↗ + + ) : } + + + {Content && ( +
    + {notes &&

    {notes.data.title}

    } + {notes?.data.highlights && ( +
      + {notes.data.highlights.map((h) =>
    • {h}
    • )} +
    + )} +
    +
    + )} +
  • ); })} @@ -319,9 +328,16 @@ for (const e of entries) { --prod: 168px; --gap: 20px; } + .cl-wrap > summary { + list-style: none; + cursor: pointer; + } + .cl-wrap > summary::-webkit-details-marker { + display: none; + } .cl-row { display: grid; - grid-template-columns: var(--date) var(--prod) minmax(0, 1fr) 72px; + grid-template-columns: var(--date) var(--prod) minmax(0, 1fr) 72px 14px; align-items: center; gap: 4px var(--gap); min-height: 44px; @@ -331,9 +347,44 @@ for (const e of entries) { transition: background 150ms; } .cl-row:hover, - .changelog-item:target .cl-row { + .changelog-item:target .cl-row, + details[open] > .cl-row { background: rgba(255, 255, 255, 0.03); } + .cl-tagcell { + display: flex; + min-width: 0; + align-items: center; + gap: 10px; + } + .cl-en { + border: 1px solid rgba(255, 255, 255, 0.14); + border-radius: 4px; + padding: 1px 5px; + font-family: var(--font-mono); + font-size: 9px; + letter-spacing: 0.06em; + color: var(--color-dim); + } + /* A chevron on the releases that open to show their notes */ + .cl-chev { + width: 7px; + height: 7px; + justify-self: center; + border-right: 1.5px solid var(--color-dim); + border-bottom: 1.5px solid var(--color-dim); + transform: translateY(-2px) rotate(45deg); + transition: transform 200ms, border-color 150ms; + } + .cl-row:hover .cl-chev { + border-color: var(--color-text); + } + details[open] > .cl-row .cl-chev { + transform: translateY(2px) rotate(225deg); + } + .cl-chev-none { + visibility: hidden; + } .changelog-item:target .cl-row { box-shadow: inset 2px 0 0 rgb(var(--a1)); } @@ -367,9 +418,13 @@ for (const e of entries) { } @media (max-width: 639px) { .cl-row { - grid-template-columns: minmax(0, 1fr) auto; + grid-template-columns: minmax(0, 1fr) auto 14px; padding-block: 10px; } + .cl-chev { + grid-column: 3; + grid-row: 1 / 3; + } .cl-prod { grid-column: 1; grid-row: 1; @@ -379,7 +434,7 @@ for (const e of entries) { grid-row: 1; justify-self: end; } - .cl-tag { + .cl-tagcell { grid-column: 1; grid-row: 2; } @@ -390,7 +445,7 @@ for (const e of entries) { } .cl-notes { - padding: 8px 0 28px; + padding: 12px 0 32px; } /* the notes line up under the version */ @media (min-width: 640px) { @@ -406,7 +461,7 @@ for (const e of entries) { color: #fff; } .cl-highlights { - margin: 14px 0 0; + margin: 14px 0 20px; padding: 0; list-style: none; display: flex; @@ -429,35 +484,6 @@ for (const e of entries) { border-radius: 99px; background: linear-gradient(135deg, rgb(var(--a1)), rgb(var(--a2))); } - .cl-more { - margin-top: 16px; - } - .cl-more summary { - display: inline-flex; - min-height: 40px; - align-items: center; - gap: 6px; - cursor: pointer; - list-style: none; - font-size: 14px; - font-weight: 500; - color: var(--color-text); - transition: color 150ms; - } - .cl-more summary::-webkit-details-marker { - display: none; - } - .cl-more summary::after { - content: "↓"; - color: var(--color-dim); - transition: transform 150ms; - } - .cl-more[open] summary::after { - transform: rotate(180deg); - } - .cl-more summary:hover { - color: #fff; - } .cl-prose { margin-top: 12px; font-size: 0.9rem; @@ -466,7 +492,11 @@ for (const e of entries) { margin-top: 1.8em; font-size: 1.1rem; } - .cl-prose :global(h2:first-child) { + .cl-prose :global(h3) { + margin-top: 1.6em; + font-size: 1rem; + } + .cl-prose :global(:is(h2, h3, p):first-child) { margin-top: 0; } /* Hide the # anchor link appended by rehypeAutolinkHeadings */ @@ -497,6 +527,18 @@ for (const e of entries) {