Skip to content

Commit b53ab8c

Browse files
Merge pull request #153 from thisdot/feat/155-changelog-item-page
Feat/155 changelog item page
2 parents b97ed64 + bf8dc2c commit b53ab8c

File tree

6 files changed

+369
-6
lines changed

6 files changed

+369
-6
lines changed

src/components/ChangelogSnippet/ChangelogCard.astro

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,17 @@ import { SvgTaillessArrowDownSmall, Typography } from "@chainlink/blocks"
33
import styles from "./ChangelogCard.module.css"
44
import type { ChangelogItem } from "./types"
55
import { clsx } from "~/lib/clsx/clsx"
6+
import CopyButton from "./CopyButton.tsx"
67
78
interface Props {
89
item: ChangelogItem
910
showBorder?: boolean
11+
autoExpand?: boolean
12+
showCopyButton?: boolean
13+
disableHover?: boolean
1014
}
1115
12-
const { item, showBorder = true } = Astro.props
16+
const { item, showBorder = true, autoExpand = false, showCopyButton = true, disableHover = false } = Astro.props
1317
1418
// Format the date
1519
const formatDate = (dateString: string) => {
@@ -24,7 +28,12 @@ const formatDate = (dateString: string) => {
2428
const formattedDate = formatDate(item["date-of-release"])
2529
---
2630

27-
<div class={clsx(styles.cardWrapper, showBorder && styles.withBorder)} data-expandable="wrapper">
31+
<div
32+
class={clsx(styles.cardWrapper, showBorder && styles.withBorder)}
33+
data-expandable="wrapper"
34+
data-auto-expand={autoExpand}
35+
data-disable-hover={disableHover}
36+
>
2837
<div class={styles.card} data-expandable="card">
2938
<div class={styles.header}>
3039
<div class={styles.metaSection}>
@@ -51,6 +60,8 @@ const formattedDate = formatDate(item["date-of-release"])
5160
{item["text-description"] && <div class={styles.description} set:html={item["text-description"]} />}
5261
</div>
5362
</div>
63+
64+
{showCopyButton && <CopyButton client:only="react" url={item.slug} />}
5465
</div>
5566

5667
<div class={styles.contentFooter} data-expandable="footer">
@@ -114,6 +125,18 @@ const formattedDate = formatDate(item["date-of-release"])
114125

115126
if (!card || !content || !button) return
116127

128+
// Check if auto-expand is enabled
129+
const autoExpand = (wrapper as HTMLElement).dataset.autoExpand === "true"
130+
131+
if (autoExpand) {
132+
// Auto-expand: set to full height and hide footer
133+
;(wrapper as HTMLElement).style.maxHeight = "none"
134+
wrapper.classList.add("expanded")
135+
footer.style.opacity = "0"
136+
footer.style.pointerEvents = "none"
137+
return // Skip the rest of the logic
138+
}
139+
117140
// Wait for images to load before checking height
118141
const images = card.querySelectorAll("img")
119142
let loadedImages = 0
@@ -312,4 +335,21 @@ const formattedDate = formatDate(item["date-of-release"])
312335
.log-item__list-chains .hidden {
313336
display: none;
314337
}
338+
339+
/* Disable hover effects when data-disable-hover is true */
340+
[data-disable-hover="true"]:hover {
341+
background-color: transparent !important;
342+
}
343+
344+
[data-disable-hover="true"]:hover .copyButton {
345+
opacity: 0 !important;
346+
}
347+
348+
[data-disable-hover="true"].withBorder:hover {
349+
background-color: transparent !important;
350+
}
351+
352+
[data-disable-hover="true"].withBorder:hover .contentFooter {
353+
background: none !important;
354+
}
315355
</style>

src/components/ChangelogSnippet/ChangelogCard.module.css

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@
99
background-color: var(--gray-50);
1010
}
1111

12+
&:hover .copyButton {
13+
opacity: 1;
14+
}
15+
1216
& .card {
1317
padding: var(--space-6x);
1418
}
@@ -132,11 +136,40 @@
132136
transition: transform 0.3s ease;
133137
}
134138

135-
@media screen and (max-width: 425px) {
136-
.card {
137-
flex-direction: column;
139+
.copyButton {
140+
display: flex;
141+
height: fit-content;
142+
gap: var(--space-2x);
143+
border-radius: var(--space-1x);
144+
border: 1px solid var(--border);
145+
width: 118px;
146+
justify-content: center;
147+
align-items: center;
148+
padding: var(--space-2x) 0;
149+
transition: all 0.2s ease;
150+
opacity: 0;
151+
152+
& > svg {
153+
color: var(--muted-foreground);
154+
}
155+
156+
&:hover {
157+
border: 1px solid var(--foreground);
138158
}
159+
}
139160

161+
.checkmark {
162+
stroke: var(--success-foreground);
163+
}
164+
.copyIconMobile {
165+
display: none;
166+
}
167+
168+
.copyIconDesktop {
169+
display: block;
170+
}
171+
172+
@media screen and (max-width: 425px) {
140173
.changelogType {
141174
font-size: 14px;
142175
}
@@ -150,6 +183,7 @@
150183
.card {
151184
padding: var(--space-4x);
152185
gap: var(--space-4x);
186+
flex-direction: column;
153187
}
154188

155189
.header {
@@ -172,4 +206,27 @@
172206
.contentFooter {
173207
padding-left: var(--space-4x);
174208
}
209+
210+
.copyIconDesktop {
211+
display: none;
212+
}
213+
214+
.copyIconMobile {
215+
display: block;
216+
}
217+
.copyText {
218+
display: none;
219+
}
220+
221+
.copyButton {
222+
width: 32px;
223+
}
224+
}
225+
226+
@media screen and (max-width: 990px) {
227+
.copyButton {
228+
position: absolute;
229+
right: var(--space-4x);
230+
top: var(--space-4x);
231+
}
175232
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import { SvgCopy, Typography } from "@chainlink/blocks"
2+
import styles from "./ChangelogCard.module.css"
3+
import { useState } from "react"
4+
5+
export default function CopyButton({ url }: { url: string }) {
6+
const [isCopied, setIsCopied] = useState(false)
7+
8+
const copyToClipboard = () => {
9+
const mode = import.meta.env.MODE === "development" ? "http://localhost:4321" : "https://dev.chain.link"
10+
navigator.clipboard.writeText(`${mode}/changelog/${url}`)
11+
setIsCopied(true)
12+
setTimeout(() => setIsCopied(false), 2000)
13+
}
14+
15+
return (
16+
<button className={styles.copyButton} onClick={copyToClipboard}>
17+
{isCopied ? (
18+
<>
19+
<svg
20+
xmlns="http://www.w3.org/2000/svg"
21+
width="16"
22+
height="16"
23+
viewBox="0 0 24 24"
24+
fill="none"
25+
stroke-width="2"
26+
stroke-linecap="round"
27+
stroke-linejoin="round"
28+
className={styles.checkmark}
29+
>
30+
<path d="M20 6 9 17l-5-5" />
31+
</svg>
32+
<Typography color="success" variant="body-xs" className={styles.copyText}>
33+
Copied
34+
</Typography>
35+
</>
36+
) : (
37+
<>
38+
<SvgCopy
39+
style={{
40+
width: "13px",
41+
height: "12px",
42+
}}
43+
className={styles.copyIconDesktop}
44+
/>
45+
<svg
46+
xmlns="http://www.w3.org/2000/svg"
47+
width="16"
48+
height="16"
49+
viewBox="0 0 24 24"
50+
fill="none"
51+
stroke="currentColor"
52+
stroke-width="2"
53+
stroke-linecap="round"
54+
stroke-linejoin="round"
55+
className={styles.copyIconMobile}
56+
>
57+
<path d="M12 3v12" />
58+
<path d="m17 8-5-5-5 5" />
59+
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
60+
</svg>
61+
<Typography color="muted" variant="body-xs" className={styles.copyText}>
62+
Copy URL
63+
</Typography>
64+
</>
65+
)}
66+
</button>
67+
)
68+
}

src/components/ChangelogSnippet/README.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,54 @@ import ChangelogSnippet from "@components/ChangelogSnippet/ChangelogSnippet.astr
4040
```
4141

4242
This will display the latest CCIP-related changelog entry with a link to view the full changelog.
43+
44+
---
45+
46+
# ChangelogCard Component
47+
48+
## What This Component Does
49+
50+
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.
51+
52+
## How to Use It
53+
54+
Import the component and pass a changelog item:
55+
56+
```astro
57+
import ChangelogCard from "@components/ChangelogSnippet/ChangelogCard.astro" import type {ChangelogItem} from "@components/ChangelogSnippet/types"
58+
const item: ChangelogItem = {
59+
// ... changelog item data
60+
}
61+
62+
<ChangelogCard item={item} />
63+
```
64+
65+
## Props
66+
67+
| Prop | Type | Required | Default | Description |
68+
| ---------------- | ------------- | -------- | ------- | -------------------------------------------------------------------------------------------------------------------- |
69+
| `item` | ChangelogItem | Yes | - | The changelog item to display |
70+
| `showBorder` | boolean | No | `true` | Whether to show a border around the card |
71+
| `autoExpand` | boolean | No | `false` | Whether to automatically expand the card to full height (skips height restrictions and hides expand/collapse button) |
72+
| `showCopyButton` | boolean | No | `true` | Whether to show the "Copy URL" button |
73+
| `disableHover` | boolean | No | `false` | Whether to disable hover effects (background color change) |
74+
75+
## Usage Examples
76+
77+
### Default Card (with border and interactions)
78+
79+
```astro
80+
<ChangelogCard item={changelogItem} />
81+
```
82+
83+
### Card without border (like on main changelog page)
84+
85+
```astro
86+
<ChangelogCard item={changelogItem} showBorder={false} />
87+
```
88+
89+
### Fully expanded card without interactions (like on individual pages)
90+
91+
```astro
92+
<ChangelogCard item={changelogItem} showBorder={false} autoExpand={true} showCopyButton={false} disableHover={true} />
93+
```

0 commit comments

Comments
 (0)