Skip to content

Components

Chip

Variants

The Chip has two variants: tonal (default) and outlined.

Tonal
Outlined
html
<div class="chip tonal">
  <span class="text">Tonal</span>
</div>

<div class="chip outlined">
  <span class="text">Outlined</span>
</div>

Icon

The icon can be placed before or after the text.
Make sure the text is wrapped in a .text wrapper.

Tonal
Outlined
html
<div class="chip">
  <svg></svg>
  <span class="text">Text</span>
</div>

<div class="chip">
  <span class="text">Text</span>
  <svg></svg>
</div>

Button

html
<button class="chip">
  <span class="text">Without icon</span>
</button>

<button class="chip">
  <svg></svg>
  <span class="text">With icon</span>
</button>
html
<a href="#" class="chip">
  <span class="text">Without icon</span>
</a href="#">

<a href="#" class="chip">
  <span class="text">With icon</span>
  <svg></svg>
</a href="#">

Sizes

Small
Default
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sodales.
html
<div class="chip small">
  <span class="text">Small</span>
</div>

<div class="chip">
  <span class="text">Default</span>
</div>

<div class="chip multiline">
  <span class="text"
    >Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus
    sodales.</span
  >
</div>

Anatomy

  1. Container: div, a or button
  2. Text
  3. Icon (optional): <svg> element
Chip example
html
<div class="chip">
  <svg></svg>
  <span class="text">Text</span>
</div>

API

TypeModifiersDefaultDescription
Containerdiv.chip, a.chip, button.chip-Container element type.
Children& > .text, & > svg-Optional child content.
Sizes.small, default, .multilinedefaultThe size to use.
Variants.tonal,.outlined.tonalThe variant to use.

Browser compatibility

Installation

css
@layer components.base {
  :where(.chip) {
    --_bg-color: var(--surface-tonal);
    --_border-color: var(--border-color);
    --_color: var(--text-color-1);

    align-items: center;
    background: var(--_bg-color) var(--ripple, none);
    border: 1px solid var(--_border-color);
    border-radius: var(--radius-2, 0.5rem);
    color: var(--_color);
    display: inline-flex;
    font-size: var(--font-size-0, 0.75rem);
    gap: var(--size-1);
    block-size: var(--size-7, 2rem);
    padding-inline: var(--size-2);
    text-decoration: none;

    /* Variants */
    &.tonal {
      --_bg-color: var(--surface-tonal);
      --_color: var(--text-color-1);
    }

    &.outlined {
      --_bg-color: var(--surface-default);
      --_color: var(--text-color-1);
    }

    /* TODO: should this be out of the box? */
    /* Colors */
    /* &:hover {
      --_bg-color: var(--color-11);
      --_border-color: var(--color-11);
      --_color: var(--text-color-1);
    } */
    /* &.red,
    &.blue,
    &.green,
    &.orange,
    &.primary {
      --_bg-color: var(--color-5);
      --_border-color: var(--color-7);
      --_color: var(--text-color-1-contrast);

      &:hover {
        --_bg-color: var(--color-7);
        --_border-color: var(--color-7);
        --_color: var(--text-color-1-contrast);

        &:active {
          --_bg-color: var(--color-8);
          --_border-color: var(--color-8);
        }
      }

      &.outlined {
        --_bg-color: var(--surface-tonal);
        --_color: var(--text-color-1);
        --_border-color: var(--color-9);

        &:hover {
          --_bg-color: var(--color-9);
          --_border-color: var(--color-9);
          --_color: var(--text-color-1);

          &:active {
            --_bg-color: var(--color-11);
            --_border-color: var(--color-11);
          }
        }
      }
    } */

    &:where(button, a):where(:not([disabled])) {
      &:where(:not(:active)):hover {
        --_bg-color: light-dark(
          oklch(from var(--surface-tonal) calc(l * 0.98) c h),
          oklch(from var(--surface-tonal) calc(l * 1.1) c h)
        );
      }
    }

    /* Icon */
    &:has(svg:first-child) {
      padding-inline: var(--size-1) var(--size-2);
    }
    &:has(svg:last-child) {
      padding-inline: var(--size-2) var(--size-1);
    }

    &:has(svg) {
      svg {
        flex-shrink: 0;
        inline-size: var(--size-3);
      }
    }

    /* Sizes */
    &.small {
      block-size: var(--size-5);
    }
    &.multiline {
      block-size: auto;
    }

    /* Ripple effect */
    background-position: center;

    &:where(:not([disabled])) {
      &:where(:not(:active):hover) {
        --ripple: radial-gradient(circle, transparent 1%, var(--_bg-color) 1%)
          center/15000%;

        transition: background var(--button-ripple-duration);
      }

      &:where(:hover:active) {
        background-size: var(--button-ripple-size);
        transition: background 0s;
      }
    }

    /* Disabled */
    &:where([disabled]) {
      opacity: 0.64;
      --_text-color: color-mix(
        in oklch,
        var(--text-color-2) 50%,
        var(--surface-default)
      );
      cursor: not-allowed;
    }
  }
}