feat(ui): board toolbar — search, filter chips, view switch (U3)#405
Conversation
Mockup's toolbar row on the shared design system, functional from day
one in both pilots:
- libs/ui: presentational BoardToolbar (controlled search input with
shortcut hint, single-active filter chips with aria-pressed,
segmented Board/Table/Timeline switch with per-view disabled) — CSS
values taken from desktop-kanban-board-v2 (.toolbar/.chip/.view-toggle)
- libs/ui: pure filterUiTasks({query, status}) — case-insensitive match
over id/title/description + status narrowing, shared by both pilots
- pilots (web + Electron): live client-side filtering wired to the
toolbar; Board active, Table/Timeline rendered disabled until those
views exist; i18n en/fr (kanban:pilot.toolbar.*, tasks:kanbanPilot.toolbar.*)
Verified: libs/ui tsc 0, Electron 24/24 vitest + tsc 0, web 13/13 +
baseline-only tsc; live demo — search narrows to matching card, chip
narrows to Review columns, active states and disabled views confirmed
via DOM; toolbar visuals match the mockup (proof pack refreshed).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Oleg Miagkov <mrobenner@gmail.com>
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
|
Warning Review limit reached
Next review available in: 38 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (10)
📝 WalkthroughWalkthroughThis PR adds shared task filtering and a reusable board toolbar, then wires both into the Kanban pilot pages in the frontend and web frontend. It also adds matching English/French locale strings and tests for the filtering behavior. ChangesToolbar filtering feature
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant User
participant BoardToolbar
participant PilotBoard
participant useBoardFilter
participant filterUiTasks
User->>BoardToolbar: type search / select filter
BoardToolbar->>PilotBoard: onSearchChange / onSelectFilter
PilotBoard->>useBoardFilter: query and filterId state update
useBoardFilter->>filterUiTasks: filterUiTasks(tasks, { query, status })
filterUiTasks-->>useBoardFilter: visibleTasks
useBoardFilter-->>PilotBoard: visibleTasks and filtering state
PilotBoard-->>User: filtered Kanban board
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 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 `@apps/frontend/src/renderer/components/KanbanPilotView.tsx`:
- Around line 39-78: The `PilotBoard` toolbar state and wiring are duplicated in
this component and `KanbanPilot` in the web app, so extract the shared
filter/search logic into a reusable hook such as `useBoardFilterState` instead
of keeping separate `FILTER_STATUS`, `query`/`filterId` state, `visibleTasks`
memo, and `BoardToolbar` prop setup in both places. Reuse `filterUiTasks` and
`BoardToolbar` from `libs/ui` through that hook so both `PilotBoard` and the web
page stay in sync as filters and views evolve.
In `@libs/ui/src/screens/BoardToolbar.css`:
- Around line 24-33: The `.ac-toolbar__search input` rule removes the default
focus outline without providing any replacement, so add a visible focus
indicator for keyboard users by styling the input’s focus state, ideally with a
`:focus-visible` rule in `BoardToolbar.css` using `outline`, `box-shadow`, or a
similar accessible indicator while keeping the existing base styles in place.
In `@libs/ui/src/screens/BoardToolbar.tsx`:
- Around line 55-68: The search input in BoardToolbar can render without an
accessible name when onSearchChange is set but searchPlaceholder is missing.
Update the BoardToolbar search field so its accessible name does not depend only
on searchPlaceholder—either require a non-empty label source, add a separate
explicit label prop, or guard rendering/accessibility attributes in the input
block to ensure the search control always has an accessible name.
🪄 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: ASSERTIVE
Plan: Pro
Run ID: 074ce76f-f5f5-4ce4-ac58-12e99e887b6e
📒 Files selected for processing (11)
apps/frontend/src/renderer/__tests__/filterUiTasks.test.tsapps/frontend/src/renderer/components/KanbanPilotView.tsxapps/frontend/src/shared/i18n/locales/en/kanban.jsonapps/frontend/src/shared/i18n/locales/fr/kanban.jsonapps/web-frontend/src/i18n/locales/en/tasks.jsonapps/web-frontend/src/i18n/locales/fr/tasks.jsonapps/web-frontend/src/pages/KanbanPilot.tsxlibs/ui/src/client/filtering.tslibs/ui/src/index.tslibs/ui/src/screens/BoardToolbar.csslibs/ui/src/screens/BoardToolbar.tsx
Adversarial review (2 lenses, 8 confirmed findings) + CodeRabbit (3): - focus visibility (WCAG 2.4.7): search wrapper gets a :focus-within ring; view buttons get an inset :focus-visible ring (the container's overflow: hidden clips outside-painted outlines) - group semantics: filters/views wrapped in role=group with injectable aria-labels (i18n en/fr); disabled view buttons no longer expose aria-pressed - accessible name: new searchLabel prop, aria-label falls back to the placeholder - narrowing feedback (WCAG 4.1.3): always-mounted <output> status line in both pilots — 'N matching tasks' / no-matches message, i18n plurals en/fr - BoardToolbar props wrapped in Readonly<> (Sonar S6759); view buttons get the BEM base class ac-toolbar__view with flattened CSS selectors - useBoardFilter hook in libs/ui replaces the duplicated state/FILTER_STATUS/memo wiring in both pilots (CodeRabbit) - web pilot imports reordered per biome organizeImports Verified: libs/ui tsc 0; Electron biome clean, tsc 0, 294 renderer tests green; web biome clean, 13/13, baseline-only tsc; focus ring, group roles, and aria-pressed omission confirmed live in the demo. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: Oleg Miagkov <mrobenner@gmail.com>
…(U3) - S6819: the chip/view groups are now semantic <fieldset>s (UA chrome reset in CSS) instead of divs with role=group - S3358 x2: the narrowing status message is computed in an if + single ternary instead of a nested ternary in JSX - new_duplicated_lines_density 3.5%>3%: the near-identical filter/view prop blocks in both pilots collapse into FILTER_IDS/VIEW_IDS maps with template i18n keys Verified: libs/ui tsc 0; biome clean both apps; Electron tsc 0 + 294 renderer tests; fieldset resets confirmed live (layout unchanged). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: Oleg Miagkov <mrobenner@gmail.com>
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
There was a problem hiding this comment.
Actionable comments posted: 6
🤖 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 `@apps/frontend/src/renderer/components/KanbanPilotView.tsx`:
- Around line 39-41: The FILTER_IDS and VIEW_IDS tuples in KanbanPilotView are
duplicated in the web pilot, so centralize them with the shared board-filter
logic instead of keeping separate copies. Export these id lists from the same
module as useBoardFilter (or from useBoardFilter.ts) and update both
KanbanPilotView and KanbanPilot to import the shared constants so the pilot
views stay in sync.
In `@apps/frontend/src/shared/i18n/locales/en/kanban.json`:
- Around line 55-59: The viewsLabel text is labeling the entire view-switching
group in BoardToolbar, but it currently names only one option. Update the i18n
value used by BoardToolbar’s aria-label so it describes the full
Board/Table/Timeline switcher, not just the Board view, and keep the wording
generic enough to cover all available view buttons.
In `@apps/frontend/src/shared/i18n/locales/fr/kanban.json`:
- Around line 55-59: The toolbar.viewsLabel string is too specific for the
Board/Table/Timeline switch fieldset and should be changed to a generic
accessible group name that describes the view selector rather than only the
Board view. Update the French locale entry in kanban.json so the label matches
the other switch options and is consistent with the component that renders the
board/table/timeline view toggle.
In `@apps/web-frontend/src/i18n/locales/en/tasks.json`:
- Around line 129-133: The toolbar locale entry for viewsLabel is mislabeling
the fieldset’s accessible name as a single option instead of the switcher
container. Update the tasks.json translation under the toolbar object so the
label describes the Board/Table/Timeline view switcher itself, and keep the
change aligned with the existing searchLabel and filtersLabel entries.
In `@apps/web-frontend/src/i18n/locales/fr/tasks.json`:
- Around line 129-133: The toolbar `viewsLabel` string in the locale file is
misnamed for the Board/Table/Timeline view switcher and should describe the
whole grouped control, not just the Board option. Update the `viewsLabel` entry
in the `toolbar` block to a generic accessible group label that matches the
sibling locale files and applies to all view choices.
In `@libs/ui/src/client/useBoardFilter.ts`:
- Around line 6-10: The filter identifiers are currently too loosely typed, so
typos can slip through and default to the “all” behavior. Introduce a shared
literal union type such as FilterId for the valid ids used by useBoardFilter and
BoardToolbarFilter.id, and replace the generic string typing in FILTER_STATUS,
filterId, and setFilterId with that union. Update the relevant board filter
logic so only known ids are accepted and any invalid id is caught at compile
time.
🪄 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: ASSERTIVE
Plan: Pro
Run ID: 0a5b37a1-cbd3-4462-9dce-4936ea4f9f48
📒 Files selected for processing (10)
apps/frontend/src/renderer/components/KanbanPilotView.tsxapps/frontend/src/shared/i18n/locales/en/kanban.jsonapps/frontend/src/shared/i18n/locales/fr/kanban.jsonapps/web-frontend/src/i18n/locales/en/tasks.jsonapps/web-frontend/src/i18n/locales/fr/tasks.jsonapps/web-frontend/src/pages/KanbanPilot.tsxlibs/ui/src/client/useBoardFilter.tslibs/ui/src/index.tslibs/ui/src/screens/BoardToolbar.csslibs/ui/src/screens/BoardToolbar.tsx
…review)
The two pilots had drifted into near-identical toolbar+status+board JSX,
pushing Sonar new_duplicated_lines_density to 9.5% (>3% gate).
- libs/ui: new BoardView composes useBoardFilter + BoardToolbar + the
match-count <output> + KanbanBoard; buildBoardViewLabels(t, prefix)
maps an app's i18n into BoardViewLabels via a generic Translate
signature (libs/ui stays framework-agnostic)
- both pilots collapse to <BoardView tasks labels columns onSelectTask>;
loading/error stays with the caller. FILTER_IDS/VIEW_IDS + the status
computation now live once in libs/ui (CodeRabbit: shared id lists)
- useBoardFilter: FilterId union ('all'|'running'|'review') + exported
FILTER_IDS; filterId/setFilterId typed to it (CodeRabbit)
- i18n: viewsLabel 'Board view' -> 'Select view' / 'Sélectionner la vue'
in all 4 locales — it names the Board/Table/Timeline switcher, not one
option (CodeRabbit)
Verified: libs/ui tsc 0; Electron tsc 0 + 24 tests; web biome clean,
13/13, baseline-only tsc; BoardView search/filter/no-match + Select-view
aria-label confirmed live in the demo (layout unchanged).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Oleg Miagkov <mrobenner@gmail.com>
|



What
First U3 (chrome) slice: the mockup's toolbar row (
desktop-kanban-board-v2) on the shared design system — and it's functional, not decorative, in both pilots.BoardToolbar— presentational: controlled search input (+⌘K-style hint slot), single-active filter chips (aria-pressed), segmented Board/Table/Timeline switch with per-viewdisabled. CSS values lifted 1:1 from the mockup (.toolbar/.chip/.view-toggle), tokens only.filterUiTasks({query, status})— pure, transport-agnostic: case-insensitive match over id/title/description + status narrowing. Shared by both pilots so the search box and chips actually filter the board.kanban:pilot.toolbar.*,tasks:kanbanPilot.toolbar.*).Verification
libs/uitsc 0 · Electron vitest 24/24 (4 newfilterUiTaskscases) + tsc 0 · web 13/13 + baseline-only tsc.authnarrows the board to the matching card; the Needs review chip narrows to the two review tasks and takes the active style; Board segment ison, Table/Timeline aredisabled..lazyweb/ui-proof) refreshed and PROOF.md updated (toolbar row → ✅; остаток U3: header-actions + ⌘K palette).🤖 Generated with Claude Code
Summary by CodeRabbit