10.1k

Swatch Group

PreviousNext

Group container for swatch toggles with single or multiple selection support.

<script setup lang="ts">
import { ref } from 'vue'
import { SwatchGroup, SwatchGroupItem } from '@/components/ui/swatch-group'

const selected = ref('blue')
</script>

<template>
  <SwatchGroup v-model="selected" type="single">
    <SwatchGroupItem value="red" hex="#ef4444" label="Red" />
    <SwatchGroupItem value="blue" hex="#3b82f6" label="Blue" />
    <SwatchGroupItem value="green" hex="#22c55e" label="Green" />
    <SwatchGroupItem value="amber" hex="#f59e0b" label="Amber" />
  </SwatchGroup>
</template>

Installation

pnpm dlx @frontic/ui add swatch-group

Usage

<script setup lang="ts">
import { SwatchGroup, SwatchGroupItem } from '@/components/ui/swatch-group'
import { ref } from 'vue'

const selected = ref('red')
</script>

<template>
  <SwatchGroup v-model="selected" type="single">
    <SwatchGroupItem value="red" hex="#ef4444" />
    <SwatchGroupItem value="blue" hex="#3b82f6" />
    <SwatchGroupItem value="green" hex="#22c55e" />
  </SwatchGroup>
</template>

With Images

Use SwatchImage inside each item for pattern or texture selection with automatic load-state handling.

<script setup lang="ts">
import { SwatchGroup, SwatchGroupItem } from '@/components/ui/swatch-group'
import { SwatchImage } from '@/components/ui/swatch'
import { ref } from 'vue'

const selected = ref('wood')
</script>

<template>
  <SwatchGroup v-model="selected" type="single">
    <SwatchGroupItem value="wood">
      <SwatchImage src="/images/wood.jpg" alt="Wood" />
    </SwatchGroupItem>
    <SwatchGroupItem value="marble">
      <SwatchImage src="/images/marble.jpg" alt="Marble" />
    </SwatchGroupItem>
  </SwatchGroup>
</template>

With Fallback

Use SwatchImage and SwatchFallback inside SwatchGroupItem for image swatches with automatic load-state handling. See the Swatch docs for details.

<script setup lang="ts">
import { SwatchGroup, SwatchGroupItem } from '@/components/ui/swatch-group'
import { SwatchFallback, SwatchImage } from '@/components/ui/swatch'
import { ref } from 'vue'

const selected = ref('red')
</script>

<template>
  <SwatchGroup v-model="selected" type="single">
    <SwatchGroupItem value="red" hex="#ef4444">
      <SwatchImage src="/images/red-pattern.jpg" alt="Red" />
      <SwatchFallback>Red</SwatchFallback>
    </SwatchGroupItem>
    <SwatchGroupItem value="blue" hex="#3b82f6">
      <SwatchImage src="/images/blue-pattern.jpg" alt="Blue" />
      <SwatchFallback>Blue</SwatchFallback>
    </SwatchGroupItem>
  </SwatchGroup>
</template>

Sizes

Control the size of all swatches in the group.

Small

Medium

Large

<script setup lang="ts">
import { ref } from 'vue'
import { SwatchGroup, SwatchGroupItem } from '@/components/ui/swatch-group'

const small = ref('blue')
const medium = ref('blue')
const large = ref('blue')
</script>

<template>
  <div class="flex flex-col gap-6">
    <div>
      <p class="mb-2 text-sm font-medium">Small</p>
      <SwatchGroup v-model="small" type="single" size="sm">
        <SwatchGroupItem value="red" hex="#ef4444" />
        <SwatchGroupItem value="blue" hex="#3b82f6" />
        <SwatchGroupItem value="green" hex="#22c55e" />
      </SwatchGroup>
    </div>
    <div>
      <p class="mb-2 text-sm font-medium">Medium</p>
      <SwatchGroup v-model="medium" type="single" size="md">
        <SwatchGroupItem value="red" hex="#ef4444" />
        <SwatchGroupItem value="blue" hex="#3b82f6" />
        <SwatchGroupItem value="green" hex="#22c55e" />
      </SwatchGroup>
    </div>
    <div>
      <p class="mb-2 text-sm font-medium">Large</p>
      <SwatchGroup v-model="large" type="single" size="lg">
        <SwatchGroupItem value="red" hex="#ef4444" />
        <SwatchGroupItem value="blue" hex="#3b82f6" />
        <SwatchGroupItem value="green" hex="#22c55e" />
      </SwatchGroup>
    </div>
  </div>
</template>

Pill

Use the pill prop to make all swatches in the group fully rounded. Combines with any size.

<script setup lang="ts">
import { ref } from 'vue'
import { SwatchGroup, SwatchGroupItem } from '@/components/ui/swatch-group'

const selected = ref('blue')
</script>

<template>
  <SwatchGroup pill v-model="selected" type="single" >
    <SwatchGroupItem value="red" hex="#ef4444" />
    <SwatchGroupItem value="blue" hex="#3b82f6" />
    <SwatchGroupItem value="green" hex="#22c55e" />
    <SwatchGroupItem value="amber" hex="#f59e0b" />
  </SwatchGroup>
</template>

Examples

Single Selection

Use type="single" for exclusive selection where only one swatch can be selected at a time.

Selected: blue

<script setup lang="ts">
import { ref } from 'vue'
import { SwatchGroup, SwatchGroupItem } from '@/components/ui/swatch-group'

const selected = ref('blue')
</script>

<template>
  <div class="flex flex-col gap-4">
    <SwatchGroup v-model="selected" type="single">
      <SwatchGroupItem value="red" hex="#ef4444" />
      <SwatchGroupItem value="orange" hex="#f97316" />
      <SwatchGroupItem value="amber" hex="#f59e0b" />
      <SwatchGroupItem value="green" hex="#22c55e" />
      <SwatchGroupItem value="blue" hex="#3b82f6" />
      <SwatchGroupItem value="purple" hex="#8b5cf6" />
    </SwatchGroup>
    <p class="text-sm text-muted-foreground">
      Selected: {{ selected }}
    </p>
  </div>
</template>

Multiple Selection

Use type="multiple" to allow selecting multiple swatches.

Selected: blue, green

<script setup lang="ts">
import { ref } from 'vue'
import { SwatchGroup, SwatchGroupItem } from '@/components/ui/swatch-group'

const selected = ref(['blue', 'green'])
</script>

<template>
  <div class="flex flex-col gap-4">
    <SwatchGroup v-model="selected" type="multiple">
      <SwatchGroupItem value="red" hex="#ef4444" />
      <SwatchGroupItem value="orange" hex="#f97316" />
      <SwatchGroupItem value="green" hex="#22c55e" />
      <SwatchGroupItem value="blue" hex="#3b82f6" />
      <SwatchGroupItem value="purple" hex="#8b5cf6" />
    </SwatchGroup>
    <p class="text-sm text-muted-foreground">
      Selected: {{ selected.join(', ') || 'None' }}
    </p>
  </div>
</template>

Vertical

Use orientation="vertical" to stack swatches vertically with labels beside each swatch.

<script setup lang="ts">
import { ref } from 'vue'
import { SwatchGroup, SwatchGroupItem } from '@/components/ui/swatch-group'

const selected = ref('blue')
</script>

<template>
  <SwatchGroup v-model="selected" type="single" orientation="vertical" label-class="text-sm font-medium text-foreground">
    <SwatchGroupItem value="red" hex="#ef4444" label="Red" />
    <SwatchGroupItem value="blue" hex="#3b82f6" label="Blue" />
    <SwatchGroupItem value="green" hex="#22c55e" label="Green" />
    <SwatchGroupItem value="amber" hex="#f59e0b" label="Amber" />
  </SwatchGroup>
</template>

With Images

<script setup lang="ts">
import { ref } from 'vue'
import { SwatchGroup, SwatchGroupItem } from '@/components/ui/swatch-group'
import { SwatchImage } from '@/components/ui/swatch'

const images = [
  { value: 'pattern1', url: 'https://images.unsplash.com/photo-1558171813-4c088753af8f?w=100&h=100&fit=crop' },
  { value: 'pattern2', url: 'https://images.unsplash.com/photo-1557682250-33bd709cbe85?w=100&h=100&fit=crop' },
  { value: 'pattern3', url: 'https://images.unsplash.com/photo-1557682224-5b8590cd9ec5?w=100&h=100&fit=crop' },
  { value: 'pattern4', url: 'https://images.unsplash.com/photo-1557682260-96773eb01377?w=100&h=100&fit=crop' },
]
const selected = ref('pattern1')
</script>

<template>
  <SwatchGroup v-model="selected" type="single">
    <SwatchGroupItem
      v-for="img in images"
      :key="img.value"
      :value="img.value"
    >
      <SwatchImage :src="img.url" :alt="img.value" />
    </SwatchGroupItem>
  </SwatchGroup>
</template>

API Reference

SwatchGroup

The container component that manages selection state.

PropTypeDefaultDescription
type'single' | 'multiple''single'Selection mode
v-modelstring | string[]Selected value(s)
pillbooleanfalseUse rounded pill shape for all items
size'sm' | 'md' | 'lg''md'Size for all items
orientation'horizontal' | 'vertical''horizontal'Layout direction
labelClassstringCSS classes for all item labels
disabledbooleanfalseDisable the entire group

SwatchGroupItem

Individual swatch items within the group.

PropTypeDefaultDescription
valuestringrequiredUnique value for this item
hexstringCSS color value to display
labelstringLabel text for the swatch
labelClassstringinheritedOverride group label classes
pillbooleaninheritedOverride group pill shape
size'sm' | 'md' | 'lg'inheritedOverride group size
disabledbooleanfalseDisable this item
<script setup lang="ts">
import { SwatchGroup, SwatchGroupItem } from '@/components/ui/swatch-group'
import { ref } from 'vue'

const selected = ref('red')
</script>

<template>
  <SwatchGroup v-model="selected" type="single" pill size="sm">
    <SwatchGroupItem value="red" hex="#ef4444" label="Red" />
    <SwatchGroupItem value="blue" hex="#3b82f6" label="Blue" />
  </SwatchGroup>
</template>