Move Skeleton to ui/components (#6247)

* Inital Move

* Skeleton story
This commit is contained in:
sean-brydon
2023-01-03 15:54:00 +00:00
committed by GitHub
parent 89a52dad21
commit d9da311141
11 changed files with 48 additions and 12 deletions
+1
View File
@@ -32,3 +32,4 @@ export type { TopBannerProps } from "./top-banner";
export { AnimatedPopover } from "./popover/index";
export { TableActions, DropdownActions } from "./table/TableActions";
export type { ActionType } from "./table/TableActions";
export { Skeleton, SkeletonAvatar, SkeletonButton, SkeletonContainer, SkeletonText } from "./skeleton";
+96
View File
@@ -0,0 +1,96 @@
import React from "react";
import classNames from "@calcom/lib/classNames";
import { useLocale } from "@calcom/lib/hooks/useLocale";
type SkeletonBaseProps = {
className?: string;
};
interface SkeletonContainer {
as?: keyof JSX.IntrinsicElements;
children?: React.ReactNode;
className?: string;
}
const SkeletonAvatar: React.FC<SkeletonBaseProps> = ({ className }) => {
return <div className={classNames(`mt-1 rounded-full bg-gray-200 ltr:mr-2 rtl:ml-2`, className)} />;
};
type SkeletonProps<T> = {
as: keyof JSX.IntrinsicElements | React.FC;
className?: string;
children: React.ReactNode;
loading?: boolean;
waitForTranslation?: boolean;
loadingClassName?: string;
} & (T extends React.FC<infer P>
? P
: T extends keyof JSX.IntrinsicElements
? JSX.IntrinsicElements[T]
: never);
const Skeleton = <T extends keyof JSX.IntrinsicElements | React.FC>({
as,
className = "",
children,
loading = false,
/**
* Assumes that the text needs translation by default and wait for it.
*/
waitForTranslation = true,
/**
* Classes that you need only in loading state
*/
loadingClassName = "",
...rest
}: SkeletonProps<T>) => {
const { isLocaleReady } = useLocale();
loading = (waitForTranslation ? !isLocaleReady : false) || loading;
const Component = as;
return (
<Component
className={classNames(
loading
? classNames(
"font-size-0 dark:white-300 animate-pulse rounded-md bg-gray-300 text-transparent",
loadingClassName
)
: "",
className
)}
{...rest}>
{children}
</Component>
);
};
const SkeletonText: React.FC<SkeletonBaseProps & { invisible?: boolean }> = ({
className = "",
invisible = false,
}) => {
return (
<span
className={classNames(
`font-size-0 dark:white-300 inline-block animate-pulse rounded-md bg-gray-300 empty:before:inline-block empty:before:content-['']`,
className,
invisible ? "invisible" : ""
)}
/>
);
};
const SkeletonButton: React.FC<SkeletonBaseProps> = ({ className }) => {
return (
<SkeletonContainer>
<div className={classNames(`rounded-md bg-gray-200`, className)} />
</SkeletonContainer>
);
};
const SkeletonContainer: React.FC<SkeletonContainer> = ({ children, as, className }) => {
const Component = as || "div";
return <Component className={classNames("animate-pulse", className)}>{children}</Component>;
};
export { Skeleton, SkeletonAvatar, SkeletonText, SkeletonButton, SkeletonContainer };
@@ -0,0 +1,36 @@
import { Canvas, Meta, Story, ArgsTable } from '@storybook/addon-docs';
import { Examples, Example, Note, Title, VariantsTable, VariantColumn, RowTitles, CustomArgsTable} from '@calcom/storybook/components'
import { Icon } from "@calcom/ui";
import { Skeleton, SkeletonAvatar, SkeletonText, SkeletonButton, SkeletonContainer } from './';
<Meta title="UI/Skeleton" component={Skeleton} />
<Title title="Skeleton" suffix="Brief" subtitle="Version 2.0 — Last Update: 22 Aug 2022"/>
## Definition
Skeletons are used as a placeholder to the content while the content is being loaded. It is used to improve the user experience by providing a visual cue that the content is loading.
## Structure
<CustomArgsTable of={Skeleton} />
<Examples title="Skeleton Avatar" >
<Example title="Primary">
<SkeletonAvatar className="h-8 w-8" />
</Example>
</Examples>
<Examples title="Skeleton Text" >
<Example title="Primary">
<SkeletonText className="h-4 w-32"/>
</Example>
</Examples>
<Examples title="Skeleton Button" >
<Example title="Primary">
<SkeletonButton className="h-8 w-32"/>
</Example>
</Examples>