mirror of
https://github.com/portainer/portainer.git
synced 2026-06-23 04:20:11 +00:00
484af3c2c8
Last system-test failure is also on dev
121 lines
2.8 KiB
TypeScript
121 lines
2.8 KiB
TypeScript
import { ReactNode } from 'react';
|
|
import clsx from 'clsx';
|
|
|
|
import { Widget } from '@@/Widget';
|
|
import { Alert } from '@@/Alert';
|
|
|
|
interface Props {
|
|
icon: ReactNode;
|
|
iconBackgroundClassName?: string;
|
|
|
|
subtitleLabel?: string;
|
|
subtitleClassName?: string;
|
|
title: string;
|
|
badge?: ReactNode;
|
|
description?: ReactNode;
|
|
|
|
rightInfo?: ReactNode;
|
|
actionBar?: ReactNode;
|
|
|
|
isLoading?: boolean;
|
|
errorMessage?: string;
|
|
|
|
containerClassName?: string;
|
|
widgetClassName?: string;
|
|
}
|
|
|
|
export function ResourceDetailHeader({
|
|
icon,
|
|
iconBackgroundClassName = 'bg-group-accent-3 th-dark:bg-group-accent-10',
|
|
subtitleLabel,
|
|
subtitleClassName = 'text-group-accent-10 th-dark:text-group-accent-8',
|
|
title,
|
|
badge,
|
|
description,
|
|
rightInfo,
|
|
actionBar,
|
|
isLoading,
|
|
errorMessage,
|
|
containerClassName = 'flex items-center gap-4 p-6',
|
|
widgetClassName = 'widget-body',
|
|
}: Props) {
|
|
return (
|
|
<Widget className={widgetClassName}>
|
|
<Widget.Body loading={isLoading}>
|
|
{errorMessage && (
|
|
<Alert color="error" title="Error">
|
|
{errorMessage}
|
|
</Alert>
|
|
)}
|
|
{!errorMessage && (
|
|
<div className={containerClassName}>
|
|
<HeaderIcon
|
|
icon={icon}
|
|
iconBackgroundClassName={iconBackgroundClassName}
|
|
/>
|
|
<HeaderInfo
|
|
subtitleLabel={subtitleLabel}
|
|
subtitleClassName={subtitleClassName}
|
|
title={title}
|
|
badge={badge}
|
|
description={description}
|
|
/>
|
|
{rightInfo}
|
|
</div>
|
|
)}
|
|
</Widget.Body>
|
|
|
|
{!isLoading && !errorMessage && actionBar}
|
|
</Widget>
|
|
);
|
|
}
|
|
|
|
interface HeaderIconProps {
|
|
icon: ReactNode;
|
|
iconBackgroundClassName: string;
|
|
}
|
|
|
|
function HeaderIcon({ icon, iconBackgroundClassName }: HeaderIconProps) {
|
|
return (
|
|
<div
|
|
className={clsx(
|
|
'flex h-14 w-14 shrink-0 items-center justify-center rounded-lg text-3xl',
|
|
iconBackgroundClassName
|
|
)}
|
|
>
|
|
{icon}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
interface HeaderInfoProps {
|
|
subtitleLabel?: string;
|
|
subtitleClassName: string;
|
|
title: string;
|
|
badge?: ReactNode;
|
|
description?: ReactNode;
|
|
}
|
|
|
|
function HeaderInfo({
|
|
subtitleLabel,
|
|
subtitleClassName,
|
|
title,
|
|
badge,
|
|
description,
|
|
}: HeaderInfoProps) {
|
|
return (
|
|
<div className="flex flex-1 flex-col">
|
|
{subtitleLabel && (
|
|
<span className={clsx('text-xs font-medium', subtitleClassName)}>
|
|
{subtitleLabel}
|
|
</span>
|
|
)}
|
|
<div className="flex items-center gap-2">
|
|
<h2 className="m-0 text-lg font-bold">{title}</h2>
|
|
{badge && <div className="flex flex-wrap gap-1">{badge}</div>}
|
|
</div>
|
|
{description && <span className="text-muted text-xs">{description}</span>}
|
|
</div>
|
|
);
|
|
}
|