svelte-multi-filter is a lightweight, type-safe library that provides a reactive way to implement complex, multi-dimensional filtering logic in your Svelte applications.
The library focuses on simplifying the core logic of filtering data based on multiple criteria. It handles the reactivity and state management, so you can focus on building your user interface. It’s designed to work with any UI components. You have complete freedom to style your filters however you want.
Features
⚡ Runes-compatible – Optimized for Svelte 5’s reactivity system.
📦 Self-contained – Zero external dependencies beyond Svelte core.
🎭 UI-neutral – Works with any component library or custom elements.
🔄 Dependent filters – Automatically adjusts available options based on selections.
🎯 Type validation – Compile-time checks enforce consistent data handling.
Use Cases
- E-commerce Product Filtering: Imagine an online store with products having attributes like category, color, size, and price range. Svelte Multi-Filter can handle updating available options. For example, if a user selects “Red” as the color, the size options could automatically update to only show sizes available in red.
- Data Dashboard Filtering: A business intelligence dashboard might have filters for date ranges, regions, product lines, and sales representatives. The library helps manage these filters and ensure the displayed data reflects all selected criteria.
- Job Board Filtering: Consider job search platforms that filter the search results. If a user selects a set of “remote” jobs, the location options could update.
- Real Estate Listings: A real estate website could allow users to filter by price, property type, number of bedrooms, and location. Svelte Multi-Filter simplifies updating available options.
- Content Library: A content platform with articles, and videos that you can be filter, it can be by category, author, and publication date.
Installation
You can install @zshzebra/svelte-multi-filter using your preferred package manager. Bun is recommended:
bunx jsr add @zshzebra/svelte-multi-filterAlternatively, you can use npm:
npx jsr add @zshzebra/svelte-multi-filterOr pnpm:
pnpm dlx jsr add @zshzebra/svelte-multi-filterUsage
First, define the data structure you want to filter, and create your data array. For example:
interface Product {
category: 'Shirt' | 'Pants' | 'Jacket';
color: 'Red' | 'Blue' | 'Black';
}
const products = [
{ category: 'Shirt', color: 'Red' },
{ category: 'Pants', color: 'Blue' },
{ category: 'Shirt', color: 'Black' }
];Next, configure the filter options and create the filter store:
import { createFilterStore, type FilterConfig } from '@zshzebra/svelte-multi-filter';
const config = {
category: ['Shirt', 'Pants', 'Jacket'],
color: ['Red', 'Blue', 'Black']
} satisfies FilterConfig<Product>;
const filter = createFilterStore(products, config);Finally, use the store in your Svelte component:
<script lang="ts">
import { createFilterStore, type FilterConfig, type FilterDimension } from '@zshzebra/svelte-multi-filter';
//Same as in the above code examples
interface Product {
category: 'Shirt' | 'Pants' | 'Jacket';
color: 'Red' | 'Blue' | 'Black';
}
const products = [
{ category: 'Shirt', color: 'Red' },
{ category: 'Pants', color: 'Blue' },
{ category: 'Shirt', color: 'Black' }
];
const config = {
category: ['Shirt', 'Pants', 'Jacket'],
color: ['Red', 'Blue', 'Black']
} satisfies FilterConfig<Product>;
const filter = createFilterStore(products, config);
let dimensions = $state<{
category: FilterDimension<string>;
color: FilterDimension<string>;
}>();
let results = $state<Product[]>([]);
let availableCategoryOptions = $state<string[]>([]);
let availableColorOptions = $state<string[]>([]);
filter.subscribe((dims) => {
dimensions = dims;
});
filter.filteredItems.subscribe((items) => {
results = items;
});
filter.getAvailableOptions('category').subscribe((options) => {
availableCategoryOptions = options;
});
filter.getAvailableOptions('color').subscribe((options) => {
availableColorOptions = options;
});
</script>
<div class="filters">
<div class="filter-group">
<h3>Category</h3>
<label>
<input
type="radio"
name="category"
value="Any"
checked={dimensions?.category?.selected === 'Any'}
onchange={() => filter.select('category', 'Any')}
/>
Any
</label>
{#each config.category as option}
<label>
<input
type="radio"
name="category"
value={option}
checked={dimensions?.category?.selected === option}
disabled={!availableCategoryOptions.includes(option)}
onchange={() => filter.select('category', option)}
/>
{option}
</label>
{/each}
</div>
<div class="filter-group">
<h3>Color</h3>
<label>
<input
type="radio"
name="color"
value="Any"
checked={dimensions?.color?.selected === 'Any'}
onchange={() => filter.select('color', 'Any')}
/>
Any
</label>
{#each config.color as option}
<label>
<input
type="radio"
name="color"
value={option}
checked={dimensions?.color?.selected === option}
disabled={!availableColorOptions.includes(option)}
onchange={() => filter.select('color', option)}
/>
{option}
</label>
{/each}
</div>
</div>
<button onclick={() => filter.reset()}>Reset Filters</button>
<div class="results">
<h3>Results ({results.length})</h3>
{#each results as item}
<div>{JSON.stringify(item)}</div>
{/each}
</div>The filter store provides methods like subscribe, select, getAvailableOptions, filteredItems, and reset. These allow you to interact with and display the filtered data. The example shows how to create radio button filters for category and color, and display the filtered results.
Related Resources
- Svelte Official Documentation: The official Svelte website provides comprehensive documentation, tutorials, and examples. https://svelte.dev/
- SvelteKit Documentation: If you’re building a full-fledged application, SvelteKit is the recommended framework. https://kit.svelte.dev/
FAQs
Q: Can I use this with Svelte components from libraries like Svelte Material UI or Flowbite Svelte?
A: Yes, @zshzebra/svelte-multi-filter is UI-agnostic. It focuses solely on the filter logic, so you can integrate it with any component library.
Q: How does this library handle large datasets?
A: While the library itself doesn’t impose limits, performance with very large datasets depends on how you render the filtered results. Consider using virtualization techniques if you’re dealing with thousands of items.
Q: Does it support asynchronous data loading?
A: The createFilterStore function expects the data to be available synchronously. If you’re fetching data asynchronously, you can create the store after the data has loaded.
Q: Can I define custom filter logic?
A: The library provides a select method for updating filter selections, which triggers reactivity. For more complex filtering scenarios, you might need to combine this with custom logic within your Svelte components.
Q: What is an Interdependent Filter? A: Interdependent filters refer to a filtering system where the options available in one filter depend on the selections made in other filters.
Preview


