A powerful, themeable expression builder for creating complex filter logic
npm install @aftui/expressoA powerful, themeable expression builder for creating complex filter logic with a visual drag-and-drop interface.
- 🎨 Fully Themeable - Injectable theme system with default light and dark themes
- 🔧 Comprehensive Operators - Comparison, arithmetic, logical, and conditional expressions
- 🎯 Drag & Drop - Intuitive interface for organizing expressions
- 💾 Presets - Save and load frequently used configurations
- 📋 Import/Export - Share expressions via JSON
- ⏱️ Undo/Redo - Full history support with keyboard shortcuts
- 🔍 Search - Find specific values within expressions
- ✅ Validation - Real-time error detection
``bash`
npm install @aftui/expressoor
yarn add @aftui/expressoor
pnpm add @aftui/expresso
This package requires React 19+ and several peer dependencies:
`bash`
npm install react react-dom sonner lucide-react @radix-ui/react-dropdown-menu @radix-ui/react-label @radix-ui/react-popover @radix-ui/react-select @radix-ui/react-switch
Important: This package uses Sonner for toast notifications. You must include the component in your app:
`tsx
import { Toaster } from 'sonner';
function App() {
return (
<>
{/ Your app content /}
>
);
}
`
Expresso uses Vanilla Extract for styling, providing a zero-runtime CSS-in-JS solution. All styles are bundled with the component, so no additional setup is required.
This component uses Radix UI which requires client-side rendering. When using with SSR frameworks:
astro
---
import { Expresso } from '@aftui/expresso';
--- client:only="react"
fields={fields}
onApply={handleApply}
/>
`$3
`tsx
'use client' // Add this at the top of your component fileimport { Expresso } from '@aftui/expresso'
`$3
`tsx
import dynamic from 'next/dynamic'const Expresso = dynamic(
() => import('@aftui/expresso').then(mod => ({ default: mod.Expresso })),
{ ssr: false }
)
`Quick Start
`tsx
import {
Expresso,
type JoinKeyExpression,
type DropdownItem
} from '@aftui/expresso';
import { Toaster } from 'sonner';function App() {
const fields: DropdownItem[] = [
{ name: 'Price', key: 'price' },
{ name: 'Status', key: 'status' },
{ name: 'Category', key: 'category' },
];
const handleApply = (expression: JoinKeyExpression | JoinKeyExpression[]) => {
console.log('Filter expression:', expression);
// Use the expression in your application
};
return (
<>
fields={fields}
onApply={handleApply}
onCancel={() => console.log('Cancelled')}
/>
>
);
}
`Theming
$3
`tsx
fields={fields}
onApply={handleApply}
onCancel={handleCancel}
/>
`$3
`tsx
import { Expresso, darkTheme } from '@aftui/expresso'; fields={fields}
onApply={handleApply}
onCancel={handleCancel}
theme={darkTheme}
/>
`$3
`tsx
import {
Expresso,
type FilterBuilderThemeConfig
} from '@aftui/expresso';const customTheme: FilterBuilderThemeConfig = {
theme: {
primary: "222.2 47.4% 11.2%",
accent: "142.1 76.2% 36.3%", // Green accent
// ... other theme properties
},
radius: "0.75rem",
};
theme={customTheme}
{...otherProps}
/>
`See THEMING.md for complete theming documentation.
Props
| Prop | Type | Required | Description |
|------|------|----------|-------------|
|
fields | DropdownItem[] | Yes | Array of available fields |
| onApply | (expression) => void | Yes | Callback when user applies filter |
| onCancel | () => void | Yes | Callback when user cancels |
| defaultExpression | JoinKeyExpression \| JoinKeyExpression[] | No | Initial expression |
| operatorConfig | OperatorConfig | No | Custom operator configuration |
| creationMetaData | CreationMetaData | No | Metadata for new expressions |
| customCategoryContent | Record | No | Custom field category content |
| theme | FilterBuilderThemeConfig | No | Custom theme |Expression Format
Expressions are structured JSON objects:
`json
{
"operator": "and",
"expressions": [
{
"operator": "gt",
"left": { "valueType": "EnrichmentField", "fieldId": "Price" },
"right": { "valueType": "constant", "value": 100 }
},
{
"operator": "eq",
"left": { "valueType": "EnrichmentField", "fieldId": "Status" },
"right": { "valueType": "constant", "value": "Active" }
}
]
}
`Optional: Section Dropdown
If you need the Section Dropdown feature (for enrichment fields with sections), wrap your app with
FieldsProvider:`tsx
import { FieldsProvider } from '@aftui/expresso';function App() {
const enrichmentFields = [
{ Id: 1, Name: 'Field1', FriendlyName: 'Field 1', Key: 'field1', Section: 'General' },
// ... more fields
];
return (
);
}
`If you don't use
FieldsProvider, the Section Dropdown will simply not appear (graceful degradation).TypeScript Support
This package is written in TypeScript and includes full type definitions.
`tsx
import type {
JoinKeyExpression,
AnyExpressionType,
DropdownItem,
FilterBuilderThemeConfig,
OperatorConfig,
} from '@aftui/expresso';
`$3
For backward compatibility, the
AdvancedFilterBuilder component name is also exported as an alias to Expresso. However, we recommend using Expresso for new projects:`tsx
// New (recommended)
import { Expresso } from '@aftui/expresso';// Old (still works)
import { AdvancedFilterBuilder } from '@aftui/expresso';
``- Chrome/Edge (latest)
- Firefox (latest)
- Safari (latest)
- GitHub: accessfintech/expresso
- NPM: @aftui/expresso
MIT
Contributions are welcome! Please open an issue or pull request at the GitHub repository.