Chip

An item that can be selected or removed.

<script setup lang="ts">
  import { ref } from 'vue'
  import { Chip, Inline } from '@hina-ui/vue'

  const genres = ['Sci-fi', 'Fantasy', 'Slice of life', 'Mystery', 'Romance']
  const picked = ref(['Sci-fi', 'Slice of life'])

  function toggle(genre: string, on: boolean) {
    picked.value = on ? [...picked.value, genre] : picked.value.filter(item => item !== genre)
  }
</script>

<template>
  <Inline>
    <Chip
      v-for="genre in genres"
      :key="genre"
      selectable
      :selected="picked.includes(genre)"
      @update:selected="toggle(genre, $event)"
    >
      {{ genre }}
    </Chip>
  </Inline>
</template>
vue

Usage

import { Chip } from '@hina-ui/vue'
ts

A chip is used in one of two ways: selectable makes it selectable, removable gives it a remove button, and the two are exclusive. A short label with no interaction is a Tag.

Sci-fi
<script setup lang="ts">
  import { ref } from 'vue'
  import { Chip, Inline } from '@hina-ui/vue'

  const finished = ref(true)
  const kept = ref(true)
</script>

<template>
  <Inline>
    <Chip v-model:selected="finished" selectable>Finished</Chip>
    <Chip v-if="kept" removable @remove="kept = false">Sci-fi</Chip>
  </Inline>
</template>
vue

Examples

Selectable

With selectable set the chip renders as a button and v-model:selected binds its selected state. A selected chip takes the accent colour and shows a check icon before its text.

<script setup lang="ts">
  import { ref } from 'vue'
  import { Chip, Inline } from '@hina-ui/vue'

  const finished = ref(true)
  const translated = ref(false)
</script>

<template>
  <Inline>
    <Chip v-model:selected="finished" selectable>Finished</Chip>
    <Chip v-model:selected="translated" selectable>Translated</Chip>
  </Inline>
</template>
vue

Removable

With removable set a remove button sits at the end of the chip and emits remove when clicked; the chip itself is not clickable.

Sci-fiSchoolRomanceEnsemble
<script setup lang="ts">
  import { ref } from 'vue'
  import { Chip, Inline } from '@hina-ui/vue'

  const tags = ref(['Sci-fi', 'School', 'Romance', 'Ensemble'])
</script>

<template>
  <Inline>
    <Chip
      v-for="tag in tags"
      :key="tag"
      removable
      @remove="tags = tags.filter(item => item !== tag)"
    >
      {{ tag }}
    </Chip>
  </Inline>
</template>
vue

Variants and tones

soft has a tinted background and outline only a border; the default is soft. The tones are neutral and accent, with neutral as the default.

<script setup lang="ts">
  import { Chip, Inline } from '@hina-ui/vue'
</script>

<template>
  <Inline>
    <Chip selectable>soft</Chip>
    <Chip selectable tone="accent">soft accent</Chip>
    <Chip selectable variant="outline">outline</Chip>
    <Chip selectable variant="outline" tone="accent">outline accent</Chip>
  </Inline>
</template>
vue

Sizes

md matches the height of a small button; sm is for inputs and dense lists.

SmallMedium
<script setup lang="ts">
  import { Chip, Inline } from '@hina-ui/vue'
</script>

<template>
  <Inline align="center">
    <Chip size="sm" selectable selected>Small</Chip>
    <Chip size="sm" removable>Small</Chip>
    <Chip selectable selected>Medium</Chip>
    <Chip removable>Medium</Chip>
  </Inline>
</template>
vue

With an icon

Put the icon in the icon slot. On a selectable chip the icon gives way to the check icon once selected.

Starred
<script setup lang="ts">
  import { ref } from 'vue'
  import { Chip, Inline } from '@hina-ui/vue'
  import { Flame, Star } from '@lucide/vue'

  const hot = ref(true)
  const starred = ref(false)
</script>

<template>
  <Inline>
    <Chip v-model:selected="hot" selectable>
      <template #icon><Flame /></template>
      Trending
    </Chip>
    <Chip v-model:selected="starred" selectable>
      <template #icon><Star /></template>
      Starred
    </Chip>
    <Chip removable>
      <template #icon><Star /></template>
      Starred
    </Chip>
  </Inline>
</template>
vue

Disabled

A disabled chip ignores clicks, and its remove button is disabled as well.

Locked
<script setup lang="ts">
  import { Chip, Inline } from '@hina-ui/vue'
</script>

<template>
  <Inline>
    <Chip selectable disabled>Unselected</Chip>
    <Chip selectable selected disabled>Selected</Chip>
    <Chip removable disabled>Locked</Chip>
  </Inline>
</template>
vue

Behaviour

  • A selectable chip is a native button: click, Enter and Space all toggle it.
  • Once selected a check icon appears before the text; with an icon slot, the icon gives way to the check.
  • With the remove button focused, Enter, Space, Backspace and Delete all emit remove; clicking the remove button does not trigger a click on the chip.
  • Setting both selectable and removable warns in development and ignores removable.
  • A disabled chip ignores clicks and leaves the keyboard focus order.

Accessibility

  • A selectable chip carries aria-pressed, so screen readers announce it as a toggle button.
  • The remove button is named “Remove”, taken from chip.remove in the locale.
  • A removable chip is not focusable itself; keyboard focus lands on the remove button directly.

API

Props

Prop
Type
Default
Description
selectable
boolean
false
Whether the chip can be selected
selected
boolean
false
Selected state, supports v-model:selected
removable
boolean
false
Whether the chip has a remove button
variant
'soft' | 'outline'
'soft'
Visual style
tone
'neutral' | 'accent'
'neutral'
Tone
size
'sm' | 'md'
'md'
Size
disabled
boolean
false
Whether the chip is disabled
ripple
boolean
true
Whether pressing shows a ripple
as
string
—
The rendered tag: button when selectable, otherwise span
class
string
—
Classes appended to the root element

Events

Event
Payload
Description
update:selected
selected: boolean
The selected state changed
remove
—
The remove button was clicked

Slots

Slot
Description
default
The chip’s text
icon
An icon before the text