Skip to main content

FilterBar

Result
Loading...
Live Editor
function ManagedFilter() {
	const [filters, setFilters] = React.useState([
		<NumberFilter id="number-filter" filterName="Number Filter" />,
	]);

	return (
		<FilterBar
			id="filter-bar"
			addFilterOptions={[{ label: 'New Number Filter' }]}
			onAddFilterClick={({ label }) => {
				setFilters([...filters, <NumberFilter id="number-filter" filterName={label} />]);
			}}
		>
			{filters}
		</FilterBar>
	);
}

Creating dynamic filters

You can store the filter props and type in state to generate dynamic Filters that will be used within a FilterBar.

Result
Loading...
Live Editor
const singleSelectOptions = [
	{
		label: 'Option 1',
		value: '1',
	},
	{
		label: 'Option 2',
		value: '2',
	},
	{
		label: 'Option 3',
		value: '3',
	},
];

const accountTypeOptions = [
	{
		label: 'Roth IRA',
		value: 'roth-ira',
	},
	{
		label: '401k',
		value: '401k',
	},
	{
		label: 'Checking',
		value: 'checking',
	},
	{
		label: '403b',
		value: '403b',
	},
	{
		label: 'Mortgage',
		value: 'mortgage',
	},
	{
		label: 'Savings',
		value: 'savings',
	},
];

const foodMenuOptions = [
	{ label: 'Meat', id: 'Meat' },
	{ label: 'Treats', id: 'Treats' },
	{
		id: 'Fruit',
		label: 'Fruit',
		children: [
			{
				label: 'Apple',
				id: 'Apple',
			},
			{
				label: 'Banana',
				id: 'Banana',
			},
			{
				label: 'Cantaloupe',
				id: 'Cantaloupe',
			},
		],
	},
	{
		id: 'Vegetables',
		label: 'Vegetables',
		children: [
			{
				label: 'Spinach',
				id: 'Spinach',
			},
			{
				label: 'Kale',
				id: 'Kale',
			},
		],
	},
	{
		id: 'Cheese',
		label: 'Cheese',
		children: [
			{
				label: 'Mozzarella',
				id: 'Mozzarella',
			},
			{
				label: 'Gouda',
				id: 'Gouda',
			},
			{
				label: 'Stilton',
				id: 'Stilton',
			},
			{
				label: 'Cheddar',
				id: 'Cheddar',
			},
			{
				label: 'String',
				id: 'String',
			},
		],
	},
];

const NUMBER_TYPE = 'Number Filter';
const SINGLE_SELECT_TYPE = 'Single Select Filter';
const ACCOUNT_TYPE = 'Account Type';
const FOOD_TYPE = 'Food Menu';
const DATE_TYPE = 'Date Range';

const filterComponents = {
	[NUMBER_TYPE]: NumberFilter,
	[SINGLE_SELECT_TYPE]: SingleSelectFilter,
	[ACCOUNT_TYPE]: MultiSelectFilter,
	[FOOD_TYPE]: CollapsibleMultiSelectFilter,
	[DATE_TYPE]: DateRangeFilter,
};

const ManagedFilterBar = (props) => {
	const [filters, setFilters] = useState([]);
	const [addFilterOptions, setAddFilterOptions] = useState({
		[NUMBER_TYPE]: false,
		[SINGLE_SELECT_TYPE]: false,
		[ACCOUNT_TYPE]: false,
		[FOOD_TYPE]: false,
		[DATE_TYPE]: false,
	});

	const removeFilter = (id, type) => {
		setFilters((currentFilters) =>
			currentFilters.filter(({ filterProps }) => filterProps.id !== id),
		);

		setAddFilterOptions((currentAddFilterOptions) => ({
			...currentAddFilterOptions,
			[type]: false,
		}));
	};

	const addFilter = (type) => {
		const id = crypto.randomUUID();
		let filterProps = {
			id,
			removable: true,
			filterName: type,
			onRemove: () => removeFilter(id, type),
		};

		if (type === SINGLE_SELECT_TYPE) {
			filterProps.options = singleSelectOptions;
		} else if (type === ACCOUNT_TYPE) {
			filterProps.options = accountTypeOptions;
		} else if (type === FOOD_TYPE) {
			filterProps.options = foodMenuOptions;
		} else if (type === DATE_TYPE) {
			filterProps.minYear = 2000;
			filterProps.maxYear = 2010;
		}

		setFilters([...filters, { filterProps, type }]);
		setAddFilterOptions({
			...addFilterOptions,
			[type]: true,
		});
	};

	return (
		<FilterBar
			addFilterOptions={Object.keys(addFilterOptions).map((filterOption) => ({
				label: filterOption,
				disabled: addFilterOptions[filterOption],
			}))}
			onAddFilterClick={(filter) => {
				addFilter(filter.label);
			}}
			id="dynamic-filters"
		>
			<SingleSelectFilter
				removable={false}
				filterName="Non removable single select"
				options={[
					{ label: 'Option1', value: 'o1' },
					{ label: 'Option2', value: 'o2' },
				]}
				id="non-removable-single-select"
			/>
			<MultiSelectFilter
				removable={false}
				filterName="Non removable multi select"
				options={[
					{ label: 'Option1', value: 'o1' },
					{ label: 'Option2', value: 'o2' },
				]}
				id="non-removable-multi-select"
			/>

			{filters.map(({ filterProps, type }) => {
				const Component = filterComponents[type];
				return <Component {...filterProps} key={filterProps.id} />;
			})}
		</FilterBar>
	);
};

render(<ManagedFilterBar />);

Props