X Enterprises
nuxt-x-affiliate

Search Filters

Faceted search filter sidebar with checkbox, radio, and range groups. Two-way bound state, collapsible groups, clear-all support.

Search Filters

The XAFSearchFilters component renders a faceted filter sidebar that pairs with <XAFSearchBar> and <XAFSearchResults>. It supports three filter types — checkbox (multi-select), radio (single-select), and range (numeric min/max) — and exposes a single v-model for the whole filter state.

Components

<XAFSearchFilters />

<script setup lang="ts">
const filters = ref({ brand: [], price: { min: undefined, max: undefined } })
</script>

<XAFSearchFilters
  v-model="filters"
  title="Filter products"
  :filters="[
    {
      id: 'brand',
      label: 'Brand',
      type: 'checkbox',
      options: [
        { value: 'amazon', label: 'Amazon', count: 124 },
        { value: 'walmart', label: 'Walmart', count: 89 },
        { value: 'target', label: 'Target', count: 56 },
      ],
    },
    {
      id: 'price',
      label: 'Price',
      type: 'range',
      range: { min: 0, max: 500, step: 10, unit: 'USD' },
    },
  ]"
/>

Props

PropTypeDefaultDescription
filtersSearchFilter[]requiredFilter group definitions. Each filter has an id, label, optional type ('checkbox' / 'radio' / 'range'), options for choice groups, or range for numeric.
modelValueSearchFiltersStaterequiredTwo-way bound filter state. Keyed by filter id.
titlestring'Filter'Section title shown above the filter groups
showClearbooleantrueShow a "Clear all" button when any filter is active
collapsiblebooleanfalseCollapse each group by default (mobile-friendly)

Events

EventPayloadDescription
update:modelValueSearchFiltersStateEmitted when any filter changes. Use with v-model.

Filter state shape

The modelValue is a Record<string, T> keyed by each filter's id:

type SearchFiltersState = Record<
  string,
  string[] |                 // checkbox: selected values
  string |                   // radio: selected value
  { min?: number; max?: number } |  // range: bounds
  undefined                  // cleared
>

Usage

With <XAFSearchResults>

<script setup lang="ts">
const filters = ref({ brand: [], price: { min: undefined, max: undefined } as { min?: number; max?: number } })

// Reactive query — refetch when filters change.
const results = computed(() => applyFilters(allProducts, filters.value))
</script>

<template>
  <div class="grid grid-cols-[280px_1fr] gap-6">
    <XAFSearchFilters v-model="filters" :filters="filterDefs" />
    <XAFSearchResults :results="results" />
  </div>
</template>

With <XAFPagination>

<XAFPagination
  :current-page="page"
  :total-pages="Math.ceil(results.length / pageSize)"
  base-url="/search"
/>

Collapsible (mobile)

<XAFSearchFilters v-model="filters" :filters="filterDefs" collapsible />

Tips

  • The component is purely presentational — apply the filters to your data on the consuming side.
  • Use count on checkbox/radio options to show how many items match each filter (great UX signal).
  • Range filters persist as { min, max } so consumers can render "Under $50" labels or similar UI even when only one bound is set.

AI Context

component: XAFSearchFilters
package: "@xenterprises/nuxt-x-affiliate"
use-when: Faceted search filter sidebar for product/review/content discovery
Copyright © 2026