Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions public/assets/icons/add.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
42 changes: 42 additions & 0 deletions src/components/CCIP/AddButton/AddButton.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
export interface Props {
href: string
text: string
}

const { href, text } = Astro.props
---

<a class="add-button" href={href}>
<img src="/assets/icons/add.svg" alt="Add" class="add-button-icon" />
{text}
</a>

<style>
.add-button {
display: inline-flex;
align-items: center;
gap: var(--space-2x);
padding: var(--space-2x) var(--space-4x);
border: 1px solid var(--tertiary-border);
border-radius: var(--space-1x);
font-family: "Inter", sans-serif;
font-size: var(--space-3x);
font-weight: 600;
line-height: var(--space-4x);
color: var(--tertiary-foreground);
text-decoration: none;
background-color: transparent;
transition: all 0.2s ease;
}

.add-button:hover {
background-color: var(--gray-100);
border-color: var(--gray-400);
}

.add-button-icon {
width: var(--space-3x);
height: var(--space-3x);
}
</style>
40 changes: 40 additions & 0 deletions src/components/CCIP/Cards/Card.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
.card__container {
display: flex;
padding: var(--space-6x);
gap: var(--space-3x);
width: 100%;
background: var(--white);
border: 1px solid var(--gray-200);
border-radius: var(--space-1x);
/* Optimize rendering performance */
contain: layout style paint;
will-change: background-color;
}

.card__container:hover {
background-color: var(--gray-50);
}

.card__container img,
.card__container object,
.card__container object img {
width: var(--space-10x);
height: var(--space-10x);
margin-top: auto;
margin-bottom: auto;
}

.card__container h3 {
font-size: var(--space-4x);
font-weight: var(--font-weight-medium);
line-height: var(--space-6x);
color: var(--gray-950);
margin-bottom: var(--space-1x);
}

.card__container p {
margin-bottom: 0;
font-size: var(--space-3x);
line-height: var(--space-5x);
color: var(--gray-500);
}
43 changes: 43 additions & 0 deletions src/components/CCIP/Cards/Card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { memo, type ReactNode } from "react"
import "./Card.css"

interface CardProps {
logo: ReactNode
title: string
subtitle?: string
link?: string
onClick?: () => void
ariaLabel?: string
}

const Card = memo(function Card({ logo, title, subtitle, link, onClick, ariaLabel }: CardProps) {
const content = (
<>
{logo}
<div>
<h3>{title}</h3>
{subtitle && <p>{subtitle}</p>}
</div>
</>
)

if (link) {
return (
<a href={link} aria-label={ariaLabel}>
<div className="card__container">{content}</div>
</a>
)
}

if (onClick) {
return (
<button type="button" className="card__container" onClick={onClick} aria-label={ariaLabel || title}>
{content}
</button>
)
}

return <div className="card__container">{content}</div>
})

export default Card
16 changes: 4 additions & 12 deletions src/components/CCIP/Cards/NetworkCard.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { memo } from "react"
import "./NetworkCard.css"
import Card from "./Card.tsx"

interface NetworkCardProps {
name: string
Expand All @@ -9,17 +9,9 @@ interface NetworkCardProps {
}

const NetworkCard = memo(function NetworkCard({ name, totalLanes, totalTokens, logo }: NetworkCardProps) {
return (
<div className="network-card__container">
<img src={logo} alt="" loading="lazy" />
<div>
<h3>{name}</h3>
<p>
{totalLanes} {totalLanes > 1 ? "lanes" : "lane"} | {totalTokens} {totalTokens > 1 ? "tokens" : "token"}
</p>
</div>
</div>
)
const subtitle = `${totalLanes} ${totalLanes === 1 ? "lane" : "lanes"} | ${totalTokens} ${totalTokens === 1 ? "token" : "tokens"}`

return <Card logo={<img src={logo} alt="" loading="lazy" />} title={name} subtitle={subtitle} />
})

export default NetworkCard
26 changes: 14 additions & 12 deletions src/components/CCIP/Cards/TokenCard.css
Original file line number Diff line number Diff line change
@@ -1,19 +1,11 @@
.token-card__container {
display: flex;
width: 100%;
height: 110px;
min-width: 110px;
margin: 0 auto;
flex-direction: column;
align-items: center;
text-align: center;
padding: var(--space-4x);
padding: var(--space-6x);
gap: var(--space-3x);
background: #ffffff;
width: 100%;
background: var(--white);
border: 1px solid var(--gray-200);
border-radius: var(--space-1x);
justify-content: center;
cursor: pointer;
/* Optimize rendering performance */
contain: layout style paint;
will-change: background-color;
Expand All @@ -27,14 +19,24 @@
.token-card__container object img {
width: var(--space-10x);
height: var(--space-10x);
margin-top: auto;
margin-bottom: auto;
border-radius: 50%;
}

.token-card__container h3 {
font-size: var(--space-4x);
font-weight: 500;
font-weight: var(--font-weight-medium);
line-height: var(--space-6x);
color: var(--gray-950);
margin-bottom: var(--space-1x);
}

.token-card__container p {
margin-bottom: 0;
font-size: var(--space-3x);
line-height: var(--space-5x);
color: var(--gray-500);
}

.truncate {
Expand Down
49 changes: 18 additions & 31 deletions src/components/CCIP/Cards/TokenCard.tsx
Original file line number Diff line number Diff line change
@@ -1,48 +1,35 @@
import { memo } from "react"
import { fallbackTokenIconUrl } from "~/features/utils/index.ts"
import Card from "./Card.tsx"
import "./TokenCard.css"

interface TokenCardProps {
id: string
logo?: string
link?: string
onClick?: () => void
totalNetworks?: number
}

const TokenCard = memo(function TokenCard({ id, logo, link, onClick }: TokenCardProps) {
if (link) {
return (
<a href={link}>
<div className="token-card__container">
{/* We cannot use the normal Image/onError syntax as a fallback as the element is server rendered
and the onerror does not seem to work correctly. Using Picture will also not work. */}
<object data={logo} type="image/png" aria-label={`${id} token logo`}>
<img src={fallbackTokenIconUrl} alt={`${id} token logo`} loading="lazy" />
</object>
<h3>{id}</h3>
</div>
</a>
)
}
const TokenCard = memo(function TokenCard({ id, logo, link, onClick, totalNetworks }: TokenCardProps) {
const logoElement = (
<object data={logo} type="image/png" aria-label={`${id} token logo`}>
<img src={fallbackTokenIconUrl} alt={`${id} token logo`} loading="lazy" />
</object>
)

if (onClick) {
return (
<button type="button" className="token-card__container" onClick={onClick} aria-label={`View ${id} token details`}>
<object data={logo} type="image/png" aria-label={`${id} token logo`}>
<img src={fallbackTokenIconUrl} alt={`${id} token logo`} loading="lazy" />
</object>
<h3>{id}</h3>
</button>
)
}
const subtitle =
totalNetworks !== undefined ? `${totalNetworks} ${totalNetworks === 1 ? "network" : "networks"}` : undefined

return (
<div className="token-card__container">
<object data={logo} type="image/png">
<img src={fallbackTokenIconUrl} alt="" loading="lazy" />
</object>
<h3>{id}</h3>
</div>
<Card
logo={logoElement}
title={id}
subtitle={subtitle}
link={link}
onClick={onClick}
ariaLabel={`View ${id} token details`}
/>
)
})

Expand Down
10 changes: 2 additions & 8 deletions src/components/CCIP/Chain/Chain.astro
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import ChainTokenGrid from "./ChainTokenGrid"
import { generateChainStructuredData } from "~/utils/ccipStructuredData"
import StructuredData from "~/components/StructuredData.astro"
import { DOCS_BASE_URL } from "~/utils/structuredData"
import AddButton from "~/components/CCIP/AddButton/AddButton.astro"

interface Props {
environment: Environment
Expand Down Expand Up @@ -128,14 +129,7 @@ const chainStructuredData = generateChainStructuredData(
<h2>Tokens <span>({allTokens.length})</span></h2>
{
network.chainType !== "solana" && network.chainType !== "aptos" && (
<a class="button secondary" href="/ccip/tutorials/evm/token-manager#verifying-your-token">
<img
src="/assets/icons/plus.svg"
alt="Add"
style={{ width: "1em", height: "1em", marginRight: "0.5em", verticalAlign: "middle" }}
/>
Add my token
</a>
<AddButton href="/ccip/tutorials/evm/token-manager#verifying-your-token" text="Add my token" />
)
}
</div>
Expand Down
12 changes: 12 additions & 0 deletions src/components/CCIP/Landing/Grid.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.grid {
display: grid;
grid-template-columns: 1fr;
gap: var(--space-2x);
}

@media (min-width: 992px) {
.grid {
grid-template-columns: 1fr 1fr 1fr 1fr;
gap: var(--space-4x);
}
}
27 changes: 27 additions & 0 deletions src/components/CCIP/Landing/Grid.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { useState, type ReactNode } from "react"
import SeeMore from "../SeeMore/SeeMore.tsx"
import "./Grid.css"

interface GridProps {
items: any[]

Check warning on line 6 in src/components/CCIP/Landing/Grid.tsx

View workflow job for this annotation

GitHub Actions / eslint

Unexpected any. Specify a different type

Check warning on line 6 in src/components/CCIP/Landing/Grid.tsx

View workflow job for this annotation

GitHub Actions / eslint

Unexpected any. Specify a different type
renderItem: (item: any, index: number) => ReactNode

Check warning on line 7 in src/components/CCIP/Landing/Grid.tsx

View workflow job for this annotation

GitHub Actions / eslint

Unexpected any. Specify a different type

Check warning on line 7 in src/components/CCIP/Landing/Grid.tsx

View workflow job for this annotation

GitHub Actions / eslint

Unexpected any. Specify a different type
initialDisplayCount: number
seeMoreLabel: string
className?: string
seeMoreLink?: string
}

function Grid({ items, renderItem, initialDisplayCount, seeMoreLabel, className = "grid", seeMoreLink }: GridProps) {
const [seeMore, setSeeMore] = useState(items.length <= initialDisplayCount)

return (
<>
<div className={className}>
{items.slice(0, seeMore ? items.length : initialDisplayCount).map((item, index) => renderItem(item, index))}
</div>
{!seeMore && <SeeMore onClick={() => setSeeMore(!seeMore)} label={seeMoreLabel} href={seeMoreLink} />}
</>
)
}

export default Grid
2 changes: 1 addition & 1 deletion src/components/CCIP/Landing/NetworkGrid.css
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

@media (min-width: 992px) {
.networks__grid {
grid-template-columns: 1fr 1fr;
grid-template-columns: 1fr 1fr 1fr 1fr;
gap: var(--space-6x);
}
}
Loading
Loading