58 lines
1.5 KiB
TypeScript
58 lines
1.5 KiB
TypeScript
import React, { ReactNode } from 'react';
|
|
import { Surface } from './Surface';
|
|
import { Box, BoxProps } from './Box';
|
|
import { Text } from './Text';
|
|
|
|
interface PanelProps extends Omit<BoxProps<'div'>, 'variant' | 'padding'> {
|
|
children: ReactNode;
|
|
title?: string;
|
|
description?: string;
|
|
variant?: 'default' | 'muted' | 'dark' | 'glass';
|
|
padding?: 0 | 1 | 2 | 3 | 4 | 6 | 8 | 10 | 12;
|
|
border?: boolean;
|
|
className?: string;
|
|
}
|
|
|
|
/**
|
|
* A semantic wrapper for content panels.
|
|
* Follows the "Precision Racing Minimal" theme.
|
|
*/
|
|
export function Panel({
|
|
children,
|
|
title,
|
|
description,
|
|
variant = 'default',
|
|
padding = 6,
|
|
border = true,
|
|
...props
|
|
}: PanelProps) {
|
|
return (
|
|
<Surface
|
|
variant={variant}
|
|
padding={padding}
|
|
border={border}
|
|
display="flex"
|
|
flexDirection="col"
|
|
gap={4}
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
{...(props as any)}
|
|
>
|
|
{(title || description) && (
|
|
<Box display="flex" flexDirection="col" gap={1} borderBottom borderStyle="solid" borderColor="border-gray/30" pb={4} mb={2}>
|
|
{title && (
|
|
<Text as="h3" size="xs" weight="bold" color="text-gray-500" uppercase letterSpacing="widest">
|
|
{title}
|
|
</Text>
|
|
)}
|
|
{description && (
|
|
<Text size="sm" color="text-gray-400">
|
|
{description}
|
|
</Text>
|
|
)}
|
|
</Box>
|
|
)}
|
|
{children}
|
|
</Surface>
|
|
);
|
|
}
|