From 91d4f1c21914978fcc7e5dc37c81d6077d0a122f Mon Sep 17 00:00:00 2001 From: Lauris Skraucis Date: Wed, 19 Mar 2025 12:30:48 +0100 Subject: [PATCH] feat: booker atom confirm and back button styling (#20162) * feat: submitButtonDisabled Booker atom prop * feat: confirmStep.confirmButton & backButton booker styles * refactor: rename submitButtonDisabled to confirmButtonDisabled * feat: implement this feature for skip confirm step * refactor: naming --- docs/platform/atoms/booker.mdx | 114 +++++++++++++++--- packages/features/bookings/Booker/Booker.tsx | 8 ++ .../Booker/components/AvailableTimeSlots.tsx | 8 ++ .../BookEventForm/BookEventForm.tsx | 19 ++- packages/features/bookings/Booker/types.ts | 5 + .../bookings/components/AvailableTimes.tsx | 10 +- .../atoms/booker/BookerPlatformWrapper.tsx | 2 + packages/platform/atoms/booker/types.ts | 1 + .../examples/base/src/pages/booking.tsx | 5 + 9 files changed, 150 insertions(+), 22 deletions(-) diff --git a/docs/platform/atoms/booker.mdx b/docs/platform/atoms/booker.mdx index efc95db129..44c891b62b 100644 --- a/docs/platform/atoms/booker.mdx +++ b/docs/platform/atoms/booker.mdx @@ -122,24 +122,100 @@ Below is a list of props that can be passed to the booker atom. | bannerUrl | No | Adds custom banner to the booker atom | | onBookerStateChange | No | Callback function that is triggered when the state of the booker atom changes. | | allowUpdatingUrlParams | No | Boolean indicating if the URL parameters should be updated, defaults to false. | +| confirmButtonDisabled | No | Boolean indicating if the submit button should be disabled, defaults to false. | -Along with the props, booker atom accepts custom styles via the **customClassNames** prop. Below is a list of props that fall under this **customClassNames** prop. -

+## Styling -| Name | Description | -|:-----------------------------|:----------------------------------------------------------------------| -| bookerContainer | Adds styling to the whole of the booker atom | -| eventMetaContainer | Styles the event meta component containing details about an event | -| eventMetaTitle | Adds styles to the event meta title | -| eventMetaTimezoneSelect | Adds styles to the event meta timezone selector | -| datePickerContainer | Adds styling to the date picker | -| datePickerTitle | Styles the date picker title | -| datePickerDays | Adds styling to all days in the date picker | -| datePickerDate | Adds styling to all dates in the date picker | -| datePickerDatesActive | Styles only the dates with available slots | -| datePickerToggle | Styles the left and right toggle buttons | -| availableTimeSlotsContainer | Adds styling to the available time slots component | -| availableTimeSlotsHeaderContainer | Styles only the header container | -| availableTimeSlotsTitle | Adds styles to the title | -| availableTimeSlotsTimeFormatToggle | Adds styles to the format toggle buttons | -| availableTimes | Styles all the available times container | \ No newline at end of file +Booker atom accepts custom styles via the `customClassNames` prop. This prop is an object that contains root level styles and nested objects for styling different parts of the booker component. Each nested object groups related styles for a specific section of the booker (e.g., eventMeta, datePicker, availableTimeSlots, etc). + +Here is an example booker with root level style `bookerContainer` and nested object `datePickerCustomClassNames` with `datePickerDatesActive` style: +```js +import { Booker } from "@calcom/atoms"; + +export default function Booker( props : BookerProps ) { + return ( + <> + + + ) +} +``` + +Below is a list of **customClassNames** properties grouped by their parent objects: + +### Root Level Styles +| Property | Description | +|:---------|:-------------| +| bookerContainer | Adds styling to the whole of the booker atom | + +### Event Meta Styles (`eventMetaCustomClassNames`) +| Property | Description | +|:---------|:-------------| +| eventMetaContainer | Styles the event meta component containing details about an event | +| eventMetaTitle | Adds styles to the event meta title | +| eventMetaTimezoneSelect | Adds styles to the event meta timezone selector | + +### Date Picker Styles (`datePickerCustomClassNames`) +| Property | Description | +|:---------|:-------------| +| datePickerContainer | Adds styling to the date picker | +| datePickerTitle | Styles the date picker title | +| datePickerDays | Adds styling to all days in the date picker | +| datePickerDate | Adds styling to all dates in the date picker | +| datePickerDatesActive | Styles only the dates with available slots | +| datePickerToggle | Styles the left and right toggle buttons | + +### Available Time Slots Styles (`availableTimeSlotsCustomClassNames`) +| Property | Description | +|:---------|:-------------| +| availableTimeSlotsContainer | Adds styling to the available time slots component | +| availableTimeSlotsHeaderContainer | Styles only the header container | +| availableTimeSlotsTitle | Adds styles to the title | +| availableTimeSlotsTimeFormatToggle | Adds styles to the format toggle buttons | +| availableTimes | Styles all the available times container | + +### Confirmation Step Styles (`confirmStep`) +| Property | Description | +|:---------|:-------------| +| confirmButton | Styles the confirm button in the booking form | +| backButton | Styles the back button in the booking form | + +Here is an example with more custom styles: +```js +import { Booker } from "@calcom/atoms"; + +export default function Booker( props : BookerProps ) { + return ( + <> + + + ) +} +``` \ No newline at end of file diff --git a/packages/features/bookings/Booker/Booker.tsx b/packages/features/bookings/Booker/Booker.tsx index 6b929ccffd..0840ed04dc 100644 --- a/packages/features/bookings/Booker/Booker.tsx +++ b/packages/features/bookings/Booker/Booker.tsx @@ -82,6 +82,7 @@ const BookerComponent = ({ isBookingDryRun: isBookingDryRunProp, renderCaptcha, hashedLink, + confirmButtonDisabled, }: BookerProps & WrappedBookerProps) => { const searchParams = useCompatSearchParams(); const isPlatformBookerEmbed = useIsPlatformBookerEmbed(); @@ -239,6 +240,11 @@ const BookerComponent = ({ extraOptions={extraOptions} rescheduleUid={rescheduleUid} isVerificationCodeSending={isVerificationCodeSending} + confirmButtonDisabled={confirmButtonDisabled} + classNames={{ + confirmButton: customClassNames?.confirmStep?.confirmButton, + backButton: customClassNames?.confirmStep?.backButton, + }} isPlatform={isPlatform}> <> {!isPlatform && ( @@ -483,6 +489,8 @@ const BookerComponent = ({ skipConfirmStep={skipConfirmStep} shouldRenderCaptcha={shouldRenderCaptcha} watchedCfToken={watchedCfToken} + confirmButtonDisabled={confirmButtonDisabled} + confirmStepClassNames={customClassNames?.confirmStep} /> diff --git a/packages/features/bookings/Booker/components/AvailableTimeSlots.tsx b/packages/features/bookings/Booker/components/AvailableTimeSlots.tsx index fa82497b9e..a141d3ca2b 100644 --- a/packages/features/bookings/Booker/components/AvailableTimeSlots.tsx +++ b/packages/features/bookings/Booker/components/AvailableTimeSlots.tsx @@ -33,6 +33,9 @@ type AvailableTimeSlotsProps = { availableTimeSlotsTimeFormatToggle?: string; availableTimes?: string; }; + confirmStepClassNames?: { + confirmButton?: string; + }; loadingStates: IUseBookingLoadingStates; isVerificationCodeSending: boolean; renderConfirmNotVerifyEmailButtonCond: boolean; @@ -44,6 +47,7 @@ type AvailableTimeSlotsProps = { * This is the list of time slots that are unavailable to book */ unavailableTimeSlots: string[]; + confirmButtonDisabled?: boolean; }; /** @@ -65,6 +69,8 @@ export const AvailableTimeSlots = ({ seatsPerTimeSlot, onSubmit, unavailableTimeSlots, + confirmButtonDisabled, + confirmStepClassNames, ...props }: AvailableTimeSlotsProps) => { const selectedDate = useBookerStore((state) => state.selectedDate); @@ -224,6 +230,8 @@ export const AvailableTimeSlots = ({ skipConfirmStep={skipConfirmStep} seatsPerTimeSlot={seatsPerTimeSlot} handleSlotClick={handleSlotClick} + confirmButtonDisabled={confirmButtonDisabled} + confirmStepClassNames={confirmStepClassNames} {...props} /> diff --git a/packages/features/bookings/Booker/components/BookEventForm/BookEventForm.tsx b/packages/features/bookings/Booker/components/BookEventForm/BookEventForm.tsx index 559da7a6de..bf727818d7 100644 --- a/packages/features/bookings/Booker/components/BookEventForm/BookEventForm.tsx +++ b/packages/features/bookings/Booker/components/BookEventForm/BookEventForm.tsx @@ -31,6 +31,11 @@ type BookEventFormProps = { isVerificationCodeSending: boolean; isTimeslotUnavailable: boolean; shouldRenderCaptcha?: boolean; + confirmButtonDisabled?: boolean; + classNames?: { + confirmButton?: string; + backButton?: string; + }; }; export const BookEventForm = ({ @@ -49,6 +54,8 @@ export const BookEventForm = ({ isPlatform = false, isTimeslotUnavailable, shouldRenderCaptcha, + confirmButtonDisabled, + classNames, }: Omit & { eventQuery: { isError: boolean; @@ -195,7 +202,12 @@ export const BookEventForm = ({ ) : ( <> {!!onCancel && ( - )} @@ -203,12 +215,15 @@ export const BookEventForm = ({