Skip to content

feat(filters): add contact filter - #4111

Merged
shepilov merged 1 commit into
masterfrom
feat/contact-filter
Jul 30, 2026
Merged

shepilov merged 1 commit into
masterfrom
feat/contact-filter

Conversation

@shepilov

@shepilov shepilov commented Jul 29, 2026

Copy link
Copy Markdown
Member

Summary

  • Add a searchable contact filter for contacts and groups.
  • Extend the shared filter to support non-select inputs and custom input adornments.
  • Add localized labels and behavioral coverage for searching, result limits, loading, selection, and clearing.

Summary by CodeRabbit

  • New Features
    • Added a contact filter with a “me” option, clear/reset text, and avatar-based autosuggest suggestions.
    • Added contact filter translations in English, French, Russian, and Vietnamese.
  • Enhancements
    • Improved the generic Filter component to support optional InputProps and configurable selectable behavior.
    • Updated contact filter behavior so a disabled filter won’t open the suggestions list.
  • Styling
    • Simplified contact filter styling for the dropdown, search input, and suggestion states.
  • Tests
    • Updated contact filter tests to render avatars from option data and added coverage for the disabled state.

@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Refines the contact filter by requiring avatars in option data, removing the kind discriminator, and retaining normalized filtering capped at 20 results. Extends the shared Filter with select and merged InputProps, updates ContactFilter rendering and styles, adds loading and empty states, exports, translations, TypeScript packages, and verifies disabled behavior with updated test fixtures.

Possibly related PRs

Suggested reviewers: rezk2ll, zatteo, lethemanh

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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 clearly summarizes the main change: adding a contact filter to the filters module.
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 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/contact-filter

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.

codescene-delta-analysis[bot]

This comment was marked as outdated.

@bundlemon

bundlemon Bot commented Jul 29, 2026

Copy link
Copy Markdown

BundleMon

Unchanged files (18)
Status Path Size Limits
static/resource/(hash).js
336.09KB -
services/qualificationMigration.js
275.6KB -
services/dacc.js
255.74KB -
static/js/main.(hash).js
57.96KB -
static/js/lib-react.(hash).js
43.88KB -
static/js/public.(hash).js
27.12KB -
static/js/lib-polyfill.(hash).js
22.76KB -
static/js/lib-router.(hash).js
21.92KB -
static/js/intents.(hash).js
18.11KB -
static/css/main.(hash).css
13.99KB -
static/js/async/(chunkId).(hash).js
7.5KB -
manifest.webapp
6.02KB -
static/css/public.(hash).css
2.71KB -
static/js/(chunkId).(hash).js
2.08KB -
index.html
822B -
public/index.html
771B -
intents/index.html
679B -
assets/manifest.json
185B -

Total files change +4B 0%

Groups updated (1)
Status Path Size Limits
**/*.js
6.15MB (+176B 0%) -
Unchanged groups (2)
Status Path Size Limits
**/*.{png,svg,ico}
2.16MB -
**/*.css
73.58KB -

Final result: ✅

View report in BundleMon website ➡️


Current branch size history | Target branch size history

@shepilov
shepilov marked this pull request as ready for review July 29, 2026 16:57
codescene-delta-analysis[bot]

This comment was marked as outdated.

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

🧹 Nitpick comments (1)
src/components/Filters/ContactFilter.tsx (1)

256-282: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Autosuggest defaults to a non-unique id.

menuId is already generated per-instance for the wrapper/aria-controls, but the <Autosuggest> itself isn't given an id, so it falls back to the library's static default. Per the react-autosuggest docs, multiple simultaneously-rendered instances must use unique ids to avoid colliding aria-owns/aria-activedescendant targets.

♿ Proposed fix
             <Autosuggest<ContactFilterOption, never>
               alwaysRenderSuggestions
               focusInputOnSuggestionClick={false}
               getSuggestionValue={getSuggestionValue}
               highlightFirstSuggestion
+              id={menuId}
               inputProps={{

Based on external documentation: "When rendering a single Autosuggest, don't set the id (it will be set to '1', by default). When rendering multiple Autosuggest components on a page, make sure to give them unique ids."

🤖 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 `@src/components/Filters/ContactFilter.tsx` around lines 256 - 282, Pass the
existing per-instance menuId as the unique id prop on the Autosuggest component,
alongside its current configuration. Do not change the generated menuId or
surrounding aria-controls usage; reuse that identifier to prevent duplicate
react-autosuggest accessibility targets.
🤖 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.

Nitpick comments:
In `@src/components/Filters/ContactFilter.tsx`:
- Around line 256-282: Pass the existing per-instance menuId as the unique id
prop on the Autosuggest component, alongside its current configuration. Do not
change the generated menuId or surrounding aria-controls usage; reuse that
identifier to prevent duplicate react-autosuggest accessibility targets.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 8ab019cb-267a-4c1b-a96a-98e4f2ddb9ea

📥 Commits

Reviewing files that changed from the base of the PR and between ce266cb and 0d28b94.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (11)
  • package.json
  • src/components/Filters/ContactFilter.spec.tsx
  • src/components/Filters/ContactFilter.styl
  • src/components/Filters/ContactFilter.tsx
  • src/components/Filters/Filter.jsx
  • src/components/Filters/contactFilterOptions.ts
  • src/components/Filters/index.js
  • src/locales/en.json
  • src/locales/fr.json
  • src/locales/ru.json
  • src/locales/vi.json

@shepilov
shepilov force-pushed the feat/contact-filter branch from 0d28b94 to c4eefdd Compare July 29, 2026 17:10
codescene-delta-analysis[bot]

This comment was marked as outdated.

@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

🤖 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 `@src/components/Filters/ContactFilter.styl`:
- Around line 38-46: Add a keyboard-visible focus indicator for the search field
by introducing a :focus-visible rule on .searchInput or a :focus-within rule on
.search, while retaining the existing visual reset for non-focused states.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: c7eba414-1a25-4c12-8ab0-11c25c91fb79

📥 Commits

Reviewing files that changed from the base of the PR and between 0d28b94 and c4eefdd.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (11)
  • package.json
  • src/components/Filters/ContactFilter.spec.tsx
  • src/components/Filters/ContactFilter.styl
  • src/components/Filters/ContactFilter.tsx
  • src/components/Filters/Filter.jsx
  • src/components/Filters/contactFilterOptions.ts
  • src/components/Filters/index.js
  • src/locales/en.json
  • src/locales/fr.json
  • src/locales/ru.json
  • src/locales/vi.json
🚧 Files skipped from review as they are similar to previous changes (8)
  • src/components/Filters/index.js
  • src/locales/en.json
  • src/locales/ru.json
  • src/locales/vi.json
  • src/components/Filters/Filter.jsx
  • src/components/Filters/ContactFilter.spec.tsx
  • src/components/Filters/contactFilterOptions.ts
  • src/components/Filters/ContactFilter.tsx

Comment thread src/components/Filters/ContactFilter.styl Outdated
Comment thread src/components/Filters/ContactFilter.tsx Outdated
Comment thread src/components/Filters/ContactFilter.tsx Outdated
Comment thread src/components/Filters/ContactFilter.tsx
Comment thread src/components/Filters/ContactFilter.tsx Outdated
Comment thread src/components/Filters/ContactFilter.tsx Outdated
Comment thread src/components/Filters/ContactFilter.tsx Outdated
Comment thread src/components/Filters/ContactFilter.tsx Outdated
Comment thread src/components/Filters/ContactFilter.tsx Outdated
Comment thread src/components/Filters/ContactFilter.tsx Outdated
@zatteo

zatteo commented Jul 30, 2026

Copy link
Copy Markdown
Member

@shepilov why using a new intermediate type ContactFilterOption? As input, you have io.cozy.contacts and io.cozy.contacts.group?

We have helper and existing components that can help for this kind of UI like getInitials that you rewrite here for ContactFilterOption type.

@shepilov

shepilov commented Jul 30, 2026

Copy link
Copy Markdown
Member Author

@shepilov why using a new intermediate type ContactFilterOption? As input, you have io.cozy.contacts and io.cozy.contacts.group?

We have helper and existing components that can help for this kind of UI like getInitials that you rewrite here for ContactFilterOption type.

@zatteo because I don't know what model we will have there, I haven't looked yet what we have inside the sharings. But it's supposed to be not all the contacts from the addressbook, but a set of members from the existing shares

@shepilov
shepilov force-pushed the feat/contact-filter branch from c4eefdd to 5f5c175 Compare July 30, 2026 12:58
codescene-delta-analysis[bot]

This comment was marked as outdated.

@zatteo

zatteo commented Jul 30, 2026

Copy link
Copy Markdown
Member

@shepilov why using a new intermediate type ContactFilterOption? As input, you have io.cozy.contacts and io.cozy.contacts.group?
We have helper and existing components that can help for this kind of UI like getInitials that you rewrite here for ContactFilterOption type.

@zatteo because I don't know what model we will have there, I haven't looked yet what we have inside the sharings. But it's supposed to be not all the contacts from the addressbook, but a set of members from the existing shares

If you are more in a "build UI components" mode, let's go like this for now. But if at the end we get io.cozy.contacts and io.cozy.contacts.group OR sharing members, we may more components to mutualize/use from cozy-ui/cozy-sharing. For example there is already an "autocomplete on contact or group" in the sharing modal.

Comment thread src/components/Filters/ContactFilter.styl Outdated
Comment thread src/components/Filters/contactFilterOptions.ts Outdated
Comment thread src/components/Filters/contactFilterOptions.ts
Comment thread src/components/Filters/ContactFilterSuggestion.tsx Outdated
Comment thread src/components/Filters/ContactFilterSuggestion.tsx Outdated
Comment thread src/components/Filters/ContactFilter.styl
codescene-delta-analysis[bot]

This comment was marked as outdated.

@shepilov

Copy link
Copy Markdown
Member Author

@shepilov why using a new intermediate type ContactFilterOption? As input, you have io.cozy.contacts and io.cozy.contacts.group?
We have helper and existing components that can help for this kind of UI like getInitials that you rewrite here for ContactFilterOption type.

@zatteo because I don't know what model we will have there, I haven't looked yet what we have inside the sharings. But it's supposed to be not all the contacts from the addressbook, but a set of members from the existing shares

If you are more in a "build UI components" mode, let's go like this for now. But if at the end we get io.cozy.contacts and io.cozy.contacts.group OR sharing members, we may more components to mutualize/use from cozy-ui/cozy-sharing. For example there is already an "autocomplete on contact or group" in the sharing modal.

yes, at first I was going to use "autocomplete on contact or group" on a sharing modal, but it has different behavior then the existing one; we too many customizations in it, like the source of the option, and how the selected results should be displayed, multiselect ant etc, we can discuss how we can mutualize it, but for me it looked to many differences

codescene-delta-analysis[bot]

This comment was marked as outdated.

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/components/Filters/ContactFilter.tsx (1)

155-186: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Reset the menu state when the filter becomes disabled.

The conditional onClick blocks new opens, but an already-open menu leaves isOpen set to true. Toggling disabled while open can leave aria-expanded and the icon inconsistent with the hidden menu, then reopen the menu with the stale query when re-enabled. Close/reset the state on disable and derive all open-state UI from isOpen && !disabled.

🤖 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 `@src/components/Filters/ContactFilter.tsx` around lines 155 - 186, Update the
ContactFilter component’s disabled-state handling to close/reset the menu when
disabled becomes true, clearing any stale query as appropriate. Derive
aria-expanded, the trigger icon state, and menu visibility from isOpen &&
!disabled so all open-state UI remains synchronized and reopening starts
cleanly.
🤖 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.

Outside diff comments:
In `@src/components/Filters/ContactFilter.tsx`:
- Around line 155-186: Update the ContactFilter component’s disabled-state
handling to close/reset the menu when disabled becomes true, clearing any stale
query as appropriate. Derive aria-expanded, the trigger icon state, and menu
visibility from isOpen && !disabled so all open-state UI remains synchronized
and reopening starts cleanly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: f334d767-287a-4dc2-abde-4d1c4e2bc3eb

📥 Commits

Reviewing files that changed from the base of the PR and between 0fcbb38 and f576c3d.

📒 Files selected for processing (6)
  • src/components/Filters/ContactFilter.spec.tsx
  • src/components/Filters/ContactFilter.styl
  • src/components/Filters/ContactFilter.tsx
  • src/components/Filters/ContactFilterSuggestion.tsx
  • src/components/Filters/ContactFilterSuggestionsContainer.tsx
  • src/components/Filters/contactFilterOptions.ts
💤 Files with no reviewable changes (1)
  • src/components/Filters/ContactFilter.styl

Comment thread src/components/Filters/contactFilterOptions.ts Outdated
Comment thread src/components/Filters/contactFilterOptions.ts Outdated

@JF-Cozy JF-Cozy 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.

approve to unlock but comments should be considered :) welcome to the frontend world, and well done so far 👍

Comment thread src/components/Filters/ContactFilterSuggestionsContainer.tsx Outdated
Comment thread src/components/Filters/ContactFilterSuggestionsContainer.tsx
Comment thread src/components/Filters/ContactFilter.tsx Outdated
Comment thread src/components/Filters/ContactFilter.tsx Outdated
Comment thread src/components/Filters/ContactFilter.tsx Outdated
Comment thread src/components/Filters/ContactFilter.styl
codescene-delta-analysis[bot]

This comment was marked as outdated.

@shepilov
shepilov force-pushed the feat/contact-filter branch from f35cbd3 to 589aa8b Compare July 30, 2026 15:03
codescene-delta-analysis[bot]

This comment was marked as outdated.

@shepilov
shepilov force-pushed the feat/contact-filter branch from 589aa8b to addef43 Compare July 30, 2026 15:07

@codescene-delta-analysis codescene-delta-analysis 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.

Our agent can fix these. Install it.

Gates Passed
3 Quality Gates Passed

Quality Gate Profile: The Bare Minimum
Install CodeScene MCP: safeguard and uplift AI-generated code. Catch issues early with our IDE extension and CLI tool.

@shepilov
shepilov merged commit 1281b9c into master Jul 30, 2026
7 checks passed
@shepilov
shepilov deleted the feat/contact-filter branch July 30, 2026 15:23
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.

4 participants