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
π 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.