From 678348a3341d5a32e312633ade677f6f6573cdeb Mon Sep 17 00:00:00 2001 From: Tyrel Chambers Date: Tue, 18 Nov 2025 15:11:23 -0500 Subject: [PATCH 1/6] copy button --- .../ChangelogSnippet/ChangelogCard.astro | 3 + .../ChangelogSnippet/ChangelogCard.module.css | 63 ++++++++++++++++- .../ChangelogSnippet/CopyButton.tsx | 67 +++++++++++++++++++ src/pages/changelog/[...id].astro | 0 .../index.astro} | 2 +- 5 files changed, 131 insertions(+), 4 deletions(-) create mode 100644 src/components/ChangelogSnippet/CopyButton.tsx create mode 100644 src/pages/changelog/[...id].astro rename src/pages/{changelog.astro => changelog/index.astro} (98%) diff --git a/src/components/ChangelogSnippet/ChangelogCard.astro b/src/components/ChangelogSnippet/ChangelogCard.astro index 087bcbbf03a..2e36501f5b9 100644 --- a/src/components/ChangelogSnippet/ChangelogCard.astro +++ b/src/components/ChangelogSnippet/ChangelogCard.astro @@ -3,6 +3,7 @@ import { SvgTaillessArrowDownSmall, Typography } from "@chainlink/blocks" import styles from "./ChangelogCard.module.css" import type { ChangelogItem } from "./types" import { clsx } from "~/lib/clsx/clsx" +import CopyButton from "./CopyButton.tsx" interface Props { item: ChangelogItem @@ -51,6 +52,8 @@ const formattedDate = formatDate(item["date-of-release"]) {item["text-description"] &&
}
+ +
diff --git a/src/components/ChangelogSnippet/ChangelogCard.module.css b/src/components/ChangelogSnippet/ChangelogCard.module.css index 56437e6fb33..536a5c22f0e 100644 --- a/src/components/ChangelogSnippet/ChangelogCard.module.css +++ b/src/components/ChangelogSnippet/ChangelogCard.module.css @@ -9,6 +9,10 @@ background-color: var(--gray-50); } + &:hover .copyButton { + opacity: 1; + } + & .card { padding: var(--space-6x); } @@ -132,11 +136,40 @@ transition: transform 0.3s ease; } -@media screen and (max-width: 425px) { - .card { - flex-direction: column; +.copyButton { + display: flex; + height: fit-content; + gap: var(--space-2x); + border-radius: var(--space-1x); + border: 1px solid var(--border); + width: 118px; + justify-content: center; + align-items: center; + padding: var(--space-2x) 0; + transition: all 0.2s ease; + opacity: 0; + + & > svg { + color: var(--muted-foreground); + } + + &:hover { + border: 1px solid var(--foreground); } +} +.checkmark { + stroke: var(--success-foreground); +} +.copyIconMobile { + display: none; +} + +.copyIconDesktop { + display: block; +} + +@media screen and (max-width: 425px) { .changelogType { font-size: 14px; } @@ -150,6 +183,7 @@ .card { padding: var(--space-4x); gap: var(--space-4x); + flex-direction: column; } .header { @@ -172,4 +206,27 @@ .contentFooter { padding-left: var(--space-4x); } + + .copyIconDesktop { + display: none; + } + + .copyIconMobile { + display: block; + } + .copyText { + display: none; + } + + .copyButton { + width: 32px; + } +} + +@media screen and (max-width: 990px) { + .copyButton { + position: absolute; + right: var(--space-4x); + top: var(--space-4x); + } } diff --git a/src/components/ChangelogSnippet/CopyButton.tsx b/src/components/ChangelogSnippet/CopyButton.tsx new file mode 100644 index 00000000000..5fabe5dfdd2 --- /dev/null +++ b/src/components/ChangelogSnippet/CopyButton.tsx @@ -0,0 +1,67 @@ +import { SvgCopy, Typography } from "@chainlink/blocks" +import styles from "./ChangelogCard.module.css" +import { useState } from "react" + +export default function CopyButton({ url }: { url: string }) { + const [isCopied, setIsCopied] = useState(false) + + const copyToClipboard = () => { + navigator.clipboard.writeText(`/changelog/${url}`) + setIsCopied(true) + setTimeout(() => setIsCopied(false), 2000) + } + + return ( + + ) +} diff --git a/src/pages/changelog/[...id].astro b/src/pages/changelog/[...id].astro new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/pages/changelog.astro b/src/pages/changelog/index.astro similarity index 98% rename from src/pages/changelog.astro rename to src/pages/changelog/index.astro index a5301884c34..74c1207b4b4 100644 --- a/src/pages/changelog.astro +++ b/src/pages/changelog/index.astro @@ -1,6 +1,6 @@ --- import BaseLayout from "~/layouts/BaseLayout.astro" -import * as CONFIG from "../config" +import * as CONFIG from "../../config" import { Typography } from "@chainlink/blocks" import { getSecret } from "astro:env/server" From 8d8b35df8f404ac41a9d710c5cd8e8f7769b40b7 Mon Sep 17 00:00:00 2001 From: Tyrel Chambers Date: Tue, 18 Nov 2025 15:35:04 -0500 Subject: [PATCH 2/6] add individual changelog page --- .../ChangelogSnippet/CopyButton.tsx | 3 +- src/pages/changelog/[...id].astro | 52 +++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/src/components/ChangelogSnippet/CopyButton.tsx b/src/components/ChangelogSnippet/CopyButton.tsx index 5fabe5dfdd2..d52f32aa96f 100644 --- a/src/components/ChangelogSnippet/CopyButton.tsx +++ b/src/components/ChangelogSnippet/CopyButton.tsx @@ -6,7 +6,8 @@ export default function CopyButton({ url }: { url: string }) { const [isCopied, setIsCopied] = useState(false) const copyToClipboard = () => { - navigator.clipboard.writeText(`/changelog/${url}`) + const mode = import.meta.env.MODE === "development" ? "http://localhost:4321" : "https://dev.chain.link" + navigator.clipboard.writeText(`${mode}/changelog/${url}`) setIsCopied(true) setTimeout(() => setIsCopied(false), 2000) } diff --git a/src/pages/changelog/[...id].astro b/src/pages/changelog/[...id].astro index e69de29bb2d..346768182ee 100644 --- a/src/pages/changelog/[...id].astro +++ b/src/pages/changelog/[...id].astro @@ -0,0 +1,52 @@ +--- +import BaseLayout from "~/layouts/BaseLayout.astro" +import * as CONFIG from "../../config" +import { getSecret } from "astro:env/server" +import { searchClient, SearchClient } from "@algolia/client-search" +import { ChangelogItem } from "~/components/ChangelogSnippet/types" + +export const prerender = false + +const { id } = Astro.params + +console.log(id) + +const appId = getSecret("ALGOLIA_APP_ID") +const apiKey = getSecret("PUBLIC_ALGOLIA_SEARCH_PUBLIC_API_KEY") + +let client: SearchClient +let latestLog: ChangelogItem | undefined = undefined + +// Initialize client if appId and apiKey are available to avoid needing to update +// the github actions with the new keys (satisfies linkcheck-internal) +if (appId && apiKey) { + client = searchClient(appId, apiKey) + + const req = await client.search({ + requests: [ + { + indexName: "Changelog", + restrictSearchableAttributes: ["slug"], + query: id, + hitsPerPage: 1, + }, + ], + }) + + console.log(req) + + const firstResult = req.results[0] + const results = "hits" in firstResult ? (firstResult.hits as ChangelogItem[]) : [] + + // logs are returned sorted by created_at DESC + latestLog = results[0] +} + +console.log(latestLog) + +const formattedContentTitle = `Changelog and Releases | ${CONFIG.SITE.title}` +--- + + +
+
From 825c4cf11df4abb5c687ee2f56cb76c6d5607028 Mon Sep 17 00:00:00 2001 From: Tyrel Chambers Date: Wed, 19 Nov 2025 13:41:24 -0500 Subject: [PATCH 3/6] styling --- .../ChangelogSnippet/ChangelogCard.astro | 21 ++- src/pages/changelog/[...id].astro | 144 +++++++++++++----- 2 files changed, 129 insertions(+), 36 deletions(-) diff --git a/src/components/ChangelogSnippet/ChangelogCard.astro b/src/components/ChangelogSnippet/ChangelogCard.astro index 2e36501f5b9..cf0f6242cab 100644 --- a/src/components/ChangelogSnippet/ChangelogCard.astro +++ b/src/components/ChangelogSnippet/ChangelogCard.astro @@ -8,9 +8,10 @@ import CopyButton from "./CopyButton.tsx" interface Props { item: ChangelogItem showBorder?: boolean + autoExpand?: boolean } -const { item, showBorder = true } = Astro.props +const { item, showBorder = true, autoExpand = false } = Astro.props // Format the date const formatDate = (dateString: string) => { @@ -25,7 +26,11 @@ const formatDate = (dateString: string) => { const formattedDate = formatDate(item["date-of-release"]) --- -
+
@@ -117,6 +122,18 @@ const formattedDate = formatDate(item["date-of-release"]) if (!card || !content || !button) return + // Check if auto-expand is enabled + const autoExpand = (wrapper as HTMLElement).dataset.autoExpand === "true" + + if (autoExpand) { + // Auto-expand: set to full height and hide footer + ;(wrapper as HTMLElement).style.maxHeight = "none" + wrapper.classList.add("expanded") + footer.style.opacity = "0" + footer.style.pointerEvents = "none" + return // Skip the rest of the logic + } + // Wait for images to load before checking height const images = card.querySelectorAll("img") let loadedImages = 0 diff --git a/src/pages/changelog/[...id].astro b/src/pages/changelog/[...id].astro index 346768182ee..073966b1283 100644 --- a/src/pages/changelog/[...id].astro +++ b/src/pages/changelog/[...id].astro @@ -2,51 +2,127 @@ import BaseLayout from "~/layouts/BaseLayout.astro" import * as CONFIG from "../../config" import { getSecret } from "astro:env/server" -import { searchClient, SearchClient } from "@algolia/client-search" +import { searchClient } from "@algolia/client-search" import { ChangelogItem } from "~/components/ChangelogSnippet/types" +import ChangelogCard from "~/components/ChangelogSnippet/ChangelogCard.astro" +import { SvgArrowLeft, SvgArrowLeft2, SvgTaillessArrowLeftSmall, Typography } from "@chainlink/blocks" -export const prerender = false +export async function getStaticPaths() { + const appId = getSecret("ALGOLIA_APP_ID") + const apiKey = getSecret("PUBLIC_ALGOLIA_SEARCH_PUBLIC_API_KEY") -const { id } = Astro.params + // Return empty array if credentials are not available (CI/CD environments) + if (!appId || !apiKey) { + console.warn("Algolia credentials not available, skipping changelog static generation") + return [] + } -console.log(id) + const client = searchClient(appId, apiKey) -const appId = getSecret("ALGOLIA_APP_ID") -const apiKey = getSecret("PUBLIC_ALGOLIA_SEARCH_PUBLIC_API_KEY") + try { + // Fetch all changelog items from Algolia + const req = await client.search({ + requests: [ + { + indexName: "Changelog", + hitsPerPage: 1000, // Adjust based on expected total number of changelog items + }, + ], + }) -let client: SearchClient -let latestLog: ChangelogItem | undefined = undefined + console.log(req) + const firstResult = req.results[0] + const logs = "hits" in firstResult ? (firstResult.hits as ChangelogItem[]) : [] -// Initialize client if appId and apiKey are available to avoid needing to update -// the github actions with the new keys (satisfies linkcheck-internal) -if (appId && apiKey) { - client = searchClient(appId, apiKey) - - const req = await client.search({ - requests: [ - { - indexName: "Changelog", - restrictSearchableAttributes: ["slug"], - query: id, - hitsPerPage: 1, - }, - ], - }) - - console.log(req) - - const firstResult = req.results[0] - const results = "hits" in firstResult ? (firstResult.hits as ChangelogItem[]) : [] + // Generate static paths for each changelog item + return logs.map((log) => ({ + params: { id: log.slug }, + props: { log }, + })) + } catch (error) { + console.error("Error fetching changelog items:", error) + return [] + } +} - // logs are returned sorted by created_at DESC - latestLog = results[0] +interface Props { + log: ChangelogItem } -console.log(latestLog) +const { log } = Astro.props -const formattedContentTitle = `Changelog and Releases | ${CONFIG.SITE.title}` +const pageTitle = `Changelog and Releases | ${CONFIG.SITE.title}` --- - -
+ +
+
+ + + Back to Changelog + + + Integration +
+ +
+ +
+
+ + From 7dec2c2c956fb1da49cca20645dd74929a80d035 Mon Sep 17 00:00:00 2001 From: Tyrel Chambers Date: Wed, 19 Nov 2025 13:51:47 -0500 Subject: [PATCH 4/6] make individual page for changelog item --- .../ChangelogSnippet/ChangelogCard.astro | 24 ++++++++- src/components/ChangelogSnippet/README.md | 51 +++++++++++++++++++ src/pages/changelog/[...id].astro | 2 +- 3 files changed, 74 insertions(+), 3 deletions(-) diff --git a/src/components/ChangelogSnippet/ChangelogCard.astro b/src/components/ChangelogSnippet/ChangelogCard.astro index cf0f6242cab..f53563a7a4c 100644 --- a/src/components/ChangelogSnippet/ChangelogCard.astro +++ b/src/components/ChangelogSnippet/ChangelogCard.astro @@ -9,9 +9,11 @@ interface Props { item: ChangelogItem showBorder?: boolean autoExpand?: boolean + showCopyButton?: boolean + disableHover?: boolean } -const { item, showBorder = true, autoExpand = false } = Astro.props +const { item, showBorder = true, autoExpand = false, showCopyButton = true, disableHover = false } = Astro.props // Format the date const formatDate = (dateString: string) => { @@ -30,6 +32,7 @@ const formattedDate = formatDate(item["date-of-release"]) class={clsx(styles.cardWrapper, showBorder && styles.withBorder)} data-expandable="wrapper" data-auto-expand={autoExpand} + data-disable-hover={disableHover} >
@@ -58,7 +61,7 @@ const formattedDate = formatDate(item["date-of-release"])
- + {showCopyButton && }
@@ -332,4 +335,21 @@ const formattedDate = formatDate(item["date-of-release"]) .log-item__list-chains .hidden { display: none; } + + /* Disable hover effects when data-disable-hover is true */ + [data-disable-hover="true"]:hover { + background-color: transparent !important; + } + + [data-disable-hover="true"]:hover .copyButton { + opacity: 0 !important; + } + + [data-disable-hover="true"].withBorder:hover { + background-color: transparent !important; + } + + [data-disable-hover="true"].withBorder:hover .contentFooter { + background: none !important; + } diff --git a/src/components/ChangelogSnippet/README.md b/src/components/ChangelogSnippet/README.md index c594abf7bf2..484eb334cd8 100644 --- a/src/components/ChangelogSnippet/README.md +++ b/src/components/ChangelogSnippet/README.md @@ -40,3 +40,54 @@ import ChangelogSnippet from "@components/ChangelogSnippet/ChangelogSnippet.astr ``` This will display the latest CCIP-related changelog entry with a link to view the full changelog. + +--- + +# ChangelogCard Component + +## What This Component Does + +The ChangelogCard component displays a single changelog item in a card format. It shows the changelog entry's type, date, title, and description with optional expand/collapse functionality. + +## How to Use It + +Import the component and pass a changelog item: + +```astro +import ChangelogCard from "@components/ChangelogSnippet/ChangelogCard.astro" import type {ChangelogItem} from "@components/ChangelogSnippet/types" +const item: ChangelogItem = { + // ... changelog item data +} + + +``` + +## Props + +| Prop | Type | Required | Default | Description | +| ---------------- | ------------- | -------- | ------- | -------------------------------------------------------------------------------------------------------------------- | +| `item` | ChangelogItem | Yes | - | The changelog item to display | +| `showBorder` | boolean | No | `true` | Whether to show a border around the card | +| `autoExpand` | boolean | No | `false` | Whether to automatically expand the card to full height (skips height restrictions and hides expand/collapse button) | +| `showCopyButton` | boolean | No | `true` | Whether to show the "Copy URL" button | +| `disableHover` | boolean | No | `false` | Whether to disable hover effects (background color change) | + +## Usage Examples + +### Default Card (with border and interactions) + +```astro + +``` + +### Card without border (like on main changelog page) + +```astro + +``` + +### Fully expanded card without interactions (like on individual pages) + +```astro + +``` diff --git a/src/pages/changelog/[...id].astro b/src/pages/changelog/[...id].astro index 073966b1283..728f9cdc588 100644 --- a/src/pages/changelog/[...id].astro +++ b/src/pages/changelog/[...id].astro @@ -66,7 +66,7 @@ const pageTitle = `Changelog and Releases | ${CONFIG.SITE.title}`
- +
From ce7d5d072ee36bed4f190d8f41eb863a0d03a1ca Mon Sep 17 00:00:00 2001 From: Tyrel Chambers Date: Wed, 19 Nov 2025 14:33:53 -0500 Subject: [PATCH 5/6] add pagination --- src/pages/changelog/[...id].astro | 49 +++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/src/pages/changelog/[...id].astro b/src/pages/changelog/[...id].astro index 728f9cdc588..d9dad29635c 100644 --- a/src/pages/changelog/[...id].astro +++ b/src/pages/changelog/[...id].astro @@ -5,7 +5,7 @@ import { getSecret } from "astro:env/server" import { searchClient } from "@algolia/client-search" import { ChangelogItem } from "~/components/ChangelogSnippet/types" import ChangelogCard from "~/components/ChangelogSnippet/ChangelogCard.astro" -import { SvgArrowLeft, SvgArrowLeft2, SvgTaillessArrowLeftSmall, Typography } from "@chainlink/blocks" +import { SvgArrowLeft2, Typography } from "@chainlink/blocks" export async function getStaticPaths() { const appId = getSecret("ALGOLIA_APP_ID") @@ -20,22 +20,41 @@ export async function getStaticPaths() { const client = searchClient(appId, apiKey) try { - // Fetch all changelog items from Algolia - const req = await client.search({ - requests: [ - { - indexName: "Changelog", - hitsPerPage: 1000, // Adjust based on expected total number of changelog items - }, - ], - }) - - console.log(req) - const firstResult = req.results[0] - const logs = "hits" in firstResult ? (firstResult.hits as ChangelogItem[]) : [] + const records: ChangelogItem[] = [] + let currentPage = 0 + let nbPages = 1 + const hitsPerPage = 1000 // Maximum allowed by Algolia + + // Fetch all changelog items from Algolia with pagination + while (currentPage < nbPages) { + const req = await client.search({ + requests: [ + { + indexName: "Changelog", + hitsPerPage, + page: currentPage, + }, + ], + }) + + const firstResult = req.results[0] + + if ("hits" in firstResult) { + // Add hits from current page to records + const hits = firstResult.hits as ChangelogItem[] + records.push(...hits) + + // Update nbPages from the response + if ("nbPages" in firstResult) { + nbPages = firstResult.nbPages as number + } + } + + currentPage++ + } // Generate static paths for each changelog item - return logs.map((log) => ({ + return records.map((log) => ({ params: { id: log.slug }, props: { log }, })) From bf8dc2c9d31e07d6f7a48943042f8a90a6252bdb Mon Sep 17 00:00:00 2001 From: Tyrel Chambers Date: Wed, 19 Nov 2025 14:50:48 -0500 Subject: [PATCH 6/6] Update [...id].astro --- src/pages/changelog/[...id].astro | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/changelog/[...id].astro b/src/pages/changelog/[...id].astro index d9dad29635c..f5e2b5d7eb6 100644 --- a/src/pages/changelog/[...id].astro +++ b/src/pages/changelog/[...id].astro @@ -99,8 +99,8 @@ const pageTitle = `Changelog and Releases | ${CONFIG.SITE.title}` } .changelog-header { - margin-bottom: var(--space-6x); - padding: 0 var(--space-8x); + margin-bottom: var(--space-8x); + padding: 0 var(--space-6x); } .back-link {