Isaiah

BJORK Flap ledger

Component

About

Flap ledger is a production-ready tables 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 Flap ledger to your project and fits it to your theme.

Code

How BJORK Flap ledger 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 { useCallback, useMemo, useRef, useState, useSyncExternalStore } from "react";
import { useVisibleLoop } from "@/components/ui/bjork-flap-ledger-utils/components-bjork-ui-_core-loop";
import { FLAP_LEDGER_SAMPLE_ROWS, FlapLedger, type FlapColumn, type FlapRow, type FlapStatus } from "@/components/ui/bjork-flap-ledger";

const columns: FlapColumn[] = [
  { key: "time", header: "Time", width: 5, charset: "0123456789: " },
  { key: "flight", header: "Flight", width: 6, charset: "alnum" },
  { key: "destination", header: "Destination", width: 12, charset: "alpha" },
  { key: "gate", header: "Gate", width: 3, charset: "alnum" },
  { key: "status", header: "Status", width: 11, charset: ["ON TIME", "BOARDING", "DELAYED", "GATE CLOSED", "DEPARTED"] },
];

const statusLed = (row: FlapRow): FlapStatus => {
  if (row.status === "ON TIME" || row.status === "BOARDING") return "ok";
  if (row.status === "DELAYED" || row.status === "GATE CLOSED") return "warn";
  return "off";
};

const narrowQuery = "(max-width: 639px)";

function subscribeNarrow(onChange: () => void) {
  const query = window.matchMedia(narrowQuery);
  query.addEventListener("change", onChange);
  return () => query.removeEventListener("change", onChange);
}

function useNarrowViewport() {
  return useSyncExternalStore(
    subscribeNarrow,
    () => window.matchMedia(narrowQuery).matches,
    () => false,
  );
}

const sizes = ["sm", "md", "lg"] as const;

const cascades = ["changed", "left", "right"] as const;
function SourceDemo(){
const isPreview = false;
const previewTheme = null;
const attractParam = null === "1";
const tone = previewTheme === "light" || previewTheme === "dark" ? previewTheme : undefined;
const [sizeChoice, setSizeChoice] = useState<(typeof sizes)[number]>("sm");
const [cascade, setCascade] = useState<(typeof cascades)[number]>("changed");
const narrow = useNarrowViewport();
const size = isPreview ? "md" : narrow ? "sm" : sizeChoice;
const [step, setStep] = useState(0);
const [wrapEl, setWrapEl] = useState<HTMLDivElement | null>(null);
const wrapRef = useMemo(() => ({ current: wrapEl }), [wrapEl]);
const accRef = useRef(0);
const tick = useCallback((dt: number) => {
    accRef.current += dt;
    if (accRef.current >= 6) {
      accRef.current = 0;
      setStep((s) => (s + 1) % FLAP_LEDGER_SAMPLE_ROWS.length);
    }
  }, []);
useVisibleLoop(wrapRef, tick, { enabled: !isPreview && !attractParam });
const rows = FLAP_LEDGER_SAMPLE_ROWS[isPreview ? 0 : step];
return <>

      <div ref={setWrapEl} className="w-full min-w-0">
        <FlapLedger
          columns={columns}
          rows={rows}
          size={size}
          cascadeFrom={cascade}
          status={statusLed}
          ariaLabel="Departures"
          tone={tone}
          attract={attractParam}
        />
      </div>
    
</>;
}
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.4K
  • Reveal Text

    Reveal Text

    1.1K
  • Leads Data Table

    Leads Data Table

    943
  • Portfolio Gallery

    Portfolio Gallery

    939
  • Message Dock

    Message Dock

    842
  • Ruler Carousel

    Ruler Carousel

    628