- Accordion
- Alert
- Alert Dialog
- Aspect Ratio
- Avatar
- Badge
- Breadcrumb
- Button
- Button Group
- Calendar
- Card
- Carousel
- Checkbox
- Collapsible
- Combobox
- Command
- Context Menu
- Data Table
- Date Picker
- Dialog
- Drawer
- Dropdown Menu
- Empty
- Field
- Filter
- Form
- Hover Card
- Image
- Input
- Input Group
- Input OTP
- Item
- Kbd
- Label
- Mega Menu
- Menubar
- Native Select
- Navigation Menu
- Number Field
- Pagination
- Pin Input
- Popover
- Price
- Progress
- Radio Group
- Radio Stack
- Range Calendar
- Rating
- Resizable
- Scroll Area
- Select
- Separator
- Sheet
- Sidebar
- Skeleton
- Slider
- Sonner
- Spinner
- Stepper
- Swatch
- Swatch Group
- Switch
- Table
- Tabs
- Tags Input
- Textarea
- Toast
- Toggle
- Toggle Group
- Tooltip
- Typography
Group container for swatch toggles with single or multiple selection support.
This is a Frontic UI custom component.
<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.
| Prop | Type | Default | Description |
|---|---|---|---|
type | 'single' | 'multiple' | 'single' | Selection mode |
v-model | string | string[] | — | Selected value(s) |
pill | boolean | false | Use rounded pill shape for all items |
size | 'sm' | 'md' | 'lg' | 'md' | Size for all items |
orientation | 'horizontal' | 'vertical' | 'horizontal' | Layout direction |
labelClass | string | — | CSS classes for all item labels |
disabled | boolean | false | Disable the entire group |
SwatchGroupItem
Individual swatch items within the group.
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | required | Unique value for this item |
hex | string | — | CSS color value to display |
label | string | — | Label text for the swatch |
labelClass | string | inherited | Override group label classes |
pill | boolean | inherited | Override group pill shape |
size | 'sm' | 'md' | 'lg' | inherited | Override group size |
disabled | boolean | false | Disable 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>