add light theme support, underline links to block detail
This commit is contained in:
44
src/ThemeProvider.tsx
Normal file
44
src/ThemeProvider.tsx
Normal file
@@ -0,0 +1,44 @@
|
||||
import { state, useStateObservable } from "@react-rxjs/core"
|
||||
import {
|
||||
createContext,
|
||||
FC,
|
||||
PropsWithChildren,
|
||||
useContext,
|
||||
useLayoutEffect,
|
||||
} from "react"
|
||||
import { fromEvent, map } from "rxjs"
|
||||
|
||||
const getCurrentMedia = (): "light" | "dark" =>
|
||||
window.matchMedia
|
||||
? window.matchMedia("(prefers-color-scheme: dark)")
|
||||
? "dark"
|
||||
: "light"
|
||||
: "dark"
|
||||
|
||||
const defaultTheme = getCurrentMedia()
|
||||
|
||||
const ThemeContext = createContext<"light" | "dark">(defaultTheme)
|
||||
|
||||
export const useTheme = () => useContext(ThemeContext)
|
||||
|
||||
const theme$ = state(
|
||||
fromEvent<MediaQueryListEvent>(
|
||||
window.matchMedia("(prefers-color-scheme: dark)"),
|
||||
"change",
|
||||
).pipe(map((evt) => (evt.matches ? "dark" : "light"))),
|
||||
defaultTheme,
|
||||
)
|
||||
|
||||
export const ThemeProvider: FC<PropsWithChildren> = ({ children }) => {
|
||||
const theme = useStateObservable(theme$)
|
||||
|
||||
useLayoutEffect(() => {
|
||||
if (theme === "dark") {
|
||||
document.body.classList.add("dark")
|
||||
} else {
|
||||
document.body.classList.remove("dark")
|
||||
}
|
||||
}, [theme])
|
||||
|
||||
return <ThemeContext.Provider value={theme}>{children}</ThemeContext.Provider>
|
||||
}
|
||||
@@ -110,7 +110,7 @@ export const CStruct: ViewStruct = ({
|
||||
<ul
|
||||
className={twMerge(
|
||||
"flex flex-col w-full",
|
||||
hasParentTitle && "border-l border-primary",
|
||||
hasParentTitle && "border-l border-treeBorder",
|
||||
)}
|
||||
>
|
||||
{Object.entries(innerComponents).map(([name, jsx]) => (
|
||||
|
||||
@@ -5,26 +5,31 @@ import ReactJson from "react18-json-view"
|
||||
import "react18-json-view/src/dark.css"
|
||||
import "react18-json-view/src/style.css"
|
||||
import "./jsonDisplay.css"
|
||||
import { useTheme } from "@/ThemeProvider"
|
||||
|
||||
export const JsonDisplay: FC<{
|
||||
src: unknown
|
||||
}> = ({ src }) => (
|
||||
<ReactJson
|
||||
src={src}
|
||||
dark
|
||||
theme="a11y"
|
||||
replacer={(v) => (v instanceof Binary ? bytesToString(v) : v)}
|
||||
customizeCopy={(v) =>
|
||||
JSON.stringify(
|
||||
v,
|
||||
(_, v) =>
|
||||
typeof v === "bigint"
|
||||
? `${v}n`
|
||||
: v instanceof Binary
|
||||
? bytesToString(v)
|
||||
: v,
|
||||
2,
|
||||
)
|
||||
}
|
||||
/>
|
||||
)
|
||||
}> = ({ src }) => {
|
||||
const theme = useTheme()
|
||||
|
||||
return (
|
||||
<ReactJson
|
||||
src={src}
|
||||
dark={theme === "dark"}
|
||||
theme="a11y"
|
||||
replacer={(v) => (v instanceof Binary ? bytesToString(v) : v)}
|
||||
customizeCopy={(v) =>
|
||||
JSON.stringify(
|
||||
v,
|
||||
(_, v) =>
|
||||
typeof v === "bigint"
|
||||
? `${v}n`
|
||||
: v instanceof Binary
|
||||
? bytesToString(v)
|
||||
: v,
|
||||
2,
|
||||
)
|
||||
}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
13
src/main.tsx
13
src/main.tsx
@@ -9,16 +9,19 @@ import { TooltipProvider } from "./components/Tooltip.tsx"
|
||||
import "./index.css"
|
||||
import { explorer$ } from "./pages/Explorer"
|
||||
import { transactions$ } from "./pages/Transactions"
|
||||
import { ThemeProvider } from "./ThemeProvider.tsx"
|
||||
|
||||
createRoot(document.getElementById("root")!).render(
|
||||
<Subscribe source$={merge(dynamicBuilder$, explorer$, transactions$)}>
|
||||
<RemoveSubscribe>
|
||||
<StrictMode>
|
||||
<BrowserRouter>
|
||||
<TooltipProvider>
|
||||
<App />
|
||||
</TooltipProvider>
|
||||
</BrowserRouter>
|
||||
<ThemeProvider>
|
||||
<BrowserRouter>
|
||||
<TooltipProvider>
|
||||
<App />
|
||||
</TooltipProvider>
|
||||
</BrowserRouter>
|
||||
</ThemeProvider>
|
||||
</StrictMode>
|
||||
</RemoveSubscribe>
|
||||
</Subscribe>,
|
||||
|
||||
@@ -57,7 +57,7 @@ export const BlockPopover: FC<{ hash: string }> = ({ hash }) => {
|
||||
Block
|
||||
<Link
|
||||
to={hash}
|
||||
className="font-mono font-normal text-primary/70 hover:text-primary"
|
||||
className="font-mono font-normal text-primary/70 hover:text-primary underline"
|
||||
>
|
||||
{hash.slice(0, 18)}…
|
||||
</Link>
|
||||
|
||||
@@ -266,7 +266,7 @@ const BlockLink: FC<{ hash: string }> = ({ hash }) => {
|
||||
|
||||
return (
|
||||
<Link
|
||||
className="text-primary/70 hover:text-primary align-middle inline-flex items-center gap-1"
|
||||
className="text-primary/70 hover:text-primary align-middle inline-flex items-center gap-1 underline"
|
||||
to={`../${hash}`}
|
||||
>
|
||||
{<BlockStatusIcon state={block.status} size={20} />}
|
||||
|
||||
@@ -13,7 +13,7 @@ export const EventPopover: FC<{ event: EventInfo }> = ({ event }) => {
|
||||
Event{" "}
|
||||
<Link
|
||||
to={`${event.hash}#event=${event.index}`}
|
||||
className="text-primary/70 hover:text-primary"
|
||||
className="text-primary/70 hover:text-primary underline"
|
||||
>
|
||||
{eventKey(event)}
|
||||
</Link>
|
||||
|
||||
@@ -2,7 +2,7 @@ import { groupBy } from "@/lib/groupBy"
|
||||
import type { SystemEvent } from "@polkadot-api/observable-client"
|
||||
import { state } from "@react-rxjs/core"
|
||||
import { combineKeys } from "@react-rxjs/utils"
|
||||
import { filter, map, takeWhile, tap } from "rxjs"
|
||||
import { filter, map, takeWhile } from "rxjs"
|
||||
import { blockInfo$, BlockState, recordedBlocks$ } from "./block.state"
|
||||
import { MAX_LENGTH } from "./BlockTable"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user