Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add copyable behavior to links/addresses in blob, block and transaction tables #622

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
5 changes: 5 additions & 0 deletions .changeset/tricky-yaks-bake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@blobscan/web": minor
---

Added copyable behavior to hashes and addresses in blob, block and transaction tables.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type { FC } from "react";
import { ArrowRightIcon, ChevronDownIcon } from "@heroicons/react/24/outline";

import { Collapsable } from "~/components/Collapsable";
import { Copyable } from "~/components/Copyable";
import { EtherUnitDisplay } from "~/components/Displays/EtherUnitDisplay";
import { IconButton } from "~/components/IconButton";
import { RollupIcon } from "~/components/RollupIcon";
Expand Down Expand Up @@ -219,9 +220,10 @@ const BlobTransactionCard: FC<BlobTransactionCardProps> = function ({
<React.Fragment key={`${versionedHash}-${index}`}>
<TableCol>{index}</TableCol>
<TableCol>
<Link href={buildBlobRoute(versionedHash)}>
{versionedHash}
</Link>
<Copyable
href={buildBlobRoute(versionedHash)}
value={versionedHash}
/>
</TableCol>
<TableCol>{formatBytes(size)}</TableCol>
</React.Fragment>
Expand Down
28 changes: 11 additions & 17 deletions apps/web/src/components/CopyToClipboard.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import type { FC } from "react";
import { useState } from "react";
import { CheckIcon } from "@heroicons/react/24/outline";

import Copy from "~/icons/copy.svg";
import { Tooltip, TooltipContent, TooltipTrigger } from "./Tooltip";

type CopyToClipboardProps = {
label?: string;
tooltipText?: string;
value: string;
};

export function CopyToClipboard({
label = "Copy to clipboard",
export const CopyToClipboard: FC<CopyToClipboardProps> = ({
tooltipText,
value,
}: CopyToClipboardProps) {
}) => {
const [isCopied, setIsCopied] = useState(false);

return (
Expand All @@ -23,7 +24,9 @@ export function CopyToClipboard({
}
}}
>
<TooltipContent>{isCopied ? "Copied!" : label}</TooltipContent>
{(tooltipText || isCopied) && (
<TooltipContent>{isCopied ? "Copied!" : tooltipText}</TooltipContent>
)}
<TooltipTrigger
className="text-contentTertiary-light hover:text-link-light dark:text-contentTertiary-dark dark:hover:text-link-dark"
onClick={async () => {
Expand All @@ -36,20 +39,11 @@ export function CopyToClipboard({
}}
>
{isCopied ? (
<CheckIcon className="h-5 w-5" />
<CheckIcon className="h-4 w-4" />
) : (
<Copy className="h-5 w-5" />
<Copy className="h-4 w-4" />
)}
</TooltipTrigger>
</Tooltip>
);
}

export function Copyable({ label, value }: CopyToClipboardProps) {
return (
<div className="flex items-center gap-2">
<div className="truncate">{value}</div>
<CopyToClipboard value={value} label={label} />
</div>
);
}
};
30 changes: 30 additions & 0 deletions apps/web/src/components/Copyable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import type { FC } from "react";
import React from "react";

import { CopyToClipboard } from "./CopyToClipboard";
import { Link } from "./Link";

export interface CopyableProps {
href?: string;
value: string;
tooltipText?: string;
children?: React.ReactNode;
}

export const Copyable: FC<CopyableProps> = ({
href,
value,
tooltipText,
children,
}) => {
return (
<div className="flex items-center gap-1" title={value}>
{href ? (
<Link href={href}>{children || value}</Link>
) : (
<div className="truncate">{children || value}</div>
)}
<CopyToClipboard value={value} tooltipText={tooltipText} />
</div>
);
};
16 changes: 11 additions & 5 deletions apps/web/src/pages/blob/[hash].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import { StorageBadge } from "~/components/Badges/StorageBadge";
import { BlobViewer, DEFAULT_BLOB_VIEW_MODES } from "~/components/BlobViewer";
import type { BlobViewMode } from "~/components/BlobViewer";
import { Card } from "~/components/Cards/Card";
import { Copyable, CopyToClipboard } from "~/components/CopyToClipboard";
import { CopyToClipboard } from "~/components/CopyToClipboard";
import { Copyable } from "~/components/Copyable";
import { Dropdown } from "~/components/Dropdown";
import type { DropdownProps } from "~/components/Dropdown";
import type { DetailsLayoutProps } from "~/components/Layouts/DetailsLayout";
Expand Down Expand Up @@ -110,11 +111,13 @@ const Blob: NextPage = function () {
detailsFields.push(
{
name: "Commitment",
value: <Copyable value={blob.commitment} label="Copy commitment" />,
value: (
<Copyable value={blob.commitment} tooltipText="Copy commitment" />
),
},
{
name: "Proof",
value: <Copyable value={blob.proof} label="Copy proof" />,
value: <Copyable value={blob.proof} tooltipText="Copy proof" />,
}
);

Expand Down Expand Up @@ -148,7 +151,7 @@ const Blob: NextPage = function () {
title={txHash}
>
{<Link href={buildTransactionRoute(txHash)}>{txHash}</Link>}
<CopyToClipboard value={txHash} label="Copy tx hash" />
<CopyToClipboard value={txHash} tooltipText="Copy tx hash" />
</div>
</div>
<div className="flex gap-1">
Expand Down Expand Up @@ -176,7 +179,10 @@ const Blob: NextPage = function () {
<div>Blob Data</div>
{blob && (
<div className="flex items-center gap-4">
<CopyToClipboard label="Copy blob data" value={blob.data} />
<CopyToClipboard
tooltipText="Copy blob data"
value={blob.data}
/>
<div className="flex items-center gap-2">
<div className="text-sm font-normal text-contentSecondary-light dark:text-contentSecondary-dark">
View as:
Expand Down
24 changes: 20 additions & 4 deletions apps/web/src/pages/blobs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { useMemo } from "react";
import type { NextPage } from "next";
import NextError from "next/error";

import { Copyable } from "~/components/Copyable";
import { Filters } from "~/components/Filters";
import { Header } from "~/components/Header";
import { Link } from "~/components/Link";
Expand Down Expand Up @@ -39,6 +40,10 @@ const BLOBS_TABLE_HEADERS = [
item: "Timestamp",
className: "2xl:w-[185px] xl:w-[160px] lg:w-[127px] w-[100px]",
},
{
item: "Category",
className: "w-[60px]",
},
{
item: "Size",
className: "2xl:w-[178px] xl:w-[145px] lg:w-[101px] w-[66px]",
Expand Down Expand Up @@ -87,16 +92,24 @@ const Blobs: NextPage = function () {
cells: [
{
item: (
<Link href={buildBlobRoute(versionedHash)}>
<Copyable
href={buildBlobRoute(versionedHash)}
value={versionedHash}
tooltipText="Copy versioned hash"
>
{shortenAddress(versionedHash, 8)}
</Link>
</Copyable>
),
},
{
item: (
<Link href={buildTransactionRoute(txHash)}>
<Copyable
href={buildTransactionRoute(txHash)}
value={txHash}
tooltipText="Copy transaction hash"
>
{shortenAddress(txHash, 8)}
</Link>
</Copyable>
),
},
{
Expand All @@ -115,6 +128,9 @@ const Blobs: NextPage = function () {
</div>
),
},
{
item: <span></span>,
},
{
item: (
<div className="flex gap-2">
Expand Down
4 changes: 2 additions & 2 deletions apps/web/src/pages/block/[id].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import type { NextRouter } from "next/router";

import { Card } from "~/components/Cards/Card";
import { BlobTransactionCard } from "~/components/Cards/SurfaceCards/BlobTransactionCard";
import { Copyable } from "~/components/CopyToClipboard";
import { Copyable } from "~/components/Copyable";
import { BlobGasUsageDisplay } from "~/components/Displays/BlobGasUsageDisplay";
import { EtherUnitDisplay } from "~/components/Displays/EtherUnitDisplay";
import { DetailsLayout } from "~/components/Layouts/DetailsLayout";
Expand Down Expand Up @@ -113,7 +113,7 @@ const Block: NextPage = function () {
{ name: "Status", value: <BlockStatus blockNumber={blockData.number} /> },
{
name: "Hash",
value: <Copyable value={blockData.hash} label="Copy Hash" />,
value: <Copyable value={blockData.hash} tooltipText="Copy Hash" />,
},
{
name: "Timestamp",
Expand Down
17 changes: 11 additions & 6 deletions apps/web/src/pages/blocks.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useMemo } from "react";
import type { NextPage } from "next";

import { Copyable } from "~/components/Copyable";
import { BlobGasUsageDisplay } from "~/components/Displays/BlobGasUsageDisplay";
import { EtherUnitDisplay } from "~/components/Displays/EtherUnitDisplay";
import { Filters } from "~/components/Filters";
Expand Down Expand Up @@ -134,16 +135,20 @@ const Blocks: NextPage = function () {
cells: [
{
item: (
<Link href={buildTransactionRoute(transactionHash)}>
{transactionHash}
</Link>
<Copyable
href={buildTransactionRoute(transactionHash)}
value={transactionHash}
tooltipText="Copy transaction hash"
/>
),
},
{
item: (
<Link href={buildBlobRoute(blobVersionedHash)}>
{blobVersionedHash}
</Link>
<Copyable
href={buildBlobRoute(blobVersionedHash)}
value={blobVersionedHash}
tooltipText="Copy blob versioned hash"
/>
),
},
],
Expand Down
27 changes: 15 additions & 12 deletions apps/web/src/pages/tx/[hash].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import { parseDecodedData } from "~/utils/decoded-transaction";
import { RollupBadge } from "~/components/Badges/RollupBadge";
import { Card } from "~/components/Cards/Card";
import { BlobCard } from "~/components/Cards/SurfaceCards/BlobCard";
import { Copyable, CopyToClipboard } from "~/components/CopyToClipboard";
import { CopyToClipboard } from "~/components/CopyToClipboard";
import { Copyable } from "~/components/Copyable";
import { StandardEtherUnitDisplay } from "~/components/Displays/StandardEtherUnitDisplay";
import { InfoGrid } from "~/components/InfoGrid";
import { DetailsLayout } from "~/components/Layouts/DetailsLayout";
Expand Down Expand Up @@ -102,7 +103,7 @@ const Tx: NextPage = () => {
detailsFields = [
{
name: "Hash",
value: <Copyable value={hash} label="Copy Hash" />,
value: <Copyable value={hash} tooltipText="Copy Hash" />,
},
{ name: "Status", value: <BlockStatus blockNumber={blockNumber} /> },
{
Expand All @@ -124,19 +125,21 @@ const Tx: NextPage = () => {
{
name: "From",
value: (
<div className="flex items-center gap-2">
<Link href={buildAddressRoute(from)}>{from}</Link>
<CopyToClipboard value={from} label="Copy from address" />
</div>
<Copyable
href={buildAddressRoute(from)}
value={from}
tooltipText="Copy from address"
/>
),
},
{
name: "To",
value: (
<div className="flex items-center gap-2">
<Link href={buildAddressRoute(to)}>{to}</Link>
<CopyToClipboard value={to} label="Copy to address" />
</div>
<Copyable
href={buildAddressRoute(to)}
value={to}
tooltipText="Copy to address"
/>
),
},
];
Expand Down Expand Up @@ -288,7 +291,7 @@ const Tx: NextPage = () => {
</Link>
<CopyToClipboard
value={"0x" + decodedData.parentL2BlockHash}
label="Copy parent L2 block hash"
tooltipText="Copy parent L2 block hash"
/>
</div>
),
Expand All @@ -308,7 +311,7 @@ const Tx: NextPage = () => {
</Link>
<CopyToClipboard
value={"0x" + decodedData.l1OriginBlockHash}
label="Copy L1 origin block hash"
tooltipText="Copy L1 origin block hash"
/>
</div>
),
Expand Down
Loading
Loading