feat(Stat): Label wrapper for statistics

This commit is contained in:
Ilia Mashkov
2026-02-24 18:00:43 +03:00
parent 83f2bdcdda
commit eac47fb99d
2 changed files with 170 additions and 0 deletions

View File

@@ -0,0 +1,136 @@
<script module>
import { defineMeta } from '@storybook/addon-svelte-csf';
import Stat from './Stat.svelte';
const { Story } = defineMeta({
title: 'Shared/Stat',
component: Stat,
tags: ['autodocs'],
parameters: {
docs: {
description: {
component: 'A single key:value pair in Space Mono. Optional trailing divider.',
},
story: { inline: false },
},
layout: 'centered',
},
argTypes: {
label: {
control: 'text',
description: 'Stat label/key',
defaultValue: 'Label',
},
value: {
control: 'text',
description: 'Stat value',
defaultValue: 'Value',
},
variant: {
control: 'select',
options: ['default', 'accent', 'muted', 'success', 'warning', 'error'],
description: 'Value variant',
defaultValue: 'default',
},
separator: {
control: 'boolean',
description: 'Show trailing divider',
defaultValue: false,
},
},
});
</script>
<Story
name="Default/Basic"
args={{ label: 'Label', value: 'Value' }}
parameters={{ docs: { description: { story: 'Standard stat with label and value' } } }}
>
{#snippet template()}
<Stat label="Label" value="Value" />
{/snippet}
</Story>
<Story
name="With string value"
args={{ label: 'Font', value: 'Inter' }}
>
{#snippet template()}
<Stat label="Font" value="Inter" />
{/snippet}
</Story>
<Story
name="With number value"
args={{ label: 'Weight', value: 400 }}
>
{#snippet template()}
<Stat label="Weight" value={400} />
{/snippet}
</Story>
<Story
name="With separator"
args={{ label: 'Size', value: '16px', separator: true }}
>
{#snippet template()}
<div class="flex items-center">
<Stat label="Size" value="16px" separator />
<Stat label="Line" value="1.5" />
</div>
{/snippet}
</Story>
<Story
name="Default variant"
args={{ variant: 'default', label: 'Status', value: 'Active' }}
>
{#snippet template()}
<Stat label="Status" value="Active" variant="default" />
{/snippet}
</Story>
<Story
name="Accent variant"
args={{ variant: 'accent', label: 'Status', value: 'Active' }}
>
{#snippet template()}
<Stat label="Status" value="Active" variant="accent" />
{/snippet}
</Story>
<Story
name="Muted variant"
args={{ variant: 'muted', label: 'Status', value: 'Inactive' }}
>
{#snippet template()}
<Stat label="Status" value="Inactive" variant="muted" />
{/snippet}
</Story>
<Story
name="Success variant"
args={{ variant: 'success', label: 'Status', value: 'Success' }}
>
{#snippet template()}
<Stat label="Status" value="Success" variant="success" />
{/snippet}
</Story>
<Story
name="Warning variant"
args={{ variant: 'warning', label: 'Status', value: 'Warning' }}
>
{#snippet template()}
<Stat label="Status" value="Warning" variant="warning" />
{/snippet}
</Story>
<Story
name="Error variant"
args={{ variant: 'error', label: 'Status', value: 'Error' }}
>
{#snippet template()}
<Stat label="Status" value="Error" variant="error" />
{/snippet}
</Story>

View File

@@ -0,0 +1,34 @@
<!--
Component: Stat
A single key:value pair in Space Mono. Optional trailing divider.
-->
<script lang="ts">
import { cn } from '$shared/shadcn/utils/shadcn-utils';
import { Label } from '$shared/ui';
import type { ComponentProps } from 'svelte';
interface Props extends Pick<ComponentProps<typeof Label>, 'variant'> {
label: string;
value: string | number;
/** Renders a 1px vertical divider after the stat. */
separator?: boolean;
class?: string;
}
let {
label,
value,
variant = 'default',
separator = false,
class: className,
}: Props = $props();
</script>
<div class={cn('flex items-center gap-1', className)}>
<Label variant="muted" size="xs">{label}:</Label>
<Label {variant} size="xs" bold>{value}</Label>
</div>
{#if separator}
<div class="w-px h-2 bg-black/10 dark:bg-white/10"></div>
{/if}