Skip to content

Filter bar

The filter bar combines a search input with dynamic filter buttons into a single toolbar. Active filters are shown as individual buttons with a badge indicating the selected value. When the bar runs out of space, overflow filters collapse into a flyout menu. This component is an alternative to Filter and is well suited for use above data tables.

TIP

Don't make your view too complex. Limit yourself to one filter bar per view.

Required icons

angle-left
angle-right
magnifying-glass
rotate-left
sliders-simple
trash

Props

model-value: FluxFilterState
The filter state.

search?: string
The current search query.

is-searchable?: boolean
Whether the search input is shown.

search-placeholder?: string
The placeholder text for the search input.

Emits

update:model-value: [FluxFilterState]
Triggered when the filter state changes.

update:search: [string]
Triggered when the search query changes.

clear: [string]
Triggered when a filter's value is cleared via the trash button. Receives the name of the cleared filter.

reset: [string]
Triggered when a filter is reset to its default value. Receives the name of the reset filter.

Slots

default
This slot should contain filter components.

start
Content rendered before the search input, at the start of the bar.

end
Content rendered after the filter button, at the end of the bar.

Examples

Basic

A basic filter bar with a search input and filters.

<template>
    <FluxFilterBar
        v-model="filterState"
        v-model:search="search"
        is-searchable
        search-placeholder="Search items...">
        <FluxFilterOption
            icon="circle-check"
            label="Status"
            name="status"
            :options="[
                {label: 'Active', value: 'active'},
                {label: 'Inactive', value: 'inactive'},
                {label: 'Pending', value: 'pending'}
            ]"/>

        <FluxFilterOption
            icon="clone"
            label="Category"
            name="category"
            :options="[
                {label: 'Electronics', value: 'electronics'},
                {label: 'Clothing', value: 'clothing'},
                {label: 'Books', value: 'books'}
            ]"/>

        <FluxFilterRange
            icon="coin"
            label="Price"
            name="price"
            :formatter="priceFormatter"
            :max="1000"
            :min="0"
            :step="10"/>
    </FluxFilterBar>
</template>

<script
    lang="ts"
    setup>
    import { FluxFilterBar, FluxFilterOption, FluxFilterRange } from '@flux-ui/components';
    import type { FluxFilterState } from '@flux-ui/types';
    import { ref } from 'vue';

    const search = ref('');

    const filterState = ref<FluxFilterState>({
        status: null,
        category: null,
        price: null
    });

    function priceFormatter(value: number): string {
        return new Intl.NumberFormat(navigator.language, {
            currency: 'EUR',
            maximumFractionDigits: 0,
            style: 'currency'
        }).format(value / 100);
    }
</script>

Start and end slots

Adding custom content before the search input and after the filter button.

<template>
    <FluxFilterBar
        v-model="filterState"
        v-model:search="search"
        is-searchable
        search-placeholder="Search items...">
        <template #start>
            <FluxSecondaryButton
                icon-leading="arrow-down-to-line"
                label="Export"/>
        </template>

        <FluxFilterOption
            icon="circle-check"
            label="Status"
            name="status"
            :options="[
                {label: 'Active', value: 'active'},
                {label: 'Inactive', value: 'inactive'},
                {label: 'Pending', value: 'pending'}
            ]"/>

        <FluxFilterOption
            icon="clone"
            label="Category"
            name="category"
            :options="[
                {label: 'Electronics', value: 'electronics'},
                {label: 'Clothing', value: 'clothing'},
                {label: 'Books', value: 'books'}
            ]"/>

        <template #end>
            <FluxPrimaryButton
                icon-leading="plus"
                label="Add item"/>
        </template>
    </FluxFilterBar>
</template>

<script
    lang="ts"
    setup>
    import { FluxFilterBar, FluxFilterOption, FluxPrimaryButton, FluxSecondaryButton } from '@flux-ui/components';
    import type { FluxFilterState } from '@flux-ui/types';
    import { ref } from 'vue';

    const search = ref('');

    const filterState = ref<FluxFilterState>({
        status: null,
        category: null
    });
</script>

Used components