Isaiah

BJORK Approval gate

Component

About

Approval gate is a production-ready ai 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 Approval gate to your project and fits it to your theme.

Code

How BJORK Approval gate 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 { useState } from "react";
import { ApprovalGate, SAMPLE_APPROVAL_REQUESTS, type ApprovalDecision } from "@/components/ui/bjork-approval-gate";

const RISKS = ["high", "medium", "low"] as const;

type Risk = (typeof RISKS)[number];

const DEFAULT_RISK: Risk = "high";

const DEFAULT_TIMEOUT = true;

function Demo({
  risk,
  timeout,
  run,
  last,
  onDecision,
}: {
  risk: Risk;
  timeout: boolean;
  run: number;
  last: ApprovalDecision | null;
  onDecision: (decision: ApprovalDecision) => void;
}) {
  const isPreview = false;
  const request = SAMPLE_APPROVAL_REQUESTS.find((r) => r.risk === risk) ?? SAMPLE_APPROVAL_REQUESTS[0];

  if (isPreview) {
    return (
      <div className="w-[min(540px,calc(100vw-56px))]">
        <ApprovalGate
          request={SAMPLE_APPROVAL_REQUESTS[0]}
          requireHold
          timeoutMs={30_000}
          pose={{ hold: 0.58, remaining: 0.64 }}
        />
      </div>
    );
  }

  return (
    <div className="flex w-[min(540px,calc(100vw-56px))] flex-col items-stretch gap-6">
      <ApprovalGate
        key={`${run}-${risk}-${timeout}`}
        request={request}
        requireHold
        timeoutMs={timeout ? 30_000 : undefined}
        onDecision={onDecision}
      />
      <p className="min-h-5 text-center font-mono text-[11px] text-[color:var(--bjork-text-faint)]">
        {last
          ? `onDecision → ${last.status}${last.reason ? ` · "${last.reason}"` : ""}${last.alwaysAllow ? " · always allow" : ""}`
          : "High risk asks you to hold Approve. Hover the card to pause the countdown."}
      </p>
    </div>
  );
}
function SourceDemo(){
const [risk, setRisk] = useState<Risk>(DEFAULT_RISK);
const [timeout, setTimeoutOn] = useState(DEFAULT_TIMEOUT);
const [run, setRun] = useState(0);
const [last, setLast] = useState<ApprovalDecision | null>(null);
const reset = () => {
    setRisk(DEFAULT_RISK);
    setTimeoutOn(DEFAULT_TIMEOUT);
    setLast(null);
    setRun((r) => r + 1);
  };
return <>

      <Demo risk={risk} timeout={timeout} run={run} last={last} onDecision={setLast} />
    
</>;
}
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

    617