The day-grouped event and ticket list that powers the cart drawer's body. It's
exported on its own so you can render it on a full /cart page.
container: the drawer body, or a full page with a Cart
header (ticket count + live expiry) and a sticky footerformatSeatRangeCartDetails and it renders. It has no overlay
and does no fetchingIt's the same component CartDrawer renders internally, so a /cart page and
the docked drawer stay visually identical over one shared core.
This is how a /cart page would use it: in a normal page column, with no
overlay. The frame below is a fixed-height "page area". Use the React / Vue tabs to compare
the skins, and the controls to test:
container switches the layout. page fills the frame with a Cart header
(ticket count + live expiry), a sticky edge-to-edge footer, and a centred empty
state. drawer is the body-only list (no header/footer) for embedding in your
own chrome.pnpm add @oztix/roadie-widgets
CartContents is presentational, so it needs lighter peers than the full drawer (no react-query). Install the peers for the skin you use.
React
pnpm add react react-dom @oztix/roadie-components motion @number-flow/react \@phosphor-icons/react
Vue
pnpm add vue @number-flow/vue @phosphor-icons/vue focus-trap
CartContents' classes live in the package's compiled output, so Tailwind needs to scan it. Otherwise the styles never make it into your CSS. Add the CSS imports for the skin you use to your global stylesheet.
React. The React skin renders @oztix/roadie-components, so include its CSS
as well:
/* app/globals.css */@import '@oztix/roadie-core/css';@import '@oztix/roadie-components/css';@import '@oztix/roadie-widgets/css';
Vue. The Vue skin uses core classes only, so it needs no components CSS:
/* app/globals.css */@import '@oztix/roadie-core/css';@import '@oztix/roadie-widgets/css';
Each package's CSS ships its own @source, so Tailwind scans the compiled
classes without you ever writing a node_modules path.
// Reactimport { CartContents } from '@oztix/roadie-widgets/cart-contents/react'import type { CartDetails } from '@oztix/roadie-widgets/cart-contents/react'
// Vueimport { CartContents } from '@oztix/roadie-widgets/cart-contents/vue'
Either entry pulls in only the list. It brings none of the drawer's overlay, drag, focus-trap, or expiry code. The cart drawer composes this same component, so the standalone page and the docked drawer stay identical.
Pass a CartDetails and the presentational props; the host owns data fetching
and routing. Build a CartDetails however you like, or reuse the shared cart
client:
container is the layout preset. drawer (default) is the body-only list
(no header or footer, natural height) for embedding in your own chrome. It's
what CartDrawer renders. page is the full /cart experience: a fill-height
column with a Cart header (ticket count + live expiry), a sticky
edge-to-edge footer pinned to the bottom, and a centred empty state. Give the
parent a height (e.g. <div className="min-h-full">). You don't need an
external flex-1, mt-auto, or justify-center.
onRemoveEvent / busy wire per-event removal. busy disables the
trash triggers while a remove is in flight.
removingEventId takes the event you're deleting for the duration of
your async remove. CartContents dims the whole list and shows a danger
Removing… overlay on that event until it leaves cart. Pair it with your
remove handler:
Vue is identical. Bind :removing-event-id="removingId" and handle
@remove-event.
When cart has no tickets, CartContents renders the empty state with the
browseHref call to action. Under container="page" it's centred and uses the
larger (md) empty-state size; the drawer preset uses the compact (sm) size.
Removing the last event animates the list out and the empty state in.
App-specific browse target for the empty state.
Pre-validated checkout URL. Null when the safety check failed — CTA disabled.
Layout preset. `drawer` (default) is body-only; `page` adds the header, sticky footer and fill-height.
Defaults to drawer.
Optional per-event remove handler. Receives the `eventId`.
True while a remove is in flight — disables the trash triggers.
Defaults to false.
Event currently being removed. Dims the list and shows a "Removing…" overlay on that event until it leaves `cart`. Set it for the duration of your async remove.
Defaults to null.