---
title: "SeatPicker reference"
description: "Complete buyer widget options, callbacks, methods, checkout handoff, modal mode, 3D, holds, and responsive behavior."
---

> Documentation Index
> Fetch the complete documentation index at: https://docs.seatlayer.io/llms.txt
> Use this file to discover all available pages before exploring further.

# SeatPicker reference

`SeatPicker` is the complete buyer experience: live map, confirmation, tier/GA
controls, selection tray, hold countdown, best available, 2D/3D, view from seat,
mobile bottom sheet, sold-out/closed states, and checkout handoff.

```js title="browser/picker.js"
import { SeatPicker } from "@seatlayer/js";

const picker = new SeatPicker({
  container: "#picker",
  event: "ev_9f3a",
  onCheckout: (_hold, _seats, handoff) => {
    startCheckout({ holdId: handoff.holdId });
  },
});

await picker.render();
```

## Choose the surface

| | `SeatPicker` | `SeatingChart` |
|---|---|---|
| Map canvas | Included | Included |
| Cart/tray, CTA, timer, states | Included | Host builds |
| Seat confirmation and 360 view | Included | Host builds |
| Modal helper | `SeatPicker.open()` | No |
| Best for | Complete, styleable buyer flow | Fully custom cart and controls |

## Constructor options

| Option | Type | Default/notes |
|---|---|---|
| `container` | `string \| HTMLElement` | Required inline; omit for `open()` |
| `event` | `string` | Required event key |
| `apiBase` | `string` | `https://api.seatlayer.io` |
| `transport` | `PickerTransport` | Built-in public transport; useful for controlled adapters/tests |
| `publicKey` | `string` | Reserved; not current browser authorization |
| `maxSelection` | `number` | `10` |
| `locale` | `string` | Browser language → `en`; built-in `en`, `es`, `de`, `fr` |
| `messages` | `Record<string,string>` | Per-message copy overrides |
| `currency` | `string` | `USD` fallback; event/org data wins |
| `colorblindSafe` | `boolean` | `false` |
| `initialView` | `RendererViewMode` | Use `flat`; legacy perspective values are deprecated |
| `enable3D` | `boolean` | `true` when WebGL2 is available |
| `onAnalytics` | `(event, props) => void` | Optional Preview 3D journey sink |
| `hideBadge` | `boolean` | Host preference; entitlement/chart theme also applies |
| `theme` | `SeatPickerTheme` | Partial host overrides |
| `pricing` | `SeatPickerPricing` | Buyer display overrides; not server ledger authority |
| `holdTtlMs` | `number` | Sent to hold; server clamps |
| `initialHoldId` | `string` | Verify/restore an existing event hold |
| `restoreHold` | `boolean` | `true`; uses per-event session storage |
| `confirmSelection` | `boolean` | `true` |
| `seatView` | `boolean` | `true` |

## Callbacks

| Callback | Signature | Meaning |
|---|---|---|
| `onCheckout` | `(hold, seats, handoff) => void` | Hold succeeded and buyer chose checkout |
| `onBooked` | `(handoff) => void` | Realtime state confirms this handed-off hold was booked |
| `onSelectionChange` | `(seats) => void` | Selection changes |
| `onHoldChange` | `(hold, seats, handoff) => void` | Hold created/restored/extended/partially released/released |
| `onHoldExpired` | `() => void` | Current hold expired and widget reset |
| `onHoldRestored` | `(hold, seats, handoff) => void` | Prior hold verified and restored |
| `onClose` | `() => void` | Modal closes |
| `onError` | `(error) => void` | Render/transport operation fails |

Use the third `onCheckout` argument for new integrations:

```ts
interface CheckoutHandoff {
  holdId: string;
  expiresAt: number;
  currency: string;
  lineItems: CheckoutLineItem[];
  total: number;
}

interface CheckoutLineItem {
  label: string;
  displayLabel?: string;
  displayType?: string;
  objectId: string;
  objectType: "seat" | "booth" | "ga" | "table";
  categoryKey: string;
  tierId: string | null;
  unitPrice: number;
  currency: string;
  quantity: number;
}
```

The browser handoff is excellent display context, but payment still uses a fresh
server hold inspection.

## Public methods

| Method | Result |
|---|---|
| `render()` | `Promise<this>` |
| `close()` | Close modal or destroy inline picker |
| `getSelection()` | Current `PickerSeat[]` |
| `isColorblindSafe()` | Current accessible palette state |
| `setColorblindSafe(on)` | Change accessible palette state |
| `setViewMode(mode)` / `getViewMode()` | Legacy 2D renderer mode compatibility |
| `getBuyerView()` | `"map" \| "venue3d"` |
| `setBuyerView(view, { flyToSeatId? })` | Switch buyer surface/programmatic 3D tour |
| `getCurrentHold()` | `HoldResult \| null` |
| `resumeHold(holdId)` | Verify and restore a hold |
| `removeHeldTicket(label)` | Remove one held item and keep the rest |
| `bestAvailable(qty, categoryKey?, options?)` | Hold a server-selected group |
| `release()` | Release current hold and reset |
| `destroy()` | Remove DOM, socket, listeners, and timers |

## Modal mode

```js
const picker = await SeatPicker.open({
  event: "ev_9f3a",
  onCheckout: (_hold, _seats, handoff) => {
    startCheckout({ holdId: handoff.holdId });
  },
  onClose: () => restoreHostUI(),
});

picker.close();
```

The modal traps focus, closes through Escape/scrim/close button, restores scroll
and prior focus, and fires `onClose`.

## Holds and restore

The picker persists the current hold id in `sessionStorage` by default. On a
return visit it verifies that hold against the same event before showing it as
owned.

Set `restoreHold: false` when your router/cart owns persistence, then supply
`initialHoldId` or call `resumeHold()`. Clear host cart state when
`onHoldChange(null, …)` fires.

The built-in countdown offers an extension in the final minute and resets on
confirmed extension. Server limits and renewal caps remain authoritative.

## Buyer 3D and analytics

`enable3D` controls whether the Map/3D affordance is offered. The 3D module is
lazy-loaded only after use and falls back to the complete 2D experience when
WebGL2 is unavailable.

Use `setBuyerView("venue3d", { flyToSeatId })` for a guided tour and
`onAnalytics` to forward Preview journey events to your own system.

See [3D buyer view](/buyer-sdk/3d-view) and
[buyer analytics](/buyer-sdk/analytics).

## Responsive behavior

Layout responds to the picker container, not only the viewport:

- wide containers show a side panel and docked details;
- narrow containers use a bottom sheet and touch-first map controls; and
- fullscreen uses the native API or a platform fallback.

Give the container a definite height. Test the actual embed width, mobile browser
chrome, keyboard, reduced motion, and colorblind-safe mode.

## Lifecycle checklist

- [ ] Construct once per mounted host view.
- [ ] Await `render()` and expose failures through `onError`.
- [ ] Send only `holdId` to the booking server boundary.
- [ ] Clear host state when the hold disappears.
- [ ] Use stable order ids for booking retries.
- [ ] Call `destroy()` during application unmount.
- [ ] Test inline/modal, narrow/wide, 2D/no-WebGL, expiry, and conflict paths.

Continue with [holds and checkout](/buyer-sdk/holds-and-checkout),
[customization](/customization/buyer-experience), or the
[SeatingChart reference](/buyer-sdk/seating-chart).

Source: https://docs.seatlayer.io/buyer-sdk/seat-picker/index.mdx
