Files
frontend-svelte/src/shared/ui/Section/Section.svelte
T

104 lines
2.2 KiB
Svelte

<!--
Component: Section
Provides a container for a page widget with snippets for a title
-->
<script lang="ts">
import { type Snippet } from 'svelte';
import { cubicOut } from 'svelte/easing';
import type { HTMLAttributes } from 'svelte/elements';
import {
type FlyParams,
fly,
} from 'svelte/transition';
import SectionHeader from './SectionHeader/SectionHeader.svelte';
import SectionTitle from './SectionTitle/SectionTitle.svelte';
interface Props extends Omit<HTMLAttributes<HTMLElement>, 'title'> {
/**
* Section ID
*/
id?: string;
/**
* CSS classes
*/
class?: string;
/**
* Section title
*/
title: string;
/**
* Breadcrumb title
*/
breadcrumbTitle?: string;
/**
* Description snippet
*/
description?: Snippet<[{ className?: string }]>;
/**
* Header title
*/
headerTitle?: string;
/**
* Header subtitle
*/
headerSubtitle?: string;
/**
* Header action callback
*/
headerAction?: (node: HTMLElement) => void;
/**
* Section index
*/
index?: number;
/**
* Content snippet
*/
content?: Snippet<[{ className?: string }]>;
/**
* Header content snippet
*/
headerContent?: Snippet<[{ className?: string }]>;
}
let {
class: className,
title,
headerTitle,
headerSubtitle,
headerContent,
headerAction = () => {},
index = 0,
id,
content,
}: Props = $props();
const flyParams: FlyParams = {
y: 0,
x: -50,
duration: 300,
easing: cubicOut,
opacity: 0.2,
};
</script>
<section
{id}
class="w-full max-w-7xl mx-auto px-4 md:px-6 py-8 md:py-16 {className}"
in:fly={flyParams}
out:fly={flyParams}
>
<div
use:headerAction
class="flex flex-col md:flex-row md:items-end justify-between mb-8 md:mb-12 gap-4 md:gap-6"
>
<div>
{#if headerTitle}
<SectionHeader title={headerTitle} subtitle={headerSubtitle} {index} />
{/if}
<SectionTitle text={title} />
</div>
{@render headerContent?.({})}
</div>
{@render content?.({})}
</section>