- 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
This is a Frontic UI custom component.
<script setup lang="ts">
import { Swatch } from '@/components/ui/swatch'
</script>
<template>
<div class="flex flex-wrap items-start gap-4">
<Swatch hex="#ef4444" label="Red" />
<Swatch hex="#3b82f6" label="Blue" />
<Swatch hex="#22c55e" label="Green" />
<Swatch hex="#f59e0b" label="Amber" />
</div>
</template>Installation
pnpm dlx @frontic/ui add swatch
Usage
<script setup lang="ts">
import { Swatch } from '@/components/ui/swatch'
</script>
<template>
<Swatch hex="#3b82f6" />
</template>With Image
Use SwatchImage inside a Swatch to display an image with automatic load-state handling.
<script setup lang="ts">
import { Swatch, SwatchImage } from '@/components/ui/swatch'
</script>
<template>
<Swatch>
<SwatchImage src="/images/pattern.jpg" alt="Pattern" />
</Swatch>
</template>With Fallback
Use SwatchImage and SwatchFallback for image swatches with automatic load-state handling. When the image loads, the fallback hides. When it fails, the fallback shows.
<script setup lang="ts">
import { Swatch, SwatchFallback, SwatchImage } from '@/components/ui/swatch'
</script>
<template>
<div class="flex flex-wrap items-center gap-4">
<Swatch hex="#ef4444">
<SwatchImage src="https://images.unsplash.com/photo-1558171813-4c088753af8f?w=100&h=100&fit=crop" alt="Red pattern" />
<SwatchFallback class="flex items-center justify-center text-[10px] text-white">Red</SwatchFallback>
</Swatch>
<Swatch hex="#3b82f6">
<SwatchImage src="/invalid-image.jpg" alt="Broken image" />
<SwatchFallback class="flex items-center justify-center text-[10px] text-white">Blue</SwatchFallback>
</Swatch>
<Swatch>
<SwatchImage src="/invalid-image.jpg" alt="Broken image" />
<SwatchFallback class="flex items-center justify-center bg-violet-400 text-[10px] text-white">Violet</SwatchFallback>
</Swatch>
</div>
</template><script setup lang="ts">
import { Swatch, SwatchFallback, SwatchImage } from '@/components/ui/swatch'
</script>
<template>
<Swatch hex="#ef4444">
<SwatchImage src="/images/pattern.jpg" alt="Red pattern" />
<SwatchFallback>Red</SwatchFallback>
</Swatch>
</template>Sizes
<script setup lang="ts">
import { Swatch } from '@/components/ui/swatch'
</script>
<template>
<div class="flex flex-wrap items-center gap-4">
<Swatch size="sm" hex="#3b82f6" />
<Swatch size="md" hex="#3b82f6" />
<Swatch size="lg" hex="#3b82f6" />
</div>
</template>Pill
Use the pill prop to make the swatch fully rounded. Combines with any size.
<script setup lang="ts">
import { Swatch } from '@/components/ui/swatch'
</script>
<template>
<div class="flex flex-wrap items-center gap-4">
<Swatch pill hex="#ef4444" />
<Swatch pill hex="#3b82f6" />
<Swatch pill hex="#22c55e" />
<Swatch pill hex="#f59e0b" />
</div>
</template>Examples
Color Swatches
<script setup lang="ts">
import { ref } from 'vue'
import { Swatch } from '@/components/ui/swatch'
const colors = ['#ef4444', '#f97316', '#f59e0b', '#22c55e', '#3b82f6', '#8b5cf6', '#ec4899']
const selected = ref('#3b82f6')
</script>
<template>
<div class="flex flex-wrap items-center gap-2">
<Swatch
v-for="color in colors"
:key="color"
:hex="color"
:pressed="selected === color"
@update:pressed="selected = color"
/>
</div>
</template>Image Swatches
<script setup lang="ts">
import { ref } from 'vue'
import { Swatch, SwatchImage } from '@/components/ui/swatch'
const images = [
'https://images.unsplash.com/photo-1558171813-4c088753af8f?w=100&h=100&fit=crop',
'https://images.unsplash.com/photo-1557682250-33bd709cbe85?w=100&h=100&fit=crop',
'https://images.unsplash.com/photo-1557682224-5b8590cd9ec5?w=100&h=100&fit=crop',
'https://images.unsplash.com/photo-1557682260-96773eb01377?w=100&h=100&fit=crop',
]
const selected = ref(images[0])
</script>
<template>
<div class="flex flex-wrap items-center gap-2">
<Swatch
v-for="image in images"
:key="image"
:pressed="selected === image"
@update:pressed="selected = image"
>
<SwatchImage :src="image" alt="Pattern" />
</Swatch>
</div>
</template>Controlled Selection
Use v-model:pressed to control the toggle state for selection UI.
Selected: #3b82f6
<script setup lang="ts">
import { ref } from 'vue'
import { Swatch } from '@/components/ui/swatch'
const colors = ['#ef4444', '#3b82f6', '#22c55e']
const selectedColor = ref<string | null>('#3b82f6')
function selectColor(color: string) {
selectedColor.value = selectedColor.value === color ? null : color
}
</script>
<template>
<div class="flex flex-col gap-4">
<div class="flex flex-wrap items-center gap-2">
<Swatch
v-for="color in colors"
:key="color"
:hex="color"
:pressed="selectedColor === color"
@update:pressed="selectColor(color)"
/>
</div>
<p class="text-sm text-muted-foreground">
Selected: {{ selectedColor ?? 'None' }}
</p>
</div>
</template>API Reference
Swatch
Renders a toggle button. Use hex for color swatches or compose with SwatchImage for pattern/texture swatches.
| Prop | Type | Default | Description |
|---|---|---|---|
hex | string | — | CSS color value to display |
label | string | — | Label text below the swatch |
labelClass | string | — | CSS classes for the label |
size | 'sm' | 'md' | 'lg' | 'md' | Swatch size |
pill | boolean | false | Use rounded pill shape |
pressed | boolean | false | Toggle state |
disabled | boolean | false | Disable the swatch |
<script setup lang="ts">
import { Swatch } from '@/components/ui/swatch'
</script>
<template>
<Swatch hex="#3b82f6" pill size="lg" label="Blue" />
</template>SwatchLabel
Renders a label for a swatch. Used internally when the label prop is set, or use directly via the #label slot for custom styling.
| Prop | Type | Default | Description |
|---|---|---|---|
class | string | — | Additional CSS classes |
SwatchImage
Renders an image inside a swatch with automatic load-state tracking. Must be used inside Swatch or SwatchGroupItem. Shows only when the image has loaded successfully.
| Prop | Type | Default | Description |
|---|---|---|---|
src | string | required | Image URL |
alt | string | — | Alt text for the image |
referrerPolicy | string | — | Referrer policy for the image |
crossOrigin | string | — | Cross-origin setting for the image |
asChild | boolean | false | Render as child element |
| Event | Payload | Description |
|---|---|---|
loadingStatusChange | 'idle' | 'loading' | 'loaded' | 'error' | Emitted when image loading status changes |
SwatchFallback
Renders fallback content when SwatchImage fails to load or is not provided. Must be used inside Swatch or SwatchGroupItem.
| Prop | Type | Default | Description |
|---|---|---|---|
delayMs | number | — | Delay before showing fallback (ms) |
asChild | boolean | false | Render as child element |