Skip to content

feat: add SearchSelect component with sync and async support - #3752

Merged
akshaydeo merged 8 commits into
devfrom
05-26-feat_searchselect_component
May 27, 2026
Merged

feat: add SearchSelect component with sync and async support#3752
akshaydeo merged 8 commits into
devfrom
05-26-feat_searchselect_component

Conversation

@impoiler

@impoiler impoiler commented May 26, 2026

Copy link
Copy Markdown
Contributor

Summary

Introduces a new reusable SearchSelect component that renders a popover-based search input with a filterable list of selectable options. It supports both synchronous (client-side filtered) and asynchronous (server-driven search) modes.

Changes

  • Added SearchSelect component built on top of cmdk and the existing Popover, Skeleton, and utility primitives.
  • Supports controlled and uncontrolled open state via optional open/onOpenChange props.
  • Async mode exposes onSearchChange, isSearching, isLoading, isError, and errorMessage props; when async, the cmdk filter is bypassed so results are fully controlled externally.
  • Provides a default entry view rendering a label, optional description, and a Plus icon, with an entryView render prop for custom item rendering.
  • Loading state renders skeleton placeholders; error state renders a destructive message; empty state uses CommandPrimitive.Empty.
  • Accepts a footer slot rendered below the list, separated by a border.
  • Exported SearchSelect, SearchSelectOption, and SearchSelectProps types for external use.

Type of change

  • Bug fix
  • Feature
  • Refactor
  • Documentation
  • Chore/CI

Affected areas

  • Core (Go)
  • Transports (HTTP)
  • Providers/Integrations
  • Plugins
  • UI (React)
  • Docs

How to test

cd ui
pnpm i || npm i
pnpm build || npm run build

Render the component with a static options array and verify:

  1. The popover opens on trigger click and the search input is auto-focused.
  2. Typing filters the list (sync mode).
  3. Selecting an item calls onValueSelect with the correct option object.
  4. In async mode, onSearchChange is called on input and loading/error/empty states render correctly.

Screenshots/Recordings

Add before/after screenshots or a short clip demonstrating the component in use.

Breaking changes

  • Yes
  • No

Related issues

Link related issues and discussions.

Security considerations

No auth, secrets, or PII involved. Options and search values are UI-local.

Checklist

  • I read docs/contributing/README.md and followed the guidelines
  • I added/updated tests where appropriate
  • I updated documentation where needed
  • I verified builds succeed (Go and UI)
  • I verified the CI pipeline passes locally if applicable

@coderabbitai

coderabbitai Bot commented May 26, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@impoiler, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 4 minutes and 21 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

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.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 61304054-0cad-4b95-8910-c49c02712d45

📥 Commits

Reviewing files that changed from the base of the PR and between 1b4ba73 and 2ace481.

📒 Files selected for processing (1)
  • ui/components/ui/searchSelect.tsx
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 05-26-feat_searchselect_component

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

@impoiler
impoiler force-pushed the 05-26-feat_searchselect_component branch from 88ab961 to 45fa77b Compare May 26, 2026 09:40
@impoiler
impoiler force-pushed the 05-26-fix_governance_pages_views_and_layout_fixes branch from 0454568 to b636d08 Compare May 26, 2026 09:44
@impoiler
impoiler force-pushed the 05-26-feat_searchselect_component branch from 45fa77b to 92fb78c Compare May 26, 2026 09:44
@impoiler
impoiler force-pushed the 05-26-feat_searchselect_component branch from 92fb78c to 181c2ae Compare May 26, 2026 17:00
@impoiler
impoiler force-pushed the 05-26-fix_governance_pages_views_and_layout_fixes branch from b636d08 to 05d8a2f Compare May 26, 2026 17:00
@impoiler
impoiler force-pushed the 05-26-feat_searchselect_component branch from 181c2ae to 1f01017 Compare May 27, 2026 04:06
@impoiler
impoiler force-pushed the 05-26-fix_governance_pages_views_and_layout_fixes branch from 05d8a2f to 1b6f765 Compare May 27, 2026 04:06
@impoiler impoiler changed the title feat: searchSelect component feat: add SearchSelect component with sync and async support May 27, 2026
@impoiler impoiler self-assigned this May 27, 2026
@impoiler
impoiler force-pushed the 05-26-fix_governance_pages_views_and_layout_fixes branch from 1b6f765 to e02f244 Compare May 27, 2026 09:13
@impoiler
impoiler force-pushed the 05-26-feat_searchselect_component branch from 1f01017 to 72c07b4 Compare May 27, 2026 09:13
@impoiler
impoiler marked this pull request as ready for review May 27, 2026 10:25
@greptile-apps

greptile-apps Bot commented May 27, 2026

Copy link
Copy Markdown
Contributor

Confidence Score: 4/5

Safe to merge after addressing the double search-clear callback and the cmdk item identity collision.

The double-clear bug means async consumers receive onSearchChange("") twice on every close, potentially firing two server requests and confusing debounced handlers. The value={option.label} issue means any dataset with non-unique labels will silently drop options from the list. Both are correctable in-place before the component is wired to real data.

ui/components/ui/searchSelect.tsx — the only changed file; both issues are confined to it.

Important Files Changed

Filename Overview
ui/components/ui/searchSelect.tsx New reusable SearchSelect component with sync/async modes; has two logic bugs: duplicate onSearchChange("") calls on close and cmdk item identity collision when options share a label.

Reviews (4): Last reviewed commit: "feat: searchSelect component" | Re-trigger Greptile

Comment thread ui/components/ui/searchSelect.tsx Outdated
Comment thread ui/components/ui/searchSelect.tsx Outdated
Comment thread ui/components/ui/searchSelect.tsx
@impoiler
impoiler force-pushed the 05-26-feat_searchselect_component branch from f6486ca to 051f5c7 Compare May 27, 2026 12:19
coderabbitai[bot]
coderabbitai Bot previously approved these changes May 27, 2026
@impoiler
impoiler force-pushed the 05-26-fix_governance_pages_views_and_layout_fixes branch from 8991c33 to 7f82c60 Compare May 27, 2026 12:30
@impoiler
impoiler force-pushed the 05-26-feat_searchselect_component branch from 051f5c7 to 7703dab Compare May 27, 2026 12:30
@impoiler
impoiler force-pushed the 05-26-fix_governance_pages_views_and_layout_fixes branch from 7f82c60 to 1b4ba73 Compare May 27, 2026 13:16
@impoiler
impoiler force-pushed the 05-26-feat_searchselect_component branch from 7703dab to 2ace481 Compare May 27, 2026 13:16
Comment thread ui/components/ui/searchSelect.tsx

akshaydeo commented May 27, 2026

Copy link
Copy Markdown
Contributor

Merge activity

  • May 27, 1:44 PM UTC: A user started a stack merge that includes this pull request via Graphite.
  • May 27, 1:54 PM UTC: @akshaydeo merged this pull request with Graphite.

@akshaydeo
akshaydeo changed the base branch from 05-26-fix_governance_pages_views_and_layout_fixes to graphite-base/3752 May 27, 2026 13:51
@akshaydeo
akshaydeo changed the base branch from graphite-base/3752 to dev May 27, 2026 13:54
@akshaydeo
akshaydeo dismissed coderabbitai[bot]’s stale review May 27, 2026 13:54

The base branch was changed.

@akshaydeo
akshaydeo merged commit 59efe4b into dev May 27, 2026
10 checks passed
@akshaydeo
akshaydeo deleted the 05-26-feat_searchselect_component branch May 27, 2026 13:54
akshaydeo pushed a commit that referenced this pull request May 29, 2026
## Summary

Introduces a new reusable `SearchSelect` component that renders a popover-based search input with a filterable list of selectable options. It supports both synchronous (client-side filtered) and asynchronous (server-driven search) modes.

## Changes

- Added `SearchSelect` component built on top of `cmdk` and the existing `Popover`, `Skeleton`, and utility primitives.
- Supports controlled and uncontrolled open state via optional `open`/`onOpenChange` props.
- Async mode exposes `onSearchChange`, `isSearching`, `isLoading`, `isError`, and `errorMessage` props; when async, the `cmdk` filter is bypassed so results are fully controlled externally.
- Provides a default entry view rendering a label, optional description, and a `Plus` icon, with an `entryView` render prop for custom item rendering.
- Loading state renders skeleton placeholders; error state renders a destructive message; empty state uses `CommandPrimitive.Empty`.
- Accepts a `footer` slot rendered below the list, separated by a border.
- Exported `SearchSelect`, `SearchSelectOption`, and `SearchSelectProps` types for external use.

## Type of change

- [ ] Bug fix
- [x] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI

## Affected areas

- [ ] Core (Go)
- [ ] Transports (HTTP)
- [ ] Providers/Integrations
- [ ] Plugins
- [x] UI (React)
- [ ] Docs

## How to test

```sh
cd ui
pnpm i || npm i
pnpm build || npm run build
```

Render the component with a static options array and verify:
1. The popover opens on trigger click and the search input is auto-focused.
2. Typing filters the list (sync mode).
3. Selecting an item calls `onValueSelect` with the correct option object.
4. In async mode, `onSearchChange` is called on input and loading/error/empty states render correctly.

## Screenshots/Recordings

_Add before/after screenshots or a short clip demonstrating the component in use._

## Breaking changes

- [ ] Yes
- [x] No

## Related issues

_Link related issues and discussions._

## Security considerations

No auth, secrets, or PII involved. Options and search values are UI-local.

## Checklist

- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [ ] I added/updated tests where appropriate
- [ ] I updated documentation where needed
- [ ] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable
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