11---
22import StarlightPage from " @astrojs/starlight/components/StarlightPage.astro" ;
3- import { getCollection } from " astro:content" ;
3+ import { getCollection , type CollectionEntry } from " astro:content" ;
44
55import Header from " ~/components/changelogs/Header.astro" ;
66import ProductPills from " ~/components/changelogs/ProductPills.astro" ;
@@ -10,9 +10,7 @@ import { format } from "date-fns";
1010
1111const notes = await getCollection (" release-notes" );
1212
13- const days = Object .entries (
14- Object .groupBy (notes , (note ) => note .id .split (" /" ).slice (0 , 3 ).join (" /" )),
15- );
13+ notes .sort ((a , b ) => b .data .date .getTime () - a .data .date .getTime ());
1614---
1715
1816<StarlightPage
@@ -24,58 +22,89 @@ const days = Object.entries(
2422 hideTitle ={ true }
2523 hideBreadcrumbs ={ true }
2624>
27- <Header />
25+ <Header entries = { notes } />
2826 <div
29- class =" max-w-[50rem] justify-self-center px-4 md:grid md:grid-cols-[15%_auto]"
27+ class =" w-full max-w-[50rem] justify-self-center px-4 md:grid md:grid-cols-[15%_auto]"
3028 >
3129 {
32- days
33- .sort ()
34- .reverse ()
35- .map (([date , entries ]) => {
36- const formatted = format (date , " MMMM dd" );
37-
38- return (
39- <>
40- <div class = " !mt-0" >
41- <p class = " md:content-center md:pr-4 md:text-right md:leading-none" >
42- <strong class = " text-xs" >{ formatted } </strong >
43- <span class = " text-xs" >12:00PM</span >
44- </p >
45- </div >
46- <Steps >
47- <ol class = " !mt-0" >
48- { entries ?.map (async (entry ) => {
49- const { Content } = await entry .render ();
50-
51- return (
52- <li >
53- <div >
54- <a
55- href = { ` /release-notes/${entry .slug }/ ` }
56- class = " no-underline hover:underline"
57- >
58- <h3 class = " mb-4 !leading-[28px] text-black" >
59- { entry .data .title }
60- </h3 >
61- </a >
62- <ProductPills products = { entry .data .products } />
63- </div >
64- <p >
65- <Content />
66- </p >
67- </li >
68- );
69- })}
70- </ol >
71- </Steps >
72- </>
73- );
74- })
30+ notes .map (async (entry ) => {
31+ const date = format (entry .data .date , " MMM dd, yyyy" );
32+ const time = format (entry .data .date , " hh:mm a" );
33+ const productIds = JSON .stringify (
34+ entry .data .products .map ((product ) => product .id ),
35+ );
36+
37+ const { Content } = await entry .render ();
38+
39+ return (
40+ <>
41+ <div class = " !mt-0" data-products = { productIds } >
42+ <p class = " md:content-center md:pr-4 md:text-right md:leading-none" >
43+ <strong class = " text-xs" >{ date } </strong >
44+ <span class = " text-xs" >{ time } </span >
45+ </p >
46+ </div >
47+ <Steps >
48+ <ol class = " !mt-0" data-products = { productIds } >
49+ <li >
50+ <div >
51+ <a
52+ href = { ` /release-notes/${entry .slug }/ ` }
53+ class = " no-underline hover:underline"
54+ >
55+ <h3 class = " mb-4 !leading-[28px] text-black" >
56+ { entry .data .title }
57+ </h3 >
58+ </a >
59+ <ProductPills products = { entry .data .products } />
60+ </div >
61+ <p >
62+ <Content />
63+ </p >
64+ </li >
65+ </ol >
66+ </Steps >
67+ </>
68+ );
69+ })
7570 }
7671 </div >
7772</StarlightPage >
7873
74+ <script >
75+ const filter = document.querySelector<HTMLSelectElement>(
76+ "#release-notes-filter",
77+ );
78+
79+ filter?.addEventListener("change", () => {
80+ const entries = document.querySelectorAll<HTMLElement>("[data-products]");
81+
82+ if (!entries) return;
83+
84+ const value = filter.value;
85+
86+ if (value === "all") {
87+ entries.forEach((entry) => (entry.style.display = ""));
88+
89+ return;
90+ }
91+
92+ for (const entry of entries) {
93+ if (!entry.dataset.products) continue;
94+
95+ const products = JSON.parse(entry.dataset.products);
96+
97+ const show = products.includes(value);
98+
99+ if (show) {
100+ entry.style.display = "";
101+ } else {
102+ entry.style.display = "none";
103+ }
104+ }
105+ });
106+ </script >
107+
79108<style >
80109 :root {
81110 --sl-content-width: 100% !important;
0 commit comments