feat(shared/ui): add Card, Section, and TechStackBrick components
This commit is contained in:
32
src/shared/ui/Section/Container.svelte
Normal file
32
src/shared/ui/Section/Container.svelte
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<!--
|
||||||
|
Component: Container
|
||||||
|
Centered max-width wrapper. Three size presets for responsive layouts up to 4K.
|
||||||
|
-->
|
||||||
|
<script lang="ts">
|
||||||
|
import { cn } from '$shared/lib/cn';
|
||||||
|
import type { Snippet } from 'svelte';
|
||||||
|
import type { ContainerSize } from './types';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
/** Max-width preset @default 'default' */
|
||||||
|
size?: ContainerSize;
|
||||||
|
children?: Snippet;
|
||||||
|
class?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
let { size = 'default', children, class: className }: Props = $props();
|
||||||
|
|
||||||
|
const sizeStyles: Record<ContainerSize, string> = {
|
||||||
|
'default': 'max-w-7xl',
|
||||||
|
'wide': 'max-w-[1920px]',
|
||||||
|
'ultra-wide': 'max-w-[2560px]',
|
||||||
|
};
|
||||||
|
|
||||||
|
const classes = $derived(cn('mx-auto px-6 md:px-12 lg:px-16', sizeStyles[size], className));
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class={classes}>
|
||||||
|
{#if children}
|
||||||
|
{@render children()}
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
42
src/shared/ui/Section/Section.stories.svelte
Normal file
42
src/shared/ui/Section/Section.stories.svelte
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
<script module>
|
||||||
|
import { defineMeta } from '@storybook/addon-svelte-csf';
|
||||||
|
import Container from './Container.svelte';
|
||||||
|
import Section from './Section.svelte';
|
||||||
|
|
||||||
|
const { Story } = defineMeta({
|
||||||
|
title: 'Shared/Section',
|
||||||
|
component: Section,
|
||||||
|
tags: ['autodocs'],
|
||||||
|
parameters: { layout: 'fullscreen' },
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Story name="Ochre (default)">
|
||||||
|
{#snippet template()}
|
||||||
|
<Section>
|
||||||
|
<Container>
|
||||||
|
<p class="py-16">Section content</p>
|
||||||
|
</Container>
|
||||||
|
</Section>
|
||||||
|
{/snippet}
|
||||||
|
</Story>
|
||||||
|
|
||||||
|
<Story name="Slate">
|
||||||
|
{#snippet template()}
|
||||||
|
<Section background="slate">
|
||||||
|
<Container>
|
||||||
|
<p class="py-16">Section content on slate</p>
|
||||||
|
</Container>
|
||||||
|
</Section>
|
||||||
|
{/snippet}
|
||||||
|
</Story>
|
||||||
|
|
||||||
|
<Story name="Bordered">
|
||||||
|
{#snippet template()}
|
||||||
|
<Section bordered>
|
||||||
|
<Container>
|
||||||
|
<p class="py-16">Section with brutal top and bottom borders</p>
|
||||||
|
</Container>
|
||||||
|
</Section>
|
||||||
|
{/snippet}
|
||||||
|
</Story>
|
||||||
37
src/shared/ui/Section/Section.svelte
Normal file
37
src/shared/ui/Section/Section.svelte
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<!--
|
||||||
|
Component: Section
|
||||||
|
Full-width page section. Controls background and optional top/bottom brutal borders.
|
||||||
|
-->
|
||||||
|
<script lang="ts">
|
||||||
|
import { cn } from '$shared/lib/cn';
|
||||||
|
import type { Snippet } from 'svelte';
|
||||||
|
import type { SectionBackground } from './types';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
background?: SectionBackground;
|
||||||
|
/** Add brutal border on top and bottom @default false */
|
||||||
|
bordered?: boolean;
|
||||||
|
children?: Snippet;
|
||||||
|
class?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
let { background = 'ochre', bordered = false, children, class: className }: Props = $props();
|
||||||
|
|
||||||
|
const backgroundStyles: Record<SectionBackground, string> = {
|
||||||
|
ochre: 'bg-ochre-clay text-carbon-black',
|
||||||
|
slate: 'bg-slate-indigo text-ochre-clay',
|
||||||
|
white: 'bg-white text-carbon-black',
|
||||||
|
};
|
||||||
|
|
||||||
|
const classes = $derived(cn(
|
||||||
|
backgroundStyles[background],
|
||||||
|
bordered && 'brutal-border-top brutal-border-bottom',
|
||||||
|
className,
|
||||||
|
));
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<section class={classes}>
|
||||||
|
{#if children}
|
||||||
|
{@render children()}
|
||||||
|
{/if}
|
||||||
|
</section>
|
||||||
3
src/shared/ui/Section/index.ts
Normal file
3
src/shared/ui/Section/index.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
export { default as Section } from './Section.svelte';
|
||||||
|
export { default as Container } from './Container.svelte';
|
||||||
|
export type { SectionBackground, ContainerSize } from './types';
|
||||||
2
src/shared/ui/Section/types.ts
Normal file
2
src/shared/ui/Section/types.ts
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
export type SectionBackground = 'ochre' | 'slate' | 'white';
|
||||||
|
export type ContainerSize = 'default' | 'wide' | 'ultra-wide';
|
||||||
Reference in New Issue
Block a user