Skip to content

ECHOES-1363 Implement Toolbar component#708

Merged
gregaubert merged 1 commit into
mainfrom
greg/filter-toolbar
Jun 19, 2026
Merged

ECHOES-1363 Implement Toolbar component#708
gregaubert merged 1 commit into
mainfrom
greg/filter-toolbar

Conversation

@gregaubert

@gregaubert gregaubert commented Jun 17, 2026

Copy link
Copy Markdown
Member

Summary by Gitar

  • New component:
    • Implemented Toolbar component to support filtering, search, sorting, and dataset controls.
  • Component features:
    • Added support for dynamic filterTags and a configurable "Clear filters" action.
    • Included contextual labels like labelEmptyFilterTags for empty states and labelFilterTags for applied counts.
  • Documentation and testing:
    • Added comprehensive Storybook stories in Toolbar-stories.tsx.
    • Included unit and accessibility tests in Toolbar-test.tsx.
  • Localization:
    • Added i18n keys for toolbar.clear-all and toolbar.filter-tags-count in keys.json.

This will update automatically on new commits.

@netlify

netlify Bot commented Jun 17, 2026

Copy link
Copy Markdown

Deploy Preview for echoes-react ready!

Name Link
🔨 Latest commit b9d25d7
🔍 Latest deploy log https://app.netlify.com/projects/echoes-react/deploys/6a350b2d8214550008c46382
😎 Deploy Preview https://deploy-preview-708--echoes-react.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@hashicorp-vault-sonar-prod

hashicorp-vault-sonar-prod Bot commented Jun 17, 2026

Copy link
Copy Markdown

ECHOES-1363

Comment thread src/components/toolbar/__tests__/Toolbar-test.tsx
Comment thread src/components/index.ts
Comment thread src/components/toolbar/Toolbar.tsx Outdated
@gregaubert gregaubert force-pushed the greg/filter-toolbar branch from 4b0732e to 7926af7 Compare June 17, 2026 15:16
Comment thread src/components/toolbar/Toolbar.tsx
Comment thread src/components/toolbar/Toolbar.tsx
@gregaubert gregaubert force-pushed the greg/filter-toolbar branch from 7926af7 to 514775c Compare June 18, 2026 08:00

@jeremy-davis-sonarsource jeremy-davis-sonarsource 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.

Looks great! Just a few things to iron out 👍

Comment thread src/components/toolbar/Toolbar.tsx
Comment thread src/components/toolbar/Toolbar.tsx
Comment thread stories/toolbar/Toolbar-stories.tsx
Comment thread src/components/toolbar/Toolbar.tsx
@gregaubert gregaubert force-pushed the greg/filter-toolbar branch from 514775c to b9d25d7 Compare June 19, 2026 09:26
@sonarqube-next

Copy link
Copy Markdown

@gregaubert gregaubert merged commit d5e0097 into main Jun 19, 2026
10 checks passed
@gregaubert gregaubert deleted the greg/filter-toolbar branch June 19, 2026 09:32
@gitar-bot

gitar-bot Bot commented Jun 19, 2026

Copy link
Copy Markdown
Code Review ✅ Approved 5 resolved / 5 findings

Implements the new Toolbar component with comprehensive filtering, search, and sorting features. Accessibility, i18n support, and test coverage improvements addressed the initial configuration and rendering issues.

✅ 5 resolved
Quality: First test bypasses the renderToolbar() shared helper

📄 src/components/toolbar/tests/Toolbar-test.tsx:27-41 📄 src/components/toolbar/tests/Toolbar-test.tsx:173-179
The test file defines a shared renderToolbar() helper (line 173) that wraps render(), but the first test case (renders search, filters, sorting, and datasetControls in the top row, lines 27-42) calls render(<Toolbar .../>) directly instead. Per the project testing conventions, raw render() calls inside it() blocks are not permitted when a shared helper exists — they bypass the consistent wiring and make refactoring harder.

Suggested fix: route this test through renderToolbar(), overriding searchInput and adding the other controls via props, e.g. renderToolbar({ datasetControls: ..., filterControls: ..., searchInput: <input ... />, sortControls: ... }).

Quality: toolbar export breaks alphabetical order in components/index.ts

📄 src/components/index.ts:30-32
export * from './toolbar'; was inserted between ./filters and ./form, but the barrel file is otherwise alphabetically ordered, so toolbar belongs after ./toggle-tip/near the end, not before form. This is a minor consistency issue that can cause noisy diffs and merge conflicts later.

Suggested fix: move the ./toolbar export to its correct alphabetical position in the list.

Bug: Custom labelFilterTags renders literal {count} instead of the number

📄 src/components/toolbar/Toolbar.tsx:137-144 📄 stories/toolbar/Toolbar-stories.tsx:129 📄 src/components/toolbar/Toolbar.tsx:65-70
labelFilterTags is rendered as a plain string ({labelFilterTags ?? <FormattedMessage .../>} in Toolbar.tsx:137-144). Only the default label interpolates {count} via react-intl's FormattedMessage. A consumer-supplied string is treated as static text, so the {count} token is never substituted.

The Default story passes labelFilterTags: 'Applied filters ({count})' (Toolbar-stories.tsx:129), which will literally display "Applied filters ({count})" rather than "Applied filters (1)". This both ships a broken demo and exposes a misleading API: the prop's TSDoc shows the example "Applied filters (3)" and the default value "Applied filters ({count})", leading consumers to assume {count} is interpolated.

Suggested fix: either (a) document that labelFilterTags is a static string and update the story to a literal like 'Applied filters', or (b) change the prop to accept the count, e.g. labelFilterTags?: (count: number) => ReactNode (or perform interpolation when a {count} token is present). No test currently covers a custom labelFilterTags containing {count}, so this gap is untested.

Edge Case: Toolbar root lacks role/aria-label for its control group

📄 src/components/toolbar/Toolbar.tsx:121-122 📄 src/components/toolbar/Toolbar.tsx:173-181
The Toolbar renders its control rows inside a plain div (ToolbarWrapper) with no semantic grouping. As a named Toolbar component that groups interactive controls (search, filters, sort, dataset actions), exposing an accessible grouping role and label helps assistive-technology users understand the relationship of the contained controls (per the project's WCAG 2.2 AA guidance on roles/labels).

Consider allowing/forwarding an aria-label (already possible via restProps) and documenting it, and/or applying an appropriate landmark/grouping role. Note that role="toolbar" carries ARIA roving-focus expectations, so if full arrow-key navigation is not implemented, prefer a labelled grouping (e.g. role="group" with aria-label) rather than role="toolbar".

Quality: Hardcoded max-width: 40% not routed through a design token

📄 src/components/toolbar/Toolbar.tsx:200-204
ToolbarSearchWrapper uses a raw max-width: 40% (Toolbar.tsx:202). Per the styling conventions, layout/sizing values should come from design tokens via cssVar where one exists; the surrounding code already uses cssVar('sizes-form-field-medium') for min-width. If no token represents this constraint, consider documenting why the literal is used; otherwise route it through cssVar.

Options

Auto-apply is off → Gitar will not commit updates to this branch.
Display: compact → Showing less information.

Comment with these commands to change:

Auto-apply Compact
gitar auto-apply:on         
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

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.

2 participants