Компоненты рейтинга предназначены для визуального отображения количественной оценки — чаще всего в виде звёзд, шкал или иконок. В контексте SvelteKit UI-библиотек такие компоненты должны быть:
Минимальный компонент рейтинга на Svelte:
<script>
export let value = 0;
export let max = 5;
export let readonly = false;
const handleClick = (index) => {
if (!readonly) {
value = index;
}
};
</script>
<div class="flex gap-1">
{#each Array(max) as _, i}
<button
class="text-yellow-400"
on:click={() => handleClick(i + 1)}
aria-label={`Rate ${i + 1}`}
>
{i < value ? '★' : '☆'}
</button>
{/each}
</div>
Svelte позволяет легко реализовать binding:
<Rating bind:value={rating} />
Это делает компонент пригодным для форм, отзывов и интерактивных интерфейсов.
Для более точных оценок (например, 4.5) требуется дополнительная логика:
{#each Array(max) as _, i}
<span>
{#if i + 1 <= value}
★
{:else if i < value}
⯨
{:else}
☆
{/if}
</span>
{/each}
Здесь используется частично заполненная иконка.
UI-библиотеки часто предоставляют возможность переопределить отображение:
<Rating let:item let:active>
<MyStar {active} />
</Rating>
Это позволяет использовать SVG, анимации и любые визуальные элементы.
Ключевые аспекты:
role="slider" или role="radiogroup"aria-valuenow, aria-valuemin,
aria-valuemaxПример:
<div
role="slider"
aria-valuenow={value}
aria-valuemin="0"
aria-valuemax={max}
tabindex="0"
on:keydown={(e) => {
if (e.key === 'ArrowRight') value = Math.min(value + 1, max);
if (e.key === 'ArrowLeft') value = Math.max(value - 1, 0);
}}
>
<input type="hidden" name="rating" value={value} />
Позволяет использовать компонент внутри <form> без
дополнительной логики.
Бейджи — компактные визуальные элементы для отображения статуса, количества или категории. Используются в списках, карточках, навигации и уведомлениях.
<script>
export let text = '';
</script>
<span class="px-2 py-1 text-xs rounded bg-gray-200">
{text}
</span>
UI-библиотеки обычно предлагают набор предопределённых стилей:
<script>
export let variant = 'default';
const styles = {
default: 'bg-gray-200 text-gray-800',
success: 'bg-green-200 text-green-800',
warning: 'bg-yellow-200 text-yellow-800',
danger: 'bg-red-200 text-red-800'
};
</script>
<span class={`px-2 py-1 rounded ${styles[variant]}`}>
<slot />
</span>
Часто используются для уведомлений:
<span class="relative">
<slot />
<span class="absolute -top-2 -right-2 bg-red-500 text-white text-xs px-1 rounded-full">
{count}
</span>
</span>
Реактивность Svelte позволяет легко менять содержимое:
$: statusColor = status === 'active' ? 'green' : 'gray';
<span class={`bg-${statusColor}-200`}>
{status}
</span>
<span class="flex items-center gap-1 bg-blue-100 px-2 py-1 rounded">
<Icon name="info" />
Info
</span>
<a href="/notifications" class="badge">
Notifications
</a>
или
<button class="badge" on:click={handleClick}>
Clickable
</button>
<div class="flex gap-2">
<Badge>New</Badge>
<Badge variant="success">Active</Badge>
<Badge variant="danger">Error</Badge>
</div>
Многие Svelte UI-библиотеки (например, shadcn-svelte, skeleton, melt-ui) реализуют headless-компоненты:
Пример:
const rating = createRating();
<div use:rating.root>
{#each rating.items as item}
<button use:rating.item={item} />
{/each}
</div>
value)export let value;
let internal = value ?? 0;
Использование CSS variables:
.badge {
background-color: var(--badge-bg);
}
Позволяет централизованно управлять стилями.
Использование keyed each:
{#each items as item (item.id)}
Рейтинг часто используется в списках:
Проверка:
<Rating bind:value={product.rating} readonly />
<form>
<Rating bind:value={rating} />
<textarea bind:value={comment}></textarea>
</form>
<Badge variant="success">Online</Badge>
<Badge>{notifications.length}</Badge>
<span class:scale-110={hovered}>
<Tooltip content="New feature">
<Badge>New</Badge>
</Tooltip>
<div class="flex items-center gap-2">
<Rating value={4.5} readonly />
<Badge>Top Rated</Badge>
</div>
value без
$:)При использовании в SvelteKit:
window в компонентеonMount только при необходимости<Rating>
<Rating.Item />
<Rating.Item />
</Rating>
setContext('rating', { value });
const { value } = getContext('rating');
Позволяет управлять состоянием без проп-дриллинга.
Такие компоненты формируют основу интерфейсных паттернов: компактное отображение информации (badges) и интуитивная оценка (rating). Их качественная реализация напрямую влияет на UX, особенно в интерфейсах с высокой плотностью данных.