Skip to content

cv-chip ​

Compact interactive token for filters, applied facets, tags, and secondary action clusters.

Use cv-chip when the visible token does something: activates a filter editor, toggles a value through cv-chip-group, or exposes a dedicated remove action.

Usage ​

View source
html
<div class="chip-demo-shell" data-demo="chip">
  <section class="chip-demo-hero" aria-labelledby="chip-demo-title">
    <div class="chip-demo-copy">
      <span class="chip-demo-kicker">Interactive token</span>
      <h3 id="chip-demo-title">Use chips when the label is also a control.</h3>
      <p>
        A chip carries a stable value, optional selected state, and optional remove action in the same compact
        surface.
      </p>
    </div>

    <div class="chip-demo-rack" aria-label="Chip behavior examples">
      <div class="chip-demo-cell chip-demo-cell--good">
        <span class="chip-demo-label">Applied filter</span>
        <cv-chip value="local" selected removable>
          <span slot="prefix">#</span>
          Local vault
        </cv-chip>
        <p>Selected token with a remove affordance.</p>
      </div>

      <div class="chip-demo-cell">
        <span class="chip-demo-label">Quick action</span>
        <cv-chip value="filter-rule">
          <span slot="prefix">+</span>
          Add rule
        </cv-chip>
        <p>Clickable token that can open a focused editor.</p>
      </div>
    </div>
  </section>

  <section class="chip-demo-section" aria-labelledby="chip-demo-states-title">
    <div class="chip-demo-section-header">
      <span class="chip-demo-kicker">States</span>
      <h4 id="chip-demo-states-title">Action, selected, removable, disabled, and size variants</h4>
    </div>

    <div class="chip-demo-state-grid">
      <div class="chip-demo-cell">
        <span class="chip-demo-label">Action</span>
        <cv-chip value="edit-filter">Open filter</cv-chip>
      </div>

      <div class="chip-demo-cell">
        <span class="chip-demo-label">Selected</span>
        <cv-chip value="work" selected>Work</cv-chip>
      </div>

      <div class="chip-demo-cell">
        <span class="chip-demo-label">Removable</span>
        <cv-chip value="otp" removable>OTP seeds</cv-chip>
      </div>

      <div class="chip-demo-cell">
        <span class="chip-demo-label">Disabled</span>
        <cv-chip value="remote" disabled>Remote sync</cv-chip>
      </div>

      <div class="chip-demo-cell">
        <span class="chip-demo-label">Small</span>
        <cv-chip value="small" size="small">Compact</cv-chip>
      </div>

      <div class="chip-demo-cell">
        <span class="chip-demo-label">Large pill</span>
        <cv-chip value="large" size="large" pill selected>Threat model</cv-chip>
      </div>
    </div>
  </section>

  <section class="chip-demo-section" aria-labelledby="chip-demo-events-title">
    <div class="chip-demo-section-header">
      <span class="chip-demo-kicker">Event contract</span>
      <h4 id="chip-demo-events-title">Activation and removal emit different events</h4>
    </div>

    <div class="chip-demo-event-panel">
      <div class="chip-demo-event-row" aria-label="Interactive chip event examples">
        <cv-chip value="files" removable selected>Files</cv-chip>
        <cv-chip value="notes">Notes</cv-chip>
        <cv-chip value="media" removable>Media</cv-chip>
      </div>
      <output class="chip-demo-output" aria-live="polite">Event log appears here.</output>
    </div>
  </section>
</div>

<script>
  document.querySelectorAll('.chip-demo-shell[data-demo="chip"]:not([data-ready])').forEach((shell) => {
    shell.dataset.ready = 'true'
    const output = shell.querySelector('.chip-demo-output')
    shell.addEventListener('cv-chip-action', (event) => {
      output.textContent = `cv-chip-action: ${event.detail.value} via ${event.detail.source}`
    })
    shell.addEventListener('cv-chip-remove', (event) => {
      output.textContent = `cv-chip-remove: ${event.detail.value}`
    })
  })
</script>

Anatomy ​

<cv-chip> (host)
└── <span part="base" role="button">
    ├── <span part="prefix">
    ├── <span part="label">
    ├── <span part="suffix">
    └── <button part="remove-button"> optional

Attributes ​

AttributeTypeDefaultDescription
valueString""Value used by chip-group selection
selectedBooleanfalseSelected state
disabledBooleanfalseBlocks chip action and remove events
removableBooleanfalseShows remove button
variantString"neutral"Visual variant
sizeString"medium""small", "medium", or "large"
pillBooleanfalseFully rounded chip shape

Slots ​

SlotDescription
(default)Chip label
prefixLeading content
suffixTrailing content

CSS Parts ​

PartDescription
baseAction surface
prefixPrefix slot wrapper
labelDefault slot wrapper
suffixSuffix slot wrapper
remove-buttonRemove action button

CSS Custom Properties ​

Custom propertyDefaultDescription
--cv-chip-radiusvar(--cv-radius-sm, 6px)Fallback border radius and radius used by browsers without corner-shape.
--cv-chip-corner-shapesquircle in supporting UAsEnhanced corner shape for non-pill chips when corner-shape is supported.

Events ​

EventDetailDescription
cv-chip-action{ value: string, source: "click" | "keyboard" }Emitted by a chip activation
cv-chip-remove{ value: string }Emitted by a chip remove button

Keyboard ​

KeyBehavior
Enter/SpaceActivates the focused chip

Arrow-key roving focus is handled by cv-chip-group, not by a standalone chip.

When to use chip vs badge ​

NeedUse
Applied filter, selected tag, quick facet, removable tagcv-chip
Passive state, count, warning label, status dotcv-badge
Single or multiple selection across several chipscv-chip-group

Behavior notes ​

  • selected changes the pressed state and maps to aria-pressed.
  • disabled removes the chip from tab order and blocks action/remove events.
  • removable adds a nested remove button that emits cv-chip-remove without also emitting cv-chip-action.
  • value is the stable payload consumed by events and by cv-chip-group.
  • corner-shape is applied only inside @supports; unsupported browsers keep the regular border-radius shape.
  • pill chips keep round ends even in browsers that support enhanced corner shapes.

ChromVoid UIKit documentation