90 lines
2.0 KiB
TypeScript
90 lines
2.0 KiB
TypeScript
import * as React from 'react';
|
|
import { clsx } from 'clsx';
|
|
|
|
export interface PanelProps extends React.HTMLAttributes<HTMLElement> {
|
|
as?: 'section' | 'aside' | 'article' | 'div';
|
|
density?: 'compact' | 'normal' | 'spacious';
|
|
}
|
|
|
|
const panelPadding: Record<NonNullable<PanelProps['density']>, string> = {
|
|
compact: 'p-4',
|
|
normal: 'p-5',
|
|
spacious: 'p-6',
|
|
};
|
|
|
|
export function Panel({
|
|
as: Comp = 'section',
|
|
density = 'normal',
|
|
className,
|
|
children,
|
|
...props
|
|
}: PanelProps) {
|
|
return (
|
|
<Comp
|
|
className={clsx(
|
|
'rounded-xl border border-[var(--bl-border)] bg-[var(--bl-surface-card)] shadow-sm shadow-black/[0.04]',
|
|
panelPadding[density],
|
|
className
|
|
)}
|
|
{...props}
|
|
>
|
|
{children}
|
|
</Comp>
|
|
);
|
|
}
|
|
|
|
export type PanelHeaderProps = React.HTMLAttributes<HTMLDivElement>;
|
|
|
|
export function PanelHeader({ className, children, ...props }: PanelHeaderProps) {
|
|
return (
|
|
<div
|
|
className={clsx(
|
|
'flex flex-col gap-1 sm:flex-row sm:items-center sm:justify-between sm:gap-3',
|
|
className
|
|
)}
|
|
{...props}
|
|
>
|
|
{children}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export type PanelBodyProps = React.HTMLAttributes<HTMLDivElement>;
|
|
|
|
export function PanelBody({ className, children, ...props }: PanelBodyProps) {
|
|
return (
|
|
<div className={clsx('grid gap-4', className)} {...props}>
|
|
{children}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export type PanelTitleProps = React.ComponentPropsWithoutRef<'h2'>;
|
|
|
|
export function PanelTitle({ className, children, ...props }: PanelTitleProps) {
|
|
return (
|
|
<h2
|
|
className={clsx(
|
|
'm-0 text-base font-semibold leading-6 text-[var(--bl-text-primary)]',
|
|
className
|
|
)}
|
|
{...props}
|
|
>
|
|
{children}
|
|
</h2>
|
|
);
|
|
}
|
|
|
|
export type PanelDescriptionProps = React.ComponentPropsWithoutRef<'p'>;
|
|
|
|
export function PanelDescription({ className, children, ...props }: PanelDescriptionProps) {
|
|
return (
|
|
<p
|
|
className={clsx('m-0 text-sm leading-6 text-[var(--bl-text-secondary)]', className)}
|
|
{...props}
|
|
>
|
|
{children}
|
|
</p>
|
|
);
|
|
}
|