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.
π Installationβ
npm install @nodeblocks/frontend-filter-list-block@0.2.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"
style={{
backgroundColor: '#f8f9fa',
border: '1px solid #e9ecef',
borderRadius: '12px',
padding: '16px',
maxWidth: '400px',
margin: '0 auto'
}}>
{({ defaultBlocks, defaultBlockOrder }) => ({
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 selected filter list with enhanced styling
selectedFilterList: {
...defaultBlocks.selectedFilterList,
props: {
...defaultBlocks.selectedFilterList.props,
style: {
backgroundColor: '#fff3e0',
border: '1px solid #ffcc02',
borderRadius: '8px',
padding: '12px',
marginBottom: '16px',
minHeight: '60px',
display: 'flex',
alignItems: 'center',
flexWrap: 'wrap',
gap: '8px',
},
},
},
// π Custom accordion list with enhanced styling
accordionList: {
...defaultBlocks.accordionList,
props: {
...defaultBlocks.accordionList.props,
style: {
backgroundColor: 'white',
borderRadius: '8px',
border: '1px solid #e0e0e0',
marginBottom: '16px',
overflow: 'hidden',
boxShadow: '0 2px 4px rgba(0,0,0,0.1)',
},
},
},
// π 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>
),
// π¨ Custom action buttons with enhanced styling
actions: {
...defaultBlocks.actions,
props: {
...defaultBlocks.actions.props,
style: {
backgroundColor: '#e9ecef',
borderRadius: '8px',
padding: '16px',
display: 'flex',
gap: '12px',
border: '1px solid #dee2e6',
},
},
},
// π Custom reset button with enhanced styling
resetButton: {
...defaultBlocks.resetButton,
props: {
...defaultBlocks.resetButton.props,
style: {
backgroundColor: '#6c757d',
color: 'white',
border: 'none',
borderRadius: '6px',
padding: '12px 24px',
cursor: 'pointer',
fontWeight: 'bold',
flex: 1,
},
},
},
// β
Custom submit button with enhanced styling
submitButton: {
...defaultBlocks.submitButton,
props: {
...defaultBlocks.submitButton.props,
style: {
backgroundColor: '#007bff',
color: 'white',
border: 'none',
borderRadius: '6px',
padding: '12px 24px',
cursor: 'pointer',
fontWeight: 'bold',
flex: 2,
},
},
},
},
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 | Required | Label for the submit/apply button (defaults to "Apply" in function signature) |
resetButtonLabel | string | Required | Label for the reset/clear button (defaults to "Reset" in function signature) |
defaultSelectedFilters | FilterChild[] | [] | Initial selected filters on component mount |
className | string | undefined | Additional CSS class name for styling the container |
children | BlocksOverride | undefined | Custom block components to override default rendering |
Note: The main component inherits all HTML div element 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β
| Prop | Type | Default | Description |
|---|---|---|---|
child | FilterChild | Required | Filter item to display as a chip |
onClickRemoveFilter | (filter: FilterChild) => void | From context | Callback fired when chip is removed |
Note: This component inherits all HTML div element props.
FilterList.SelectedFilterListβ
| Prop | Type | Default | Description |
|---|---|---|---|
selectedFilters | FilterChild[] | From context | List of currently selected filters |
onClickRemoveFilter | (filter: FilterChild) => void | From context | Callback for removing selected filters |
Note: This component inherits all HTML div element props.
FilterList.AccordionArrowβ
| Prop | Type | Default | Description |
|---|---|---|---|
isExpanded | boolean | Required | Whether the accordion is expanded |
Note: This component inherits all HTML span element props.
FilterList.Accordionβ
| Prop | Type | Default | Description |
|---|---|---|---|
child | FilterChild | Required | Filter group to display as accordion |
Note: This component inherits all HTML div element props.
FilterList.AccordionListβ
| Prop | Type | Default | Description |
|---|---|---|---|
options | FilterChild[] | From context | List of filter options to display as accordions |
Note: This component inherits all HTML div element props.
FilterList.ResetButtonβ
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | Context resetButtonLabel | Button content/text |
onClick | () => void | Context onClickResetFilters | Click handler for reset action |
className | string | undefined | Additional CSS class name for styling |
Note: This component inherits all HTML button element props.
FilterList.SubmitButtonβ
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | Context submitButtonLabel | Button content/text |
onClick | () => void | Context onApplyFilters with selected filters | Click handler for submit action |
className | string | undefined | Additional CSS class name for styling |
Note: This component inherits all HTML button element props.
FilterList.Actionsβ
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | undefined | Additional CSS class name for styling the actions container |
Note: This component inherits all HTML div element props. Renders a FilterList.ResetButton and FilterList.SubmitButton component.
π§ TypeScript Supportβ
Full TypeScript support with comprehensive type definitions:
import {FilterList} from '@nodeblocks/frontend-filter-list-block';
import {ComponentProps} from 'react';
// FilterChild type definition (not exported, define locally)
type FilterChild = {
label: string;
subtitle: string;
value: string;
groupName?: string;
checked?: boolean;
children?: FilterChild[];
columns?: 1 | 2;
};
// Main component interface
interface FilterListProps extends ComponentProps<'div'> {
options: FilterChild[];
onApplyFilters: (selectedFilters: FilterChild[]) => void;
onResetFilters: () => void;
submitButtonLabel: string;
resetButtonLabel: string;
defaultSelectedFilters?: FilterChild[];
}
// Example usage with hierarchical filters
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'},
],
},
];
// Advanced example with custom styling and handlers
function CustomFilterList() {
const handleApplyFilters = (selectedFilters: FilterChild[]) => {
console.log('Applied filters:', selectedFilters);
// Process selected filters
};
const handleResetFilters = () => {
console.log('Filters reset');
};
return (
<FilterList
options={filterOptions}
onApplyFilters={handleApplyFilters}
onResetFilters={handleResetFilters}
submitButtonLabel="Apply Filters"
resetButtonLabel="Clear All"
defaultSelectedFilters={[]}
className="my-custom-filter-list">
<FilterList.SelectedFilterList className="selected-chips" />
<FilterList.AccordionList className="filter-accordions" />
<FilterList.Actions className="filter-actions">
<FilterList.ResetButton>Clear All</FilterList.ResetButton>
<FilterList.SubmitButton>Apply Filters</FilterList.SubmitButton>
</FilterList.Actions>
</FilterList>
);
}
Built with β€οΈ using React, TypeScript, and modern web standards.