Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
88991ae
feat(data-table): redesign Filters — menu-driven add flow + segmented…
itsprade Jul 15, 2026
427706a
feat(data-table): add experimental 3-column panel add-filter variant (B)
itsprade Jul 15, 2026
83767de
refactor(data-table): panel variant — Apply button, fixed height, pin…
itsprade Jul 15, 2026
0a7c35e
fix(data-table): panel date editor uses segmented DateField (no popov…
itsprade Jul 15, 2026
93fa43b
style(data-table): match filter chip surface to the outline Add-filte…
itsprade Jul 20, 2026
c8c252a
refactor(data-table): ship panel filter as the only variant; remove v…
itsprade Jul 20, 2026
2f7f617
fix(data-table): address Copilot review on the filter panel
itsprade Jul 20, 2026
d8b5e37
feat(data-table): filter panel polish — clear actions, inline range e…
itsprade Jul 21, 2026
bd1f37e
feat(data-table): datetime picker (date + time box), full-type demo, …
itsprade Jul 21, 2026
3417329
feat(data-table): single-datetime panel editor uses inline calendar +…
itsprade Jul 21, 2026
ee633bd
feat(data-table): date/datetime "between" uses inline calendar with F…
itsprade Jul 21, 2026
c2f520e
fix(data-table): taller filter panel so the datetime range time picke…
itsprade Jul 21, 2026
431a416
fix(data-table): trim filter panel height (h-[32rem] → h-[28rem])
itsprade Jul 21, 2026
74b1dc3
fix(data-table): filter panel always reopens on the first field
itsprade Jul 22, 2026
f0c5c41
fix(data-table): distinct hover vs selection in panel; demo preset tabs
itsprade Jul 22, 2026
06c2006
demo(data-table): stack preset tabs above the filter chips row
itsprade Jul 22, 2026
9e81fdb
feat(data-table): add `slot` prop to DataTable.Filters for split tool…
itsprade Jul 22, 2026
d083e46
demo(data-table): add Add-filter placement examples (far-left, after-…
itsprade Jul 22, 2026
7e2197f
feat(data-table): add `addIconOnly` prop for an icon-only Add filter …
itsprade Jul 22, 2026
3b04d74
demo(data-table): consolidate to the icon-only Add filter layout
itsprade Jul 22, 2026
17fca4f
fix(data-table): keep slot="add" trigger at natural width in a column…
itsprade Jul 22, 2026
30242b9
docs(data-table): TODO to swap temporal filter stopgaps for real pickers
itsprade Jul 22, 2026
2878abf
Merge remote-tracking branch 'origin/main' into feat/data-table-filte…
itsprade Jul 23, 2026
34a1a3c
chore(data-table): address review — untrack .claude/launch.json, simp…
itsprade Jul 23, 2026
cae9723
Merge remote-tracking branch 'origin/main' into feat/data-table-filte…
itsprade Jul 23, 2026
764ebea
Merge remote-tracking branch 'origin/main' into feat/data-table-filte…
Copilot Jul 24, 2026
a635817
Merge branch 'main' into feat/data-table-filter-panel-variant
IzumiSy Jul 24, 2026
1a93566
Merge branch 'main' into feat/data-table-filter-panel-variant
IzumiSy Jul 24, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .changeset/data-table-filter-redesign.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
"@tailor-platform/app-shell": minor
---

Redesign `DataTable.Filters` for a faster, more direct filtering experience.

- **Add-filter panel**: replaces the old popover + nested selects with a single popover laid out in up to three columns — **field ▸ condition ▸ value**. The condition column appears for fields with more than one operator; single-operator fields (enum, uuid) go straight to the value. Values are drafted and committed with an **Apply**/**Update** button, and the panel stays open so several filters can be added in a row. A per-field **Clear** and a sticky **Clear all filters** are built in.
- **Segmented filter chips**: each active filter renders as `field │ operator │ value │ ✕`. The operator segment opens a searchable dropdown to switch the condition; the value segment opens the type-specific editor. Long values are truncated.
- **Date & time use app-shell's own components**: single date → inline `Calendar`; single datetime → inline calendar + a "Choose time" picker; `date`/`datetime` **between** → one inline calendar with **From / To** tabs; `time` → native time input. (Swaps to the dedicated date-range / datetime pickers 1:1 once those land.)
- Friendlier operator labels (`is`, `is not`, `is between`, `is any of`, …), multi-select enum values summarized as "N items" (localized), an inline error for reversed `between` ranges, and a consistent primary-colored checkbox across every filter surface.
- **New `slot` prop** on `DataTable.Filters` (`"all"` | `"chips"` | `"add"`) to render the chips and the **Add filter** trigger separately for custom toolbar layouts (e.g. trigger in a header row, chips on the row below).
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ dist
*.tsbuildinfo
.DS_Store
.cursor/
.claude/
.pnpm-store
60 changes: 46 additions & 14 deletions docs/components/data-table.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ function JournalsPage() {
| `DataTable.Root` | Context provider. Wraps all other sub-components. Required. |
| `DataTable.Table` | Renders the `<table>` with headers and body. Required. |
| `DataTable.Toolbar` | Container for toolbar content (e.g. filters). Optional. Pass `columnSettings` to render the built-in "Columns" control (show/hide + reorder + pin) at the top-right. See props below. |
| `DataTable.Filters` | Auto-generated filter chips from column filter configs. Requires `control` from `useCollectionVariables`. |
| `DataTable.Filters` | Add-filter panel + active filter chips, auto-generated from column filter configs. Requires `control` from `useCollectionVariables`. |
| `DataTable.Footer` | Footer container for pagination and other footer content. Optional. |
| `DataTable.Pagination` | Pre-built pagination controls with optional row count and selection info. Requires `control` from `useCollectionVariables`. Place inside `DataTable.Footer`. |

Expand All @@ -167,6 +167,31 @@ function JournalsPage() {
| `columnSettings` | `boolean` | `false` | Render the built-in "Columns" control (show/hide + reorder + pin) anchored to the top-right. Persists per-user when `useDataTable` has a `tableId`. |
| `className` | `string` | — | Additional CSS class for the toolbar container. |

### `DataTable.Filters` Props

| Prop | Type | Default | Description |
| ------------- | --------------------------- | ------- | ---------------------------------------------------------------------------------------------- |
| `slot` | `"all" \| "chips" \| "add"` | `"all"` | Which part to render (see below). |
| `addIconOnly` | `boolean` | `false` | Render the **Add filter** trigger as an icon-only button (the label becomes its `aria-label`). |
| `className` | `string` | — | Additional CSS class for the filters container. |

By default `DataTable.Filters` renders the active filter chips plus the **Add filter** trigger together. The `slot` prop lets you split them across a custom toolbar layout:

- `"all"` — chips + the **Add filter** trigger (default).
- `"chips"` — only the active chips (renders nothing when there are none).
- `"add"` — only the **Add filter** trigger.

```tsx
// Add filter in a header row (with tabs, etc.); chips on the row below.
<DataTable.Toolbar>
<div className="flex items-center justify-between">
<MyViewTabs />
<DataTable.Filters slot="add" />
</div>
<DataTable.Filters slot="chips" />
</DataTable.Toolbar>
```

### `DataTable.Pagination` Props

| Prop | Type | Default | Description |
Expand Down Expand Up @@ -506,32 +531,39 @@ When you spread `...infer("field")`, add `accessor` when you want a typed render

## `FilterConfig`

The `filter` property on a column accepts a `FilterConfig` object. When set, the column appears as an option in `DataTable.Filters` and the filter chip renders an input editor appropriate for the type.
The `filter` property on a column accepts a `FilterConfig` object. When set, the column becomes filterable in `DataTable.Filters` — available in the **Add filter** panel, and rendered as a segmented chip once active.

| Property | Type | Description |
| --------- | ---------------- | ------------------------------------------------------------ |
| `field` | `string` | API field name used in the generated query input. |
| `type` | `FilterType` | Filter editor type (see table below). |
| `options` | `SelectOption[]` | Required when `type` is `"enum"`. List of selectable values. |

### Adding and editing filters

`DataTable.Filters` renders active filters as segmented chips followed by an **Add filter** button:

- **Add filter panel** — a single popover laid out in up to three columns: **field ▸ condition ▸ value**. The condition column appears for fields with more than one operator (number, date/time, string); single-operator fields (enum, uuid) go straight to the value. Enter a value and click **Apply**; the panel stays open so several filters can be added in a row.
- **Segmented chip** — each active filter shows `field │ operator │ value │ ✕`. The operator segment opens a searchable dropdown to change the condition; the value segment reopens the type-specific editor; `✕` removes the filter. Multi-select enum values are summarized as "N items" (e.g. "2 statuses").

### Filter Types and Operators

| Type | Input editor | Supported operators |
| ---------- | -------------- | ------------------------------------------------------------------------------------------------------------ |
| `string` | Text | `eq`, `ne`, `contains`, `notContains`, `hasPrefix`, `hasSuffix`, `notHasPrefix`, `notHasSuffix`, `in`, `nin` |
| `number` | Number | `eq`, `ne`, `gt`, `gte`, `lt`, `lte`, **`between`**, `in`, `nin` |
| `datetime` | Datetime-local | `eq`, `ne`, `gt`, `gte`, `lt`, `lte`, **`between`**, `in`, `nin` |
| `date` | **DatePicker** | `eq` (_exact date_), `gte` (_after_), `lte` (_before_), **`between`** |
| `time` | Time | `eq`, `ne`, `gt`, `gte`, `lt`, `lte`, **`between`**, `in`, `nin` |
| `enum` | Dropdown | `eq`, `ne`, `in`, `nin` |
| `boolean` | Toggle | `eq`, `ne` |
| `uuid` | Text | `eq`, `ne`, `in`, `nin` |
| Type | Input editor | Supported operators |
| ---------- | ------------------------- | ------------------------------------------------------------------------------------------------------------ |
| `string` | Text | `eq`, `ne`, `contains`, `notContains`, `hasPrefix`, `hasSuffix`, `notHasPrefix`, `notHasSuffix`, `in`, `nin` |
| `number` | Number | `eq`, `ne`, `gt`, `gte`, `lt`, `lte`, **`between`**, `in`, `nin` |
| `datetime` | Datetime-local | `eq`, `ne`, `gt`, `gte`, `lt`, `lte`, **`between`**, `in`, `nin` |
| `date` | **Calendar / DatePicker** | `eq` (_exact date_), `gte` (_after_), `lte` (_before_), **`between`** |
| `time` | Time | `eq`, `ne`, `gt`, `gte`, `lt`, `lte`, **`between`**, `in`, `nin` |
| `enum` | Dropdown | `eq`, `ne`, `in`, `nin` |
| `boolean` | Toggle | `eq`, `ne` |
| `uuid` | Text | `eq`, `ne`, `in`, `nin` |

When the user selects the `between` operator on a `number`, `datetime`, `date`, or `time` column, the filter chip renders a range input with **min** and **max** bounds.
When the `between` operator is selected on a `number`, `datetime`, `date`, or `time` column, the value editor renders a range input with **min**/**max** (or **From**/**To** for dates) bounds.

### Date Filters

`date` columns use the app-shell [`DatePicker`](./date-picker.md) as the filter input (single value and `between` ranges) and present a friendlier, slimmer operator set:
`date` columns render app-shell date components as the value editor: single-value operators (`eq` / `gte` / `lte`) use an inline `Calendar`, and the `between` range uses two [`DatePicker`](./date-picker.md) **From** / **To** fields. (The range fields are a stopgap — they'll be replaced with a single range calendar once date-range support lands in the date-picker component.) `date` columns also present a friendlier, slimmer operator set:

| Operator | Label | Meaning |
| --------- | ------------ | -------------------------- |
Expand Down
Loading
Loading