forge-digital-booking
v0.1.0
Published
A flexible Vue 3 booking calendar component with month, week, and day views
Maintainers
Readme
forge-digital-booking
A flexible, fully-typed Vue 3 booking calendar component with month, week, and day views. Supports time-slot booking and full-day selection modes. The component is purely presentational — it emits events and your app owns all booking state.
Features
- Three calendar views: Month, Week, and Day — switchable via UI buttons or the
defaultViewprop - Two booking modes:
slot(time-based, e.g. 09:00 / 09:30) andday(full-day / multi-day selection) - Stateless / emit-only: No internal booking state. Your parent component owns the data.
- Slot status support: Mark slots as
available,booked, ordisabledvia theeventsprop - Dark mode: Apply
theme="dark"for a dark theme - Locale support: Pass any BCP 47 locale string
- Configurable time grid: Set
slotDuration,slotStartTime, andslotEndTime - Min/max date constraints: Restrict selectable date ranges
- Keyboard accessible: Full keyboard navigation and ARIA attributes
- SCSS + CSS custom properties: Easy theming without rebuilding
- TypeScript: Fully typed props, emits, and exported types
Installation
pnpm add forge-digital-bookingAlso import the stylesheet in your app entry or component:
import "forge-digital-booking/styles";Quick Start
Register globally (plugin)
// main.ts
import { createApp } from "vue";
import App from "./App.vue";
import ForgeDigitalBooking from "forge-digital-booking";
import "forge-digital-booking/styles";
const app = createApp(App);
app.use(ForgeDigitalBooking);
app.mount("#app");Register locally
<script setup lang="ts">
import { BookingCalendar } from "forge-digital-booking";
import type { BookingSelectPayload, CalendarEvent } from "forge-digital-booking";
import "forge-digital-booking/styles";
import { ref } from "vue";
const events = ref<CalendarEvent[]>([
{
date: "2026-03-10",
slots: [
{ time: "09:00", status: "available" },
{ time: "09:30", status: "booked" },
{ time: "10:00", status: "available" },
{ time: "10:30", status: "disabled" },
],
},
]);
function onSlotClick(payload: BookingSelectPayload) {
console.log("Slot clicked:", payload);
// payload.date => "2026-03-10"
// payload.slot => { time: "09:00", status: "available" }
// Add booking logic here, update your events prop
}
function onDateClick(payload: { date: string }) {
console.log("Date clicked:", payload.date);
}
</script>
<template>
<BookingCalendar
mode="slot"
default-view="month"
:events="events"
slot-start-time="09:00"
slot-end-time="17:00"
:slot-duration="30"
locale="en-US"
@slot-click="onSlotClick"
@date-click="onDateClick"
/>
</template>Props
| Prop | Type | Default | Description |
| ---------------- | ---------------------------- | --------- | ------------------------------------------------------------------------------------------------- |
| mode | 'slot' \| 'day' | 'slot' | Booking interaction mode. slot opens a time-slot picker on day click. day selects whole days. |
| defaultView | 'month' \| 'week' \| 'day' | 'month' | Initial calendar view. Also reactive — changing this prop switches the view. |
| events | CalendarEvent[] | [] | Array of events with date and optional time slots. Controls slot availability display. |
| slotDuration | number | 30 | Duration of each time slot in minutes (e.g. 15, 30, 60). |
| slotStartTime | string | '08:00' | Start of the bookable time range in HH:MM 24h format. |
| slotEndTime | string | '18:00' | End of the bookable time range in HH:MM 24h format. |
| disabledDates | string[] | [] | Array of ISO date strings (YYYY-MM-DD) that are fully disabled. |
| locale | string | 'en-US' | BCP 47 locale string for date formatting (e.g. 'fr-FR', 'de-DE'). |
| firstDayOfWeek | number | 0 | First day of week: 0 = Sunday, 1 = Monday. |
| minDate | string \| null | null | Minimum selectable date (YYYY-MM-DD). Dates before this are disabled. |
| maxDate | string \| null | null | Maximum selectable date (YYYY-MM-DD). Dates after this are disabled. |
| theme | 'light' \| 'dark' | 'light' | Color theme. Sets data-vbc-theme on the root element. |
Events
| Event | Payload | Description |
| ------------- | ---------------------- | ------------------------------------------------------------------------------------------------- |
| date-click | { date: string } | Emitted when any clickable date cell is clicked. date is YYYY-MM-DD. |
| slot-click | BookingSelectPayload | Emitted when a time slot or day (in day mode) is selected. Includes date and optionally slot. |
| view-change | CalendarView | Emitted when the user switches between Month / Week / Day views. |
| navigate | string (ISO date) | Emitted after prev/next/today navigation. Payload is the new current date. |
BookingSelectPayload
interface BookingSelectPayload {
date: string; // "YYYY-MM-DD"
slot?: TimeSlot; // present only in slot mode
}
interface TimeSlot {
time: string; // "HH:MM"
status: SlotStatus;
data?: unknown; // any consumer data you attached
}CSS Customization
The component uses CSS custom properties scoped under .vbc-calendar. Override them in your own stylesheet:
.vbc-calendar {
--vbc-primary: #7c3aed; /* accent / selected color */
--vbc-primary-hover: #6d28d9;
--vbc-bg: #ffffff; /* main background */
--vbc-surface: #f9fafb; /* secondary surfaces */
--vbc-border: #e5e7eb; /* borders */
--vbc-text: #111827; /* primary text */
--vbc-text-muted: #6b7280; /* secondary text */
--vbc-today-bg: #ede9fe; /* today highlight background */
--vbc-booked-bg: #fef2f2; /* booked slot background */
--vbc-booked-text: #dc2626; /* booked slot text */
--vbc-available-bg: #f0fdf4; /* available slot background */
--vbc-available-text: #16a34a; /* available slot text */
--vbc-disabled-opacity: 0.4; /* opacity for disabled items */
--vbc-radius: 8px; /* border radius */
--vbc-slot-height: 48px; /* height of each time slot row */
}Dark Mode
Pass theme="dark" to the component:
<BookingCalendar theme="dark" />Or toggle it dynamically:
<BookingCalendar :theme="isDark ? 'dark' : 'light'" />The dark theme overrides the CSS variables on [data-vbc-theme="dark"], so you can also further customize it:
[data-vbc-theme="dark"] .vbc-calendar {
--vbc-primary: #818cf8;
}TypeScript
All types are exported from the package root:
import type {
CalendarView,
BookingMode,
SlotStatus,
TimeSlot,
BookedDay,
CalendarEvent,
BookingSelectPayload,
} from "forge-digital-booking";Contributing
- Fork the repository
- Create a feature branch:
git checkout -b feat/my-feature - Install dependencies:
pnpm install - Run dev server:
pnpm dev - Make your changes, ensure type-check passes:
npm run type-check - Build:
pnpm build - Submit a pull request
License
MIT © forge-digital-booking
