feat(shared/ui): add Card, Section, and TechStackBrick components

This commit is contained in:
Ilia Mashkov
2026-03-06 23:16:34 +03:00
parent 30f5d01370
commit fc245407a1
5 changed files with 116 additions and 0 deletions

View 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>

View 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>

View 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>

View 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';

View File

@@ -0,0 +1,2 @@
export type SectionBackground = 'ochre' | 'slate' | 'white';
export type ContainerSize = 'default' | 'wide' | 'ultra-wide';