Skip to content

Interactive Answers

Slot Picker

Pick a time the agent proposed — days, free slots, time zone and a confirm step.

2 variantsMIT

Preview

Design review with Ana

Times in Lisbon (UTC+0)

Suggested Busy

Installation

Copies the component into components/ui and installs its dependencies and theme tokens.

pnpm dlx shadcn@latest add https://tuffui.com/r/slot-picker.json

Usage

Pass your own data and wire the callbacks to your agent runtime.

import { SlotPicker } from "@/components/ui/slot-picker";

// The scheduling agent proposes free slots from both calendars.
export function ProposeTimes({ proposal }: { proposal: Proposal }) {
  return (
    <SlotPicker
      data={{
        title: proposal.title,
        slots: proposal.slots, // { id, day: "2026-11-10", start: "14:30", end: "15:00", busy?, suggested? }
        timeZone: { label: "Lisbon (UTC+0)", offset: 0 },
        attendeeZone: { label: "New York (UTC−5)", offset: -5 },
      }}
      onConfirm={(slot) => agent.sendToolResult(proposal.callId, { slotId: slot.id })}
    />
  );
}

Props

PropTypeDefaultDescription
data*{ title?: string; slots: Slot[]; timeZone: SlotZone; attendeeZone?: SlotZone }—Candidate slots in `timeZone`. With `attendeeZone` a switch shows the times in the other person's zone.
variant"week" | "day""week"Day columns for up to five days, or one day at a time with durations.
selectedId / onSelectstring | null—The picked slot. Picking shows a confirm row under the panel.
onConfirm(slot: Slot) => void—Called from the confirm row; the card switches to the confirmed summary.
confirmedId / onChangestring | null—Controls the confirmed state. onChange fires from “Pick another time”.
classNamestring—Extra classes for the shell.
type Slot = {
  id: string;
  day: string;   // ISO date
  start: string; // "HH:MM" in data.timeZone
  end: string;
  busy?: boolean;      // shown striped and disabled
  suggested?: boolean; // marked with a dot
};

type SlotZone = { label: string; offset: number }; // hours from UTC