caliper uidocs

Prediction market

Block

Outcomes with probabilities and a way to take a position.

Installs components/ui/prediction-market.tsxDepends on @radix-ui/react-slot, lucide-reactMotion shared motion tokens
pnpm dlx shadcn@latest add https://caliperui.site/r/prediction-market.json

Will the new library ship before December?

Resolves Yes if version 3.0 is published by 23:59 on November 30.

Volume $184KCloses Nov 30

Outcome

Price per share
62¢
Shares
—
If Yes happens, you receive
—

Prices are chances, not promises. If you are wrong you lose what you spend. Sample market for demonstration.

When to use #

Use it for

  • Showing a market on a question.

Skip it when

  • Real money is involved without confirmations.

Installation #

terminal
pnpm dlx shadcn@latest add https://caliperui.site/r/prediction-market.json

Adds its 10 files to components/ui/, each with its own stylesheet, and installs their packages. No account needed. The first part also adds Caliper UI’s tokens; import them once as in Installation.

Usage #

This is the code behind the preview above.

example.tsx
import { PredictionMarket } from "@/components/ui/prediction-market"

const wait = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));

export function PredictionMarketDemo() {
  return (
    <PredictionMarket
            question="Will the new library ship before December?"
            description="Resolves Yes if version 3.0 is published by 23:59 on November 30."
            outcomes={[
              { id: "yes", label: "Yes", price: 0.62, change: 0.04 },
              { id: "no", label: "No", price: 0.38, change: -0.04 },
            ]}
            volume={184000}
            closes="Closes Nov 30"
            balance={250}
            onTrade={async ({ amount }) => {
              await wait(900);
              if (amount > 200) return { error: "Orders above $200 need a second approval in this demo." };
            }}
          />
  );
}

API reference #

PredictionMarket

component
PropTypeDefaultDescription
question *string—
descriptionstring—
outcomes *readonly MarketOutcome[]—
volume *number—
closes *string—Readable close time, such as "Closes Dec 1".
balance *number—Spendable balance.
currencystring"USD"
onTrade *(order: { outcomeId: string; amount: number; shares: number; }) => TradeResult | Promise<TradeResult>—
classNamestring—

Accessibility #

It exposes status semantics, with aria-label and aria-hidden kept in step with state. Changes that matter are announced through a live region.

No custom key handling; Tab and the native activation keys do the work.

Motion #

Transitions use the shared duration and easing tokens. Under prefers-reduced-motion those tokens collapse to instant and travel distances go to zero, so state changes still happen without movement.