Skip to content

Commit

Permalink
feat: add classNames prop to Booker atom for passing external styles (
Browse files Browse the repository at this point in the history
#14270)

* add classnames prop to pass external styles

* fix import

* add comments

* ignore this commit: tinkering with styling

* update typings

* mostly creating props and passing it down to child components

* remove unnecessary comment

* merge conflicts

* fixup

* fixup

* fix conflicts

* fix merge conflicts

* fix merge conflicts

* fix failing type checks

* type checks fix

* add custom classnames to booker props

* update typings

* pass in props down wherever necessary

* fixup

* still passing down around some more props

* addressing pr feedback

* final fixes

* address feedback

* fixup! address feedback

* fixup! fixup! address feedback

* fixup! fixup! fixup! address feedback

---------

Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com>
Co-authored-by: Morgan Vernay <morgan@cal.com>
  • Loading branch information
3 people committed Apr 12, 2024
1 parent 1809382 commit c467167
Show file tree
Hide file tree
Showing 14 changed files with 232 additions and 39 deletions.
40 changes: 30 additions & 10 deletions packages/features/bookings/Booker/Booker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ const BookerComponent = ({
verifyCode,
isPlatform,
orgBannerUrl,
customClassNames,
}: BookerProps & WrappedBookerProps) => {
const { t } = useLocale();
const [bookerState, setBookerState] = useBookerStore((state) => [state.state, state.setState], shallow);
Expand Down Expand Up @@ -268,14 +269,14 @@ const BookerComponent = ({
<div
ref={animationScope}
className={classNames(
// Sets booker size css variables for the size of all the columns.
...getBookerSizeClassNames(layout, bookerState, hideEventTypeDetails),
"bg-default dark:bg-muted grid max-w-full items-start dark:[color-scheme:dark] sm:transition-[width] sm:duration-300 sm:motion-reduce:transition-none md:flex-row",
`bg-default dark:bg-muted grid max-w-full items-start dark:[color-scheme:dark] sm:transition-[width] sm:duration-300 sm:motion-reduce:transition-none md:flex-row`,
// We remove border only when the content covers entire viewport. Because in embed, it can almost never be the case that it covers entire viewport, we show the border there
(layout === BookerLayouts.MONTH_VIEW || isEmbed) && "border-subtle rounded-md border",
(layout === BookerLayouts.MONTH_VIEW || isEmbed) && "border-subtle rounded-md",
!isEmbed && "sm:transition-[width] sm:duration-300",
isEmbed && layout === BookerLayouts.MONTH_VIEW && "border-booker sm:border-booker-width",
!isEmbed && layout === BookerLayouts.MONTH_VIEW && "border-subtle"
!isEmbed && layout === BookerLayouts.MONTH_VIEW && `border-subtle`,
`${customClassNames?.bookerContainer}`
)}>
<AnimatePresence>
{!isInstantMeeting && (
Expand Down Expand Up @@ -339,8 +340,17 @@ const BookerComponent = ({
src={orgBannerUrl}
/>
)}

<EventMeta event={event.data} isPending={event.isPending} isPlatform={isPlatform} />
<EventMeta
classNames={{
eventMetaContainer: customClassNames?.eventMetaCustomClassname?.eventMetaContainer,
eventMetaTitle: customClassNames?.eventMetaCustomClassname?.eventMetaTitle,
eventMetaTimezoneSelect:
customClassNames?.eventMetaCustomClassname?.eventMetaTimezoneSelect,
}}
event={event.data}
isPending={event.isPending}
isPlatform={isPlatform}
/>
{layout !== BookerLayouts.MONTH_VIEW &&
!(layout === "mobile" && bookerState === "booking") && (
<div className="mt-auto px-5 py-3 ">
Expand All @@ -353,7 +363,7 @@ const BookerComponent = ({
<BookerSection
key="book-event-form"
area="main"
className="border-subtle sticky top-0 ml-[-1px] h-full p-6 md:w-[var(--booker-main-width)] md:border-l"
className="sticky top-0 ml-[-1px] h-full p-6 md:w-[var(--booker-main-width)] md:border-l"
{...fadeInLeft}
visible={bookerState === "booking" && !shouldShowFormInDialog}>
{EventBooker}
Expand All @@ -366,7 +376,18 @@ const BookerComponent = ({
{...fadeInLeft}
initial="visible"
className="md:border-subtle ml-[-1px] h-full flex-shrink px-5 py-3 md:border-l lg:w-[var(--booker-main-width)]">
<DatePicker event={event} schedule={schedule} />
<DatePicker
classNames={{
datePickerContainer: customClassNames?.datePickerCustomClassname?.datePickerContainer,
datePickerTitle: customClassNames?.datePickerCustomClassname?.datePickerTitle,
datePickerDays: customClassNames?.datePickerCustomClassname?.datePickerDays,
datePickerDate: customClassNames?.datePickerCustomClassname?.datePickerDate,
datePickerDatesActive: customClassNames?.datePickerCustomClassname?.datePickerDatesActive,
datePickerToggle: customClassNames?.datePickerCustomClassname?.datePickerToggle,
}}
event={event}
schedule={schedule}
/>
</BookerSection>

<BookerSection
Expand Down Expand Up @@ -398,6 +419,7 @@ const BookerComponent = ({
ref={timeslotsRef}
{...fadeInLeft}>
<AvailableTimeSlots
customClassnames={customClassNames?.availableTimeSlotsCustomClassname}
extraDays={extraDays}
limitHeight={layout === BookerLayouts.MONTH_VIEW}
schedule={schedule?.data}
Expand All @@ -409,7 +431,6 @@ const BookerComponent = ({
</BookerSection>
</AnimatePresence>
</div>

<HavingTroubleFindingTime
visible={bookerState !== "booking" && layout === BookerLayouts.MONTH_VIEW && !isMobile}
dayCount={dayCount}
Expand All @@ -418,7 +439,6 @@ const BookerComponent = ({
setDayCount(null);
}}
/>

{!hideBranding && !isPlatform && (
<m.span
key="logo"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ type AvailableTimeSlotsProps = {
seatsPerTimeSlot?: number | null;
showAvailableSeatsCount?: boolean | null;
event: useEventReturnType;
customClassnames?: {
availableTimeSlotsContainer?: string;
availableTimeSlotsTitle?: string;
availableTimeSlotsTimeFormatToggle: string;
availableTimes?: string;
};
};

/**
Expand All @@ -37,6 +43,7 @@ export const AvailableTimeSlots = ({
schedule,
isLoading,
event,
customClassnames,
}: AvailableTimeSlotsProps) => {
const selectedDate = useBookerStore((state) => state.selectedDate);
const setSelectedTimeslot = useBookerStore((state) => state.setSelectedTimeslot);
Expand Down Expand Up @@ -81,13 +88,17 @@ export const AvailableTimeSlots = ({

return (
<>
<div className="flex">
<div className={classNames(`flex`, `${customClassnames?.availableTimeSlotsContainer}`)}>
{isLoading ? (
<div className="mb-3 h-8" />
) : (
slotsPerDay.length > 0 &&
slotsPerDay.map((slots) => (
<AvailableTimesHeader
customClassnames={{
availableTimeSlotTitle: customClassnames?.availableTimeSlotsTitle,
availableTimeSlotTimeFormatToggle: customClassnames?.availableTimeSlotsTimeFormatToggle,
}}
key={slots.date}
date={dayjs(slots.date)}
showTimeFormatToggle={!isColumnView}
Expand All @@ -105,7 +116,8 @@ export const AvailableTimeSlots = ({
ref={containerRef}
className={classNames(
limitHeight && "scroll-bar flex-grow overflow-auto md:h-[400px]",
!limitHeight && "flex h-full w-full flex-row gap-4"
!limitHeight && "flex h-full w-full flex-row gap-4",
`${customClassnames?.availableTimeSlotsContainer}`
)}>
{isLoading && // Shows exact amount of days as skeleton.
Array.from({ length: 1 + (extraDays ?? 0) }).map((_, i) => <AvailableTimesSkeleton key={i} />)}
Expand All @@ -114,6 +126,8 @@ export const AvailableTimeSlots = ({
slotsPerDay.map((slots) => (
<div key={slots.date} className="scroll-bar h-full w-full overflow-y-auto overflow-x-hidden">
<AvailableTimes
className={customClassnames?.availableTimeSlotsContainer}
customClassnames={customClassnames?.availableTimes}
showTimeFormatToggle={!isColumnView}
onTimeSelect={onTimeSelect}
slots={slots.slots}
Expand Down
17 changes: 17 additions & 0 deletions packages/features/bookings/Booker/components/DatePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,18 @@ import type { useEventReturnType, useScheduleForEventReturnType } from "../utils
export const DatePicker = ({
event,
schedule,
classNames,
}: {
event: useEventReturnType;
schedule: useScheduleForEventReturnType;
classNames?: {
datePickerContainer?: string;
datePickerTitle?: string;
datePickerDays?: string;
datePickerDate?: string;
datePickerDatesActive?: string;
datePickerToggle?: string;
};
}) => {
const { i18n } = useLocale();
const [month, selectedDate] = useBookerStore((state) => [state.month, state.selectedDate], shallow);
Expand All @@ -27,6 +36,14 @@ export const DatePicker = ({

return (
<DatePickerComponent
customClassNames={{
datePickerTitle: classNames?.datePickerTitle,
datePickerDays: classNames?.datePickerDays,
datePickersDates: classNames?.datePickerDate,
datePickerDatesActive: classNames?.datePickerDatesActive,
datePickerToggle: classNames?.datePickerToggle,
}}
className={classNames?.datePickerContainer}
isPending={schedule.isPending}
onChange={(date: Dayjs | null) => {
setSelectedDate(date === null ? date : date.format("YYYY-MM-DD"));
Expand Down
12 changes: 9 additions & 3 deletions packages/features/bookings/Booker/components/EventMeta.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,16 @@ export const EventMeta = ({
event,
isPending,
isPlatform = true,
classNames,
}: {
event: useEventReturnType["data"];
isPending: useEventReturnType["isPending"];
isPlatform?: boolean;
classNames?: {
eventMetaContainer?: string;
eventMetaTitle?: string;
eventMetaTimezoneSelect?: string;
};
}) => {
const { setTimezone, timeFormat, timezone } = useTimePreferences();
const selectedDuration = useBookerStore((state) => state.selectedDuration);
Expand Down Expand Up @@ -78,7 +84,7 @@ export const EventMeta = ({
: "text-bookinghighlight";

return (
<div className="relative z-10 p-6" data-testid="event-meta">
<div className={`${classNames?.eventMetaContainer} relative z-10 p-6`} data-testid="event-meta">
{isPending && (
<m.div {...fadeInUp} initial="visible" layout>
<EventMetaSkeleton />
Expand All @@ -92,7 +98,7 @@ export const EventMeta = ({
profile={event.profile}
entity={event.entity}
/>
<EventTitle className="my-2">{event?.title}</EventTitle>
<EventTitle className={`${classNames?.eventMetaTitle} my-2`}>{event?.title}</EventTitle>
{event.description && (
<EventMetaBlock contentClassName="mb-8 break-words max-w-full max-h-[180px] scroll-bar pr-4">
<div dangerouslySetInnerHTML={{ __html: event.description }} />
Expand Down Expand Up @@ -126,7 +132,6 @@ export const EventMeta = ({
</EventMetaBlock>
)}
<EventDetails event={event} />

<EventMetaBlock
className="cursor-pointer [&_.current-timezone:before]:focus-within:opacity-100 [&_.current-timezone:before]:hover:opacity-100"
contentClassName="relative max-w-[90%]"
Expand All @@ -140,6 +145,7 @@ export const EventMeta = ({
}`}>
<TimezoneSelect
menuPosition="fixed"
timezoneSelectCustomClassname={classNames?.eventMetaTimezoneSelect}
classNames={{
control: () => "!min-h-0 p-0 w-full border-0 bg-transparent focus-within:ring-0",
menu: () => "!w-64 max-w-[90vw]",
Expand Down
28 changes: 28 additions & 0 deletions packages/features/bookings/Booker/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ export interface BookerProps {
username: string;
orgBannerUrl?: string | null;

/*
all custom classnames related to booker styling go here
*/
customClassNames?: CustomClassNames;

/**
* Whether is a team or org, we gather basic info from both
*/
Expand Down Expand Up @@ -125,3 +130,26 @@ export type WrappedBookerProps = WrappedBookerPropsForPlatform | WrappedBookerPr
export type BookerState = "loading" | "selecting_date" | "selecting_time" | "booking";
export type BookerLayout = BookerLayouts | "mobile";
export type BookerAreas = "calendar" | "timeslots" | "main" | "meta" | "header";

export type CustomClassNames = {
bookerContainer?: string;
eventMetaCustomClassname?: {
eventMetaContainer?: string;
eventMetaTitle?: string;
eventMetaTimezoneSelect?: string;
};
datePickerCustomClassname?: {
datePickerContainer?: string;
datePickerTitle?: string;
datePickerDays?: string;
datePickerDate?: string;
datePickerDatesActive?: string;
datePickerToggle?: string;
};
availableTimeSlotsCustomClassname: {
availableTimeSlotsContainer?: string;
availableTimeSlotsTitle?: string;
availableTimeSlotsTimeFormatToggle: string;
availableTimes?: string;
};
};
10 changes: 8 additions & 2 deletions packages/features/bookings/components/AvailableTimes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ type AvailableTimesProps = {
className?: string;
selectedSlots?: string[];
event: useEventReturnType;
customClassnames?: string;
};

const SlotItem = ({
Expand All @@ -45,13 +46,15 @@ const SlotItem = ({
onTimeSelect,
showAvailableSeatsCount,
event,
customClassnames,
}: {
slot: Slots[string][number];
seatsPerTimeSlot?: number | null;
selectedSlots?: string[];
onTimeSelect: TOnTimeSelect;
showAvailableSeatsCount?: boolean | null;
event: useEventReturnType;
customClassnames?: string;
}) => {
const { t } = useLocale();

Expand Down Expand Up @@ -121,8 +124,9 @@ const SlotItem = ({
data-time={slot.time}
onClick={onButtonClick}
className={classNames(
"min-h-9 hover:border-brand-default mb-2 flex h-auto w-full flex-grow flex-col justify-center py-2",
selectedSlots?.includes(slot.time) && "border-brand-default"
`min-h-9 hover:border-brand-default mb-2 flex h-auto w-full flex-grow flex-col justify-center py-2`,
selectedSlots?.includes(slot.time) && "border-brand-default",
`${customClassnames}`
)}
color="secondary">
<div className="flex items-center gap-2">
Expand Down Expand Up @@ -193,6 +197,7 @@ export const AvailableTimes = ({
className,
selectedSlots,
event,
customClassnames,
}: AvailableTimesProps) => {
const { t } = useLocale();

Expand Down Expand Up @@ -223,6 +228,7 @@ export const AvailableTimes = ({
if (slot.away) return null;
return (
<SlotItem
customClassnames={customClassnames}
key={slot.time}
onTimeSelect={onTimeSelect}
slot={slot}
Expand Down

0 comments on commit c467167

Please sign in to comment.