90 lines
2.5 KiB
TypeScript
90 lines
2.5 KiB
TypeScript
import { LucideIcon } from 'lucide-react';
|
|
import { ReactNode } from 'react';
|
|
import { Box } from './Box';
|
|
import { Button } from './Button';
|
|
import { Heading } from './Heading';
|
|
import { Icon } from './Icon';
|
|
import { Surface } from './Surface';
|
|
import { Text } from './Text';
|
|
|
|
export interface PageHeroProps {
|
|
title: string;
|
|
description?: string;
|
|
children?: ReactNode;
|
|
image?: ReactNode;
|
|
icon?: LucideIcon;
|
|
actions?: Array<{
|
|
label: string;
|
|
onClick: () => void;
|
|
variant?: 'primary' | 'secondary';
|
|
icon?: LucideIcon;
|
|
}>;
|
|
}
|
|
|
|
export const PageHero = ({
|
|
title,
|
|
description,
|
|
children,
|
|
image,
|
|
icon,
|
|
actions
|
|
}: PageHeroProps) => {
|
|
return (
|
|
<Surface
|
|
variant="dark"
|
|
rounded="xl"
|
|
padding={8}
|
|
style={{ position: 'relative', overflow: 'hidden', border: '1px solid var(--ui-color-border-default)' }}
|
|
>
|
|
<Box display="flex" flexDirection={{ base: 'col', lg: 'row' }} alignItems="center" gap={8}>
|
|
<Box flex={1}>
|
|
<Box display="flex" alignItems="center" gap={4} marginBottom={4}>
|
|
{icon && (
|
|
<Box padding={3} rounded="lg" bg="var(--ui-color-bg-surface-muted)">
|
|
<Icon icon={icon} size={8} intent="primary" />
|
|
</Box>
|
|
)}
|
|
<Heading level={1}>{title}</Heading>
|
|
</Box>
|
|
{description && (
|
|
<Text size="lg" variant="low" marginBottom={6} block>
|
|
{description}
|
|
</Text>
|
|
)}
|
|
{actions && (
|
|
<Box display="flex" gap={4} marginBottom={children ? 6 : 0}>
|
|
{actions.map((action) => (
|
|
<Button
|
|
key={action.label}
|
|
variant={action.variant || 'primary'}
|
|
onClick={action.onClick}
|
|
icon={action.icon ? <Icon icon={action.icon} size={4} /> : undefined}
|
|
>
|
|
{action.label}
|
|
</Button>
|
|
))}
|
|
</Box>
|
|
)}
|
|
{children}
|
|
</Box>
|
|
{image && (
|
|
<Box flex={1} display="flex" justifyContent="center">
|
|
{image}
|
|
</Box>
|
|
)}
|
|
</Box>
|
|
|
|
{/* Decorative elements */}
|
|
<Box
|
|
position="absolute"
|
|
top="-4rem"
|
|
right="-4rem"
|
|
width="16rem"
|
|
height="16rem"
|
|
bg="var(--ui-color-intent-primary)"
|
|
style={{ opacity: 0.05, filter: 'blur(64px)', borderRadius: '9999px' }}
|
|
/>
|
|
</Surface>
|
|
);
|
|
};
|