simplify colors of block explorer homepage
This commit is contained in:
+10
-10
@@ -10,17 +10,17 @@ import { Transactions } from "./pages/Transactions"
|
||||
|
||||
export default function App() {
|
||||
return (
|
||||
<div className="w-full max-w-screen-lg h-screen bg-polkadot-950 flex flex-col">
|
||||
<div className="w-full max-w-screen-lg h-screen bg-background flex flex-col">
|
||||
<Header />
|
||||
<Routes>
|
||||
<Route path="explorer/*" element={<Explorer />} />
|
||||
<Route path="extrinsics/*" element={<Extrinsics />} />
|
||||
<Route path="storage/*" element={<Storage />} />
|
||||
<Route path="constants/*" element={<Constants />} />
|
||||
<Route path="runtimeCalls/*" element={<RuntimeCalls />} />
|
||||
<Route path="metadata/*" element={<Metadata />} />
|
||||
<Route path="*" element={<Navigate to="/extrinsics" replace />} />
|
||||
</Routes>
|
||||
<Routes>
|
||||
<Route path="explorer/*" element={<Explorer />} />
|
||||
<Route path="extrinsics/*" element={<Extrinsics />} />
|
||||
<Route path="storage/*" element={<Storage />} />
|
||||
<Route path="constants/*" element={<Constants />} />
|
||||
<Route path="runtimeCalls/*" element={<RuntimeCalls />} />
|
||||
<Route path="metadata/*" element={<Metadata />} />
|
||||
<Route path="*" element={<Navigate to="/extrinsics" replace />} />
|
||||
</Routes>
|
||||
<Transactions />
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -19,7 +19,7 @@ export const CircularProgress: FC<{
|
||||
`}
|
||||
strokeWidth={STROKE_W}
|
||||
fill="transparent"
|
||||
className="transition-all ease-linear stroke-polkadot-500"
|
||||
className="transition-all ease-linear stroke-primary"
|
||||
opacity="0.3"
|
||||
/>
|
||||
{progress ? (
|
||||
@@ -33,7 +33,7 @@ export const CircularProgress: FC<{
|
||||
strokeWidth={STROKE_W}
|
||||
strokeLinecap="round"
|
||||
fill="transparent"
|
||||
className="transition-all ease-linear stroke-polkadot-500"
|
||||
className="transition-all ease-linear stroke-primary"
|
||||
opacity="0.7"
|
||||
/>
|
||||
) : null}
|
||||
@@ -48,7 +48,7 @@ export const CircularProgress: FC<{
|
||||
strokeWidth={STROKE_W}
|
||||
strokeLinecap="round"
|
||||
fill="transparent"
|
||||
className="transition-all ease-linear stroke-polkadot-500"
|
||||
className="transition-all ease-linear stroke-primary"
|
||||
/>
|
||||
) : null}
|
||||
<text
|
||||
@@ -56,7 +56,7 @@ export const CircularProgress: FC<{
|
||||
y={CENTER}
|
||||
textAnchor="middle"
|
||||
dy=".3em"
|
||||
className="tabular-nums fill-polkadot-200"
|
||||
className="tabular-nums fill-foreground/80"
|
||||
>
|
||||
{text}
|
||||
</text>
|
||||
|
||||
@@ -7,9 +7,9 @@ export const Popover: FC<
|
||||
<Root open={open}>
|
||||
<Trigger asChild>{children}</Trigger>
|
||||
<Portal>
|
||||
<Content className="bg-polkadot-950 border border-polkadot-700 p-2 rounded max-w-[100vw]">
|
||||
<Content className="bg-popover text-popover-foreground border p-2 rounded max-w-[100vw]">
|
||||
{content}
|
||||
<Arrow className="fill-polkadot-700" />
|
||||
<Arrow className="fill-border" />
|
||||
</Content>
|
||||
</Portal>
|
||||
</Root>
|
||||
|
||||
+34
-31
@@ -39,54 +39,56 @@ dialog {
|
||||
opacity: 1;
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
@layer base {
|
||||
:root {
|
||||
--background: 0 0% 100%;
|
||||
--foreground: 0 0% 3.9%;
|
||||
--foreground: 240 10% 3.9%;
|
||||
--card: 0 0% 100%;
|
||||
--card-foreground: 0 0% 3.9%;
|
||||
--card-foreground: 240 10% 3.9%;
|
||||
--popover: 0 0% 100%;
|
||||
--popover-foreground: 0 0% 3.9%;
|
||||
--primary: 0 0% 9%;
|
||||
--primary-foreground: 0 0% 98%;
|
||||
--secondary: 0 0% 96.1%;
|
||||
--secondary-foreground: 0 0% 9%;
|
||||
--muted: 0 0% 96.1%;
|
||||
--muted-foreground: 0 0% 45.1%;
|
||||
--accent: 0 0% 96.1%;
|
||||
--accent-foreground: 0 0% 9%;
|
||||
--popover-foreground: 240 10% 3.9%;
|
||||
--primary: 328 100% 45%;
|
||||
--primary-foreground: 355.7 100% 97.3%;
|
||||
--secondary: 240 4.8% 95.9%;
|
||||
--secondary-foreground: 240 5.9% 10%;
|
||||
--muted: 240 4.8% 95.9%;
|
||||
--muted-foreground: 240 3.8% 46.1%;
|
||||
--accent: 240 4.8% 95.9%;
|
||||
--accent-foreground: 240 5.9% 10%;
|
||||
--destructive: 0 84.2% 60.2%;
|
||||
--destructive-foreground: 0 0% 98%;
|
||||
--border: 0 0% 89.8%;
|
||||
--input: 0 0% 89.8%;
|
||||
--ring: 0 0% 3.9%;
|
||||
--border: 240 5.9% 90%;
|
||||
--input: 240 5.9% 90%;
|
||||
--ring: 328 100% 45%;
|
||||
--radius: 0.5rem;
|
||||
--chart-1: 12 76% 61%;
|
||||
--chart-2: 173 58% 39%;
|
||||
--chart-3: 197 37% 24%;
|
||||
--chart-4: 43 74% 66%;
|
||||
--chart-5: 27 87% 67%;
|
||||
--radius: 0.5rem;
|
||||
}
|
||||
|
||||
.dark {
|
||||
--background: 0 0% 3.9%;
|
||||
--foreground: 0 0% 98%;
|
||||
--card: 0 0% 3.9%;
|
||||
--card-foreground: 0 0% 98%;
|
||||
--popover: 0 0% 3.9%;
|
||||
--popover-foreground: 0 0% 98%;
|
||||
--primary: 0 0% 98%;
|
||||
--primary-foreground: 0 0% 9%;
|
||||
--secondary: 0 0% 14.9%;
|
||||
--background: 20 14.3% 4.1%;
|
||||
--foreground: 0 0% 95%;
|
||||
--card: 24 9.8% 10%;
|
||||
--card-foreground: 0 0% 95%;
|
||||
--popover: 0 0% 9%;
|
||||
--popover-foreground: 0 0% 95%;
|
||||
--primary: 328 100% 45%;
|
||||
--primary-foreground: 355.7 100% 97.3%;
|
||||
--secondary: 240 3.7% 15.9%;
|
||||
--secondary-foreground: 0 0% 98%;
|
||||
--muted: 0 0% 14.9%;
|
||||
--muted-foreground: 0 0% 63.9%;
|
||||
--accent: 0 0% 14.9%;
|
||||
--muted: 0 0% 15%;
|
||||
--muted-foreground: 240 5% 64.9%;
|
||||
--accent: 12 6.5% 15.1%;
|
||||
--accent-foreground: 0 0% 98%;
|
||||
--destructive: 0 62.8% 30.6%;
|
||||
--destructive-foreground: 0 0% 98%;
|
||||
--border: 0 0% 14.9%;
|
||||
--input: 0 0% 14.9%;
|
||||
--ring: 0 0% 83.1%;
|
||||
--destructive-foreground: 0 85.7% 97.3%;
|
||||
--border: 240 3.7% 15.9%;
|
||||
--input: 240 3.7% 15.9%;
|
||||
--ring: 328 100% 45%;
|
||||
--chart-1: 220 70% 50%;
|
||||
--chart-2: 160 60% 45%;
|
||||
--chart-3: 30 80% 55%;
|
||||
@@ -94,6 +96,7 @@ dialog {
|
||||
--chart-5: 340 75% 55%;
|
||||
}
|
||||
}
|
||||
|
||||
@layer base {
|
||||
* {
|
||||
@apply border-border;
|
||||
|
||||
@@ -8,6 +8,7 @@ import { map } from "rxjs"
|
||||
import { blockInfoState$ } from "./block.state"
|
||||
import { BlockStatusIcon, statusText } from "./Detail/BlockState"
|
||||
import { filterEvt } from "./Events"
|
||||
import { CopyText } from "@/components/Copy"
|
||||
|
||||
const maxBlockWeight$ = state(
|
||||
runtimeCtx$.pipe(
|
||||
@@ -51,21 +52,23 @@ export const BlockPopover: FC<{ hash: string }> = ({ hash }) => {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h3 className="font-bold text-lg hover:text-polkadot-200">
|
||||
<Link to={hash}>
|
||||
Block{" "}
|
||||
<span className="font-mono text-sm font-normal text-slate-300 hover:text-polkadot-200">
|
||||
{hash}
|
||||
</span>
|
||||
</Link>
|
||||
</h3>
|
||||
<p>
|
||||
Status:{" "}
|
||||
<span className="inline-flex gap-1 items-center align-middle">
|
||||
<div className="flex justify-between items-center gap-4 mb-2">
|
||||
<h3 className="font-bold flex gap-1 items-center">
|
||||
Block
|
||||
<Link
|
||||
to={hash}
|
||||
className="font-mono font-normal text-primary/70 hover:text-primary"
|
||||
>
|
||||
{hash.slice(0, 18)}…
|
||||
</Link>
|
||||
<CopyText className="ml-1" text={hash} binary />
|
||||
</h3>
|
||||
<p className="flex gap-1">
|
||||
Status:
|
||||
<BlockStatusIcon state={block.status} />
|
||||
{statusText[block.status]}
|
||||
</span>
|
||||
</p>
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex justify-between items-start">
|
||||
{eventGroups && (
|
||||
<div>
|
||||
@@ -83,7 +86,10 @@ export const BlockPopover: FC<{ hash: string }> = ({ hash }) => {
|
||||
<td className="px-2">
|
||||
{filteredEvents}/
|
||||
{eventGroups["ApplyExtrinsic"]?.length ?? 0}
|
||||
<span className="text-slate-300"> (filtered/total)</span>
|
||||
<span className="text-popover-foreground/60">
|
||||
{" "}
|
||||
(filtered/total)
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
||||
@@ -7,6 +7,7 @@ import { combineLatest, debounceTime, map, switchMap } from "rxjs"
|
||||
import { twMerge } from "tailwind-merge"
|
||||
import { BlockInfo, blocksByHeight$, finalized$ } from "./block.state"
|
||||
import { BlockPopover } from "./BlockPopover"
|
||||
import * as Finalizing from "./FinalizingTable"
|
||||
|
||||
const best$ = chainHead$.pipeState(switchMap((chainHead) => chainHead.best$))
|
||||
|
||||
@@ -101,69 +102,63 @@ export const BlockTable = () => {
|
||||
if (!finalized) return null
|
||||
|
||||
return (
|
||||
<div className="w-full px-3 py-2 border border-polkadot-700">
|
||||
<h2 className="font-bold p-2 border-b border-slate-400 mb-2">
|
||||
Recent Blocks
|
||||
</h2>
|
||||
<table className="border-collapse m-auto">
|
||||
<tbody>
|
||||
{rows.map((row, i) => (
|
||||
<tr
|
||||
key={row.block.hash}
|
||||
className={twMerge(
|
||||
row.block.number <= finalized.number ? "bg-polkadot-900" : "",
|
||||
row.block.number === finalized.number &&
|
||||
row.position === 0 &&
|
||||
"border-t",
|
||||
)}
|
||||
>
|
||||
{rows[i - 1]?.block.number !== row.block.number ? (
|
||||
<td
|
||||
rowSpan={numberSpan(i)}
|
||||
className={twMerge(
|
||||
"px-2",
|
||||
numberSpan(i) > 1
|
||||
? twMerge(
|
||||
i > 0 ? "border-y" : "border-b",
|
||||
"border-slate-500",
|
||||
)
|
||||
: null,
|
||||
row.block.number === finalized.number && "border-t-white",
|
||||
row.block.number === finalized.number + 1 &&
|
||||
"border-b-white",
|
||||
)}
|
||||
>
|
||||
{row.block.number.toLocaleString()}
|
||||
</td>
|
||||
) : null}
|
||||
<td className="p-0">
|
||||
<ForkRenderer row={row} />
|
||||
<Finalizing.Root>
|
||||
<Finalizing.Title>Recent Blocks</Finalizing.Title>
|
||||
<Finalizing.Table>
|
||||
{rows.map((row, i) => (
|
||||
<Finalizing.Row
|
||||
key={row.block.hash}
|
||||
number={row.block.number}
|
||||
finalized={finalized.number}
|
||||
firstInGroup={row.position === 0}
|
||||
>
|
||||
{rows[i - 1]?.block.number !== row.block.number ? (
|
||||
<td
|
||||
rowSpan={numberSpan(i)}
|
||||
className={twMerge(
|
||||
"px-2",
|
||||
numberSpan(i) > 1
|
||||
? twMerge(
|
||||
i > 0 ? "border-y" : "border-b",
|
||||
"border-card-foreground/25",
|
||||
)
|
||||
: null,
|
||||
row.block.number === finalized.number &&
|
||||
"border-t-card-foreground/50",
|
||||
row.block.number === finalized.number + 1 &&
|
||||
"border-b-card-foreground/50",
|
||||
)}
|
||||
>
|
||||
{row.block.number.toLocaleString()}
|
||||
</td>
|
||||
<td className="max-w-xs w-full">
|
||||
<div className="flex gap-1">
|
||||
<Popover content={<BlockPopover hash={row.block.hash} />}>
|
||||
<button
|
||||
className={twMerge(
|
||||
"overflow-hidden text-ellipsis whitespace-nowrap font-mono text-sm",
|
||||
"hover:text-polkadot-200",
|
||||
row.position === 0
|
||||
? ""
|
||||
: row.block.number > finalized.number
|
||||
? "opacity-80"
|
||||
: "opacity-50",
|
||||
)}
|
||||
>
|
||||
{row.block.hash}
|
||||
</button>
|
||||
</Popover>
|
||||
<CopyText text={row.block.hash} binary />
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
) : null}
|
||||
<td className="p-0">
|
||||
<ForkRenderer row={row} />
|
||||
</td>
|
||||
<td className="max-w-xs w-full">
|
||||
<div className="flex gap-1">
|
||||
<Popover content={<BlockPopover hash={row.block.hash} />}>
|
||||
<button
|
||||
className={twMerge(
|
||||
"overflow-hidden text-ellipsis whitespace-nowrap font-mono text-sm",
|
||||
"text-card-foreground/80 hover:text-card-foreground/100",
|
||||
row.position === 0
|
||||
? ""
|
||||
: row.block.number > finalized.number
|
||||
? "opacity-80"
|
||||
: "opacity-50",
|
||||
)}
|
||||
>
|
||||
{row.block.hash}
|
||||
</button>
|
||||
</Popover>
|
||||
<CopyText text={row.block.hash} binary />
|
||||
</div>
|
||||
</td>
|
||||
</Finalizing.Row>
|
||||
))}
|
||||
</Finalizing.Table>
|
||||
</Finalizing.Root>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -179,7 +174,7 @@ const ForkRenderer: FC<{ row: PositionedBlock }> = ({ row }) => {
|
||||
<svg
|
||||
height={CELL_HEIGHT}
|
||||
width={CELL_WIDTH * totalCells}
|
||||
className="stroke-polkadot-200"
|
||||
className="stroke-card-foreground/60"
|
||||
>
|
||||
{row.branches.map((branch, i) => (
|
||||
<line
|
||||
|
||||
@@ -16,6 +16,8 @@ import { JsonDisplay } from "@/components/JsonDisplay"
|
||||
import { groupBy } from "@/lib/groupBy"
|
||||
import { Link } from "react-router-dom"
|
||||
import { BlockStatusIcon, statusText } from "./Detail/BlockState"
|
||||
import * as Finalizing from "./FinalizingTable"
|
||||
import { CopyText } from "@/components/Copy"
|
||||
|
||||
export const Events = () => {
|
||||
const events = useStateObservable(recentEvents$)
|
||||
@@ -35,71 +37,70 @@ export const Events = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="w-full px-3 py-2 border border-polkadot-700">
|
||||
<h2 className="font-bold p-2 border-b border-slate-400 mb-2">
|
||||
Recent Events
|
||||
</h2>
|
||||
<table className="w-full">
|
||||
<tbody>
|
||||
{events.map((evt, idx) => {
|
||||
const key = eventKey(evt)
|
||||
const span = numberSpan(idx)
|
||||
<Finalizing.Root>
|
||||
<Finalizing.Title>Recent Events</Finalizing.Title>
|
||||
<Finalizing.Table>
|
||||
{events.map((evt, idx) => {
|
||||
const key = eventKey(evt)
|
||||
const span = numberSpan(idx)
|
||||
|
||||
return (
|
||||
<tr
|
||||
key={`${evt.hash}-${evt.extrinsicNumber}-${evt.index}`}
|
||||
className={twMerge(
|
||||
idx === finalizedIdx ? "border-t border-white" : "",
|
||||
finalized && evt.number <= finalized.number
|
||||
? "bg-polkadot-900"
|
||||
: "",
|
||||
)}
|
||||
>
|
||||
{eventKey(events[idx - 1]) !== key && (
|
||||
<td
|
||||
className={twMerge(
|
||||
"p-2 whitespace-nowrap",
|
||||
span > 1 &&
|
||||
twMerge(
|
||||
idx > 0 ? "border-y" : "border-b",
|
||||
"border-slate-500",
|
||||
),
|
||||
idx === finalizedIdx && "border-t-white",
|
||||
idx === finalizedIdx - span && "border-b-white",
|
||||
)}
|
||||
rowSpan={span}
|
||||
>
|
||||
{key}
|
||||
</td>
|
||||
)}
|
||||
<td className="p-1 w-full">
|
||||
{"event" in evt ? (
|
||||
<Popover content={<EventPopover event={evt} />}>
|
||||
<button className="w-full p-1 text-left hover:text-polkadot-200">{`${evt.event.type}.${evt.event.value.type}`}</button>
|
||||
</Popover>
|
||||
) : (
|
||||
`… ${evt.length} more`
|
||||
return (
|
||||
<Finalizing.Row
|
||||
key={`${evt.hash}-${evt.extrinsicNumber}-${evt.index}`}
|
||||
number={events.length - idx}
|
||||
finalized={events.length - finalizedIdx}
|
||||
firstInGroup
|
||||
>
|
||||
{eventKey(events[idx - 1]) !== key && (
|
||||
<td
|
||||
className={twMerge(
|
||||
"p-2 whitespace-nowrap",
|
||||
span > 1 &&
|
||||
twMerge(
|
||||
idx > 0 ? "border-y" : "border-b",
|
||||
"border-card-foreground/25",
|
||||
),
|
||||
idx === finalizedIdx &&
|
||||
"border-t-border-card-foreground/50",
|
||||
idx === finalizedIdx - span &&
|
||||
"border-b-border-card-foreground/50",
|
||||
)}
|
||||
rowSpan={span}
|
||||
>
|
||||
{key}
|
||||
</td>
|
||||
</tr>
|
||||
)
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
)}
|
||||
<td className="p-1 w-full">
|
||||
{"event" in evt ? (
|
||||
<Popover content={<EventPopover event={evt} />}>
|
||||
<button className="w-full p-1 text-left hover:text-polkadot-200">{`${evt.event.type}.${evt.event.value.type}`}</button>
|
||||
</Popover>
|
||||
) : (
|
||||
`… ${evt.length} more`
|
||||
)}
|
||||
</td>
|
||||
</Finalizing.Row>
|
||||
)
|
||||
})}
|
||||
</Finalizing.Table>
|
||||
{events.length === 0 ? (
|
||||
<div className="text-slate-400">(No events yet)</div>
|
||||
) : null}
|
||||
</div>
|
||||
</Finalizing.Root>
|
||||
)
|
||||
}
|
||||
|
||||
const EventPopover: FC<{ event: EventInfo }> = ({ event }) => {
|
||||
return (
|
||||
<div>
|
||||
<div className="flex justify-between">
|
||||
<div className="flex justify-between items-center gap-4 mb-2">
|
||||
<h3 className="font-bold text-lg">
|
||||
<Link to={`${event.hash}#event=${event.index}`}>
|
||||
Event {eventKey(event)}
|
||||
Event{" "}
|
||||
<Link
|
||||
to={`${event.hash}#event=${event.index}`}
|
||||
className="text-primary/70 hover:text-primary"
|
||||
>
|
||||
{eventKey(event)}
|
||||
</Link>
|
||||
</h3>
|
||||
<p className="flex gap-1">
|
||||
@@ -108,8 +109,9 @@ const EventPopover: FC<{ event: EventInfo }> = ({ event }) => {
|
||||
{statusText[event.status]}
|
||||
</p>
|
||||
</div>
|
||||
<p className="overflow-hidden text-ellipsis whitespace-nowrap text-slate-400">
|
||||
Block: {event.hash}
|
||||
<p className="overflow-hidden text-ellipsis whitespace-nowrap flex items-center gap-2">
|
||||
Block: {event.hash.slice(0, 18)}…
|
||||
<CopyText text={event.hash} binary />
|
||||
</p>
|
||||
<p className="font-bold">{`${event.event.type}.${event.event.value.type}`}</p>
|
||||
<JsonDisplay src={event.event.value.value} />
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
import { FC, PropsWithChildren } from "react"
|
||||
import { twMerge } from "tailwind-merge"
|
||||
|
||||
export const Title: FC<PropsWithChildren> = ({ children }) => (
|
||||
<h2 className="font-bold p-2 border-b border-slate-400 mb-2">{children}</h2>
|
||||
)
|
||||
|
||||
export const Table: FC<PropsWithChildren> = ({ children }) => (
|
||||
<table className="border-collapse m-auto">
|
||||
<tbody>{children}</tbody>
|
||||
</table>
|
||||
)
|
||||
|
||||
export const Row: FC<
|
||||
PropsWithChildren<{
|
||||
number: number
|
||||
finalized: number
|
||||
firstInGroup: boolean
|
||||
}>
|
||||
> = ({ children, number, finalized, firstInGroup }) => (
|
||||
<tr
|
||||
className={twMerge(
|
||||
number <= finalized ? "bg-primary/5" : "",
|
||||
number === finalized &&
|
||||
firstInGroup &&
|
||||
"border-t border-card-foreground/50",
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</tr>
|
||||
)
|
||||
|
||||
export const Root: FC<PropsWithChildren> = ({ children }) => {
|
||||
return (
|
||||
<div className="w-full px-3 py-2 border bg-card text-card-foreground">
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -16,21 +16,12 @@ const best$ = chainHead$.pipeState(
|
||||
export const Summary: FC = () => {
|
||||
return (
|
||||
<div className="flex gap-4 items-center py-2">
|
||||
<SummaryItem
|
||||
title="Block Time"
|
||||
className="bg-opacity-0"
|
||||
>
|
||||
<SummaryItem title="Block Time" className="bg-card/0 border-none">
|
||||
<BlockTime />
|
||||
</SummaryItem>
|
||||
<div className="flex-1" />
|
||||
<SummaryItem
|
||||
title="Finalized"
|
||||
>
|
||||
{finalized$}
|
||||
</SummaryItem>
|
||||
<SummaryItem title="Best">
|
||||
{best$}
|
||||
</SummaryItem>
|
||||
<SummaryItem title="Finalized">{finalized$}</SummaryItem>
|
||||
<SummaryItem title="Best">{best$}</SummaryItem>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -39,9 +30,16 @@ const SummaryItem: FC<
|
||||
PropsWithChildren<{ title: string; className?: string }>
|
||||
> = ({ title, className, children }) => {
|
||||
return (
|
||||
<div className={twMerge("flex flex-col items-center bg-polkadot-800 px-3 py-2", className)}>
|
||||
<div
|
||||
className={twMerge(
|
||||
"flex flex-col items-center border rounded bg-card text-card-foreground px-3 py-2",
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<h3>{title}</h3>
|
||||
<div className="tabular-nums text-slate-300 text-sm">{children}</div>
|
||||
<div className="tabular-nums text-sm text-card-foreground/80">
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
+27
-38
@@ -1,5 +1,7 @@
|
||||
import { Link } from "react-router-dom"
|
||||
import { Link, useLocation } from "react-router-dom"
|
||||
import { NetworkSwitcher } from "./Network/Network"
|
||||
import { FC, PropsWithChildren } from "react"
|
||||
import { twMerge } from "tailwind-merge"
|
||||
|
||||
export const Header = () => (
|
||||
<div className="flex p-4 pb-2 items-center flex-shrink-0 gap-2">
|
||||
@@ -14,43 +16,30 @@ export const Header = () => (
|
||||
</h1>
|
||||
</div>
|
||||
<NetworkSwitcher />
|
||||
<div className="flex flex-row items-center justify-end bg-polkadot-800 px-1 py-1 rounded-full text-nowrap">
|
||||
<Link
|
||||
to="/explorer"
|
||||
className="cursor-pointer hover:text-polkadot-0 px-3 py-1 hover:bg-polkadot-500 rounded-full"
|
||||
>
|
||||
Explorer
|
||||
</Link>
|
||||
<Link
|
||||
to="/storage"
|
||||
className="cursor-pointer hover:text-polkadot-0 px-3 py-1 hover:bg-polkadot-500 rounded-full"
|
||||
>
|
||||
Storage
|
||||
</Link>
|
||||
<Link
|
||||
to="/extrinsics"
|
||||
className="cursor-pointer hover:text-polkadot-0 px-3 py-1 hover:bg-polkadot-500 rounded-full"
|
||||
>
|
||||
Extrinsics
|
||||
</Link>
|
||||
<Link
|
||||
to="/constants"
|
||||
className="cursor-pointer hover:text-polkadot-0 px-3 py-1 hover:bg-polkadot-500 rounded-full"
|
||||
>
|
||||
Constants
|
||||
</Link>
|
||||
<Link
|
||||
to="/runtimeCalls"
|
||||
className="cursor-pointer hover:text-polkadot-0 px-3 py-1 hover:bg-polkadot-500 rounded-full"
|
||||
>
|
||||
Runtime Calls
|
||||
</Link>
|
||||
<Link
|
||||
to="/metadata"
|
||||
className="cursor-pointer hover:text-polkadot-0 px-3 py-1 hover:bg-polkadot-500 rounded-full"
|
||||
>
|
||||
Metadata
|
||||
</Link>
|
||||
<div className="flex flex-row items-center justify-end px-1 py-1 text-nowrap">
|
||||
<NavLink to="/explorer">Explorer</NavLink>
|
||||
<NavLink to="/storage">Storage</NavLink>
|
||||
<NavLink to="/extrinsics">Extrinsics</NavLink>
|
||||
<NavLink to="/constants">Constants</NavLink>
|
||||
<NavLink to="/runtimeCalls">Runtime Calls</NavLink>
|
||||
<NavLink to="/metadata">Metadata</NavLink>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
const NavLink: FC<PropsWithChildren<{ to: string }>> = ({ to, children }) => {
|
||||
const location = useLocation()
|
||||
const active = location.pathname.startsWith(to)
|
||||
|
||||
return (
|
||||
<Link
|
||||
to={to}
|
||||
className={twMerge(
|
||||
"transition-colors text-foreground/75 hover:text-foreground cursor-pointer px-3 py-1",
|
||||
active && "text-foreground font-bold",
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user