Filter List Block
The FilterList Component is a fully customizable and accessible filter interface built with React and TypeScript. It provides a complete filtering experience with accordion-style filter groups, selected filter chips, and flexible customization options. Built on top of MUI components for consistent styling.
π Installationβ
npm install @nodeblocks/frontend-filter-list-block@0.3.0
π Usageβ
import {FilterList} from '@nodeblocks/frontend-filter-list-block';
- Basic Usage
- Advanced Usage
function BasicFilterList() { const filterOptions = [ { label: 'Category', subtitle: 'Filter by product category', value: 'category', columns: 2, children: [ {label: 'Electronics', value: 'electronics', subtitle: '', groupName: 'category'}, {label: 'Clothing', value: 'clothing', subtitle: '', groupName: 'category'}, {label: 'Books', value: 'books', subtitle: '', groupName: 'category'}, {label: 'Home & Garden', value: 'home-garden', subtitle: '', groupName: 'category'}, ], }, { label: 'Price Range', subtitle: 'Select your budget', value: 'price', columns: 1, children: [ {label: 'Under $25', value: 'under-25', subtitle: '', groupName: 'price'}, {label: '$25 - $50', value: '25-50', subtitle: '', groupName: 'price'}, {label: '$50 - $100', value: '50-100', subtitle: '', groupName: 'price'}, {label: 'Over $100', value: 'over-100', subtitle: '', groupName: 'price'}, ], }, ]; return ( <FilterList options={filterOptions} submitButtonLabel="Apply Filters" resetButtonLabel="Clear All" onApplyFilters={selectedFilters => { console.log('Applied filters:', selectedFilters); }} onResetFilters={() => { console.log('Filters reset'); }} defaultSelectedFilters={[]} > <FilterList.SelectedFilterList /> <FilterList.AccordionList /> <FilterList.Actions /> </FilterList> ); }
function AdvancedFilterList() { const filterOptions = [ { label: 'Brand', subtitle: 'Select your preferred brands', value: 'brand', columns: 2, children: [ {label: 'Apple', value: 'apple', subtitle: '', groupName: 'brand'}, {label: 'Samsung', value: 'samsung', subtitle: '', groupName: 'brand'}, {label: 'Google', value: 'google', subtitle: '', groupName: 'brand'}, {label: 'Microsoft', value: 'microsoft', subtitle: '', groupName: 'brand'}, {label: 'Sony', value: 'sony', subtitle: '', groupName: 'brand'}, {label: 'LG', value: 'lg', subtitle: '', groupName: 'brand'}, ], }, { label: 'Price Range', subtitle: 'Filter by your budget', value: 'price', columns: 1, children: [ {label: 'Under $100', value: 'under-100', subtitle: '', groupName: 'price'}, {label: '$100 - $500', value: '100-500', subtitle: '', groupName: 'price'}, {label: '$500 - $1000', value: '500-1000', subtitle: '', groupName: 'price'}, {label: 'Over $1000', value: 'over-1000', subtitle: '', groupName: 'price'}, ], }, { label: 'Features', subtitle: 'Special features and capabilities', value: 'features', columns: 2, children: [ {label: 'Wireless', value: 'wireless', subtitle: '', groupName: 'features'}, {label: 'Waterproof', value: 'waterproof', subtitle: '', groupName: 'features'}, {label: 'Fast Charging', value: 'fast-charging', subtitle: '', groupName: 'features'}, {label: 'HD Display', value: 'hd-display', subtitle: '', groupName: 'features'}, ], }, ]; const preselectedFilters = [ {label: 'Apple', value: 'apple', subtitle: '', groupName: 'brand'}, {label: '$100 - $500', value: '100-500', subtitle: '', groupName: 'price'}, ]; return ( <FilterList options={filterOptions} submitButtonLabel="Apply Filters" resetButtonLabel="Clear All" onApplyFilters={selectedFilters => { console.log('Applied filters:', selectedFilters); }} onResetFilters={() => { console.log('Filters reset'); }} defaultSelectedFilters={preselectedFilters} className="custom-filter-list" sx={{ backgroundColor: '#f8f9fa', border: '1px solid #e9ecef', borderRadius: '12px', padding: '16px', maxWidth: '400px', margin: '0 auto', }} > {({defaultBlocks}) => ({ blocks: { ...defaultBlocks, // π Custom header with filter count filterHeader: ( <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '16px', backgroundColor: '#e3f2fd', borderRadius: '8px', marginBottom: '16px', border: '1px solid #bbdefb', }} > <h3 style={{ margin: 0, color: '#1976d2', fontSize: '18px', fontWeight: 'bold', }} > π Advanced Filters </h3> <span style={{ fontSize: '14px', color: '#666', backgroundColor: '#bbdefb', padding: '4px 8px', borderRadius: '12px', }} > {filterOptions.length} categories </span> </div> ), // π Custom filter stats filterStats: ( <div style={{ display: 'flex', justifyContent: 'space-between', padding: '12px 16px', backgroundColor: '#f8f9fa', borderRadius: '8px', marginBottom: '16px', border: '1px solid #dee2e6', }} > <div style={{textAlign: 'center'}}> <div style={{fontSize: '20px', fontWeight: 'bold', color: '#28a745'}}>{preselectedFilters.length}</div> <div style={{fontSize: '12px', color: '#666'}}>Active</div> </div> <div style={{textAlign: 'center'}}> <div style={{fontSize: '20px', fontWeight: 'bold', color: '#007bff'}}> {filterOptions.reduce((acc, option) => acc + (option.children?.length || 0), 0)} </div> <div style={{fontSize: '12px', color: '#666'}}>Available</div> </div> <div style={{textAlign: 'center'}}> <div style={{fontSize: '20px', fontWeight: 'bold', color: '#6c757d'}}>{filterOptions.length}</div> <div style={{fontSize: '12px', color: '#666'}}>Categories</div> </div> </div> ), }, blockOrder: ['filterHeader', 'selectedFilterList', 'filterStats', 'accordionList', 'actions'], })} </FilterList> ); }
π§ Props Referenceβ
Main Component Propsβ
| Prop | Type | Default | Description |
|---|---|---|---|
options | FilterChild[] | Required | Array of filter options with hierarchical structure |
onApplyFilters | (selectedFilters: FilterChild[]) => void | Required | Callback function triggered when filters are applied |
onResetFilters | () => void | Required | Callback function triggered when filters are reset |
submitButtonLabel | string | 'Apply' | Label for the submit/apply button |
resetButtonLabel | string | 'Reset' | Label for the reset/clear button |
defaultSelectedFilters | FilterChild[] | [] | Initial selected filters on component mount |
className | string | undefined | Additional CSS class name for styling the container |
sx | SxProps<Theme> | { backgroundColor: 'background.paper' } | MUI system props for custom styling |
children | BlocksOverride | undefined | Custom block components to override default rendering |
Note: This component inherits all MUI Stack component props.
Sub-Componentsβ
The FilterList component provides several sub-components. All sub-components receive their default values from the main component's context and can override these values through props.
FilterList.FilterChipβ
Renders a selected filter as a removable chip using MUI Chip.
| Prop | Type | Default | Description |
|---|---|---|---|
child | FilterChild | Required | Filter item to display as a chip |
onClickRemoveFilter | (filter: FilterChild) => void | Context value | Callback fired when chip is removed |
className | string | undefined | Additional CSS class name for styling |
sx | SxProps<Theme> | undefined | MUI system props for custom styling |
Note: This component inherits all MUI Chip component props.
FilterList.SelectedFilterListβ
Renders the list of currently selected filters using MUI Box.
| Prop | Type | Default | Description |
|---|---|---|---|
selectedFilters | FilterChild[] | Context value | List of currently selected filters |
onClickRemoveFilter | (filter: FilterChild) => void | Context value | Callback for removing selected filters |
className | string | undefined | Additional CSS class name for styling |
sx | SxProps<Theme> | undefined | MUI system props for custom styling |
Note: This component inherits all MUI Box component props. Returns null when no filters are selected.
FilterList.AccordionArrowβ
Renders the accordion expand/collapse arrow icon using MUI Box (as span).
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | undefined | Additional CSS class name for styling |
sx | SxProps<Theme> | undefined | MUI system props for custom styling |
Note: This component inherits all MUI Box component props (rendered as component="span"). Uses MUI NavigateNextIcon and rotates 90Β° when expanded.
FilterList.Accordionβ
Renders a filter group as an expandable accordion using MUI Accordion.
| Prop | Type | Default | Description |
|---|---|---|---|
child | FilterChild | Required | Filter group to display as accordion |
selectedFilters | FilterChild[] | Context value | Currently selected filters (overrides context) |
onChangeCheckbox | (item: FilterChild) => void | Context value | Checkbox change callback (overrides context) |
className | string | undefined | Additional CSS class name for styling |
sx | SxProps<Theme> | undefined | MUI system props for custom styling |
Note: This component inherits all MUI Accordion component props (except children).
FilterList.AccordionListβ
Renders the list of filter accordions using MUI Box.
| Prop | Type | Default | Description |
|---|---|---|---|
options | FilterChild[] | Context value | List of filter options to display as accordions |
className | string | undefined | Additional CSS class name for styling |
sx | SxProps<Theme> | undefined | MUI system props for custom styling |
Note: This component inherits all MUI Box component props.
FilterList.ResetButtonβ
Renders the reset/clear button using MUI Button.
| Prop | Type | Default | Description |
|---|---|---|---|
resetButtonLabel | ReactNode | Context value | Button label (overrides context) |
onClickResetFilters | () => void | Context value | Reset callback (overrides context) |
children | ReactNode | Context resetButtonLabel | Button content - overrides resetButtonLabel |
onClick | () => void | Context onClickResetFilters | Click handler - overrides onClickResetFilters |
className | string | undefined | Additional CSS class name for styling |
sx | SxProps<Theme> | undefined | MUI system props for custom styling |
variant | ButtonVariant | 'outlined' | MUI Button variant |
Note: This component inherits all MUI Button component props.
FilterList.SubmitButtonβ
Renders the submit/apply button using MUI Button.
| Prop | Type | Default | Description |
|---|---|---|---|
submitButtonLabel | ReactNode | Context value | Button label (overrides context) |
onApplyFilters | (filters: FilterChild[]) => void | Context value | Apply callback (overrides context) |
selectedFilters | FilterChild[] | Context value | Selected filters to pass to callback (overrides context) |
children | ReactNode | Context submitButtonLabel | Button content - overrides submitButtonLabel |
onClick | () => void | Calls onApplyFilters with selectedFilters | Click handler - overrides default behavior |
className | string | undefined | Additional CSS class name for styling |
sx | SxProps<Theme> | undefined | MUI system props for custom styling |
variant | ButtonVariant | 'contained' | MUI Button variant |
Note: This component inherits all MUI Button component props.
FilterList.Actionsβ
Renders the action buttons container using MUI Box.
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | undefined | Additional CSS class name for styling the actions container |
sx | SxProps<Theme> | undefined | MUI system props for custom styling |
Note: This component inherits all MUI Box component props. Renders FilterList.ResetButton and FilterList.SubmitButton components.
π¨ Configuration examplesβ
Custom Selected Filters Stylingβ
<FilterList.SelectedFilterList
sx={{
bgcolor: 'primary.light',
borderRadius: 2,
p: 2
}}
/>
Custom Button Stylingβ
<FilterList.Actions sx={{ justifyContent: 'flex-end', gap: 2 }}>
<FilterList.ResetButton
variant="text"
sx={{ color: 'text.secondary' }}>
Clear All
</FilterList.ResetButton>
<FilterList.SubmitButton
variant="contained"
color="primary"
sx={{ minWidth: 120 }}>
Apply Filters
</FilterList.SubmitButton>
</FilterList.Actions>
π§ TypeScript Supportβ
Full TypeScript support with comprehensive type definitions:
import {FilterList} from '@nodeblocks/frontend-filter-list-block';
import {StackProps, ChipProps, ButtonProps, BoxProps} from '@mui/material';
// FilterChild type definition
type FilterChild = {
label: string;
subtitle: string;
value: string;
groupName?: string;
checked?: boolean;
children?: FilterChild[];
columns?: number;
};
// Main component props extend MUI StackProps
interface FilterListProps extends Omit<StackProps, 'children'> {
options: FilterChild[];
onApplyFilters: (selectedFilters: FilterChild[]) => void;
onResetFilters: () => void;
submitButtonLabel?: string;
resetButtonLabel?: string;
defaultSelectedFilters?: FilterChild[];
children?: BlocksOverride;
}
// Example with MUI styling
function TypedFilterListExample() {
const filterOptions: FilterChild[] = [
{
label: 'Brand',
subtitle: 'Select preferred brands',
value: 'brand',
columns: 2,
children: [
{label: 'Apple', value: 'apple', subtitle: '', groupName: 'brand'},
{label: 'Samsung', value: 'samsung', subtitle: '', groupName: 'brand'},
{label: 'Google', value: 'google', subtitle: '', groupName: 'brand'},
],
},
{
label: 'Price Range',
subtitle: 'Filter by price',
value: 'price',
columns: 1,
children: [
{label: 'Under $100', value: 'under-100', subtitle: '', groupName: 'price'},
{label: '$100 - $500', value: '100-500', subtitle: '', groupName: 'price'},
],
},
];
const handleApplyFilters = (selectedFilters: FilterChild[]): void => {
console.log('Applied filters:', selectedFilters);
};
const handleResetFilters = (): void => {
console.log('Filters reset');
};
return (
<FilterList
options={filterOptions}
onApplyFilters={handleApplyFilters}
onResetFilters={handleResetFilters}
submitButtonLabel="Apply Filters"
resetButtonLabel="Clear All"
defaultSelectedFilters={[]}
className="my-custom-filter-list"
sx={{maxWidth: 400, mx: 'auto'}}
>
<FilterList.SelectedFilterList sx={{bgcolor: 'grey.100'}} />
<FilterList.AccordionList />
<FilterList.Actions sx={{gap: 2}}>
<FilterList.ResetButton variant="text">Clear</FilterList.ResetButton>
<FilterList.SubmitButton color="secondary">Apply</FilterList.SubmitButton>
</FilterList.Actions>
</FilterList>
);
}
π Notesβ
- The component uses MUI's
Stackfor the main layout with defaultbackgroundColor: 'background.paper' - Selected filters are displayed as MUI
Chipcomponents with a close icon - Filter groups use MUI
AccordionwithNavigateNextIconthat rotates when expanded - Filter options within groups use MUI
CheckboxwithFormControlLabel - The
columnsproperty on FilterChild controls the grid layout of checkboxes within accordion details - The
SelectedFilterListreturnsnullwhen there are no selected filters - Reset button uses
variant="outlined"by default - Submit button uses
variant="contained"by default withflexGrow: 1 - All sub-components support the
sxprop for MUI system styling - Block override pattern allows inserting custom blocks between default blocks
Built with β€οΈ using React, TypeScript, and MUI.