<ReservationSummary>
Post-reservation breakdown. Reads useReservation().data, groups
the server-confirmed holds by ticket-type ID (preserving
wave-level splits), resolves human-readable names from
useAvailability(), and renders via the same <BreakdownTree>
primitive <EstimateBreakdown> uses — so the visual contract is
identical pre- and post-reservation.
Import
import { ReservationSummary } from "@feelrift/react";
Basic usage
import { ReservationSummary, RiftEvent, RiftProvider } from "@feelrift/react";
<RiftProvider>
<RiftEvent eventId="evt_summerfest_2026">
<ReservationSummary />
</RiftEvent>
</RiftProvider>;
Props
Accepts all HTMLAttributes<HTMLDivElement> plus:
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
asChild | boolean | No | false | Swap the root element via Radix Slot. |
children | ReactNode | No | — | Replace the default rendering. Composed inside the SDK's wrapper. |
emptyFallback | ReactNode | No | null | Rendered when there is no active reservation. |
disclaimer | ReactNode | null | No | Locale string estimate.disclaimer | Override the disclaimer rendered near the total. Pass null to hide entirely. |
className | string | No | — | Appended to the SDK's rift-reservation-summary class. |
…rest | HTMLAttributes<HTMLDivElement> | No | — | Forwarded to the root element. |
emptyFallback
Rendered when useReservation().data === null — typically the
pre-reserve state or after clearReservation() runs. Pass a
placeholder string or skeleton when the surrounding layout needs
content; leave as the default null when the component should
simply vanish until a reservation exists.
disclaimer
Same default as <EstimateBreakdown>:
"We pick the cheapest available tier first. Final price (including any fees) is confirmed when you reserve."
Visible post-reservation too because checkout may add modifier
steps (platform fees, taxes) the reservation breakdown doesn't
include. Override per-instance, globally via
<RiftProvider strings={{ "estimate.disclaimer": "…" }}>, or
hide with disclaimer={null}.
Render output
Default rendering uses <BreakdownTree> — same shape as
<EstimateBreakdown>:
General admission
1× Early bird $80.00
1× Regular $100.00
Subtotal $180.00
VIP
2× Standard $400.00
─────────────────────────────────
Total $580.00
We pick the cheapest available tier first. Final price
(including any fees) is confirmed when you reserve.
When a ticket type spans exactly one wave, the subtotal row is omitted (one line already shows the total for that type). When it spans multiple waves, both the per-line price and the subtotal appear so the math is legible.
Prices format via useLocale().formatCurrency against the
reservation's currency.
Behavior
- Data source. Reads
useReservation().reservation(server-confirmed holds withwaveIdcarried per hold),useReservation().breakdown(the server's modifier-inclusive pricing engine output), anduseAvailability().data(cached availability tree for name lookup). - Total vs subtotal. When the breakdown is present, the
component renders the modifier steps (fees, taxes) and the
modifier-inclusive
Total. When the breakdown is missing (e.g. rehydrated from an older session before the breakdown was persisted), it falls back to the line-items-only subtotal plus the disclaimer. - Name resolution. Wave and ticket-type names come from the cached availability tree. If availability hasn't loaded yet, falls back to IDs — better than rendering nothing.
- No fetch trigger. Mounting doesn't issue any requests; the
reservation is created by
<ReserveButton>oruseReservation().createReservation(). - Source of truth. Line items shown come from the reservation
response. The estimate the UI captured at reservation time is
NOT shown here — its purpose is reconciliation, surfaced by
<PriceChangedWarning>. - Persisted across reloads. The reservation is part of the SDK's persistent state; this component paints the same data after a refresh as long as the reservation hasn't expired.
Examples
Default rendering
<ReservationSummary />
Renders the tree as soon as a reservation exists. Names resolved automatically.
With an empty-state placeholder
<ReservationSummary emptyFallback={<p>Reserve to see the breakdown.</p>} />
Custom rendering
import { ReservationSummary, useLocale, useReservation } from "@feelrift/react";
function CompactSummary() {
const reservation = useReservation().data;
const { formatCurrency } = useLocale();
if (!reservation) return null;
const totalCount = reservation.holds.reduce((s, h) => s + h.quantity, 0);
return (
<ReservationSummary>
<p>
{totalCount} ticket{totalCount === 1 ? "" : "s"}:{" "}
<strong>{formatCurrency(reservation.subtotal)}</strong>
</p>
</ReservationSummary>
);
}
Hide the disclaimer (you display equivalent copy elsewhere)
<ReservationSummary disclaimer={null} />
Related
<EstimateBreakdown>— the pre-reservation counterpart, same render primitive.useReservation— underlying data source. Public types exported from@feelrift/react.<PriceChangedWarning>— surfaces estimate-vs-actual deltas.<Countdown>— usually rendered alongside.- Pricing and estimates — the wave-tier model, the disclaimer's purpose post-reservation.