Blocks
Booking
Four booking flows built on one set of steps: a meeting, a hotel stay, a restaurant table and an appointment. Going back keeps every choice, and each step checks itself before moving on.
Examples
Meeting
Choose a length, a day and a time. Times are shown in your time zone; change it and they move. Some days are fully booked, to show the jump to the next free day. Once booked, add it to your calendar.
<script lang="ts">
import Meeting from '#lib/blocks/booking/Meeting.svelte';
</script>
<Meeting
title="Reading-room tour"
host={{ name: 'Hunayn ibn Ishaq', role: 'Keeper of the translations' }}
hours={{ timeZone: 'Asia/Baghdad', open: 9, close: 17, days: [0, 1, 2, 3, 4] }}
location="Bayt al-Hikma, west reading room"
/>Hotel stay
Dates and guests first, then the rooms free for those nights. Rooms too small for your party can't be chosen, and the total updates as you go.
<script lang="ts">
import Hotel from '#lib/blocks/booking/Hotel.svelte';
</script>
<Hotel
name="Dar al-Zahra guesthouse, Córdoba"
taxRate={0.1}
rooms={[
{
id: 'garden',
name: 'Garden room',
description: 'A double bed and a door onto the orange-tree courtyard.',
rate: 9_500,
sleeps: 2
},
{
id: 'library',
name: 'Library suite',
description: 'A bedroom, a sitting room lined with books, and a daybed.',
rate: 16_000,
sleeps: 3
},
{
id: 'family',
name: 'Family rooms',
description: 'Two connecting rooms around a small fountain.',
rate: 21_000,
sleeps: 5
}
]}
/>Restaurant table
Times show in the restaurant's own time zone, and sold-out ones stay visible. Areas that can't seat your party are switched off.
<script lang="ts">
import Table from '#lib/blocks/booking/Table.svelte';
</script>
<Table
name="Bab Touma kitchen, Damascus"
phone="+963 11 555 0142"
hours={{ timeZone: 'Asia/Damascus', open: 12, close: 23, days: [0, 1, 2, 3, 4, 6] }}
areas={[
{
value: 'hall',
label: 'Dining hall',
description: 'Under the painted ceiling, near the kitchen.',
seats: 8
},
{
value: 'courtyard',
label: 'Courtyard',
description: 'Around the fountain, under the lemon trees.',
seats: 6
},
{
value: 'iwan',
label: 'Iwan',
description: 'The raised alcove, cushions and low tables.',
seats: 4
}
]}
/>Appointment
A service, a person (or anyone available), then a time that fits the service's length.
<script lang="ts">
import Appointment from '#lib/blocks/booking/Appointment.svelte';
</script>
<Appointment
place="The bimaristan of al-Nuri, Damascus"
hours={{ timeZone: 'Asia/Damascus', open: 8, close: 14, days: [0, 1, 2, 3, 4, 6] }}
services={[
{
id: 'eyes',
name: 'Eye examination',
description: 'Sight, eyelids and a look at the lens.',
minutes: 30,
price: 4_000
},
{
id: 'consult',
name: 'General consultation',
description: 'Talk it through with a physician.',
minutes: 30,
price: 3_500
},
{
id: 'bath',
name: 'Bath and massage',
description: 'The hammam, then an hour with the masseur.',
minutes: 90,
price: 6_500
}
]}
providers={[
{ id: 'ammar', name: 'Ammar al-Mawsili', role: 'Eye physician' },
{ id: 'ibn-nafis', name: 'Ibn al-Nafis', role: 'Physician' },
{ id: 'rufaida', name: 'Rufaida al-Aslamia', role: 'Nurse and masseur' }
]}
/>Installation
npx sinaui add blocks/bookingCopy src/lib/blocks/booking/, with Alert, Avatar, Button, Calendar, DatePicker, DateRangePicker, Icon, Input, NumberField, RadioCards, Segmented, Select, Skeleton, Stepper, Textarea, announce.ts, motion.ts, scroll-edges.ts and tokens.css. Needs @internationalized/date.
Connecting your data
Availability comes from later() and the demo rules at the end of booking.ts. Replace those calls with requests to your booking service, and each
flow's submit with the call that books. A failed request shows a message with Try again;
a failed booking keeps everything filled in.
Keyboard
| Key | Does |
|---|---|
| Enter in a field | Continue to the next step |
| Arrow keys in the times | Move between free times |
| Tab | Move through the fields, then Back and Continue |
Accessibility
- Moving to a step puts focus on its heading, so screen readers hear where they are.
- Times are a group of radio buttons; booked ones are skipped and named as booked.
- Loading, how many times are free, and a day with none are announced.
- If a step has a problem, focus goes to the first field that needs fixing.
- With reduced motion, steps change without sliding.