feat(Badge): rewrite Badge component to new design

This commit is contained in:
Ilia Mashkov
2026-02-27 18:43:56 +03:00
parent db518a6469
commit f7fe71f8e3
2 changed files with 106 additions and 73 deletions

View File

@@ -1,40 +1,56 @@
<!--
Component: Badge
Small status indicator with color variants and size options
Pill badge with border and optional status dot.
-->
<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';
type BadgeVariant = 'default' | 'accent' | 'success' | 'warning' | 'info';
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',
};
interface Props {
/**
* Color variant of the badge
* @default default
*/
variant?: 'default' | 'success' | 'warning' | 'error' | 'info';
/**
* Size of the badge
* @default md
*/
size?: 'sm' | 'md';
variant?: BadgeVariant;
size?: LabelSize;
/** Renders a small filled circle before the text. */
dot?: boolean;
children?: Snippet;
class?: string;
}
const { variant = 'default', size = 'md' }: Props = $props();
const baseClasses = 'inline-flex items-center justify-center rounded-full font-medium';
const variantClasses = $derived(
variant === 'success'
? 'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-400'
: variant === 'warning'
? 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900/30 dark:text-yellow-400'
: variant === 'error'
? 'bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-400'
: variant === 'info'
? 'bg-blue-100 text-blue-800 dark:bg-blue-900/30 dark:text-blue-400'
: 'bg-gray-100 text-gray-800 dark:bg-gray-800 dark:text-gray-300',
);
const sizeClasses = $derived(size === 'sm' ? 'px-2 py-0.5 text-xs' : 'px-2.5 py-0.5 text-sm');
let {
variant = 'default',
size = 'xs',
dot = false,
children,
class: className,
}: Props = $props();
</script>
<span class="{baseClasses} {variantClasses} {sizeClasses}">
<slot />
<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],
className,
)}
>
{#if dot}
<span class="w-1 h-1 rounded-full bg-current"></span>
{/if}
{#if children}
{@render children()}
{/if}
</span>