Price target fan
FreeA price history that fans out into a forecast range.
pnpm dlx shadcn@latest add https://caliperui.site/r/price-target-fan.json- Bear
- 120 −11.1%
- Median
- 152 +12.6%
- Bull
- 188 +39.3%
| Date | Price or median | Low | High |
|---|---|---|---|
| 2026-01-01 | 100 | ||
| 2026-02-01 | 105 | ||
| 2026-03-01 | 110 | ||
| 2026-04-01 | 110 | ||
| 2026-05-01 | 115 | ||
| 2026-06-01 | 115 | ||
| 2026-07-01 | 120 | ||
| 2026-08-01 | 125 | ||
| 2026-09-01 | 125 | ||
| 2026-10-01 | 130 | ||
| 2026-11-01 | 130 | ||
| 2026-12-01 | 135 | ||
| 2027-02-01 | 140 | 128 | 152 |
| 2027-05-01 | 146 | 124 | 170 |
| 2027-08-01 | 152 | 120 | 188 |
When to use #
Use it for
- Analyst targets and projections with a low, mid and high.
- Showing uncertainty growing with time.
Skip it when
- There is no forecast; use a line chart.
Installation #
terminal
pnpm dlx shadcn@latest add https://caliperui.site/r/price-target-fan.json
Adds its 3 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 { PriceTargetFan } from "@/components/ui/price-target-fan" export function TargetFan() { const history = Array.from({ length: 12 }, (_, index) => ({ date: `2026-${String(index + 1).padStart(2, "0")}-01`, value: 100 + index * 3 + ((index * 7) % 5) })); const forecast = [ { date: "2027-02-01", low: 128, mid: 140, high: 152 }, { date: "2027-05-01", low: 124, mid: 146, high: 170 }, { date: "2027-08-01", low: 120, mid: 152, high: 188 }, ]; return ( <div className="w-full max-w-xl"> <PriceTargetFan label="Price and analyst targets" history={history} forecast={forecast} /> </div> ); }
API reference #
PriceTargetFan
component
PropTypeDefaultDescription
label *string—
history *readonly PricePoint[]—
forecast *readonly PriceForecast[]—Future dates, ascending. The fan opens from the last historical value.
formatValue((value: number) => string)numberText
loadingboolean—
errorstring—
classNamestring—
Accessibility #
It exposes group and status semantics, with aria-label, aria-busy 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 #
It declares no animation in its component source. Any transition comes from its stylesheet, which uses the duration tokens that collapse to instant under prefers-reduced-motion.