Session Request

Book a session

Chooseatimethatfeelsright.Wewilltakeitfromthere.

Tell us a little about what brings you here and when you are usually free. We reply within a working day, always in person, never with a form letter.

Email
hello@beste.co
Studio
Rua da Prata 12, Lisbon
Hours
Monday to Friday, 9 to 18
Portrait of a practitioner
Portrait of a practitioner
Portrait of a practitioner

Three practitioners, one of whom will read this personally.

What are you looking for?

When are you usually free?

Nothing is booked until we have spoken. You can change your mind at any point.

About this block

Session RequestPRO

A booking section: a serif heading that settles in word by word over the intro, a ruled contact sheet and a practitioner avatar line, beside a calm request form with name and email fields, pill choices for session type and preferred time, a message box and a sliding-marker pill to send.

Booking30: Session Request

A session request built as a conversation rather than a checkout: contact lines, practitioner avatars and a reassurance on one side, and on the other a form where session type and preferred time are picked as pills instead of dropdowns.

Upgrade to Pro

Pro blocks install through the shadcn CLI with your license key and ship their full source. Docs and live previews stay open to everyone, so you can read every block's details first.

Upgrade Now

Installation

Swap YOUR_EMAIL and YOUR_KEY for the email and license key on your account. Find your license key on your account page.

Radix flavor

bash
npx shadcn add "https://ui.beste.co/r/booking30?email=YOUR_EMAIL&license_key=YOUR_KEY"

Base UI flavor

bash
npx shadcn add "https://ui.beste.co/r-base/booking30?email=YOUR_EMAIL&license_key=YOUR_KEY"

This installs the block to components/beste/block/booking30.tsx, the shadcn input, label, and textarea primitives the form is built on, and the button22 sliding-marker pill and the text1 word stagger it uses.

Quick start

The installed file exports booking30Demo alongside the block: the exact props behind the preview above. Spread it to get a working booking form in one line.

tsx
import { Booking30, booking30Demo } from "@/components/beste/block/booking30";

export default function Page() {
  return <Booking30 {...booking30Demo} />;
}

Then replace the demo with your own props. Written out, a trimmed setup looks like this:

tsx
import { Booking30 } from "@/components/beste/block/booking30";

export default function Page() {
  return (
    <Booking30
      eyebrow="Book a session"
      heading="Choose a time that feels right. We will take it from there."
      description="Tell us a little about what brings you here and when you are usually free."
      contacts={[
        { label: "Email", value: "hello@beste.co" },
        { label: "Hours", value: "Monday to Friday, 9 to 18" },
      ]}
      avatars={[{ src: "/team/one.jpg", alt: "Portrait of a practitioner" }]}
      proof="Three practitioners, one of whom will read this personally."
      sessionTypes={["First conversation", "Individual therapy", "Not sure yet"]}
      timeSlots={["Mornings", "Afternoons", "Evenings"]}
      labels={{
        name: "Your name",
        email: "Email",
        sessionType: "What are you looking for?",
        time: "When are you usually free?",
        message: "Anything you would like us to know",
        submit: "Send the request",
        note: "Nothing is booked until we have spoken.",
      }}
    />
  );
}

Props

PropTypeDefaultDescription
eyebrowstringSmall-caps line above the heading
headingstringSection heading, rendered as an h2 through Text1
descriptionstringIntro paragraph under the heading
contactsContactLine[][]Ruled contact rows in the left column
avatarsAvatar[][]Overlapping practitioner portraits
proofstringReassurance printed beside the avatars
sessionTypesstring[][]Pill choices for the session type; the group is skipped when empty
timeSlotsstring[][]Pill choices for preferred time
labelsPartial<FormLabels>{}Every string in the form
classNamestringExtra classes for the outer <section>
ts
type ContactLine = {
  label: string;
  value: string;
};

type Avatar = {
  src: string;
  alt: string;
};

type FormLabels = {
  name: string;
  email: string;
  sessionType: string;
  time: string;
  message: string;
  submit: string;
  note: string;
};

Behavior notes

  • Session type and time are pill buttons carrying aria-pressed, not a select or a radio group. They are single-choice toggles, so the pressed state is announced without inventing a listbox a keyboard user would then have to navigate.
  • Both groups initialise from the first entry of their array, so the form opens with a sensible answer already chosen rather than in an empty state the visitor has to resolve before they can start typing.
  • The pill state lives in the component and is never handed to a callback, so the chosen type and slot need wiring before they can reach your submit handler.
  • Field ids come from useId, so two of these on a page keep their labels pointing at their own inputs.
  • Contact lines are a dl on a three-column grid with the value spanning two, so long addresses wrap under themselves instead of pushing the label out of alignment.
  • Avatars overlap with -space-x-3 and each carries a border-background ring, which is what separates them from one another rather than a gap.
  • The submit button and the note under it each render only when their label is set, so a form without a note simply ends at the button.
  • The form only calls preventDefault() on submit; nothing is sent anywhere until you wire it up.

Wiring the form up

This block ships the form markup only; state, validation, and submit are yours to add. Our guide wires the shadcn Field primitives to React Hook Form, TanStack Form, and Formisch on one field system.

More Booking blocks

View all Booking
PRO

booking33

Session Picker

A booking chooser: a serif heading that settles in word by word and an intro, then a ruled list of session types on the left that swaps, with a soft blur, the muted detail card on the right showing a serif title, a description, a fact row and a sliding-marker pill.

PRO

booking31

Visit Sheet

A visit-us section: a photograph drifting inside its frame on the left, and on the right a serif heading that settles in word by word, an intro, a ruled sheet with the serif address, directions and opening hours, a sliding-marker pill and a text link.

PRO

booking32

Plain Contact

The classic contact section: a serif heading that settles in word by word, an intro and a ruled contact sheet on the left, and a plain form with name, email and message fields and a sliding-marker pill on the right, with no panel around it.

PRO

booking25

Booking Confirmed

A confirmation screen with an accent eyebrow, a two-column hairline table of the appointment details, a checked list of what to bring, and a sticky tile floating the live phone view the member also receives.

PRO

booking1

Date & Time Picker

Split-panel booking interface with interactive monthly calendar on the left and time slot grid on the right. Features today highlight, disabled dates, selected state, morning/afternoon grouping, and booking summary footer.

PRO

booking6

Restaurant Reservation

Restaurant table reservation with guest count selector, date/time picker, seating preference (indoor/outdoor/bar), special requests textarea, and booking summary. Fine dining reservation flow.