Skip to content
This repository was archived by the owner on Dec 10, 2025. It is now read-only.
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
2 changes: 1 addition & 1 deletion frontend/src/components/elevator/block-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ const BlockModal: preact.FunctionComponent<BlockModalProps> = ({
}}
className={`${buttonColor} ${buttonHover} text-white font-bold py-2 px-4 rounded-lg focus:outline-none focus:shadow-outline`}
>
Share this Block
Replay the Block
</button>
<a
href={createBlockLink(
Expand Down
1 change: 1 addition & 0 deletions frontend/src/components/elevator/car.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { ChainTheme, chainThemeAtom } from "../../states/atoms";
import ElevatorCapacity from "./capacity";
import { JSX } from "preact/jsx-runtime";
import { bodyToScreenPosition, createTooltipContent } from "../../util/scene";
import Tooltip from "../tooltip";

export interface ElevatorCarProp {
transactions: Transaction[];
Expand Down
16 changes: 11 additions & 5 deletions frontend/src/components/elevator/elevator-ui.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { chainThemeAtom, ChainTheme } from "../../states/atoms";
import { useState } from "preact/hooks";
import { compactToDifficulty, difficultyToEH } from "../../util/difficulty";
import { calcBlockOccupation, calcTotalTxSize } from "../../util/type";
import Tooltip from "../tooltip";

export interface ElevatorUIProp {
block: TipBlockResponse;
Expand Down Expand Up @@ -60,11 +61,16 @@ export const ElevatorUI: FunctionalComponent<ElevatorUIProp> = ({
doorClosing={isDoorClosing}
/>
<div className={"px-20"}>
<ElevatorCar
blockHeader={block.blockHeader}
transactions={block.committedTransactions}
setFromDoorClosing={doorClosing}
/>
<Tooltip
text="The elevator car size represents CKB max block size limit. The box size is then based on the transaction's size in bytes."
pos="bottom"
>
<ElevatorCar
blockHeader={block.blockHeader}
transactions={block.committedTransactions}
setFromDoorClosing={doorClosing}
/>
</Tooltip>
</div>
</div>
</div>
Expand Down
20 changes: 11 additions & 9 deletions frontend/src/components/elevator/miner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ const ElevatorMiner: FunctionComponent<ElevatorUpButtonProps> = ({
chainTheme === ChainTheme.mainnet
? "/assets/svg/elevator/mainnet/ape-jump.svg"
: "/assets/svg/elevator/testnet/ape-jump.svg";
const jumpClass = doorClosing ? "w-2/3 animate-jump" : "";
const jumpClass = doorClosing ? "px-[30px] animate-jump" : "";

const minerStandSvg =
chainTheme === ChainTheme.mainnet
Expand Down Expand Up @@ -98,8 +98,8 @@ const ElevatorMiner: FunctionComponent<ElevatorUpButtonProps> = ({
</div>

<div>
<Tooltip text="I am a Miner, I work hard to find the nonce for the block for coins!">
<div className="relative">
<Tooltip text="Hey there! I’m your CKB miner—honest, reliable, and impossible to deceive! I verify every transaction and only include valid ones. The harder the mining gets, the faster I have to work! Wish me luck!">
<div className="relative flex justify-center items-center">
<div className={`absolute flex justify-center`}>
<img
className={`z-50 ${jumpClass}`}
Expand All @@ -112,15 +112,17 @@ const ElevatorMiner: FunctionComponent<ElevatorUpButtonProps> = ({
/>
</div>

<img
className={`${doorClosing ? "" : spinClass}`}
src={minerWheel}
alt="Miner Wheel"
/>
<div>
<img
className={`${doorClosing ? "" : spinClass}`}
src={minerWheel}
alt="Miner Wheel"
/>
</div>
</div>
</Tooltip>

<Tooltip text="The miner difficulty is the number of leading zeros in the hash of the block header. The higher the difficulty, the harder it is to find the nonce.">
<Tooltip text="CKB runs on Proof-of-Work (PoW), just like Bitcoin! That means miners compete to solve complex puzzles to secure the network. The higher the difficulty, the harder they have to work to mine new blocks and keep everything running smoothly!">
<div className="relative">
<div className="absolute top-1/2 -translate-y-1/2 left-1/2 -translate-x-1/2 text-text-inverse">
<div
Expand Down
35 changes: 23 additions & 12 deletions frontend/src/components/elevator/out-of-service.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useAtomValue } from "jotai";
import { chainThemeAtom, ChainTheme } from "../../states/atoms";
import { carBoxSize } from "./util";
import { WebSocketConnectionState } from "../../service/ws";
import Tooltip from "../tooltip";

export interface ElevatorOutOfServiceUIProp {
connectStatus: WebSocketConnectionState;
Expand Down Expand Up @@ -37,6 +38,14 @@ export const ElevatorOutOfServiceUI: FunctionalComponent<
? "bg-elevator-mainnet-bottom"
: "bg-elevator-testnet-bottom";

const tooltipContent =
connectStatus === WebSocketConnectionState.OPEN
? "We are connected, just waiting for the newest block coming, please be patient."
: connectStatus === WebSocketConnectionState.CLOSED
? "The websocket connection is closed, waiting to reconnect..."
: connectStatus === WebSocketConnectionState.CONNECTING
? "The websocket connection is connecting, please wait..."
: "The websocket connection is not connected, please check your network connection or try refresh the page.";
return (
<div
className={
Expand All @@ -55,20 +64,22 @@ export const ElevatorOutOfServiceUI: FunctionalComponent<
<div
className={`${bgElevatorFrame} flex flex-col justify-center mx-auto rounded-lg border-[20px] ${borderBlack}`}
>
<div className={"p-4"}>
<div
className={
"w-min text-nowrap flex justify-center gap-1 text-center p-4 bg-surface-DEFAULT-inverse mx-auto rounded-lg"
}
>
<div className={"text-functional-error"}>
Status
</div>
<div className={"text-text-inverse"}>
Connection {connectStatus}
<Tooltip text={tooltipContent}>
<div className={"p-4"}>
<div
className={
"w-min text-nowrap flex justify-center gap-1 text-center p-4 bg-surface-DEFAULT-inverse mx-auto rounded-lg"
}
>
<div className={"text-functional-error"}>
Status
</div>
<div className={"text-text-inverse"}>
{connectStatus}
</div>
</div>
</div>
</div>
</Tooltip>
<div className={"px-20"}>
{/* elevator car */}
<div
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/pool/bulb.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ export interface BulbProps {
}

export const Bulb: FunctionalComponent<BulbProps> = ({
bulbColor = "bg-white",
bulbColor = "bg-functionality-error",
isOn = false,
}) => {
const bulbStyle = `rounded-full border-2 border-black w-7 h-7 flex items-center justify-center transition-colors duration-300 ${isOn ? bulbColor : "bg-white"}`;
const bulbStyle = `rounded-full border-2 border-black w-7 h-7 flex items-center justify-center transition-colors duration-300 ${isOn ? bulbColor : "bg-functional-error"}`;

return (
<div className="flex flex-col items-center">
Expand Down
1 change: 1 addition & 0 deletions frontend/src/components/pool/committed-line.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ export const CommittedLine: FunctionalComponent<CommittedLineProps> = ({
<img src={holeSvg} alt="" />
</div>
<canvas className={`z-2 relative`} ref={canvasRef} />

{/* Transaction Box Tooltip 层 */}
{tooltipContent && tooltipPosition && (
<div
Expand Down
9 changes: 7 additions & 2 deletions frontend/src/components/pool/committing-line.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { useAtomValue } from "jotai";
import { ChainTheme, chainThemeAtom } from "../../states/atoms";
import { bodyToScreenPosition, createTooltipContent } from "../../util/scene";
import { SignBoard } from "./signboard";
import Tooltip from "../tooltip";

export interface LineProps {
title: string;
Expand Down Expand Up @@ -214,7 +215,9 @@ export const CommittingLine: FunctionalComponent<LineProps> = ({
className={`relative flex justify-start items-center pt-[100px] border-b-8 border-l-8 ${borderColor}`}
>
<div className={"absolute top-0 left-1/2 -translate-x-1/2"}>
<SignBoard title={title} count={txs.length} />
<Tooltip text="Committing transactions are the ones getting locked in! Once finalized, they’ll be officially part of the blockchain.">
<SignBoard title={title} count={txs.length} />
</Tooltip>
</div>
<div className={"relative"} ref={containerRef}>
<canvas ref={canvasRef} />
Expand All @@ -233,7 +236,9 @@ export const CommittingLine: FunctionalComponent<LineProps> = ({
)}
</div>
<div className={"h-[300px] flex items-end"}>
<img src={minerRight} alt="" />
<Tooltip text="Hey there! I’m your CKB miner—fair, reliable and honest! I get to pick up transactions based on their fee. The higher the fee, the better the chance of being picked up by me faster!">
<img src={minerRight} alt="" />
</Tooltip>
</div>
</div>
</div>
Expand Down
5 changes: 4 additions & 1 deletion frontend/src/components/pool/header.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useAtomValue } from "jotai";
import { FunctionalComponent } from "preact";
import { ChainTheme, chainThemeAtom } from "../../states/atoms";
import Tooltip from "../tooltip";

export interface PoolHeaderProps {
totalTxs: number;
Expand Down Expand Up @@ -29,7 +30,9 @@ export const PoolHeader: FunctionalComponent<PoolHeaderProps> = ({
"absolute bottom-6 w-fit left-1/2 -translate-x-1/2 flex justify-center bg-surface-DEFAULT-inverse px-8 py-4 gap-2"
}
>
<div className={"text-text-inverse"}>Mempool Size (KB)</div>
<Tooltip text="The mempool is like a waiting room for transactions before they get picked by miners into a block. ">
<div className={"text-text-inverse"}>Mempool Size (KB)</div>
</Tooltip>
<div className={textColor}>{txSizeInKB}</div>
<div className={"text-text-inverse"}>Total Transactions</div>
<div className={textColor}>{totalTxs}</div>
Expand Down
32 changes: 27 additions & 5 deletions frontend/src/components/pool/pending-line.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import { useAtomValue } from "jotai";
import { ChainTheme, chainThemeAtom } from "../../states/atoms";
import { SignBoard } from "./signboard";
import Bulb from "./bulb";
import Tooltip from "../tooltip";
import { useChainService } from "../../context/chain";

export interface PendingLineProps {
title: string;
Expand All @@ -24,6 +26,7 @@ export const PendingLine: FunctionalComponent<PendingLineProps> = ({
txs,
}) => {
const chainTheme = useAtomValue(chainThemeAtom);
const { chainService } = useChainService();

const [tooltipContent, setTooltipContent] = useState<JSX.Element | null>(
null,
Expand Down Expand Up @@ -242,13 +245,30 @@ export const PendingLine: FunctionalComponent<PendingLineProps> = ({
<div
className={`text-text-inverse ${bgColor} w-[240px] h-[230px] border-[2px] border-text-secondary flex justify-center gap-2 p-4`}
>
<Bulb bulbColor="bg-functional-warning" isOn={true} />
<Bulb bulbColor="bg-functional-success" isOn={true} />
<Bulb />
<Tooltip text="Websocket connection status, green means connected, red means disconnected">
<Bulb
bulbColor="bg-functional-success"
isOn={chainService.wsClient.isConnected}
/>
</Tooltip>
<Tooltip text="Reserved for later usage.">
<Bulb
bulbColor="bg-functional-warning"
isOn={true}
/>
</Tooltip>
<Tooltip text="Reserved for later usage.">
<Bulb
bulbColor="bg-functional-warning"
isOn={true}
/>
</Tooltip>
</div>
</div>
<div className={"absolute top-0 left-1/2 -translate-x-1/2"}>
<SignBoard title={title} count={txs.length} />
<Tooltip text="Pending transactions are the ones just arrived and are waiting to be picked up by miners.">
<SignBoard title={title} count={txs.length} />
</Tooltip>
</div>
<div className={"relative"} ref={containerRef}>
<canvas ref={canvasRef} />
Expand All @@ -267,7 +287,9 @@ export const PendingLine: FunctionalComponent<PendingLineProps> = ({
)}
</div>
<div>
<img src={minerRight} alt="" />
<Tooltip text="Hey there! I’m your CKB miner—fair, reliable and honest! I get to pick up transactions based on their fee. The higher the fee, the better the chance of being picked up by me faster!">
<img src={minerRight} alt="" />
</Tooltip>
</div>
</div>
</div>
Expand Down
9 changes: 7 additions & 2 deletions frontend/src/components/pool/proposal-line.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { useAtomValue } from "jotai";
import { ChainTheme, chainThemeAtom } from "../../states/atoms";
import { bodyToScreenPosition, createTooltipContent } from "../../util/scene";
import { SignBoard } from "./signboard";
import Tooltip from "../tooltip";

export interface ProposalLineProps {
title: string;
Expand Down Expand Up @@ -212,7 +213,9 @@ export const ProposalLine: FunctionalComponent<ProposalLineProps> = ({
className={`relative w-full flex justify-end border-b-8 border-r-8 pt-[100px] ${borderColor}`}
>
<div className={"h-[300px] flex items-end"}>
<img src={minerLeft} alt="" />
<Tooltip text="Hey there! I’m your CKB miner—fair, reliable and honest! I get to pick up transactions based on their fee. The higher the fee, the better the chance of being picked up by me faster!">
<img src={minerLeft} alt="" />
</Tooltip>
</div>
<div className={"relative"} ref={containerRef}>
<canvas ref={canvasRef} />
Expand All @@ -232,7 +235,9 @@ export const ProposalLine: FunctionalComponent<ProposalLineProps> = ({
</div>

<div className={"absolute top-0 left-1/2 -translate-x-1/2"}>
<SignBoard title={title} count={txs.length} />
<Tooltip text="Proposal transactions are the ones selected and are waiting to be included in a block. But here’s the catch—if they aren’t committed within 11 blocks, they’ll go back to the pending status and have to be propose again!">
<SignBoard title={title} count={txs.length} />
</Tooltip>
</div>
</div>
);
Expand Down
41 changes: 34 additions & 7 deletions frontend/src/components/replay/header.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { FunctionalComponent } from "preact";
import { useAtomValue } from "jotai";
import { chainThemeAtom, ChainTheme } from "../../states/atoms";
import { useState } from "preact/hooks";

export interface ReplayHeaderProp {
blockHash: string;
Expand All @@ -13,6 +14,29 @@ export const ReplayHeader: FunctionalComponent<ReplayHeaderProp> = ({
chainTheme === ChainTheme.mainnet
? "text-brand-mainnet"
: "text-brand-testnet";
const [copyNotification, setCopyNotification] = useState<string | null>(
null,
);

const handleCopyClick = () => {
const link = `${window.location.origin}/replay/${blockHash}`;
navigator.clipboard
.writeText(link)
.then(() => {
setCopyNotification("Link copied!");
setTimeout(() => {
setCopyNotification(null);
}, 2000); // Clear notification after 2 seconds
})
.catch((err) => {
console.error("Failed to copy: ", err);
setCopyNotification("Failed to copy link."); //Optional, error message.
setTimeout(() => {
setCopyNotification(null);
}, 2000);
});
};

return (
<div>
<div
Expand All @@ -22,14 +46,17 @@ export const ReplayHeader: FunctionalComponent<ReplayHeaderProp> = ({
>
<h1>Elevator Block Replay </h1>
<div>
<a
className={`${textColor}`}
href="http://"
target="_blank"
rel="noopener noreferrer"
<button
className={`${textColor} border border-black rounded-md px-4 py-2`}
onClick={handleCopyClick}
>
Copy the Share Link
</a>
Share this block with your friends!
</button>
{copyNotification && (
<div className="text-text-secondary text-sm italic">
{copyNotification}
</div>
)}
</div>
</div>
</div>
Expand Down
Loading