Add PageTemplate with skeletons and apply to Framework list
Signed-off-by: Émile Ré <nemile.re@gmail.com>
This commit is contained in:
26
apps/console/src/components/PageContainer.tsx
Normal file
26
apps/console/src/components/PageContainer.tsx
Normal file
@@ -0,0 +1,26 @@
|
||||
import { FC, ReactNode } from "react";
|
||||
import { Helmet } from "react-helmet-async";
|
||||
|
||||
export interface PageContainerProps {
|
||||
children: ReactNode;
|
||||
title: string;
|
||||
}
|
||||
|
||||
export const PageContainer: FC<PageContainerProps> = ({ children, title }) => {
|
||||
return (
|
||||
<>
|
||||
<Helmet>{`${title} - Probo Console`}</Helmet>
|
||||
<div className="container">{children}</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const PageContainerSkeleton: FC<{
|
||||
title?: string;
|
||||
children: ReactNode;
|
||||
}> = ({ children, title }) =>
|
||||
title ? (
|
||||
<PageContainer title={title}>{children}</PageContainer>
|
||||
) : (
|
||||
<div className="container">{children}</div>
|
||||
);
|
||||
108
apps/console/src/components/PageHeader.tsx
Normal file
108
apps/console/src/components/PageHeader.tsx
Normal file
@@ -0,0 +1,108 @@
|
||||
import { cn } from "@/lib/utils";
|
||||
import { FC, ReactNode } from "react";
|
||||
|
||||
export interface PageHeaderProps {
|
||||
title: ReactNode;
|
||||
actions?: ReactNode;
|
||||
description?: ReactNode;
|
||||
}
|
||||
|
||||
export function PageHeaderShell({
|
||||
className,
|
||||
title,
|
||||
actions,
|
||||
description,
|
||||
}: PageHeaderProps & { className?: string }) {
|
||||
return (
|
||||
<div className={cn("space-y-6", className)}>
|
||||
{actions ? (
|
||||
<div className="flex items-center justify-between">
|
||||
{title}
|
||||
{actions}
|
||||
</div>
|
||||
) : (
|
||||
title
|
||||
)}
|
||||
{description}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function PageHeader({
|
||||
className,
|
||||
title,
|
||||
actions,
|
||||
description,
|
||||
}: PageHeaderProps & { className?: string }) {
|
||||
return (
|
||||
<PageHeaderShell
|
||||
className={className}
|
||||
title={<PageHeading>{title}</PageHeading>}
|
||||
description={<PageDescription>{description}</PageDescription>}
|
||||
actions={actions}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export function PageHeading({
|
||||
children,
|
||||
className,
|
||||
}: {
|
||||
className?: string;
|
||||
children: ReactNode;
|
||||
}) {
|
||||
return <h1 className={cn("text-3xl font-medium", className)}>{children}</h1>;
|
||||
}
|
||||
|
||||
const PageHeadingSkeleton: FC = () => {
|
||||
return (
|
||||
<div className="py-[3px]">
|
||||
<div className="bg-muted animate rounded-lg w-60 h-7.5" />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export function PageDescription({
|
||||
children,
|
||||
className,
|
||||
}: {
|
||||
className?: string;
|
||||
children: ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<p className={cn("text-md text-muted-foreground", className)}>{children}</p>
|
||||
);
|
||||
}
|
||||
|
||||
export function PageDescriptionSkeleton() {
|
||||
return (
|
||||
<div className="py-[5px]">
|
||||
<div className="bg-muted animate rounded-md w-100 h-4.5" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export const PageHeaderSkeleton: FC<{
|
||||
className?: string;
|
||||
title?: string;
|
||||
actions?: ReactNode;
|
||||
description?: ReactNode;
|
||||
withDescription?: boolean;
|
||||
}> = ({ className, title, actions, description, withDescription = false }) => {
|
||||
return (
|
||||
<PageHeaderShell
|
||||
className={className}
|
||||
title={
|
||||
title ? <PageHeading>{title}</PageHeading> : <PageHeadingSkeleton />
|
||||
}
|
||||
description={
|
||||
description ? (
|
||||
<PageDescription>{description}</PageDescription>
|
||||
) : withDescription ? (
|
||||
<PageDescriptionSkeleton />
|
||||
) : null
|
||||
}
|
||||
actions={actions}
|
||||
/>
|
||||
);
|
||||
};
|
||||
47
apps/console/src/components/PageTemplate.tsx
Normal file
47
apps/console/src/components/PageTemplate.tsx
Normal file
@@ -0,0 +1,47 @@
|
||||
import { FC, ReactNode } from "react";
|
||||
import {
|
||||
PageContainer,
|
||||
PageContainerProps,
|
||||
PageContainerSkeleton,
|
||||
} from "./PageContainer";
|
||||
import { PageHeader, PageHeaderProps, PageHeaderSkeleton } from "./PageHeader";
|
||||
|
||||
export const PageTemplate: FC<PageContainerProps & PageHeaderProps> = ({
|
||||
actions,
|
||||
title,
|
||||
description,
|
||||
children,
|
||||
}) => {
|
||||
return (
|
||||
<PageContainer title={title}>
|
||||
<PageHeader
|
||||
className="mb-17"
|
||||
title={title}
|
||||
description={description}
|
||||
actions={actions}
|
||||
/>
|
||||
{children}
|
||||
</PageContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export const PageTemplateSkeleton: FC<{
|
||||
title?: string;
|
||||
description?: ReactNode;
|
||||
withDescription?: boolean;
|
||||
actions?: ReactNode;
|
||||
children: ReactNode;
|
||||
}> = ({ actions, children, description, withDescription = false, title }) => {
|
||||
return (
|
||||
<PageContainerSkeleton title={title}>
|
||||
<PageHeaderSkeleton
|
||||
className="mb-17"
|
||||
title={title}
|
||||
description={description}
|
||||
withDescription={withDescription}
|
||||
actions={actions}
|
||||
/>
|
||||
{children}
|
||||
</PageContainerSkeleton>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user