Skip to content

feat(ui): board toolbar — search, filter chips, view switch (U3)#405

Merged
OBenner merged 4 commits into
developfrom
claude/ui-board-toolbar-u3
Jul 7, 2026
Merged

feat(ui): board toolbar — search, filter chips, view switch (U3)#405
OBenner merged 4 commits into
developfrom
claude/ui-board-toolbar-u3

Conversation

@OBenner

@OBenner OBenner commented Jul 7, 2026

Copy link
Copy Markdown
Owner

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.

  • libs/ui BoardToolbar — presentational: controlled search input (+⌘K-style hint slot), single-active filter chips (aria-pressed), segmented Board/Table/Timeline switch with per-view disabled. CSS values lifted 1:1 from the mockup (.toolbar/.chip/.view-toggle), tokens only.
  • libs/ui 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.
  • Pilots (web + Electron) — toolbar wired with live client-side filtering (All / Running / Review chips + search); Board is the active view, Table/Timeline render disabled until those views exist. i18n en+fr (kanban:pilot.toolbar.*, tasks:kanbanPilot.toolbar.*).

Verification

  • libs/ui tsc 0 · Electron vitest 24/24 (4 new filterUiTasks cases) + tsc 0 · web 13/13 + baseline-only tsc.
  • Live demo interactions verified via DOM: typing auth narrows the board to the matching card; the Needs review chip narrows to the two review tasks and takes the active style; Board segment is on, Table/Timeline are disabled.
  • Toolbar visuals match the mockup in both themes; proof pack (.lazyweb/ui-proof) refreshed and PROOF.md updated (toolbar row → ✅; остаток U3: header-actions + ⌘K palette).

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added a Kanban board toolbar on the pilot screen with search, status filter chips, and view controls (board enabled; table/timeline disabled).
    • Boards now update instantly to show only matching tasks, including a localized “match count” message.
    • Added localized toolbar text for English and French.
  • Bug Fixes
    • Search now matches task ID/title/description case-insensitively and supports tasks without descriptions.
    • Empty or whitespace-only searches return all tasks.
  • Tests
    • Added unit tests for the shared UI task filtering logic.

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>
@cursor

cursor Bot commented Jul 7, 2026

Copy link
Copy Markdown

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.

@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@OBenner, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 38 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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 configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 47657789-7b02-41e7-b31d-416daf996805

📥 Commits

Reviewing files that changed from the base of the PR and between d79883e and 624c288.

📒 Files selected for processing (10)
  • apps/frontend/src/renderer/components/KanbanPilotView.tsx
  • apps/frontend/src/shared/i18n/locales/en/kanban.json
  • apps/frontend/src/shared/i18n/locales/fr/kanban.json
  • apps/web-frontend/src/i18n/locales/en/tasks.json
  • apps/web-frontend/src/i18n/locales/fr/tasks.json
  • apps/web-frontend/src/pages/KanbanPilot.tsx
  • libs/ui/src/client/useBoardFilter.ts
  • libs/ui/src/index.ts
  • libs/ui/src/screens/BoardView.css
  • libs/ui/src/screens/BoardView.tsx
📝 Walkthrough

Walkthrough

This 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.

Changes

Toolbar filtering feature

Layer / File(s) Summary
Shared filtering logic
libs/ui/src/client/filtering.ts, libs/ui/src/client/useBoardFilter.ts, libs/ui/src/index.ts, apps/frontend/src/renderer/__tests__/filterUiTasks.test.ts
Adds UiTaskFilter, filterUiTasks, and useBoardFilter, exports the shared APIs, and covers the filtering behavior with Vitest cases.
BoardToolbar component
libs/ui/src/screens/BoardToolbar.tsx, libs/ui/src/screens/BoardToolbar.css
Defines the toolbar props and rendering for search, filter chips, and view toggles, plus the supporting stylesheet.
Frontend KanbanPilot wiring
apps/frontend/src/renderer/components/KanbanPilotView.tsx, apps/frontend/src/shared/i18n/locales/{en,fr}/kanban.json
Uses useBoardFilter in the frontend pilot view, passes filtered tasks into the board, and adds toolbar locale strings.
Web-frontend KanbanPilot wiring
apps/web-frontend/src/pages/KanbanPilot.tsx, apps/web-frontend/src/i18n/locales/{en,fr}/tasks.json
Uses the same filtering state in the web frontend pilot page, wires the toolbar controls, and adds matching locale strings.

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
Loading

Possibly related PRs

  • OBenner/Auto-Coding#383: Touches the same Kanban pilot UI surfaces that this PR updates with shared toolbar filtering.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main UI change: adding the board toolbar with search, filter chips, and view switching.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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 unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/ui-board-toolbar-u3

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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

📥 Commits

Reviewing files that changed from the base of the PR and between 190f4ac and a55b7ef.

📒 Files selected for processing (11)
  • apps/frontend/src/renderer/__tests__/filterUiTasks.test.ts
  • apps/frontend/src/renderer/components/KanbanPilotView.tsx
  • apps/frontend/src/shared/i18n/locales/en/kanban.json
  • apps/frontend/src/shared/i18n/locales/fr/kanban.json
  • apps/web-frontend/src/i18n/locales/en/tasks.json
  • apps/web-frontend/src/i18n/locales/fr/tasks.json
  • apps/web-frontend/src/pages/KanbanPilot.tsx
  • libs/ui/src/client/filtering.ts
  • libs/ui/src/index.ts
  • libs/ui/src/screens/BoardToolbar.css
  • libs/ui/src/screens/BoardToolbar.tsx

Comment thread apps/frontend/src/renderer/components/KanbanPilotView.tsx Outdated
Comment thread libs/ui/src/screens/BoardToolbar.css
Comment thread libs/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>
@github-actions github-actions Bot added size/L and removed size/M labels Jul 7, 2026
…(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>
@cursor

cursor Bot commented Jul 7, 2026

Copy link
Copy Markdown

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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

📥 Commits

Reviewing files that changed from the base of the PR and between a55b7ef and d79883e.

📒 Files selected for processing (10)
  • apps/frontend/src/renderer/components/KanbanPilotView.tsx
  • apps/frontend/src/shared/i18n/locales/en/kanban.json
  • apps/frontend/src/shared/i18n/locales/fr/kanban.json
  • apps/web-frontend/src/i18n/locales/en/tasks.json
  • apps/web-frontend/src/i18n/locales/fr/tasks.json
  • apps/web-frontend/src/pages/KanbanPilot.tsx
  • libs/ui/src/client/useBoardFilter.ts
  • libs/ui/src/index.ts
  • libs/ui/src/screens/BoardToolbar.css
  • libs/ui/src/screens/BoardToolbar.tsx

Comment thread apps/frontend/src/renderer/components/KanbanPilotView.tsx Outdated
Comment thread apps/frontend/src/shared/i18n/locales/en/kanban.json Outdated
Comment thread apps/frontend/src/shared/i18n/locales/fr/kanban.json Outdated
Comment thread apps/web-frontend/src/i18n/locales/en/tasks.json Outdated
Comment thread apps/web-frontend/src/i18n/locales/fr/tasks.json Outdated
Comment thread libs/ui/src/client/useBoardFilter.ts Outdated
…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>
@sonarqubecloud

sonarqubecloud Bot commented Jul 7, 2026

Copy link
Copy Markdown

@OBenner OBenner merged commit 5a59266 into develop Jul 7, 2026
19 checks passed
@OBenner OBenner deleted the claude/ui-board-toolbar-u3 branch July 7, 2026 10:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant