Product

ProductOptions

Variant option selector for size, color, material, and other product options.

ProductOptions

Renders each product option group (e.g., Size, Color) with selectable values. Uses v-model to track selections as a { optionId: valueId } map.

Preview

Usage

<script setup>
const selected = ref<Record<string, string>>({})
</script>

<CProductOptions
  v-model="selected"
  :items="product.options"
/>

Different Sizes

<CProductOptions v-model="selected" :items="product.options" size="sm" />
<CProductOptions v-model="selected" :items="product.options" size="lg" />

Props

PropTypeDefaultDescription
itemsProductOption[]requiredAvailable product options
modelValueRecord<string, string>requiredCurrent selections { optionId: valueId }
size'sm' | 'md' | 'lg''md'Size variant
uiPartial<{...}>Per-instance theme overrides

Events

EventPayloadDescription
update:modelValueRecord<string, string>Selection changed

Slots

SlotScoped PropsDescription
label{ option }Custom option group label
value{ option, value, selected, select }Custom value button rendering

Example: Color Swatches

<CProductOptions v-model="selected" :items="product.options">
  <template #value="{ value, selected, select }">
    <button
      :class="['size-8 rounded-full ring-2', selected ? 'ring-primary' : 'ring-transparent']"
      :style="{ backgroundColor: value.color }"
      @click="select"
    />
  </template>
</CProductOptions>

Theme

export default defineAppConfig({
  ui: {
    productOptions: {
      slots: {
        root: 'space-y-4',
        group: 'space-y-2',
        label: 'text-sm font-medium text-highlighted',
        values: 'flex flex-wrap gap-2',
        value: 'px-3 py-1.5 rounded-md text-sm ring ring-default cursor-pointer transition-colors',
        valueActive: 'ring-2 ring-primary bg-primary/10 text-primary',
      },
    },
  },
})