Isaiah

BJORK Order book

Component

About

Order book is a production-ready charts component from BJORK UI, packaged for shadcn registries.

Built with React and Tailwind. Copy the prompt and paste it into Claude Code, Cursor or Lovable: your agent adds BJORK Order book to your project and fits it to your theme.

Code

How BJORK Order book is used: the demo's code. The component's own source comes with a free account.

Usage.tsx

"use client";
import { ThemeProvider as BjorkDemoThemeProvider } from "next-themes";
import { useEffect, useMemo, useRef, useState } from "react";
import { OrderBook, createOrderBookFeed, type MyOrder, type OrderBookHandle, type OrderBookLayout, type OrderBookFeed, type OrderBookLevelInfo, type OrderBookSnapshot } from "@/components/ui/bjork-order-book";
import { DepthChart } from "@/components/ui/bjork-order-book-utils/components-bjork-ui-charts-depth-chart";
import { formatFixed } from "@/components/ui/bjork-order-book-utils/components-bjork-ui-charts-_kit-scale";
import { DemoColumn } from "@/components/ui/bjork-order-book-utils/app-charts-_demo-controls";

const TICKS = [0.05, 0.1, 0.25, 0.5, 1];

const PREVIEW = (() => {
  const feed = createOrderBookFeed({ seed: 11 });
  let last: number | undefined;
  for (let i = 0; i < 40; i++) last = feed.step().last ?? last;
  return { ...feed.snapshot(), last };
})();

function myOrdersAround(book: OrderBookSnapshot): MyOrder[] {
  const b = book.bids[3]?.price;
  const a = book.asks[5]?.price;
  return [
    ...(b !== undefined ? [{ id: "o1", side: "bid" as const, price: b, size: 40 }] : []),
    ...(a !== undefined ? [{ id: "o2", side: "ask" as const, price: a, size: 25 }] : []),
  ];
}

function LiveBook({
  feed,
  layout,
  rows,
  live,
  mine,
}: {
  feed: OrderBookFeed;
  layout: OrderBookLayout;
  rows: number;
  live: boolean;
  mine: boolean;
}) {
  const bookRef = useRef<OrderBookHandle>(null);
  const [picked, setPicked] = useState<OrderBookLevelInfo | null>(null);
  const [depth, setDepth] = useState<OrderBookSnapshot>(() => feed.snapshot());
  const myOrders = useMemo(() => (mine ? myOrdersAround(feed.snapshot()) : undefined), [mine, feed]);

  // The feed stands in for an exchange socket: one snapshot, then deltas.
  useEffect(() => feed.subscribe((msg) => bookRef.current?.apply(msg)), [feed]);
  useEffect(() => feed.setPaused(!live), [feed, live]);

  // The depth chart reads the same book, twice a second.
  useEffect(() => {
    if (!live) return;
    const id = setInterval(() => {
      const snap = bookRef.current?.getSnapshot();
      if (snap) setDepth(snap);
    }, 500);
    return () => clearInterval(id);
  }, [live]);

  return (
    <>
      <div className="flex flex-wrap items-start gap-x-8 gap-y-10">
        <div className={layout === "side-by-side" ? "w-full" : "w-full min-w-0 max-w-[440px] flex-1 basis-[360px]"}>
          <OrderBook
            ref={bookRef}
            layout={layout}
            rows={rows}
            tickSizes={TICKS}
            priceLabel="Price (USD)"
            sizeLabel="Size (KSTL)"
            myOrders={myOrders}
            onPriceSelect={setPicked}
            ariaLabel="KSTL-USD order book"
          />
        </div>
        {layout !== "side-by-side" && (
          <div className="min-w-0 flex-[1.4] basis-[320px]">
            <DepthChart bids={depth.bids} asks={depth.asks} height={300} ariaLabel="KSTL-USD depth" />
          </div>
        )}
      </div>
      <p aria-live="polite" className="min-h-4 text-center font-mono text-[11px] tabular-nums text-[color:var(--bjork-text-muted)]">
        {picked
          ? `Limit ${picked.side === "ask" ? "buy" : "sell"} ${formatFixed(picked.price, 2)} · ${picked.size.toLocaleString("en-US")} on the level`
          : "Click a level to fill the order ticket"}
      </p>
    </>
  );
}
function SourceDemo(){
const isPreview = false;
const feed = useMemo(() => createOrderBookFeed({ seed: 7 }), []);
const [layout, setLayout] = useState<OrderBookLayout>("auto");
const [rows, setRows] = useState(8);
const [live, setLive] = useState(true);
const [mine, setMine] = useState(true);
function resetControls() {
    setLayout("auto");
    setRows(8);
    setLive(true);
    setMine(true);
  }
return <>

      {isPreview ? (
        <div className="w-[740px]">
          <OrderBook
            bids={PREVIEW.bids}
            asks={PREVIEW.asks}
            lastPrice={PREVIEW.last}
            layout="side-by-side"
            rows={10}
            tickSizes={TICKS}
            priceLabel="Price (USD)"
            sizeLabel="Size (KSTL)"
            myOrders={myOrdersAround(PREVIEW)}
            showImbalance
            ariaLabel="KSTL-USD order book"
          />
        </div>
      ) : (
        <DemoColumn width={960}>
          <LiveBook feed={feed} layout={layout} rows={rows} live={live} mine={mine} />
        </DemoColumn>
      )}
    
</>;
}
export default function BjorkRegistryPreview(){return <BjorkDemoThemeProvider attribute="class" defaultTheme="dark" enableSystem={false} storageKey="bjork-review-demo-theme"><div data-component-demo className="dark flex min-h-screen w-full items-center justify-center bg-[var(--bjork-bg)] p-8 text-[var(--bjork-text)]"><div className="w-full max-w-[850px]"><SourceDemo/></div></div></BjorkDemoThemeProvider>}

Dependencies

More by Isaiah

View all
  • Agent Plan

    Agent Plan

    2.2K
  • Video Scroll Hero

    Video Scroll Hero

    1.4K
  • Voice Powered Orb

    Voice Powered Orb

    1.3K
  • Reveal Text

    Reveal Text

    1.1K
  • Leads Data Table

    Leads Data Table

    935
  • Portfolio Gallery

    Portfolio Gallery

    923
  • Message Dock

    Message Dock

    833
  • Ruler Carousel

    Ruler Carousel

    618