From d61238c8322d82e7a9058edf7f893ae023717acc Mon Sep 17 00:00:00 2001 From: sean-brydon <55134778+sean-brydon@users.noreply.github.com> Date: Tue, 26 Apr 2022 15:11:02 +0100 Subject: [PATCH] Loader Components (#2616) Co-authored-by: Peer Richelsen <peeroke@gmail.com> --- apps/web/components/apps/SkeletonLoader.tsx | 10 +++--- .../availability/SkeletonLoader.tsx | 8 +++-- .../web/components/booking/SkeletonLoader.tsx | 12 ++++--- .../components/eventtype/SkeletonLoader.tsx | 22 ++++++------ packages/ui/index.tsx | 1 + packages/ui/skeleton/index.tsx | 34 +++++++++++++++++++ 6 files changed, 65 insertions(+), 22 deletions(-) create mode 100644 packages/ui/skeleton/index.tsx diff --git a/apps/web/components/apps/SkeletonLoader.tsx b/apps/web/components/apps/SkeletonLoader.tsx index 8dc31def..a4ee7d04 100644 --- a/apps/web/components/apps/SkeletonLoader.tsx +++ b/apps/web/components/apps/SkeletonLoader.tsx @@ -1,5 +1,7 @@ import React from "react"; +import { SkeletonAvatar, SkeletonText } from "@calcom/ui"; + import { ShellSubHeading } from "@components/Shell"; function SkeletonLoader() { @@ -22,16 +24,16 @@ function SkeletonItem() { <li className="group flex w-full items-center justify-between p-3"> <div className="flex-grow truncate text-sm"> <div className="flex justify-start space-x-2"> - <div className="h-10 w-10 rounded-lg bg-gray-100"></div> + <SkeletonText width="10" height="10"></SkeletonText> <div className="space-y-2"> - <div className="h-4 w-32 rounded-md bg-gray-100"></div> - <div className="h-4 w-16 rounded-md bg-gray-100"></div> + <SkeletonText height="4" width="32"></SkeletonText> + <SkeletonText height="4" width="16"></SkeletonText> </div> </div> </div> <div className="mt-4 hidden flex-shrink-0 sm:mt-0 sm:ml-5 lg:flex"> <div className="flex justify-between space-x-2 rtl:space-x-reverse"> - <div className="h-11 w-32 rounded-md bg-gray-100"></div> + <SkeletonText width="32" height="11"></SkeletonText> </div> </div> </li> diff --git a/apps/web/components/availability/SkeletonLoader.tsx b/apps/web/components/availability/SkeletonLoader.tsx index 2ba945b8..2c12aa37 100644 --- a/apps/web/components/availability/SkeletonLoader.tsx +++ b/apps/web/components/availability/SkeletonLoader.tsx @@ -1,5 +1,7 @@ import React from "react"; +import { SkeletonText } from "@calcom/ui"; + function SkeletonLoader() { return ( <ul className="animate-pulse divide-y divide-neutral-200 border border-gray-200 bg-white sm:mx-0 sm:overflow-hidden"> @@ -17,13 +19,13 @@ function SkeletonItem() { <li className="group flex w-full items-center justify-between px-2 py-[23px] sm:px-6"> <div className="flex-grow truncate text-sm"> <div className="flex flex-col space-y-2"> - <div className="h-4 w-32 rounded-md bg-gray-100"></div> - <div className="h-2 w-32 rounded-md bg-gray-100"></div> + <SkeletonText width="32" height="4"></SkeletonText> + <SkeletonText width="32" height="2"></SkeletonText> </div> </div> <div className="mt-4 hidden flex-shrink-0 sm:mt-0 sm:ml-5 lg:flex"> <div className="flex justify-between space-x-2 rtl:space-x-reverse"> - <div className="h-6 w-12 rounded-md bg-gray-100"></div> + <SkeletonText width="12" height="6"></SkeletonText> </div> </div> </li> diff --git a/apps/web/components/booking/SkeletonLoader.tsx b/apps/web/components/booking/SkeletonLoader.tsx index e152b4d1..2e50ad0e 100644 --- a/apps/web/components/booking/SkeletonLoader.tsx +++ b/apps/web/components/booking/SkeletonLoader.tsx @@ -1,5 +1,7 @@ import React from "react"; +import { SkeletonText } from "@calcom/ui"; + import BookingsShell from "@components/BookingsShell"; function SkeletonLoader() { @@ -20,16 +22,16 @@ function SkeletonItem() { <div className="flex-grow truncate text-sm"> <div className="flex"> <div className="flex flex-col space-y-2"> - <div className="h-5 w-32 rounded-md bg-gray-100"></div> - <div className="h-4 w-16 rounded-md bg-gray-100"></div> + <SkeletonText width="32" height="5" /> + <SkeletonText width="16" height="4" /> </div> - <div className="ml-4 h-5 w-24 rounded-md bg-gray-100"></div> + <SkeletonText width="24" height="5" className="ml-4" /> </div> </div> <div className="mt-4 hidden flex-shrink-0 sm:mt-0 sm:ml-5 lg:flex"> <div className="flex justify-between space-x-2 rtl:space-x-reverse"> - <div className="h-6 w-16 rounded-md bg-gray-100"></div> - <div className="h-6 w-32 rounded-md bg-gray-100"></div> + <SkeletonText width="16" height="6" /> + <SkeletonText width="32" height="6" /> </div> </div> </li> diff --git a/apps/web/components/eventtype/SkeletonLoader.tsx b/apps/web/components/eventtype/SkeletonLoader.tsx index 8960352b..2397c698 100644 --- a/apps/web/components/eventtype/SkeletonLoader.tsx +++ b/apps/web/components/eventtype/SkeletonLoader.tsx @@ -2,22 +2,24 @@ import { LinkIcon } from "@heroicons/react/outline"; import { ClockIcon, DotsHorizontalIcon, ExternalLinkIcon, UserIcon } from "@heroicons/react/solid"; import React from "react"; +import { SkeletonAvatar, SkeletonContainer, SkeletonText } from "@calcom/ui"; + function SkeletonLoader() { return ( - <div className="animate-pulse"> + <SkeletonContainer> <div className="mb-4 flex items-center"> - <div className="mt-1 h-8 w-8 rounded-full bg-gray-200 ltr:mr-2 rtl:ml-2" /> + <SkeletonAvatar width="8" height="8"></SkeletonAvatar> <div className="space-y-1"> - <div className="h-4 w-16 rounded-md bg-gray-200"></div> - <div className="h-4 w-24 rounded-md bg-gray-200"></div> + <SkeletonText height="4" width="16"></SkeletonText> + <SkeletonText height="4" width="24"></SkeletonText> </div> </div> - <ul className="animate-pulse divide-y divide-neutral-200 border border-gray-200 bg-white sm:mx-0 sm:overflow-hidden"> + <ul className="divide-y divide-neutral-200 border border-gray-200 bg-white sm:mx-0 sm:overflow-hidden"> <SkeletonItem /> <SkeletonItem /> <SkeletonItem /> </ul> - </div> + </SkeletonContainer> ); } @@ -28,17 +30,17 @@ function SkeletonItem() { <li className="group flex w-full items-center justify-between px-4 py-4 sm:px-6"> <div className="flex-grow truncate text-sm"> <div> - <div className="h-5 w-32 rounded-md bg-gray-100"></div> + <SkeletonText width="32" height="5"></SkeletonText> </div> - <div className="text-neutral-500 dark:text-white"> + <div className=""> <ul className="mt-2 flex space-x-4 rtl:space-x-reverse "> <li className="flex items-center whitespace-nowrap"> <ClockIcon className="mt-0.5 mr-1.5 inline h-4 w-4 text-gray-200"></ClockIcon> - <div className="h-4 w-12 rounded-md bg-gray-100"></div> + <SkeletonText width="12" height="4"></SkeletonText> </li> <li className="flex items-center whitespace-nowrap"> <UserIcon className="mt-0.5 mr-1.5 inline h-4 w-4 text-gray-200"></UserIcon> - <div className="h-4 w-16 rounded-md bg-gray-100"></div> + <SkeletonText width="16" height="4"></SkeletonText> </li> </ul> </div> diff --git a/packages/ui/index.tsx b/packages/ui/index.tsx index 30b1364d..3290c411 100644 --- a/packages/ui/index.tsx +++ b/packages/ui/index.tsx @@ -1,3 +1,4 @@ export { default as Button } from "./Button"; export { default as EmptyScreen } from "./EmptyScreen"; export { default as Switch } from "./Switch"; +export * from "./skeleton"; diff --git a/packages/ui/skeleton/index.tsx b/packages/ui/skeleton/index.tsx new file mode 100644 index 00000000..ddc48712 --- /dev/null +++ b/packages/ui/skeleton/index.tsx @@ -0,0 +1,34 @@ +import classNames from "@calcom/lib/classNames"; + +type SkeletonBaseProps = { + width: string; + height: string; + className?: string; +}; + +interface AvatarProps extends SkeletonBaseProps { + // Limit this cause we don't use avatars bigger than thi + width: "2" | "3" | "4" | "5" | "6" | "8"; + height: "2" | "3" | "4" | "5" | "6" | "8"; +} + +interface SkeletonContainer { + as?: keyof JSX.IntrinsicElements; +} + +const SkeletonAvatar: React.FC<AvatarProps> = ({ width, height }) => { + return ( + <div className={`mt-1 rounded-full bg-gray-200 ltr:mr-2 rtl:ml-2 w-${width} h-${height} ${classNames}`} /> + ); +}; + +const SkeletonText: React.FC<SkeletonBaseProps> = ({ width, height }) => { + return <div className={`rounded-md bg-gray-200 w-${width} h-${height} ${classNames}`} />; +}; + +const SkeletonContainer: React.FC<SkeletonContainer> = ({ children, as }) => { + const Component = as || "div"; + return <Component className="animate-pulse">{children}</Component>; +}; + +export { SkeletonAvatar, SkeletonText, SkeletonContainer };