Skip to content

Fix/463 table design review - #527

Open
mart-sessman wants to merge 4 commits into
rcfrom
fix/463-table-design-review
Open

Fix/463 table design review#527
mart-sessman wants to merge 4 commits into
rcfrom
fix/463-table-design-review

Conversation

@mart-sessman

@mart-sessman mart-sessman commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features

    • Table control columns can be ordered around data columns using a new ordering option.
    • Column filters can switch to a modal on smaller screens, with configurable fullscreen behavior.
    • Pagination supports horizontal alignment (“between/left/right”) with responsive overrides.
  • Bug Fixes

    • Improved table control-column sizing and expand control layout to avoid cramped icon/label presentation.
    • Refined responsive table/pagination behavior for cleaner sizing and overflow handling.
  • Documentation

    • Updated table and pagination docs, examples, and Storybook content, including localized labels and enhanced date-range editing/filtering.

* controls can be now added to end of table (collapse as last col e.g.)
@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 72dead27-7f7b-40e3-a06b-d75eb1204a12

📥 Commits

Reviewing files that changed from the base of the PR and between c637f3e and dc59a74.

📒 Files selected for processing (10)
  • skills/tedi-angular/references/components.md
  • tedi/components/content/table/table.component.html
  • tedi/components/content/table/table.component.spec.ts
  • tedi/components/content/table/table.component.ts
  • tedi/components/navigation/pagination/pagination.component.html
  • tedi/components/navigation/pagination/pagination.component.scss
  • tedi/components/navigation/pagination/pagination.component.spec.ts
  • tedi/components/navigation/pagination/pagination.component.ts
  • tedi/components/navigation/pagination/pagination.stories.ts
  • tedi/components/navigation/pagination/pagination.types.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • skills/tedi-angular/references/components.md
  • tedi/components/content/table/table.component.spec.ts

📝 Walkthrough

Walkthrough

This PR adds table control-column ordering with a "content" sentinel, breakpoint-driven filter modals, date-range demo rendering, responsive pagination alignment and inputs, model-based pagination updates, and related Storybook and documentation changes.

Changes

Table Features and Demos

Layer / File(s) Summary
Table contracts and filter modal foundation
tedi/components/content/table/table.types.ts, tedi/components/content/table/table-filter-modal/*, tedi/components/content/table/table-demo-data.ts, tedi/components/content/table/table-demo.constants.ts
Adds table ordering and modal data contracts, the filter modal component, DateRange booking data, formatting helpers, specialized edit templates, and raw draft accessors.
Table control columns and filter modal behavior
tedi/components/content/table/table.component.*, tedi/components/content/table/table.component.spec.ts
Implements sentinel-based control placement, control-cell classes, breakpoint-based modal filtering, shared filter context handling, pagination wiring, and coverage for the new behavior.
Table demos and documentation
tedi/components/content/table/table.stories.ts, skills/tedi-angular/references/components.md
Updates date filtering, modal and control-ordering examples, sizing, translations, accessibility markup, and public input documentation.

Responsive Pagination

Layer / File(s) Summary
Pagination API and responsive resolution
tedi/components/navigation/pagination/pagination.types.ts, pagination.component.ts, pagination.component.html
Adds alignment and breakpoint inputs, resolves responsive settings, removes explicit change outputs, and updates navigation bindings.
Pagination responsive layout
tedi/components/navigation/pagination/pagination.component.scss
Reworks pagination slots and navigation for responsive flex/grid behavior and widens the page-size select.
Pagination validation and examples
tedi/components/navigation/pagination/pagination.component.spec.ts, pagination.stories.ts
Updates model-based tests and adds alignment, breakpoint, responsive-story, and localized examples.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant TediTableComponent
  participant BreakpointService
  participant ModalService
  participant TableFilterModalComponent
  User->>TediTableComponent: select column filter
  TediTableComponent->>BreakpointService: read current breakpoint
  TediTableComponent->>ModalService: open TableFilterModalComponent
  ModalService->>TableFilterModalComponent: provide filter data
  User->>TableFilterModalComponent: apply or clear filter
  TableFilterModalComponent->>TediTableComponent: build filter context
  TableFilterModalComponent->>ModalService: close modal
Loading

Possibly related PRs

Suggested reviewers: ly-tempel-bitweb, airikej

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is related to the table-focused changes, though it is broad and less specific than ideal.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/463-table-design-review

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 Stylelint (17.14.0)
tedi/components/navigation/pagination/pagination.component.scss

Error: Cannot resolve module "/node_modules/stylelint-scss/src/index.js". Check that module "/node_modules/stylelint-scss/src/index.js" is available and spelled correctly
at file:///usr/local/lib/node_modules/stylelint/lib/utils/dynamicImport.mjs:21:10
at async addPluginFunctions (file:///usr/local/lib/node_modules/stylelint/lib/augmentConfig.mjs:404:19)
at async augmentConfigFull (file:///usr/local/lib/node_modules/stylelint/lib/augmentConfig.mjs:148:20)
at async getConfigForFile (file:///usr/local/lib/node_modules/stylelint/lib/getConfigForFile.mjs:102:26)
at async resolveOptionValue (file:///usr/local/lib/node_modules/stylelint/lib/utils/resolveOptionValue.mjs:27:24)
at async standalone (file:///usr/local/lib/node_modules/stylelint/lib/standalone.mjs:127:22)


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Jul 7, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 70.47619% with 31 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...i/components/content/table/table-demo.constants.ts 0.00% 14 Missing ⚠️
tedi/components/content/table/table-demo-data.ts 0.00% 12 Missing and 1 partial ⚠️
tedi/components/content/table/table.component.ts 91.83% 4 Missing ⚠️

📢 Thoughts on this report? Let us know!

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
tedi/components/content/table/table.stories.ts (1)

714-720: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract a shared dateRange column factory to avoid repeating the same object 7 times.

The { id: "dateRange", header: "Kuupäev", accessorKey: "dateRange", minSize: 210, cell: bookingDateRangeCell } block (plus its sortingFn variant at Lines 998-1004) is duplicated across 7 stories. A shared helper co-located with bookingDateRangeCell in table-demo-data.ts would reduce drift risk if the column definition ever needs to change.

♻️ Proposed factory (in table-demo-data.ts)
+export function bookingDateRangeColumn(
+  overrides: Partial<TediColumnDef<Booking>> = {},
+): TediColumnDef<Booking> {
+  return {
+    id: "dateRange",
+    header: "Kuupäev",
+    accessorKey: "dateRange",
+    minSize: 210,
+    cell: bookingDateRangeCell,
+    ...overrides,
+  } as TediColumnDef<Booking>;
+}

Then in table.stories.ts:

-    {
-      id: "dateRange",
-      header: "Kuupäev",
-      accessorKey: "dateRange",
-      minSize: 210,
-      cell: bookingDateRangeCell,
-    } as TediColumnDef<Booking>,
+    bookingDateRangeColumn(),

And for the MergedCells variant (Lines 998-1004):

-      minSize: 210,
-      sortable: true,
-      sortingFn: (a, b) =>
-        (a.original.dateRange.from?.getTime() ?? 0) -
-        (b.original.dateRange.from?.getTime() ?? 0),
-      cell: bookingDateRangeCell,
-    } as TediColumnDef<Booking>,
+    bookingDateRangeColumn({
+      sortable: true,
+      sortingFn: (a, b) =>
+        (a.original.dateRange.from?.getTime() ?? 0) -
+        (b.original.dateRange.from?.getTime() ?? 0),
+    }),

Also applies to: 798-804, 896-902, 998-1004, 4285-4291, 4358-4364, 4421-4427

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tedi/components/content/table/table.stories.ts` around lines 714 - 720, The
dateRange column definition is duplicated across multiple table stories,
including the bookingDateRangeCell and sortingFn variant, which creates drift
risk. Extract a shared dateRange column factory alongside bookingDateRangeCell
in table-demo-data.ts, then replace each repeated TediColumnDef<Booking> object
in table.stories.ts with calls to that helper; keep the MergedCells sorting
variant supported by the same factory so all 7 usages stay consistent.
tedi/components/content/table/table.component.spec.ts (1)

1707-1714: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider also asserting the fullscreen modal option.

The test checks data.columnLabel but not the fullscreen field passed to modalService.open(...), which is also new behavior (filterModalFullscreen). A quick assertion would close a small coverage gap for this PR's feature surface.

✅ Suggested addition
     expect(modalOpen).toHaveBeenCalledTimes(1);
     expect(modalOpen.mock.calls[0][0]).toBe(TableFilterModalComponent);
     expect(modalOpen.mock.calls[0][1].data.columnLabel).toBe("Name");
+    expect(modalOpen.mock.calls[0][1].fullscreen).toBe(false);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tedi/components/content/table/table.component.spec.ts` around lines 1707 -
1714, The filter modal test in TableComponentSpec only verifies the modal data
payload and is missing coverage for the new fullscreen behavior. Update the spec
around the modalService.open call in the “opens the filter in a modal below the
breakpoint” case to also assert the passed fullscreen option reflects the new
filterModalFullscreen behavior, alongside the existing TableFilterModalComponent
and columnLabel checks.
tedi/components/content/table/table.component.ts (1)

2231-2266: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider routing the popover's Apply/Clear buttons through the shared context builder.

buildFilterContext's apply/clear closures now duplicate the logic already in handleFilterApply/handleFilterClear (lines 2305-2321): both do setFilterValue(draft()) + close, or draft.set(undefined) + setFilterValue(undefined) + close. The popover footer buttons in table.component.html still call the older handleFilterApply/handleFilterClear methods directly instead of filterContextFor(...).apply()/.clear(). Two parallel implementations of the same commit/close behavior risk drifting apart on future changes (e.g. adding validation before commit).

♻️ Proposed consolidation
-              <button
-                tedi-button
-                variant="secondary"
-                size="small"
-                type="button"
-                (click)="
-                  handleFilterClear(
-                    header.column,
-                    filterPopover
-                  )
-                "
-              >
+              <button
+                tedi-button
+                variant="secondary"
+                size="small"
+                type="button"
+                (click)="filterContextFor(header.column, filterPopover).clear()"
+              >
                 {{ filterClearLabel() }}
               </button>
-              <button
-                tedi-button
-                variant="primary"
-                size="small"
-                type="button"
-                (click)="
-                  handleFilterApply(
-                    header.column,
-                    filterPopover
-                  )
-                "
-              >
+              <button
+                tedi-button
+                variant="primary"
+                size="small"
+                type="button"
+                (click)="filterContextFor(header.column, filterPopover).apply()"
+              >
                 {{ filterApplyLabel() }}
               </button>

Then handleFilterApply/handleFilterClear can be removed from table.component.ts.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tedi/components/content/table/table.component.ts` around lines 2231 - 2266,
The popover Apply/Clear actions are still wired to the legacy
`handleFilterApply`/`handleFilterClear` methods instead of the shared
`buildFilterContext` flow, which duplicates commit/close behavior. Update the
popover footer in `table.component.html` to call `filterContextFor(...).apply()`
and `.clear()` through the context returned by `buildFilterContext`, so both
popover and modal use the same logic. Once that is wired through
`filterContextFor`/`buildFilterContext`, the redundant `handleFilterApply` and
`handleFilterClear` methods in `table.component.ts` can be removed.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tedi/components/content/table/table-demo.constants.ts`:
- Around line 118-125: The tedi-date-field binding in the table demo does not
accept cleared null values, but DateFieldComponent can emit null through its CVA
when the range is cleared. Update the draft update flow around
editor.setDraftValueRaw and editor.draftValueRaw so the dateRange path accepts
T[K] | null, or coerce the emitted value before passing it through, keeping the
tedi-date-field integration compatible with nullable clears.

---

Nitpick comments:
In `@tedi/components/content/table/table.component.spec.ts`:
- Around line 1707-1714: The filter modal test in TableComponentSpec only
verifies the modal data payload and is missing coverage for the new fullscreen
behavior. Update the spec around the modalService.open call in the “opens the
filter in a modal below the breakpoint” case to also assert the passed
fullscreen option reflects the new filterModalFullscreen behavior, alongside the
existing TableFilterModalComponent and columnLabel checks.

In `@tedi/components/content/table/table.component.ts`:
- Around line 2231-2266: The popover Apply/Clear actions are still wired to the
legacy `handleFilterApply`/`handleFilterClear` methods instead of the shared
`buildFilterContext` flow, which duplicates commit/close behavior. Update the
popover footer in `table.component.html` to call `filterContextFor(...).apply()`
and `.clear()` through the context returned by `buildFilterContext`, so both
popover and modal use the same logic. Once that is wired through
`filterContextFor`/`buildFilterContext`, the redundant `handleFilterApply` and
`handleFilterClear` methods in `table.component.ts` can be removed.

In `@tedi/components/content/table/table.stories.ts`:
- Around line 714-720: The dateRange column definition is duplicated across
multiple table stories, including the bookingDateRangeCell and sortingFn
variant, which creates drift risk. Extract a shared dateRange column factory
alongside bookingDateRangeCell in table-demo-data.ts, then replace each repeated
TediColumnDef<Booking> object in table.stories.ts with calls to that helper;
keep the MergedCells sorting variant supported by the same factory so all 7
usages stay consistent.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ac4c6b92-5403-47e6-99f6-de6af30a9d99

📥 Commits

Reviewing files that changed from the base of the PR and between 75cdd8a and c637f3e.

📒 Files selected for processing (12)
  • skills/tedi-angular/references/components.md
  • tedi/components/content/table/table-demo-data.ts
  • tedi/components/content/table/table-demo.constants.ts
  • tedi/components/content/table/table-filter-modal/table-filter-modal.component.html
  • tedi/components/content/table/table-filter-modal/table-filter-modal.component.ts
  • tedi/components/content/table/table.component.html
  • tedi/components/content/table/table.component.scss
  • tedi/components/content/table/table.component.spec.ts
  • tedi/components/content/table/table.component.ts
  • tedi/components/content/table/table.stories.ts
  • tedi/components/content/table/table.types.ts
  • tedi/components/navigation/pagination/pagination.component.scss

Comment on lines +118 to +125
<tedi-date-field
[inputId]="'dateRange-' + ctx.row.original.id"
size="small"
mode="range"
placeholder="pp.kk.aaaa – pp.kk.aaaa"
[ngModel]="editor.draftValueRaw(ctx.row.original.id, 'dateRange')"
(ngModelChange)="editor.setDraftValueRaw(ctx.row.original.id, 'dateRange', $event)"
/>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Inspect DateFieldComponent's value/CVA type to confirm ngModelChange emission type.
fd -e ts date-field.component --exec cat -n {}

Repository: TEDI-Design-System/angular

Length of output: 50382


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate the table demo constants and the date field component/type definitions.
git ls-files 'tedi/components/content/table/table-demo.constants.ts' \
             'tedi/components/**/*.ts' | rg 'date-field\.component|calendar/types|table-demo\.constants|date-field'

echo '--- table-demo.constants.ts (relevant region) ---'
sed -n '200,260p' tedi/components/content/table/table-demo.constants.ts

echo '--- date-field.component.ts ---'
sed -n '1,260p' tedi/components/form/date-field/date-field.component.ts

echo '--- date type definitions ---'
sed -n '1,220p' tedi/components/content/calendar/types.ts

Repository: TEDI-Design-System/angular

Length of output: 13072


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the editable table story's row type and the date-range column binding.
rg -n -C 4 'EditableValues|dateRange|setDraftValueRaw|draftValueRaw|tedi-date-field' \
  tedi/components/content/table/table.stories.ts \
  tedi/components/content/table/table-demo.constants.ts

Repository: TEDI-Design-System/angular

Length of output: 21158


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Check the Booking row type and whether dateRange is nullable.
rg -n -C 3 'type Booking|interface Booking|dateRange:' tedi/components/content/table/table.stories.ts

Repository: TEDI-Design-System/angular

Length of output: 164


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Find the Booking type and its dateRange field.
rg -n -C 4 'interface Booking|type Booking|dateRange' tedi/components/content/table

Repository: TEDI-Design-System/angular

Length of output: 16338


Allow nullable clears from tedi-date-field here. DateFieldComponent’s CVA value includes null, so clearing a range can emit null, but setDraftValueRaw(..., value: T[K]) only accepts DateRange. Widen the setter to T[K] | null or coerce before forwarding.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tedi/components/content/table/table-demo.constants.ts` around lines 118 -
125, The tedi-date-field binding in the table demo does not accept cleared null
values, but DateFieldComponent can emit null through its CVA when the range is
cleared. Update the draft update flow around editor.setDraftValueRaw and
editor.draftValueRaw so the dateRange path accepts T[K] | null, or coerce the
emitted value before passing it through, keeping the tedi-date-field integration
compatible with nullable clears.

* added align input
* flexbox instead of grid
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.

1 participant