Filter
A filter chip component for selecting/deselecting options. Unlike Radio, clicking an active chip deselects it (toggles off). In single-select mode, unselected items collapse when a selection is made, with a × reset button to clear. Use multiple for multi-select behavior.
| Name | Category | Description | Type | Default |
|---|---|---|---|---|
type | Style | Preset theme color for all filter items | 'primary' | 'success' | 'warning' | 'danger' | 'info' | — |
size | Size | Size for all filter items | 'large' | 'small' | — |
color | Color | Custom hex color for all filter items | string | — |
disabled | State | Whether to disable all filter items | boolean | false |
disabled | State | Whether disabled | boolean | false |
multiple | Behavior | Whether to enable multi-select mode, allowing multiple items to be active simultaneously | boolean | false |
name | Behavior | Native name attribute | string | — |
model-value / v-model | Content | Binding value. Single mode: clicking active item resets to undefined. Multiple mode: array of values | string | number | (string | number)[] | — |
options | Content | Array of filter items, each with value, label, disabled | FilterOptionProps[] | — |
value | Content | Identifier value of the filter item | string | number | — |
label | Content | Label text | string | — |
change | Event | Triggered when selected value changes. Value is undefined when deselected | (value: FilterValueType | FilterValueType[] | undefined) => void | — |
default | Slot | Custom filter item content (use PxFilterItem) | — | |
default | Slot | Custom label content | — |
Basic Usage
Bind v-model and provide options. Click a chip to select it; click again to deselect.
<template>
<div class="demo-filter">
<px-filter v-model="selected" :options="options" />
<p class="demo-filter__result">Selected: {{ selected ?? 'none' }}</p>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const selected = ref<string | number | undefined>('vue');
const options = [
{ value: 'vue', label: 'Vue' },
{ value: 'react', label: 'React' },
{ value: 'angular', label: 'Angular' },
{ value: 'svelte', label: 'Svelte' },
];
</script>
<style scoped>
.demo-filter {
display: flex;
flex-direction: column;
gap: 12px;
}
.demo-filter__result {
font-family: var(--px-font-family);
font-size: 14px;
color: var(--px-text-color-secondary);
}
</style>Disabled State
Use disabled on the group to disable all items, or on individual options.
<template>
<div class="demo-filter">
<p class="demo-filter__label">Group disabled:</p>
<px-filter :options="options" disabled />
<p class="demo-filter__label">Individual disabled:</p>
<px-filter v-model="selected" :options="mixedOptions" />
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const selected = ref<string | number | undefined>('a');
const options = [
{ value: 'a', label: 'Alpha' },
{ value: 'b', label: 'Beta' },
{ value: 'c', label: 'Gamma' },
];
const mixedOptions = [
{ value: 'a', label: 'Enabled' },
{ value: 'b', label: 'Disabled', disabled: true },
{ value: 'c', label: 'Enabled' },
];
</script>
<style scoped>
.demo-filter {
display: flex;
flex-direction: column;
gap: 12px;
}
.demo-filter__label {
font-family: var(--px-font-family);
font-size: 14px;
color: var(--px-text-color-secondary);
margin: 0;
}
</style>Type
Use type property to apply preset theme colors.
<template>
<div class="demo-filter">
<px-filter v-model="v1" :options="options" type="primary" />
<px-filter v-model="v2" :options="options" type="success" />
<px-filter v-model="v3" :options="options" type="warning" />
<px-filter v-model="v4" :options="options" type="danger" />
<px-filter v-model="v5" :options="options" type="info" />
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const options = [
{ value: 'a', label: 'Alpha' },
{ value: 'b', label: 'Beta' },
{ value: 'c', label: 'Gamma' },
];
const v1 = ref<string | number | undefined>('a');
const v2 = ref<string | number | undefined>('a');
const v3 = ref<string | number | undefined>('a');
const v4 = ref<string | number | undefined>('a');
const v5 = ref<string | number | undefined>('a');
</script>
<style scoped>
.demo-filter {
display: flex;
flex-direction: column;
gap: 16px;
}
</style>Custom Color
Use color property to set a custom hex color for the active state.
<template>
<div class="demo-filter">
<px-filter v-model="v1" :options="options" color="#ff6b6b" />
<px-filter v-model="v2" :options="options" color="#20c997" />
<px-filter v-model="v3" :options="options" color="#845ef7" />
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const options = [
{ value: 'a', label: 'Alpha' },
{ value: 'b', label: 'Beta' },
{ value: 'c', label: 'Gamma' },
];
const v1 = ref<string | number | undefined>('a');
const v2 = ref<string | number | undefined>('a');
const v3 = ref<string | number | undefined>('a');
</script>
<style scoped>
.demo-filter {
display: flex;
flex-direction: column;
gap: 16px;
}
</style>Different Sizes
Use size property to set the filter chip size.
<template>
<div class="demo-filter">
<px-filter v-model="v1" :options="options" size="small" />
<px-filter v-model="v2" :options="options" />
<px-filter v-model="v3" :options="options" size="large" />
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const options = [
{ value: 'a', label: 'Small' },
{ value: 'b', label: 'Default' },
{ value: 'c', label: 'Large' },
];
const v1 = ref<string | number | undefined>('a');
const v2 = ref<string | number | undefined>('b');
const v3 = ref<string | number | undefined>('c');
</script>
<style scoped>
.demo-filter {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 16px;
}
</style>Multiple Selection
Use multiple prop to enable multi-select mode. Multiple items can be active simultaneously, and clicking the × button clears all selections.
<template>
<div class="demo-filter">
<px-filter v-model="selected" :options="options" multiple />
<p class="demo-filter__result">Selected: {{ selected.length ? selected.join(', ') : 'none' }}</p>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const selected = ref<(string | number)[]>(['vue']);
const options = [
{ value: 'vue', label: 'Vue' },
{ value: 'react', label: 'React' },
{ value: 'angular', label: 'Angular' },
{ value: 'svelte', label: 'Svelte' },
];
</script>
<style scoped>
.demo-filter {
display: flex;
flex-direction: column;
gap: 12px;
}
.demo-filter__result {
font-family: var(--px-font-family);
font-size: 14px;
color: var(--px-text-color-secondary);
}
</style>Slot Children
Use PxFilterItem as slot children for more control over individual items.
<template>
<div class="demo-filter">
<px-filter v-model="selected" type="primary">
<px-filter-item value="all" label="All" />
<px-filter-item value="photos" label="Photos" />
<px-filter-item value="videos" label="Videos" />
<px-filter-item value="documents" label="Documents" />
</px-filter>
<p class="demo-filter__result">Selected: {{ selected ?? 'none' }}</p>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const selected = ref<string | number | undefined>('all');
</script>
<style scoped>
.demo-filter {
display: flex;
flex-direction: column;
gap: 12px;
}
.demo-filter__result {
font-family: var(--px-font-family);
font-size: 14px;
color: var(--px-text-color-secondary);
}
</style>