feature/project-redesign #28
139
src/shared/ui/Metric/Metric.stories.svelte
Normal file
139
src/shared/ui/Metric/Metric.stories.svelte
Normal file
@@ -0,0 +1,139 @@
|
||||
<script module>
|
||||
import { defineMeta } from '@storybook/addon-svelte-csf';
|
||||
import Metric from './Metric.svelte';
|
||||
|
||||
const { Story } = defineMeta({
|
||||
title: 'Shared/Metric',
|
||||
component: Metric,
|
||||
tags: ['autodocs'],
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
component: 'Large technical value display with label below and optional unit.',
|
||||
},
|
||||
story: { inline: false },
|
||||
},
|
||||
layout: 'centered',
|
||||
},
|
||||
argTypes: {
|
||||
value: {
|
||||
control: 'text',
|
||||
description: 'Metric value',
|
||||
defaultValue: '42',
|
||||
},
|
||||
label: {
|
||||
control: 'text',
|
||||
description: 'Metric label',
|
||||
defaultValue: 'Label',
|
||||
},
|
||||
unit: {
|
||||
control: 'text',
|
||||
description: 'Optional unit',
|
||||
},
|
||||
variant: {
|
||||
control: 'select',
|
||||
options: ['default', 'accent', 'muted', 'success', 'warning', 'error'],
|
||||
description: 'Color variant',
|
||||
defaultValue: 'accent',
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<Story
|
||||
name="With unit"
|
||||
args={{ value: 128, label: 'Font Size', unit: 'px', variant: 'accent' }}
|
||||
>
|
||||
{#snippet template()}
|
||||
<Metric value={128} label="Font Size" unit="px" variant="accent" />
|
||||
{/snippet}
|
||||
</Story>
|
||||
|
||||
<Story
|
||||
name="Without unit"
|
||||
args={{ value: 500, label: 'Weight', variant: 'accent' }}
|
||||
>
|
||||
{#snippet template()}
|
||||
<Metric value={500} label="Weight" variant="accent" />
|
||||
{/snippet}
|
||||
</Story>
|
||||
|
||||
<Story
|
||||
name="Default variant"
|
||||
args={{ value: 42, label: 'Value', variant: 'default' }}
|
||||
>
|
||||
{#snippet template()}
|
||||
<Metric value={42} label="Value" variant="default" />
|
||||
{/snippet}
|
||||
</Story>
|
||||
|
||||
<Story
|
||||
name="Accent variant"
|
||||
args={{ value: 128, label: 'Size', variant: 'accent' }}
|
||||
>
|
||||
{#snippet template()}
|
||||
<Metric value={128} label="Size" variant="accent" />
|
||||
{/snippet}
|
||||
</Story>
|
||||
|
||||
<Story
|
||||
name="Muted variant"
|
||||
args={{ value: 0, label: 'Spacing', variant: 'muted' }}
|
||||
>
|
||||
{#snippet template()}
|
||||
<Metric value={0} label="Spacing" variant="muted" />
|
||||
{/snippet}
|
||||
</Story>
|
||||
|
||||
<Story
|
||||
name="Success variant"
|
||||
args={{ value: 100, label: 'Score', variant: 'success' }}
|
||||
>
|
||||
{#snippet template()}
|
||||
<Metric value={100} label="Score" variant="success" />
|
||||
{/snippet}
|
||||
</Story>
|
||||
|
||||
<Story
|
||||
name="Warning variant"
|
||||
args={{ value: 3, label: 'Issues', variant: 'warning' }}
|
||||
>
|
||||
{#snippet template()}
|
||||
<Metric value={3} label="Issues" variant="warning" />
|
||||
{/snippet}
|
||||
</Story>
|
||||
|
||||
<Story
|
||||
name="Error variant"
|
||||
args={{ value: 1, label: 'Errors', variant: 'error' }}
|
||||
>
|
||||
{#snippet template()}
|
||||
<Metric value={1} label="Errors" variant="error" />
|
||||
{/snippet}
|
||||
</Story>
|
||||
|
||||
<Story name="All variants with unit">
|
||||
{#snippet template()}
|
||||
<div class="flex gap-6">
|
||||
<Metric value={42} label="Default" unit="px" variant="default" />
|
||||
<Metric value={42} label="Accent" unit="px" variant="accent" />
|
||||
<Metric value={42} label="Muted" unit="px" variant="muted" />
|
||||
<Metric value={42} label="Success" unit="px" variant="success" />
|
||||
<Metric value={42} label="Warning" unit="px" variant="warning" />
|
||||
<Metric value={42} label="Error" unit="px" variant="error" />
|
||||
</div>
|
||||
{/snippet}
|
||||
</Story>
|
||||
|
||||
<Story name="All variants without unit">
|
||||
{#snippet template()}
|
||||
<div class="flex gap-6">
|
||||
<Metric value={42} label="Default" variant="default" />
|
||||
<Metric value={42} label="Accent" variant="accent" />
|
||||
<Metric value={42} label="Muted" variant="muted" />
|
||||
<Metric value={42} label="Success" variant="success" />
|
||||
<Metric value={42} label="Warning" variant="warning" />
|
||||
<Metric value={42} label="Error" variant="error" />
|
||||
</div>
|
||||
{/snippet}
|
||||
</Story>
|
||||
47
src/shared/ui/Metric/Metric.svelte
Normal file
47
src/shared/ui/Metric/Metric.svelte
Normal file
@@ -0,0 +1,47 @@
|
||||
<!--
|
||||
Component: Metric
|
||||
Large technical value display with label below and optional unit.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { cn } from '$shared/shadcn/utils/shadcn-utils';
|
||||
import { Label } from '$shared/ui';
|
||||
import {
|
||||
type LabelVariant,
|
||||
labelVariantConfig,
|
||||
} from '$shared/ui/Label/config';
|
||||
|
||||
interface Props {
|
||||
value: string | number;
|
||||
label: string;
|
||||
unit?: string;
|
||||
variant?: LabelVariant;
|
||||
class?: string;
|
||||
}
|
||||
|
||||
let {
|
||||
value,
|
||||
label,
|
||||
unit,
|
||||
variant = 'accent',
|
||||
class: className,
|
||||
}: Props = $props();
|
||||
</script>
|
||||
|
||||
<div class={cn('flex flex-col gap-1', className)}>
|
||||
<div class="flex items-baseline gap-1">
|
||||
<span
|
||||
class={cn(
|
||||
"font-['Space_Mono'] text-2xl font-bold tabular-nums",
|
||||
labelVariantConfig[variant],
|
||||
)}
|
||||
>
|
||||
{value}
|
||||
</span>
|
||||
|
||||
{#if unit}
|
||||
<Label variant="muted" size="xs">{unit}</Label>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<Label variant="muted" size="xs">{label}</Label>
|
||||
</div>
|
||||
Reference in New Issue
Block a user