-
Couldn't load subscription status.
- Fork 1
31 design and implement shared reusable search bar component #37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
nancymuyeh
wants to merge
32
commits into
main
Choose a base branch
from
31-design-and-implement-shared-reusable-search-bar-component
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 2 commits
Commits
Show all changes
32 commits
Select commit
Hold shift + click to select a range
33c23f3
feat(ui): implement reusable SearchBar component
nancymuyeh dadff60
feat(ui): implement reusable SearchBar component
nancymuyeh 02fdf91
feat(ui): implement reusable SearchBar component
nancymuyeh 07f3c4a
feat(ui): implement reusable SearchBar component
nancymuyeh 581d387
Merge branch 'main' into 31-design-and-implement-shared-reusable-sear…
nancymuyeh 62a576d
fix(ui): mark SearchBar component prop as read-only
nancymuyeh 0f3de59
Merge branch '31-design-and-implement-shared-reusable-search-bar-comp…
nancymuyeh d886154
fix(ui): increase test coverage
nancymuyeh b198f93
Merge branch 'main' into 31-design-and-implement-shared-reusable-sear…
nancymuyeh 190f0b3
fix(ui): increase test coverage
nancymuyeh a24a3d9
fix(ui): refactor useSearchBar hook with extracted helper functions f…
nancymuyeh a74f693
fix(ui): refactor useSearchBar hook with extracted helper functions f…
nancymuyeh 390b514
Update packages/ui/src/components/SearchBar/SearchBar.view.tsx
nancymuyeh 7f2e481
fix(ui): refactor useSearchBar component for SonarQube compliance
nancymuyeh 5f5396c
fix(ui): refactor useSearchBar component for SonarQube compliance
nancymuyeh 216d993
fix(ui): refactor SearchBar component for SonarQube compliance
nancymuyeh e04b8bd
fix(ui): refactor SearchBar component for SonarQube compliance
nancymuyeh 3328a72
chore(ui): merge main
nancymuyeh 89b66c6
fix(ui): refactor SearchBar component for SonarQube compliance
nancymuyeh 1161ec1
fix(ui): refactor SearchBar component with more simplifies functionality
nancymuyeh cd8acd7
fix(ui): update searchbar variants and styling
nancymuyeh 1e6e858
fix(ui): remove unused dependencies
nancymuyeh 103e6c8
fix(ui): remove unused dependencies
nancymuyeh 0cd4017
fix(ui): update searchbar componenet to use global styling from style…
nancymuyeh 8ba9f4b
Merge branch 'main' into 31-design-and-implement-shared-reusable-sear…
nancymuyeh e885bf6
fix(ui): fix minor lint issue
nancymuyeh 9d2d22f
fix(ui): merge main
nancymuyeh 632273e
Merge remote-tracking branch 'origin' into 31-design-and-implement-sh…
nancymuyeh eafd972
Merge branch 'main' into 31-design-and-implement-shared-reusable-sear…
nancymuyeh 0fffcc2
Merge branch '31-design-and-implement-shared-reusable-search-bar-comp…
nancymuyeh 9999bf2
fix(ui): fix minor lint issue
nancymuyeh f87027b
fix(ui): fix minor lint issue
nancymuyeh File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,223 @@ | ||
| # Search Bar Component | ||
|
|
||
| A versatile search component that provides a consistent search experience across all applications in the Fineract ecosystem. It supports various features like suggestions, async search, keyboard navigation, and multiple visual variants. | ||
|
|
||
| ## Features | ||
|
|
||
| - **Live Search**: Real-time search with debouncing | ||
| - **Suggestions**: Both client-side and server-side suggestions support | ||
| - **Keyboard Navigation**: Full keyboard support for suggestion navigation | ||
| - **Accessibility**: ARIA compliant using Downshift | ||
| - **Loading States**: Visual feedback during async operations | ||
| - **Clear/Reset**: Optional clear button functionality | ||
| - **Multiple Variants**: Simple, with button, and expandable styles | ||
| - **Responsive Design**: Adapts to different screen sizes | ||
| - **Theme Integration**: Uses semantic color tokens | ||
|
|
||
| ## Installation | ||
|
|
||
| The SearchBar component is part of the `@fineract-apps/ui` package and is automatically available in all frontend applications. | ||
|
|
||
| ## Basic Usage | ||
|
|
||
| ```tsx | ||
| import { SearchBar } from "@fineract-apps/ui"; | ||
|
|
||
| // Simple search | ||
| <SearchBar | ||
| placeholder="Search accounts" | ||
| onSearch={(value) => console.log('Searching for:', value)} | ||
| /> | ||
|
|
||
| // With suggestions | ||
| <SearchBar | ||
| placeholder="Search accounts" | ||
| suggestions={[ | ||
| { id: '1', label: 'Account #123' }, | ||
| { id: '2', label: 'Account #456' } | ||
| ]} | ||
| onSuggestionSelect={(suggestion) => { | ||
| console.log('Selected:', suggestion); | ||
| }} | ||
| /> | ||
|
|
||
| // With async suggestions | ||
| <SearchBar | ||
| placeholder="Search accounts" | ||
| suggestionProvider={async (query, signal) => { | ||
| const res = await fetch(`/api/search?q=${query}`, { signal }); | ||
| const data = await res.json(); | ||
| return data.map(item => ({ | ||
| id: item.id, | ||
| label: item.displayName | ||
| })); | ||
| }} | ||
| /> | ||
| ``` | ||
|
|
||
| ## Props | ||
|
|
||
| | Prop | Type | Default | Description | | ||
| |------|------|---------|-------------| | ||
| | \`variant\` | \`"default" \| "simple" \| "withButton" \| "expandable"\` | \`"default"\` | The visual style variant | | ||
| | \`size\` | \`"sm" \| "md" \| "lg"\` | \`"md"\` | The size of the search bar | | ||
| | \`placeholder\` | \`string\` | \`"Search"\` | Placeholder text | | ||
| | \`onSearch\` | \`(value: string) => void\` | - | Called when search is triggered | | ||
| | \`showClear\` | \`boolean\` | \`true\` | Whether to show the clear button | | ||
| | \`onClear\` | \`() => void\` | - | Called when clear button is clicked | | ||
| | \`suggestions\` | \`Suggestion[]\` | - | Array of suggestions for client-side filtering | | ||
| | \`suggestionProvider\` | \`(query: string, signal?: AbortSignal) => Promise<Suggestion[]>\` | - | Async function to fetch suggestions | | ||
| | \`minChars\` | \`number\` | \`2\` | Minimum characters before showing suggestions | | ||
| | \`debounceMs\` | \`number\` | \`250\` | Debounce delay for suggestions in ms | | ||
| | \`maxSuggestions\` | \`number\` | \`8\` | Maximum number of suggestions to show | | ||
| | \`onSuggestionSelect\` | \`(suggestion: Suggestion) => void\` | - | Called when a suggestion is selected | | ||
| | \`isLoading\` | \`boolean\` | \`false\` | Shows loading indicator | | ||
| | \`showSearchButton\` | \`boolean\` | \`false\` | Shows search button (for withButton variant) | | ||
|
|
||
| ## Variants | ||
|
|
||
| ### Default | ||
| Standard search bar with icon and optional clear button. | ||
| ```tsx | ||
| <SearchBar placeholder="Search" /> | ||
| ``` | ||
|
|
||
| ### Simple | ||
| Compact version for space-constrained areas. | ||
| ```tsx | ||
| <SearchBar | ||
| variant="simple" | ||
| size="sm" | ||
| placeholder="Quick search" | ||
| /> | ||
| ``` | ||
|
|
||
| ### With Button | ||
| Includes a search button, useful for explicit search actions. | ||
| ```tsx | ||
| <SearchBar | ||
| variant="withButton" | ||
| showSearchButton | ||
| placeholder="Search with button" | ||
| /> | ||
| ``` | ||
|
|
||
| ### Expandable | ||
| Collapses to an icon and expands on focus, great for navigation bars. | ||
| ```tsx | ||
| <SearchBar | ||
| variant="expandable" | ||
| size="sm" | ||
| placeholder="Click to expand" | ||
| /> | ||
| ``` | ||
|
|
||
| ## Accessibility | ||
|
|
||
| The SearchBar component follows WAI-ARIA guidelines and includes: | ||
|
|
||
| - Proper ARIA roles and attributes (`combobox`, `listbox`, `option`) | ||
| - Keyboard navigation: | ||
| - `↑/↓`: Navigate through suggestions | ||
| - `Enter`: Select suggestion or trigger search | ||
| - `Esc`: Close suggestions | ||
| - Clear button has proper aria-label | ||
| - Loading state announcements | ||
| - Focus management | ||
|
|
||
| ## Examples | ||
|
|
||
| ### Basic Search | ||
| ```tsx | ||
| <SearchBar | ||
| placeholder="Search accounts" | ||
| onSearch={(value) => { | ||
| console.log('Searching:', value); | ||
| }} | ||
| /> | ||
| ``` | ||
|
|
||
| ### With Async Suggestions | ||
| ```tsx | ||
| const [loading, setLoading] = useState(false); | ||
|
|
||
| <SearchBar | ||
| placeholder="Search accounts" | ||
| suggestionProvider={async (query, signal) => { | ||
| setLoading(true); | ||
| try { | ||
| const res = await fetch(`/api/search?q=${query}`, { signal }); | ||
| const data = await res.json(); | ||
| return data.map(item => ({ | ||
| id: item.id, | ||
| label: item.name | ||
| })); | ||
| } finally { | ||
| setLoading(false); | ||
| } | ||
| }} | ||
| isLoading={loading} | ||
| onSuggestionSelect={(suggestion) => { | ||
| navigate(`/accounts/${suggestion.id}`); | ||
| }} | ||
| /> | ||
| ``` | ||
|
|
||
| ### Expandable in Navigation | ||
| ```tsx | ||
| <nav className="flex items-center justify-between"> | ||
| <Logo /> | ||
| <SearchBar | ||
| variant="expandable" | ||
| size="sm" | ||
| placeholder="Search" | ||
| className="max-w-xs" | ||
| /> | ||
| <UserMenu /> | ||
| </nav> | ||
| ``` | ||
|
|
||
| ## Technical Details | ||
|
|
||
| The SearchBar uses: | ||
| - Downshift for accessibility and keyboard interactions | ||
| - class-variance-authority for variant management | ||
| - AbortController for cancelling outdated requests | ||
| - Debouncing for performance | ||
|
|
||
| ## Best Practices | ||
|
|
||
| 1. **Error Handling**: Always handle errors in your suggestion provider: | ||
| ```tsx | ||
| const handleSuggestions = async (query: string, signal?: AbortSignal) => { | ||
| try { | ||
| const data = await fetchSuggestions(query, signal); | ||
| return data.map(toSuggestion); | ||
| } catch (err) { | ||
| if (err.name === 'AbortError') return []; | ||
| console.error('Search error:', err); | ||
| return []; // Or show error state | ||
| } | ||
| }; | ||
| ``` | ||
|
|
||
| 2. **Performance**: Use debouncing and cancellation: | ||
| ```tsx | ||
| <SearchBar | ||
| debounceMs={300} // Adjust based on your needs | ||
| minChars={2} // Prevent unnecessary searches | ||
| maxSuggestions={8} // Limit number of results | ||
| /> | ||
| ``` | ||
|
|
||
| 3. **Responsive Design**: Use appropriate variants: | ||
| ```tsx | ||
| <SearchBar | ||
| variant="default" | ||
| className="hidden md:flex" // Hide on mobile | ||
| /> | ||
| <SearchBar | ||
| variant="expandable" | ||
| className="flex md:hidden" // Show on mobile | ||
| /> | ||
| ``` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.