Files
frontend-svelte/src/shared/ui/Badge/Badge.svelte

84 lines
1.9 KiB
Svelte
Raw Normal View History

2026-02-22 11:26:11 +03:00
<!--
Component: Badge
Pill badge with border and optional status dot.
2026-02-22 11:26:11 +03:00
-->
<script lang="ts">
import { cn } from '$shared/shadcn/utils/shadcn-utils';
import {
type LabelSize,
labelSizeConfig,
} from '$shared/ui/Label/config';
import type { Snippet } from 'svelte';
import type { HTMLAttributes } from 'svelte/elements';
2026-02-22 11:26:11 +03:00
type BadgeVariant = 'default' | 'accent' | 'success' | 'warning' | 'info';
2026-02-22 11:26:11 +03:00
const badgeVariantConfig: Record<BadgeVariant, string> = {
default: 'border-black/10 dark:border-white/10 text-neutral-500',
accent: 'bg-brand/10 border-brand/20 text-brand',
success: 'bg-green-500/10 border-green-500/20 text-green-600 dark:text-green-400',
warning: 'bg-yellow-500/10 border-yellow-500/20 text-yellow-600 dark:text-yellow-400',
info: 'bg-blue-500/10 border-blue-500/20 text-blue-600 dark:text-blue-400',
};
2026-02-22 11:26:11 +03:00
interface Props extends HTMLAttributes<HTMLSpanElement> {
/**
* Visual variant
* @default 'default'
*/
variant?: BadgeVariant;
/**
* Badge size
* @default 'xs'
*/
size?: LabelSize;
/**
* Show status dot
* @default false
*/
dot?: boolean;
/**
* Prevent text wrapping
* @default false
*/
nowrap?: boolean;
/**
* Content snippet
*/
children?: Snippet;
/**
* CSS classes
*/
class?: string;
}
2026-02-22 11:26:11 +03:00
let {
variant = 'default',
size = 'xs',
dot = false,
nowrap = false,
children,
class: className,
...rest
}: Props = $props();
2026-02-22 11:26:11 +03:00
</script>
<span
class={cn(
'inline-flex items-center gap-1 px-2 py-0.5 border rounded-full',
'font-mono uppercase tracking-wide',
labelSizeConfig[size],
badgeVariantConfig[variant],
nowrap && 'text-nowrap',
className,
)}
{...rest}
>
{#if dot}
<span class="w-1 h-1 rounded-full bg-current"></span>
{/if}
{#if children}
{@render children()}
{/if}
2026-02-22 11:26:11 +03:00
</span>