Pulse/frontend-modern/src/components/shared/SectionHeader.tsx
2025-10-22 12:39:53 +00:00

65 lines
1.8 KiB
TypeScript

import { JSX, Show, splitProps, mergeProps } from 'solid-js';
type SectionHeaderProps = {
label?: JSX.Element;
title: JSX.Element;
description?: JSX.Element;
align?: 'left' | 'center';
size?: 'sm' | 'md' | 'lg';
titleClass?: string;
descriptionClass?: string;
} & Omit<JSX.HTMLAttributes<HTMLDivElement>, 'title'>;
export function SectionHeader(props: SectionHeaderProps) {
const merged = mergeProps(
{ align: 'left' as const, size: 'md' as const, titleClass: '', descriptionClass: '' },
props,
);
const [local, rest] = splitProps(merged, [
'label',
'title',
'description',
'align',
'size',
'titleClass',
'descriptionClass',
'class',
]);
const alignmentClass =
local.align === 'center' ? 'text-center items-center' : 'text-left items-start';
const sizeClass = () => {
switch (local.size) {
case 'sm':
return 'text-base sm:text-lg';
case 'lg':
return 'text-xl sm:text-2xl lg:text-3xl';
default:
return 'text-lg sm:text-xl';
}
};
return (
<div class={`flex flex-col gap-1 ${alignmentClass} ${local.class ?? ''}`.trim()} {...rest}>
<Show when={local.label}>
<span class="text-[0.7rem] font-semibold uppercase tracking-[0.18em] text-gray-500 dark:text-gray-400">
{local.label}
</span>
</Show>
<h2
class={`${sizeClass()} font-semibold leading-snug text-gray-900 dark:text-gray-100 ${local.titleClass ?? ''}`.trim()}
>
{local.title}
</h2>
<Show when={local.description}>
<p
class={`text-sm sm:text-base text-gray-600 dark:text-gray-400 ${local.descriptionClass ?? ''}`.trim()}
>
{local.description}
</p>
</Show>
</div>
);
}
export default SectionHeader;