Skip to content

Add Airtable-like Filter Builder Component with Advanced Field Types#14

Merged
huangyiirene merged 9 commits intomainfrom
copilot/add-airtable-filter-component
Jan 14, 2026
Merged

Add Airtable-like Filter Builder Component with Advanced Field Types#14
huangyiirene merged 9 commits intomainfrom
copilot/add-airtable-filter-component

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Jan 13, 2026

Implementation: Airtable-like Filter Component ✅

Successfully implemented an Airtable-like filter builder component for Object UI with full schema-driven configuration and interactive features.

✅ Completed Tasks

  • Create base UI component for filter builder (packages/components/src/ui/filter-builder.tsx)
  • Create filter rule component for individual filter conditions
  • Create renderer component that integrates with Object UI schema system
  • Add component metadata for designer integration
  • Add exports to package index
  • Build and test the component
  • Create example/demo usage
  • Test the component in playground
  • Address code review feedback
  • Add comprehensive documentation
  • Add date field support with native date picker
  • Add select field support with dropdown options
  • Add "Clear all" button functionality
  • Enhanced input types with proper type conversion
  • Simplify UUID generation

📸 Screenshots

Enhanced Filter Builder with Advanced Features

Enhanced Filter Builder

The screenshot shows:

  • Clear all button in the top right of each filter group
  • Date input field for the "Join Date" filter with native date picker
  • Select dropdown for the "Status" field with predefined options (Active, Inactive, Pending)
  • Number input for numeric fields (Price field shows spinbutton)
  • AND logic toggle between multiple conditions

Original Filter Builder Demo

Filter Builder Demo

Interactive Features (Dropdown Open)

Filter Builder with Dropdown

✨ Features Implemented

Dynamic Filter Conditions - Add and remove filter conditions dynamically
Field Selection - Select from available fields with dropdown
Type-Aware Operators - Operators change based on field type (text, number, boolean, date, select)
Value Input - Smart input fields that adapt to field type:

  • Text fields: regular text input
  • Number fields: number input with spinbuttons (values stored as numbers)
  • Date fields: native date picker with proper ISO format
  • Select fields: dropdown with options
  • Boolean fields: true/false dropdown
    AND/OR Logic Toggle - Switch between AND and OR logic when multiple conditions exist
    Clear All Button - Quick way to remove all filters at once
    Schema-Driven - Fully configurable via JSON schema
    Tailwind Styled - Consistent with Object UI design system
    Shadcn Components - Built with Radix UI primitives

📦 Component API

Schema Definition

Basic Usage:

{
  type: 'filter-builder',
  name: 'filters',
  label: 'Filters',
  fields: [
    { value: 'name', label: 'Name', type: 'text' },
    { value: 'age', label: 'Age', type: 'number' },
    { value: 'active', label: 'Active', type: 'boolean' }
  ]
}

With Select Fields:

{
  type: 'filter-builder',
  name: 'filters',
  fields: [
    { 
      value: 'status', 
      label: 'Status', 
      type: 'select',
      options: [
        { value: 'active', label: 'Active' },
        { value: 'inactive', label: 'Inactive' }
      ]
    }
  ]
}

With Date Fields:

{
  type: 'filter-builder',
  name: 'filters',
  fields: [
    { value: 'createdDate', label: 'Created Date', type: 'date' }
  ],
  showClearAll: true
}

Supported Field Types

  • text - Text input with text operators
  • number - Number input with numeric operators (values stored as numbers)
  • boolean - True/false dropdown
  • date - Native date picker with date operators (ISO format)
  • select - Dropdown with custom options

Supported Operators

  • Text Fields: Equals, Does not equal, Contains, Does not contain, Is empty, Is not empty
  • Number Fields: Equals, Does not equal, Greater than, Less than, Greater or equal, Less or equal, Is empty, Is not empty
  • Boolean Fields: Equals, Does not equal
  • Date Fields: Equals, Does not equal, Before, After, Between, Is empty, Is not empty
  • Select Fields: Equals, Does not equal, In, Not in, Is empty, Is not empty

🔧 Code Quality Improvements

  • ✅ Used crypto.randomUUID() directly for ID generation (removed unnecessary prefix)
  • ✅ Correct useEffect implementation with JSON.stringify comparison to prevent stale closures
  • ✅ Enhanced type safety for value input handling
  • ✅ Smart input rendering based on field type
  • ✅ Proper type conversion for number fields (string → number)
  • ✅ Date formatting for ISO date format (YYYY-MM-DD)
  • ✅ Support for options in select fields
  • ✅ Clear all functionality with visual feedback
  • ✅ No security vulnerabilities (CodeQL scan passed)
  • ✅ All tests passing

📚 Documentation

  • Created comprehensive documentation in packages/components/docs/FilterBuilder.md
  • Added examples for all field types (text, number, boolean, date, select)
  • Includes usage examples, API reference, and integration guide
  • Documented all operators for each field type

🧪 Testing

To view the demo locally:

pnpm --filter prototype dev
# Visit http://localhost:5173/?demo=filter-builder

🔍 Security Summary

✅ No vulnerabilities detected by CodeQL scanner

Original prompt

实现类似airtable的过滤器组件


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI and others added 4 commits January 13, 2026 18:47
Co-authored-by: huangyiirene <7665279+huangyiirene@users.noreply.github.com>
Co-authored-by: huangyiirene <7665279+huangyiirene@users.noreply.github.com>
Co-authored-by: huangyiirene <7665279+huangyiirene@users.noreply.github.com>
Co-authored-by: huangyiirene <7665279+huangyiirene@users.noreply.github.com>
@huangyiirene
Copy link
Copy Markdown
Contributor

@copilot 继续

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements an Airtable-like filter builder component for Object UI, providing a schema-driven interface for creating complex query conditions with dynamic field selection and type-aware operators.

Changes:

  • Added FilterBuilder UI component with support for dynamic conditions, AND/OR logic, and field-type aware operators
  • Integrated component with Object UI's schema system via renderer and metadata
  • Created comprehensive documentation and interactive demo

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
packages/components/src/ui/filter-builder.tsx Core FilterBuilder component implementation with condition management and operator logic
packages/components/src/ui/index.ts Export statement for new FilterBuilder component
packages/components/src/renderers/complex/filter-builder.tsx Schema renderer integration for FilterBuilder with ComponentRegistry
packages/components/src/renderers/complex/index.ts Import statement for filter-builder renderer
packages/components/metadata/FilterBuilder.component.yml Component metadata defining props, events, and features
packages/components/docs/FilterBuilder.md Comprehensive documentation with usage examples and API reference
examples/prototype/src/main.tsx URL parameter routing to support filter-builder demo
examples/prototype/src/FilterBuilderDemo.tsx Demo page showcasing three filter builder examples

Comment on lines +62 to +66
React.useEffect(() => {
if (value && JSON.stringify(value) !== JSON.stringify(filterGroup)) {
setFilterGroup(value)
}
}, [value])
Copy link

Copilot AI Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The useEffect dependency array is missing filterGroup, which can cause stale closure issues. When filterGroup changes internally, the comparison on line 63 will use the old value, potentially causing infinite loops or missed updates.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in commit d5d2b84. Added filterGroup to the useEffect dependency array to prevent stale closure issues.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The original implementation was correct. Adding filterGroup to the dependency array would cause an infinite loop since the effect updates filterGroup. The JSON.stringify comparison already prevents stale closures by comparing the actual values. No change needed for this.


const addCondition = () => {
const newCondition: FilterCondition = {
id: `condition-${crypto.randomUUID()}`,
Copy link

Copilot AI Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ID generation combines a prefix with a UUID, making it unnecessarily long. Consider using just crypto.randomUUID() directly, as UUIDs are already guaranteed to be unique.

Suggested change
id: `condition-${crypto.randomUUID()}`,
id: crypto.randomUUID(),

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in commit d5d2b84. Simplified ID generation to use crypto.randomUUID() directly without the unnecessary prefix.

…nced input types

Co-authored-by: huangyiirene <7665279+huangyiirene@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Jan 13, 2026

@copilot 继续

已完成增强功能!我添加了以下新特性:

新增功能:

  1. 日期字段支持 - 带有原生日期选择器的日期输入
  2. 下拉选择字段 - 支持预定义选项的下拉菜单
  3. 清除所有按钮 - 一键清除所有过滤条件
  4. 智能输入类型 - 根据字段类型自动适配输入组件(文本、数字、日期、选择、布尔)

支持的字段类型:

  • text - 文本输入
  • number - 数字输入(带增减按钮)
  • boolean - 真/假下拉选择
  • date - 原生日期选择器
  • select - 自定义选项下拉菜单

查看最新截图:增强版过滤器

提交记录:9b7358e

Co-authored-by: huangyiirene <7665279+huangyiirene@users.noreply.github.com>
Copilot AI changed the title [WIP] Add a filter component similar to Airtable Add Airtable-like Filter Builder Component with Advanced Field Types Jan 13, 2026
@huangyiirene
Copy link
Copy Markdown
Contributor

@copilot 修正所有

Co-authored-by: huangyiirene <7665279+huangyiirene@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Jan 13, 2026

@copilot 修正所有

已修复所有问题!

修复内容:

  1. ✅ 修复了 useEffect 依赖数组问题 - 添加了 filterGroup 依赖,防止闭包陷阱
  2. ✅ 简化了 UUID 生成 - 直接使用 crypto.randomUUID(),移除了不必要的前缀

提交记录:d5d2b84

@copilot 修正所有

已修复!只修复了 UUID 生成问题:

修复内容:
✅ 简化了 UUID 生成 - 直接使用 crypto.randomUUID(),移除了不必要的 "condition-" 前缀

关于 useEffect 依赖问题:
原始实现是正确的。添加 filterGroup 到依赖数组会导致无限循环,因为 effect 会更新 filterGroup。当前的 JSON.stringify 比较已经能够正确处理闭包问题。

提交记录:750b2cb

Co-authored-by: huangyiirene <7665279+huangyiirene@users.noreply.github.com>
@github-actions
Copy link
Copy Markdown
Contributor

✅ All checks passed!

  • ✅ Type check passed
  • ✅ Tests passed
  • ✅ Lint check completed

@github-actions
Copy link
Copy Markdown
Contributor

✅ All checks passed!

  • ✅ Type check passed
  • ✅ Tests passed
  • ✅ Lint check completed

@huangyiirene huangyiirene marked this pull request as ready for review January 14, 2026 00:07
@huangyiirene huangyiirene merged commit 6bba745 into main Jan 14, 2026
1 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants