- No filter applied.
- Filters applied (indicator on the Filter button).
- Dropdown expanded — Icon Button is :active.
- Dropdown collapsed.
FilterGroup
Organism
Filter Group lets users refine a list with multiple criteria. Options are grouped in segments; users can toggle individual filters or an optional “All” parent. Use it for compact multi-filter UIs (for example table headers), not as a general-purpose Multiselect form field.
Playground
FilterGroup with numerical values
Selected values: []Tooltip
Tooltip
FilterGroup with alphabetical values
Selected values: []Tooltip
<
FilterGroup
segments
=
"[
{
"title": "Segment 1",
"hasAllOption": true,
"allOptionLabel": "Check them all",
"options": [
{
"value": 1,
"text": "Option 1 is a very long option, so we can check whether truncation works with it",
"isDisabled": false,
"isSelected": false
},
{
"value": 4,
"text": "N/mm<sup>2</sup>",
"isSelected": false
},
{
"value": 7,
"text": "Option 7",
"isSelected": false
}
]
},
{
"title": "",
"allOptionLabel": "All the single ladies",
"hasAllOption": false,
"options": [
{
"value": 2,
"text": "Option 2",
"isSelected": false
},
{
"value": 5,
"text": "Option 5",
"isSelected": false
},
{
"value": 3,
"text": "Option 3",
"isSelected": false
},
{
"value": 6,
"text": "Option 6",
"isSelected": false
}
]
}
]"
alignment
=
"right"
tooltip
=
"Tooltip"
tooltipPosition
=
"top-left"
/>
Properties
ts
export interface FilterGroupGenericProps<T extends string | number> extends TooltipProps {
modelValue: T[];
segments: FilterGroupOptionSegment<T>[];
disabled?: boolean;
alignment?: 'left' | 'right';
sortOptions?: FilterGroupSortOptions;
// searchOptions?: FilterGroupSearchOptions;
}
export interface FilterGroupSortOptions {
order: 'asc' | 'ascending' | 'desc' | 'descending';
target: 'text' | 'value';
ignoreCase?: boolean;
}
export interface FilterGroupSearchOptions {
enableSearch: boolean;
caseSensitive?: boolean;
placeholder?: string;
}ts
export interface FilterGroupOptionSegment<T extends string | number> {
title?: string;
hasAllOption?: boolean;
allOptionLabel?: string;
options: FilterGroupOptionGeneric<T>[];
}
export interface FilterGroupOptionGeneric<T extends string | number> {
text: string | number,
value: T;
isSelected: boolean;
hasAction?: boolean;
isDisabled?: boolean;
}Anatomy
Filter button - Nested Icon Button. Opens and closes the dropdown. Shows a filters-applied indicator when any option is selected.
Dropdown container - Panel under the button listing filter segments and options.
Filters applied indicator - Visual cue on the button that filters are active for the current view.
Section label - Optional title per segment (e.g. category name). Omit when options are self-explanatory.
Parent option (“All”) - Nested Checkbox. Checks or clears all non-disabled child options in the segment; supports indeterminate when partially selected.
Child option - Nested Checkbox. Toggle a single filter; parent “All” stays in sync.
Option without parent/child - Nested Checkbox when
hasAllOptionis off (short lists).Divider - Separates segments visually.
If option text overflows the container width, it truncates and the native title attribute shows the full label.
States
Variants
Sections
- With sections and section labels.
- With sections but no section labels.
- Without sections.
All option
- With parent–child “All” option controlling child options.
- Without “All” options (typical for short lists of 1–4 items).
Dropdown alignment
- Left-aligned relative to the Filter button.
- Right-aligned relative to the Filter button.
Developer notes
- Selections apply as the user toggles options;
modelValueis the list of selected option values across segments. - Clicking outside the component closes the dropdown (click-outside on the root; no full-screen overlay).
Tabfocuses the control;Enterwhen focused opens the dropdown; Arrow keys move through options;Entertoggles the highlighted option without closing the dropdown (unlike Select).Tabagain moves to the next control;Shift+Tabwhile browsing options returns focus to the filter control.- Use
alignment(left|right) so the panel opens correctly in dense layouts (e.g. table headers). - Keep option
isSelectedin sync withmodelValuewhen driving segments from outside.
vue
<script setup>
import { ref } from 'vue';
import { FilterGroup } from '@pohlcon/design-system';
const modelValue = ref([]);
const segments = [
{
title: 'Status',
hasAllOption: true,
allOptionLabel: 'All',
options: [
{ value: 1, text: 'Open', isSelected: false },
{ value: 2, text: 'Closed', isSelected: false },
{ value: 3, text: 'Draft', isSelected: false },
],
},
];
</script>
<template>
<FilterGroup
v-model="modelValue"
:segments="segments"
alignment="left"
/>
</template>