SvChip

A compact, interactive pill for a selected value, filter token, or entity: an optional leading avatar or icon, a label, and an optional remove button.

SvChip is the interactive cousin of SvBadge. Where a badge is a static status marker, a chip can be clicked to select and dismissed to remove - perfect for tag inputs, active-filter rows, and "assigned to" pickers. It draws from the grid's --sg-* semantic tokens in both soft and solid fills.

Basic usage

<script lang="ts">
  import { SvChip } from '@svgrid/grid'
  let tags = $state(['design', 'urgent'])
</script>

{#each tags as tag}
  <SvChip removable onRemove={() => (tags = tags.filter((t) => t !== tag))}>{tag}</SvChip>
{/each}

Props

Prop Type Default Description
variant neutral | accent | success | warning | danger | info neutral Semantic color, from the matching --sg-* token.
size sm | md md Height, font size, and padding.
removable boolean false Shows a trailing remove (x) button.
onRemove () => void - Called when the remove button is clicked.
onClick () => void - Makes the label a button and fires on activation.
solid boolean false Filled solid fill instead of the default soft tint.
disabled boolean false Dims the chip and blocks interaction.
children Snippet - The chip label.
leading Snippet - Leading content such as an avatar or icon.

Patterns

Removable tags

Wire removable and onRemove to build a tag list from an array:

{#each labels as label (label)}
  <SvChip variant="accent" removable onRemove={() => remove(label)}>{label}</SvChip>
{/each}

Clickable filter chips

Give onClick to turn a chip into a toggle for an active-filter bar:

<SvChip variant={active ? 'accent' : 'neutral'} solid={active} onClick={toggle}>
  In stock
</SvChip>

Entity chips with an avatar

The leading snippet slots an SvAvatar for people and entities:

<SvChip onClick={openProfile}>
  {#snippet leading()}<SvAvatar size="sm" name="Ada Lovelace" />{/snippet}
  Ada Lovelace
</SvChip>

Active-filter token row

Reflect the current filters as a removable chip set: each chip clears its own filter, and a trailing action resets them all:

<script lang="ts">
  import { SvChip, SvButton } from '@svgrid/grid'
  let filters = $state([
    { key: 'status', label: 'Status: Open', variant: 'accent' },
    { key: 'owner', label: 'Owner: Me', variant: 'info' },
    { key: 'due', label: 'Overdue', variant: 'danger' },
  ] as const)

  const remove = (key: string) => (filters = filters.filter((f) => f.key !== key))
</script>

<div style="display:flex; flex-wrap:wrap; gap:6px; align-items:center;">
  {#each filters as f (f.key)}
    <SvChip variant={f.variant} size="sm" removable onRemove={() => remove(f.key)}>
      {f.label}
    </SvChip>
  {/each}
  {#if filters.length}
    <SvButton size="sm" variant="ghost" onclick={() => (filters = [])}>Clear all</SvButton>
  {/if}
</div>

Tip: the remove control is a separate <button> from the label, so a chip can be both clickable (onClick) and removable (removable) at once without the two hit areas overlapping.

Accessibility

See also