Zostel
Stays Room Option

Room Option

A room or a bed to add to the stay: picture, who it sleeps, what's in it, a note, the nights it's free, its rate and Select.

Preview

6 bed mixed dorm

Sleeps 1

A bed in a mixed dorm with a locker of your own and a shared washroom.

Stay three nights or more and the house rate drops.

  • Free Wi-Fi
  • Lockers
  • Bunk bed
  • A plug by the bed
  • Towels

Bed only

Rates on your dates

Deluxe private room

Sleeps 2

A room of your own with a double bed and a balcony over the valley.

The last one on your dates.

  • Free Wi-Fi
  • Private room
  • Mountain view
  • Towels

Room only

Rates on your dates

4 bed female dorm

Sleeps 1

A bed in a female dorm with a locker of your own and its own washroom.

  • Free Wi-Fi
  • Lockers
  • Bunk bed
  • A plug by the bed
  • Towels
Sold out

The rooms, notes and nights are samples; the pictures are Manali's covers and its landscape, standing in for photos.

Usage

tsx
import { RoomOption, ZostelIcon } from "zostel-ui";

<RoomOption
  name="6 bed mixed dorm"
  description="A bed in a mixed dorm with a locker of your own."
  sleeps={1}
  imageUrl={room.photo}
  onPhotos={() => openGallery(room.id)}
  amenities={[{ icon: <ZostelIcon set="zostel-ui" name="wifi" color="currentColor" />, label: "Free Wi-Fi" }]}
  price={formatPrice(room.rate)}
  unit="bed"
  quantity={beds}
  maxQuantity={room.left}
  onQuantityChange={setBeds}
  availability={room.nights}
/>

Props

name
Type: string
Default: —

The room or bed.

description · note
Type: string · ReactNode
Default: —

What it is; a rule or an offer, in italics.

sleeps
Type: number
Default: —

Who it sleeps: “Sleeps 2”.

imageUrl · onPhotos
Type: string · () => void
Default: —

Its picture; onPhotos makes the picture a button to the room’s photos (PhotoGallery with open and group).

amenities
Type: { icon: ReactNode; label: string }[]
Default: —

What’s in it: each glyph with its name beside it, on every screen (a finger can’t hover, and nobody reads glyphs alone).

plan
Type: ReactNode
Default: —

The rate plan the price belongs to, over it (“Bed only”, “With breakfast”).

price · priceUnit
Type: ReactNode · string
Default: — · "/ night"

The rate as you print it, and what follows it.

quantity · onQuantityChange · maxQuantity
Type: number · (n) => void · number
Default: —

How many are picked: 0 shows Select, more shows the stepper, up to maxQuantity. quantity and onQuantityChange come together (without them the room shows no Select). When Select and the stepper swap, the focus moves with them only if it was on the one that left: to the stepper’s first button that can act, or back to Select.

unit
Type: "bed" | "room"
Default: "bed"

“Select bed” or “Select room”; the stepper counts beds or rooms.

soldOut
Type: boolean
Default: —

Nothing left on these dates: the picture greys, it says Sold out, and the nights that are free open below. What was already picked stays in the stay: the stepper remains, to take some out but add none.

titleAs
Type: "h2" | "h3" | "h4" | "p"
Default: "h3"

The name’s element, so it sits in the page’s outline.

availability
Type: { date: Date; left: number; price? }[]
Default: —

Night by night, what’s free: the calendar button opens it (AvailabilityStrip).

className
Type: string
Default: —

More classes, merged with the component’s own (tailwind-merge).

On zostel.com

The heart of a stay’s page: one per dorm and room type, with the booking bar beside them. Select swaps for the stepper under the finger and back, and the focus goes with it, so the keyboard never loses its place (with the last room, “Add one” is off from the start, so the focus lands on “Remove one”).