Public Booking Pages (#4063)

* Teams + /book

* Consitant hoverstate across event-type cards

* Fix darkmode hover on book a team member

* Fix mobile wrapping

* Fix mobile looking awful with long links

* Fix storybook

* Fix SB

* Phone Input darkmode

* Location radio styles darkmode

* Off Topic: NIT add disable guests

* Update highlights on /book and [user]/[type]

* Fix preview URL

* Fix hover state

* Fix spacing for locations
This commit is contained in:
sean-brydon
2022-09-02 21:16:36 +00:00
committed by GitHub
parent 265af73ad0
commit 015ed6d4f9
17 changed files with 4053 additions and 169 deletions
@@ -1,3 +1,4 @@
import { TooltipProvider } from "@radix-ui/react-tooltip";
import { ComponentMeta } from "@storybook/react";
import AvatarGroup from "@calcom/ui/v2/core/AvatarGroup";
@@ -52,8 +53,8 @@ const IMAGES = [
export const Default = () => {
return (
<>
<TooltipProvider>
<AvatarGroup size="lg" items={IMAGES} />
</>
</TooltipProvider>
);
};
+19 -16
View File
@@ -8,30 +8,33 @@ import ButtonGroup from "@calcom/ui/v2/core/ButtonGroup";
export default {
title: "Button Group",
component: ButtonGroup,
decorators: [
(Story) => (
<TooltipProvider>
<Story />
</TooltipProvider>
),
],
} as ComponentMeta<typeof ButtonGroup>;
export const Default = () => (
<ButtonGroup>
<TooltipProvider>
<Button StartIcon={Trash2} size="icon" color="secondary" />
<Button StartIcon={Navigation2} size="icon" color="secondary" />
<Button StartIcon={Clipboard} size="icon" color="secondary" />
</TooltipProvider>
<Button StartIcon={Trash2} size="icon" color="secondary" />
<Button StartIcon={Navigation2} size="icon" color="secondary" />
<Button StartIcon={Clipboard} size="icon" color="secondary" />
</ButtonGroup>
);
export const Combined = () => (
<div className="flex flex-col space-y-2">
<TooltipProvider>
<ButtonGroup combined>
<Button StartIcon={Trash2} size="icon" color="secondary" combined />
<Button StartIcon={Navigation2} size="icon" color="secondary" combined />
<Button StartIcon={Clipboard} size="icon" color="secondary" combined />
</ButtonGroup>
<ButtonGroup combined>
<Button StartIcon={ArrowLeft} size="icon" color="secondary" combined />
<Button StartIcon={ArrowRight} size="icon" color="secondary" combined />
</ButtonGroup>
</TooltipProvider>
<ButtonGroup combined>
<Button StartIcon={Trash2} size="icon" color="secondary" combined />
<Button StartIcon={Navigation2} size="icon" color="secondary" combined />
<Button StartIcon={Clipboard} size="icon" color="secondary" combined />
</ButtonGroup>
<ButtonGroup combined>
<Button StartIcon={ArrowLeft} size="icon" color="secondary" combined />
<Button StartIcon={ArrowRight} size="icon" color="secondary" combined />
</ButtonGroup>
</div>
);
@@ -6,29 +6,27 @@ import { Props } from "./pages/AvailabilityPage";
export function AvailableEventLocations({ locations }: { locations: Props["eventType"]["locations"] }) {
return locations.length ? (
<div>
<div className="flex-warp dark:text-darkgray-600 mr-6 flex break-words text-sm text-gray-600">
<p className="w-full">
{locations.map((location) => {
const eventLocationType = getEventLocationType(location.type);
if (!eventLocationType) {
// It's possible that the location app got uninstalled
return null;
}
return (
<span key={location.type} className="flex flex-row items-center text-sm font-medium">
<img
src={eventLocationType.iconUrl}
className={classNames(
"mr-[10px] ml-[2px] h-4 w-4 opacity-70 dark:opacity-100",
!eventLocationType.iconUrl?.includes("api") ? "dark:invert" : ""
)}
alt={`${eventLocationType.label} icon`}
/>
<span key={location.type}>{locationKeyToString(location)} </span>
</span>
);
})}
</p>
<div className="dark:text-darkgray-600 mr-6 flex w-full flex-col space-y-2 break-words text-sm text-gray-600">
{locations.map((location) => {
const eventLocationType = getEventLocationType(location.type);
if (!eventLocationType) {
// It's possible that the location app got uninstalled
return null;
}
return (
<div key={location.type} className="flex flex-row items-center text-sm font-medium">
<img
src={eventLocationType.iconUrl}
className={classNames(
"mr-[10px] ml-[2px] h-4 w-4 opacity-70 dark:opacity-100 ",
!eventLocationType.iconUrl?.includes("api") ? "dark:invert" : ""
)}
alt={`${eventLocationType.label} icon`}
/>
<span key={location.type}>{locationKeyToString(location)} </span>
</div>
);
})}
</div>
</div>
) : (
@@ -97,8 +97,8 @@ const AvailableTimes: FC<AvailableTimesProps> = ({
<Link href={bookingUrl} prefetch={false}>
<a
className={classNames(
"text-primary-500 hover:bg-brand hover:text-brandcontrast dark:hover:bg-darkmodebrand",
"dark:hover:text-darkmodebrandcontrast dark:bg-darkgray-200 dark:hover:border-darkgray-900 mb-2 block rounded-md border bg-white py-2.5 text-sm font-medium hover:text-white dark:border-transparent dark:text-neutral-200",
"text-primary-500 hover:border-gray-900 hover:bg-gray-50",
"dark:bg-darkgray-200 dark:hover:bg-darkgray-300 dark:hover:border-darkmodebrand mb-2 block rounded-md border bg-white py-2 text-sm font-medium dark:border-transparent dark:text-neutral-200",
brand === "#fff" || brand === "#ffffff" ? "" : ""
)}
data-testid="time">
+1 -1
View File
@@ -33,7 +33,7 @@ const TimeOptions: FC<Props> = ({ onToggle24hClock, onSelectTimeZone, timeFormat
};
return selectedTimeZone !== "" ? (
<div className="max-w-80 absolute z-10 w-full rounded-sm border border-gray-200 bg-white px-4 pt-4 pb-3 shadow-sm dark:border-0 dark:bg-gray-700">
<div className="max-w-80 dark:border-darkgray-300 dark:bg-darkgray-200 absolute z-10 w-full rounded-sm border border-gray-200 bg-white px-4 pt-4 pb-3 shadow-sm">
<div className="mb-4 flex">
<div className="text-sm font-medium text-gray-600 dark:text-white">{t("time_options")}</div>
<div className="ml-auto flex items-center">
@@ -468,7 +468,7 @@ const BookingPage = ({
"dark:border-darkgray-300 rounded-md sm:border"
)}>
<div className="sm:flex">
<div className="sm:dark:border-darkgray-300 dark:text-darkgray-600 flex flex-col space-y-2 px-6 pt-6 pb-0 text-gray-600 sm:w-1/2 sm:border-r sm:pb-6">
<div className="sm:dark:border-darkgray-300 dark:text-darkgray-600 flex flex-col px-6 pt-6 pb-0 text-gray-600 sm:w-1/2 sm:border-r sm:pb-6">
<UserAvatars
profile={profile}
users={eventType.users}
@@ -479,41 +479,26 @@ const BookingPage = ({
<h2 className="mt-2 break-words text-sm font-medium text-gray-500 dark:text-gray-300">
{profile.name}
</h2>
<h1 className="font-cal dark:text-darkgray-900 mb-6 break-words text-2xl text-gray-900 ">
<h1 className="font-cal dark:text-darkgray-900 break-words text-2xl text-gray-900 ">
{eventType.title}
</h1>
{!!eventType.seatsPerTimeSlot && (
<p
className={`${
booking && booking.attendees.length / eventType.seatsPerTimeSlot >= 0.5
? "text-rose-600"
: booking && booking.attendees.length / eventType.seatsPerTimeSlot >= 0.33
? "text-yellow-500"
: "text-emerald-400"
} mb-2`}>
{booking
? eventType.seatsPerTimeSlot - booking.attendees.length
: eventType.seatsPerTimeSlot}{" "}
/ {eventType.seatsPerTimeSlot} {t("seats_available")}
</p>
)}
{eventType?.description && (
<div className="dark:text-darkgray-600 flex py-1 text-sm font-medium text-gray-600">
<div>
<Icon.FiInfo className="dark:text-darkgray-600 mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4 text-gray-500" />
<div className="mt-4 flex flex-col space-y-3 lg:mt-9">
{eventType?.description && (
<div className="dark:text-darkgray-600 flex text-sm font-medium text-gray-600">
<div>
<Icon.FiInfo className="dark:text-darkgray-600 mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4 text-gray-500" />
</div>
<EventTypeDescriptionSafeHTML eventType={eventType} />
</div>
<EventTypeDescriptionSafeHTML eventType={eventType} />
</div>
)}
{eventType?.requiresConfirmation && (
<div className="dark:text-darkgray-600 flex items-center text-sm font-medium text-gray-600">
<div>
<Icon.FiCheckSquare className="mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4 " />
)}
{eventType?.requiresConfirmation && (
<div className="dark:text-darkgray-600 flex items-center text-sm font-medium text-gray-600">
<div>
<Icon.FiCheckSquare className="mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4 " />
</div>
{t("requires_confirmation")}
</div>
{t("requires_confirmation")}
</div>
)}
<div className="flex flex-col space-y-2">
)}
<p className="dark:text-darkgray-600 text-sm font-medium text-gray-600">
<Icon.FiClock className="mr-[10px] -mt-1 ml-[2px] inline-block h-4 w-4" />
{eventType.length} {t("minutes")}
@@ -580,6 +565,24 @@ const BookingPage = ({
</p>
</div>
)}
{!!eventType.seatsPerTimeSlot && (
<div className="text-bookinghighlight flex items-start text-sm">
<Icon.FiUser className="mr-[10px] ml-[2px] mt-[2px] inline-block h-4 w-4" />
<p
className={`${
booking && booking.attendees.length / eventType.seatsPerTimeSlot >= 0.5
? "text-rose-600"
: booking && booking.attendees.length / eventType.seatsPerTimeSlot >= 0.33
? "text-yellow-500"
: "text-bookinghighlight"
} mb-2 font-medium`}>
{booking
? eventType.seatsPerTimeSlot - booking.attendees.length
: eventType.seatsPerTimeSlot}{" "}
/ {eventType.seatsPerTimeSlot} {t("seats_available")}
</p>
</div>
)}
</div>
</div>
<div className="p-6 sm:w-1/2">
@@ -645,12 +648,12 @@ const BookingPage = ({
<input
type="radio"
disabled={!!disableLocations}
className="location h-4 w-4 border-gray-300 text-black focus:ring-black ltr:mr-2 rtl:ml-2"
className="location dark:bg-darkgray-300 dark:border-darkgray-300 h-4 w-4 border-gray-300 text-black focus:ring-black ltr:mr-2 rtl:ml-2"
{...bookingForm.register("locationType", { required: true })}
value={location.type}
defaultChecked={defaultChecked}
/>
<span className="text-sm ltr:ml-2 rtl:mr-2 dark:text-gray-500">
<span className="text-sm ltr:ml-2 rtl:mr-2 dark:text-white">
{locationKeyToString(location)}
</span>
</label>
@@ -874,7 +877,15 @@ const BookingPage = ({
)}
</div>
<div className="flex items-start space-x-2 rtl:space-x-reverse">
<div className="flex justify-end space-x-2 rtl:space-x-reverse">
<Button
color="secondary"
type="button"
onClick={() => router.back()}
// We override this for this component only for now - as we don't support darkmode everywhere in the app
className="dark:border-none">
{t("cancel")}
</Button>
<Button
type="submit"
className="dark:bg-darkmodebrand dark:text-darkmodebrandcontrast rounded-md"
@@ -882,13 +893,6 @@ const BookingPage = ({
loading={mutation.isLoading || recurringMutation.isLoading}>
{rescheduleUid ? t("reschedule") : t("confirm")}
</Button>
<Button
color="secondary"
type="button"
onClick={() => router.back()}
className="rounded-md">
{t("cancel")}
</Button>
</div>
</Form>
{(mutation.isError || recurringMutation.isError) && (
+12 -48
View File
@@ -1,4 +1,3 @@
import classnames from "classnames";
import Link from "next/link";
import { TeamPageProps } from "pages/team/[slug]";
import React from "react";
@@ -6,11 +5,10 @@ import React from "react";
import { WEBAPP_URL } from "@calcom/lib/constants";
import Button from "@calcom/ui/Button";
import { Icon } from "@calcom/ui/Icon";
import { Avatar } from "@calcom/ui/v2";
import { useLocale } from "@lib/hooks/useLocale";
import Avatar from "@components/ui/Avatar";
type TeamType = TeamPageProps["team"];
type MembersType = TeamType["members"];
type MemberType = MembersType[number];
@@ -19,47 +17,20 @@ const Team = ({ team }: TeamPageProps) => {
const { t } = useLocale();
const Member = ({ member }: { member: MemberType }) => {
const classes = classnames(
"group",
"relative",
"flex flex-col",
"space-y-4",
"p-4",
"min-w-full sm:min-w-64 sm:max-w-64",
"bg-white dark:bg-neutral-800 dark:border-neutral-700 dark:bg-opacity-8",
"border border-neutral-200",
"hover:cursor-pointer",
"hover:border-brand dark:border-neutral-700 dark:hover:border-neutral-600",
"rounded-sm",
"hover:shadow-md"
);
return (
<Link key={member.id} href={`/${member.username}`}>
<div className={classes}>
<Icon.FiArrowRight
className={classnames(
"text-black dark:text-white",
"absolute top-4 right-4",
"h-4 w-4",
"transition-opacity",
"opacity-0 group-hover:block group-hover:opacity-100"
)}
<div className="sm:min-w-80 sm:max-w-80 dark:bg-darkgray-200 dark:hover:bg-darkgray-300 group flex h-full flex-col space-y-2 rounded-md bg-white p-4 hover:cursor-pointer hover:bg-gray-50 ">
<Avatar
size="md"
alt={member.name || ""}
imageSrc={WEBAPP_URL + "/" + member.username + "/avatar.png"}
/>
<div>
<Avatar
alt={member.name || ""}
imageSrc={WEBAPP_URL + "/" + member.username + "/avatar.png"}
className="-mt-4 h-12 w-12"
/>
<section className="line-clamp-4 mt-2 w-full space-y-1">
<p className="font-medium text-neutral-900 dark:text-white">{member.name}</p>
<p className="text-sm font-normal text-neutral-500 dark:text-white">
{member.bio || t("user_from_team", { user: member.name, team: team.name })}
</p>
</section>
</div>
<section className="line-clamp-4 mt-2 w-full space-y-1">
<p className="font-medium text-neutral-900 dark:text-white">{member.name}</p>
<p className="line-clamp-3 overflow-ellipsis text-sm font-normal text-neutral-500 dark:text-white">
{member.bio || t("user_from_team", { user: member.name, team: team.name })}
</p>
</section>
</div>
</Link>
);
@@ -82,13 +53,6 @@ const Team = ({ team }: TeamPageProps) => {
return (
<div>
<Members members={team.members} />
{team.eventTypes.length > 0 && (
<aside className="mt-8 text-center dark:text-white">
<Button color="secondary" href={`/team/${team.slug}`} shallow={true} StartIcon={Icon.FiArrowLeft}>
{t("go_back")}
</Button>
</aside>
)}
</div>
);
};
@@ -49,6 +49,7 @@ export const EventAdvancedTab = ({ eventType, team }: Pick<EventTypeSetupInfered
const placeholderHashedLink = `${CAL_URL}/d/${hashedUrl}/${eventType.slug}`;
const animationRef = useRef(null);
const seatsEnabled = !!eventType.seatsPerTimeSlot;
useEffect(() => {
animationRef.current && autoAnimate(animationRef.current);
@@ -172,7 +173,12 @@ export const EventAdvancedTab = ({ eventType, team }: Pick<EventTypeSetupInfered
defaultValue={eventType.requiresConfirmation}
render={({ field: { value, onChange } }) => (
<div className="flex space-x-3 ">
<Switch name="requireConfirmation" checked={value} onCheckedChange={(e) => onChange(e)} />
<Switch
name="requireConfirmation"
checked={value}
onCheckedChange={(e) => onChange(e)}
disabled={seatsEnabled}
/>
<div className="flex flex-col">
<Label className="text-sm font-semibold leading-none text-black">
{t("requires_confirmation")}
@@ -184,6 +190,27 @@ export const EventAdvancedTab = ({ eventType, team }: Pick<EventTypeSetupInfered
</div>
)}
/>
<hr />
<Controller
name="disableGuests"
control={formMethods.control}
defaultValue={eventType.disableGuests}
render={({ field: { value, onChange } }) => (
<div className="flex space-x-3 ">
<Switch
name="disableGuests"
checked={value}
onCheckedChange={(e) => onChange(e)}
disabled={seatsEnabled}
/>
<div className="flex flex-col">
<Label className="text-sm font-semibold leading-none text-black">{t("disable_guests")}</Label>
<p className="-mt-2 text-sm leading-normal text-gray-600">{t("disable_guests_description")}</p>
</div>
</div>
)}
/>
<hr />
<Controller
name="hideCalendarNotes"
+4 -4
View File
@@ -171,7 +171,7 @@ export default function User(props: inferSSRProps<typeof getServerSideProps>) {
<div
key={type.id}
style={{ display: "flex", ...eventTypeListItemEmbedStyles }}
className="dark:bg-darkgray-100 group relative border-b border-neutral-200 bg-white first:rounded-t-md last:rounded-b-md last:border-b-0 hover:bg-white dark:border-neutral-700 dark:hover:border-neutral-600">
className="dark:bg-darkgray-100 group relative border-b border-neutral-200 bg-white first:rounded-t-md last:rounded-b-md last:border-b-0 hover:bg-gray-50 dark:border-neutral-700 dark:hover:border-neutral-600">
<Icon.FiArrowRight className="absolute right-4 top-4 h-4 w-4 text-black opacity-0 transition-opacity group-hover:opacity-100 dark:text-white" />
{/* Don't prefetch till the time we drop the amount of javascript in [user][type] page which is impacting score for [user] page */}
<Link
@@ -198,11 +198,11 @@ export default function User(props: inferSSRProps<typeof getServerSideProps>) {
}}
className="block w-full p-5"
data-testid="event-type-link">
<div className="flex items-center space-x-2">
<h2 className="dark:text-darkgray-700 text-sm font-semibold text-gray-700">
<div className="flex flex-wrap items-center">
<h2 className="dark:text-darkgray-700 pr-2 text-sm font-semibold text-gray-700">
{type.title}
</h2>
<p className="dark:text-darkgray-600 text-sm font-normal leading-none text-gray-600">{`/${user.username}/${type.slug}`}</p>
<p className="dark:text-darkgray-600 hidden text-sm font-normal leading-none text-gray-600 md:block">{`/${user.username}/${type.slug}`}</p>
</div>
<EventTypeDescription eventType={type} />
</a>
+23 -20
View File
@@ -12,6 +12,7 @@ import useTheme from "@calcom/lib/hooks/useTheme";
import { getTeamWithMembers } from "@calcom/lib/server/queries/teams";
import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry";
import { Icon } from "@calcom/ui/Icon";
import { Avatar } from "@calcom/ui/v2";
import { Button } from "@calcom/ui/v2/core";
import EventTypeDescription from "@calcom/ui/v2/modules/event-types/EventTypeDescription";
@@ -22,7 +23,6 @@ import { inferSSRProps } from "@lib/types/inferSSRProps";
import { HeadSeo } from "@components/seo/head-seo";
import Team from "@components/team/screens/Team";
import Avatar from "@components/ui/Avatar";
import AvatarGroup from "@components/ui/AvatarGroup";
export type TeamPageProps = inferSSRProps<typeof getServerSideProps>;
@@ -42,25 +42,27 @@ function TeamPage({ team }: TeamPageProps) {
);
}, [telemetry, router.asPath]);
const eventTypes = (
const EventTypes = () => (
<ul className="">
{team.eventTypes.map((type) => (
{team.eventTypes.map((type, index) => (
<li
key={type.id}
key={index}
className={classNames(
"hover:border-brand dark:bg-darkgray-200 group relative border-b border-neutral-200 bg-white first:rounded-t-md last:rounded-b-md last:border-b-0 hover:bg-white dark:border-neutral-700 dark:hover:border-neutral-600",
isEmbed ? "" : "bg-white"
"dark:bg-darkgray-100 dark:border-darkgray-200 group relative rounded-sm border border-neutral-200 bg-white hover:bg-gray-50 dark:hover:border-neutral-600",
!isEmbed && "bg-white"
)}>
<Icon.FiArrowRight className="absolute right-3 top-3 h-4 w-4 text-black opacity-0 transition-opacity group-hover:opacity-100 dark:text-white" />
<Link href={`${team.slug}/${type.slug}`}>
<a className="flex justify-between p-5">
<a className="flex justify-between px-6 py-4" data-testid="event-type-link">
<div className="flex-shrink">
<h2 className="font-cal font-semibold text-neutral-900 dark:text-white">{type.title}</h2>
<div className="flex flex-wrap items-center space-x-2">
<h2 className="dark:text-darkgray-700 text-sm font-semibold text-gray-700">{type.title}</h2>
<p className="dark:text-darkgray-600 hidden text-sm font-normal leading-none text-gray-600 md:block">{`/${team.slug}/${type.slug}`}</p>
</div>
<EventTypeDescription className="text-sm" eventType={type} />
</div>
<div className="mt-1 self-center">
<AvatarGroup
border="border-2 border-white dark:border-neutral-800"
border="border-2 border-white"
truncateAfter={4}
className="flex flex-shrink-0"
size={10}
@@ -83,20 +85,20 @@ function TeamPage({ team }: TeamPageProps) {
return (
<div>
<HeadSeo title={teamName} description={teamName} />
<div className="dark:bg-darkgray-50 h-screen rounded-md bg-gray-100 px-4 pt-24 pb-12">
<div className="dark:bg-darkgray-50 h-screen rounded-md bg-gray-100 px-4 pt-12 pb-12">
<div className="max-w-96 mx-auto mb-8 text-center">
<Avatar
alt={teamName}
imageSrc={getPlaceholderAvatar(team.logo, team.name)}
className="mx-auto mb-4 h-20 w-20 rounded-full"
/>
<p className="font-cal mb-2 text-3xl tracking-wider text-gray-900 dark:text-white">{teamName}</p>
<p className="mt-2 text-sm font-normal text-neutral-500 dark:text-white">{team.bio}</p>
<Avatar alt={teamName} imageSrc={getPlaceholderAvatar(team.logo, team.name)} size="lg" />
<p className="font-cal dark:text-darkgray-900 mb-2 text-2xl tracking-wider text-gray-900">
{teamName}
</p>
<p className="dark:text-darkgray-500 mt-2 text-sm font-normal text-gray-500">{team.bio}</p>
</div>
{(showMembers.isOn || !team.eventTypes.length) && <Team team={team} />}
{!showMembers.isOn && team.eventTypes.length > 0 && (
<div className="mx-auto max-w-3xl ">
<div className="dark:border-darkgray-300 rounded-md border">{eventTypes}</div>
<div className="dark:border-darkgray-300 rounded-md border">
<EventTypes />
</div>
<div className="relative mt-12">
<div className="absolute inset-0 flex items-center" aria-hidden="true">
<div className="dark:border-darkgray-300 w-full border-t border-gray-200" />
@@ -110,8 +112,9 @@ function TeamPage({ team }: TeamPageProps) {
<aside className="mt-8 text-center dark:text-white">
<Button
color="secondary"
color="minimal"
EndIcon={Icon.FiArrowRight}
className="dark:hover:bg-darkgray-200"
href={`/team/${team.slug}?members=1`}
shallow={true}>
{t("book_a_team_member")}
+1
View File
@@ -307,6 +307,7 @@ export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeL
<Tooltip content={t("preview") as string}>
<Button
color="minimalSecondary"
target="_blank"
size="icon"
href={calLink}
StartIcon={Icon.FiExternalLink}
File diff suppressed because one or more lines are too long
+4 -2
View File
@@ -19,8 +19,10 @@ function PhoneInput<FormValues>({ control, name, className, ...rest }: PhoneInpu
name={name}
control={control}
countrySelectProps={{ className: "text-black" }}
numberInputProps={{ className: "border-0 text-sm focus:ring-0 dark:bg-gray-700" }}
className={`${className} border-1 focus-within:border-brand block w-full rounded-sm border border-gray-300 py-px pl-3 ring-black focus-within:ring-1 disabled:text-gray-500 disabled:opacity-50 dark:border-gray-900 dark:bg-gray-700 dark:text-white dark:selection:bg-green-500 disabled:dark:text-gray-500`}
numberInputProps={{
className: "border-0 text-sm focus:ring-0 dark:bg-darkgray-100 dark:placeholder:text-darkgray-600",
}}
className={`${className} border-1 focus-within:border-brand dark:bg-darkgray-100 dark:border-darkgray-300 block w-full rounded-md rounded-sm border border-gray-300 py-px pl-3 ring-black focus-within:ring-1 disabled:text-gray-500 disabled:opacity-50 dark:text-white dark:selection:bg-green-500 disabled:dark:text-gray-500`}
/>
);
}
+1 -1
View File
@@ -7,7 +7,7 @@ import BaseSelect, {
Props as SelectProps,
} from "react-timezone-select";
import { InputComponent } from "./Select";
import { InputComponent } from "@calcom/ui/v2/core/form/Select";
function TimezoneSelect({ className, ...props }: SelectProps) {
return (
+1 -1
View File
@@ -31,7 +31,7 @@ export default function Avatar(props: AvatarProps) {
<AvatarPrimitive.Root
className={classNames(
sizeClassname,
"relative inline-block aspect-square overflow-hidden rounded-full bg-gray-300"
"dark:bg-darkgray-300 relative inline-block aspect-square overflow-hidden rounded-full bg-gray-300"
)}>
<AvatarPrimitive.Image src={imageSrc ?? undefined} alt={alt} className={rootClass} />
<AvatarPrimitive.Fallback delayMs={600}>
+10 -3
View File
@@ -8,6 +8,9 @@ import classNames from "@calcom/lib/classNames";
const Switch = (
props: React.ComponentProps<typeof PrimitiveSwitch.Root> & {
label?: string;
thumbProps?: {
className?: string;
};
}
) => {
const { label, ...primitiveProps } = props;
@@ -18,14 +21,18 @@ const Switch = (
<PrimitiveSwitch.Root
className={classNames(
props.checked ? "bg-gray-900" : "bg-gray-200 hover:bg-gray-300",
"focus:ring-brand-800 h-[24px] w-[40px] rounded-full p-[3px] shadow-inner"
"focus:ring-brand-800 h-[24px] w-[40px] rounded-full p-[3px] shadow-none",
props.className
)}
{...primitiveProps}>
<PrimitiveSwitch.Thumb
id={id}
// Since we dont support global dark mode - we have to style dark mode components specifically on the instance for now
// TODO: Remove once we support global dark mode
className={classNames(
"block h-[18px] w-[18px] translate-x-0 rounded-full bg-white shadow-md transition-transform",
props.checked && "shadow-inner"
"block h-[18px] w-[18px] translate-x-0 rounded-full bg-white transition-transform",
props.checked && "shadow-inner",
props.thumbProps?.className
)}
/>
</PrimitiveSwitch.Root>
+2 -2
View File
@@ -43,7 +43,7 @@ export const Day = ({
<button
style={props.disabled ? { ...disabledDateButtonEmbedStyles } : { ...enabledDateButtonEmbedStyles }}
className={classNames(
"disabled:text-bookinglighter absolute top-0 left-0 right-0 bottom-0 mx-auto w-full rounded-md border-2 border-transparent text-center font-medium disabled:cursor-default disabled:border-transparent disabled:font-light dark:hover:border-white disabled:dark:border-transparent",
"disabled:text-bookinglighter dark:hover:border-darkmodebrand absolute top-0 left-0 right-0 bottom-0 mx-auto w-full rounded-md border-2 border-transparent text-center font-medium disabled:cursor-default disabled:border-transparent disabled:font-light disabled:dark:border-transparent",
active
? "dark:bg-darkmodebrand dark:text-darkmodebrandcontrast bg-brand text-brandcontrast border-2"
: !props.disabled
@@ -89,7 +89,7 @@ const Days = ({
<div key={`e-${idx}`} />
) : props.isLoading ? (
<button
className="absolute top-0 left-0 right-0 bottom-0 mx-auto flex w-full items-center justify-center rounded-md border-transparent bg-gray-50 text-center text-gray-400 opacity-50 dark:bg-black dark:text-gray-600/40"
className=" dark:bg-darkgray-200 absolute top-0 left-0 right-0 bottom-0 mx-auto flex w-full items-center justify-center rounded-sm border-transparent bg-gray-50 text-center text-gray-400 opacity-50 dark:text-gray-400"
key={`e-${idx}`}
disabled>
<SkeletonText width="5" height="4" />