Skip to content

Conversation

@BARNALIXD
Copy link

@BARNALIXD BARNALIXD commented Nov 17, 2025

  • Replace radio buttons with checkboxes for tech stack filter when allowMultiple is true
  • Add updateMultipleFilters method to store to handle array of selected values
  • Update Filter component to support both single and multiple selection modes
  • Modify UserInputFilterProps type to accept string or string[] for Tech stack
  • Update converter logic to handle multiple languages by joining them with space
  • Enable allowMultiple prop for Tech stack filter in FiltersContainer

This allows users to select multiple programming languages simultaneously when searching for projects, providing more flexible filtering options.

Summary by CodeRabbit

Release Notes

  • New Features
    • Tech stack filter now supports multi-select mode, allowing users to select multiple technologies simultaneously for filtering results.
    • Added Activity filter option to expand filtering capabilities.

- Replace radio buttons with checkboxes for tech stack filter when allowMultiple is true
- Add updateMultipleFilters method to store to handle array of selected values
- Update Filter component to support both single and multiple selection modes
- Modify UserInputFilterProps type to accept string or string[] for Tech stack
- Update converter logic to handle multiple languages by joining them with space
- Enable allowMultiple prop for Tech stack filter in FiltersContainer

This allows users to select multiple programming languages simultaneously
when searching for projects, providing more flexible filtering options.
@vercel
Copy link

vercel bot commented Nov 17, 2025

Someone is attempting to deploy a commit to the AJEET PRATAP SINGH's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 17, 2025

Walkthrough

The pull request introduces multi-select capability for the "Tech stack" filter. The Filter component now conditionally renders checkboxes when allowMultiple is true, while maintaining radio button behavior for single-select mode. Supporting changes include a new store method for handling multiple filter values, type definitions expanded to accept string arrays, and updated conversion logic to serialize arrays correctly.

Changes

Cohort / File(s) Summary
Filter UI Component
apps/web/src/components/ui/Filter.tsx
Adds conditional rendering logic to display Checkbox-based UI when allowMultiple is true, preserving RadioGroup behavior otherwise. Implements updateMultipleFilters callback and isChecked helper to manage both single and multiple selection modes.
Filter Configuration
apps/web/src/components/ui/FiltersContainer.tsx
Enables multi-select mode for the "Tech stack" Filter by adding allowMultiple={true} prop.
Filter Store
apps/web/src/store/useFilterInputStore.ts
Adds new public method updateMultipleFilters(filterName: string, values: string[]) to merge multiple filter values into the filter state.
Type Definitions
apps/web/src/types/filter.ts
Expands UserInputFilterProps type by widening "Tech stack" property from string to `string
Filter Conversion Logic
apps/web/src/utils/converter.ts
Updates convertUserInputToApiInput to handle both string and array inputs for "Tech stack"—arrays are joined with spaces, strings pass through unchanged.

Sequence Diagram

sequenceDiagram
    participant User
    participant Filter Component
    participant Store
    participant Converter

    User->>Filter Component: Click checkbox (allowMultiple=true)
    Filter Component->>Store: updateMultipleFilters("Tech stack", values[])
    Store->>Store: Merge values into filters
    Store-->>Filter Component: State updated

    alt Single Selection Path
        User->>Filter Component: Select radio button
        Filter Component->>Store: updateFilters("Tech stack", value)
        Store->>Store: Replace filter value
    end

    User->>Converter: Trigger conversion
    Converter->>Converter: Check if "Tech stack" is array
    alt Array Path
        Converter->>Converter: Join array with spaces
    else String Path
        Converter->>Converter: Use string directly
    end
    Converter-->>User: API-formatted output
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Filter.tsx requires careful review of the conditional rendering logic and state management for both single/multi-select modes
  • converter.ts logic change for handling both string and array inputs warrants validation of the join operation
  • Type widening in filter.ts impacts downstream usage—verify no regressions in existing single-select code paths

Possibly related issues

Poem

🐰 Checkboxes bloom where radio once stood,
Multi-select magic, just as we knew it would—
Tech stacks now dance in arrays so free,
One filter, many choices—hop with glee!

Pre-merge checks and finishing touches

❌ 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%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: add multiple tech stack selection in filters' directly and accurately summarizes the main change: enabling multi-select functionality for the tech stack filter component.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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 and usage tips.

@cla-assistant
Copy link

cla-assistant bot commented Nov 17, 2025

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.


user.name.like : "barnalixd seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
apps/web/src/store/useFilterInputStore.ts (1)

4-4: Improve type safety for the filters state.

The filters property is typed as generic object, which provides no type safety. Consider using UserInputFilterProps or Partial<UserInputFilterProps> from @/types/filter to ensure type-safe filter operations.

+import { UserInputFilterProps } from "@/types/filter";
+
 interface FilterInputState {
-  filters: object;
+  filters: Partial<UserInputFilterProps>;
   updateFilters: (newFilter: Record<string, string>) => void;
   updateMultipleFilters: (filterName: string, values: string[]) => void;
   resetFilters: () => void;
 }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 97e699a and 0449244.

📒 Files selected for processing (5)
  • apps/web/src/components/ui/Filter.tsx (3 hunks)
  • apps/web/src/components/ui/FiltersContainer.tsx (1 hunks)
  • apps/web/src/store/useFilterInputStore.ts (2 hunks)
  • apps/web/src/types/filter.ts (1 hunks)
  • apps/web/src/utils/converter.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
apps/web/src/components/ui/Filter.tsx (1)
apps/web/src/store/useFilterInputStore.ts (1)
  • useFilterInputStore (10-21)
🔇 Additional comments (7)
apps/web/src/components/ui/FiltersContainer.tsx (1)

103-103: LGTM! Multi-select enabled for Tech stack filter.

The allowMultiple={true} prop correctly enables checkbox-based multi-selection for the Tech stack filter, aligning with the PR objective.

apps/web/src/store/useFilterInputStore.ts (1)

6-6: LGTM! The updateMultipleFilters method is correctly implemented.

The new method properly merges multiple filter values into the state, supporting the multi-select functionality.

Also applies to: 16-19

apps/web/src/types/filter.ts (2)

51-51: LGTM! Type correctly supports both single and multiple selections.

Changing "Tech stack" from string to string | string[] properly enables the filter to handle both single-value and multi-value selections.


55-55: Good catch! Missing Activity field added.

The Activity field was already being used in apps/web/src/utils/converter.ts (lines 134-137) but was missing from the type definition. This addition fixes a type inconsistency, though it appears unrelated to the multi-select feature.

apps/web/src/components/ui/Filter.tsx (2)

23-45: LGTM! Multi-select logic is well-structured.

The recordFilterInput function correctly handles both single and multiple selection modes:

  • In multi-select mode, it maintains an array and toggles items in/out
  • In single-select mode, it preserves the original behavior
  • Empty array handling is appropriate

47-53: LGTM! Checkbox state helper is correct.

The isChecked function properly determines whether a filter option should be checked in multi-select mode.

apps/web/src/utils/converter.ts (1)

114-122: Verify GitHub API syntax for multiple languages and fix backend coordination.

The review comment correctly identifies two real issues:

  1. GitHub API syntax error: The correct syntax for multiple programming languages requires repeated language: qualifiers (e.g., language:python language:javascript), not space-separated values. The current code produces "javascript typescript" which won't work.

  2. Empty array handling: An empty array [] is truthy, so the code would set data.language = "", creating an invalid query language:.

However, the suggested fix in the review would create a different problem. The backend code (apps/api/src/services/project.service.ts:31) already adds the language: prefix with queryParts.push(\language:${filters.language}`). If the frontend sends "language:javascript language:typescript", the backend would wrap it again, creating language:language:javascript language:typescript"` (double prefix).

The fix requires backend coordination:

  • Either the backend should be modified to handle arrays of languages or detect pre-formatted query strings
  • Or the frontend should pass languages differently (not as a single space-separated string)
  • The empty array check is still needed regardless

Recommend verifying the intended architecture with the backend implementation to ensure multiple language support works correctly.

Comment on lines +72 to +84
<Checkbox
id={filter}
checked={isChecked(filter)}
onCheckedChange={() => recordFilterInput(filter)}
className="border-[#28282c] bg-[#141418] text-ox-purple transition data-[state=checked]:border-ox-purple data-[state=checked]:bg-ox-purple/20 data-[state=checked]:ring-2 data-[state=checked]:ring-ox-purple/50"
/>
<Label
htmlFor={filter}
onClick={() => recordFilterInput(filter)}
className="text-sm text-zinc-300 cursor-pointer transition-colors"
>
{filter}
</Label>
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Critical: Double-triggering due to redundant onClick handlers.

Both the Checkbox component and the Label are calling recordFilterInput(filter):

  1. Line 75: Checkbox has onCheckedChange={() => recordFilterInput(filter)}
  2. Lines 78-80: Label has both htmlFor={filter} AND onClick={() => recordFilterInput(filter)}

When a user clicks the label:

  • The htmlFor association triggers the checkbox, firing onCheckedChange
  • Then the label's onClick fires, calling recordFilterInput again
  • This causes the selection to toggle twice, reverting to the original state

Remove the onClick handler from the Label since htmlFor already provides the click association:

                   <Label
                     htmlFor={filter}
-                    onClick={() => recordFilterInput(filter)}
                     className="text-sm text-zinc-300 cursor-pointer transition-colors"
                   >
                     {filter}
                   </Label>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<Checkbox
id={filter}
checked={isChecked(filter)}
onCheckedChange={() => recordFilterInput(filter)}
className="border-[#28282c] bg-[#141418] text-ox-purple transition data-[state=checked]:border-ox-purple data-[state=checked]:bg-ox-purple/20 data-[state=checked]:ring-2 data-[state=checked]:ring-ox-purple/50"
/>
<Label
htmlFor={filter}
onClick={() => recordFilterInput(filter)}
className="text-sm text-zinc-300 cursor-pointer transition-colors"
>
{filter}
</Label>
<Checkbox
id={filter}
checked={isChecked(filter)}
onCheckedChange={() => recordFilterInput(filter)}
className="border-[#28282c] bg-[#141418] text-ox-purple transition data-[state=checked]:border-ox-purple data-[state=checked]:bg-ox-purple/20 data-[state=checked]:ring-2 data-[state=checked]:ring-ox-purple/50"
/>
<Label
htmlFor={filter}
className="text-sm text-zinc-300 cursor-pointer transition-colors"
>
{filter}
</Label>
🤖 Prompt for AI Agents
In apps/web/src/components/ui/Filter.tsx around lines 72 to 84, the Label and
Checkbox both invoke recordFilterInput(filter) causing double-triggering when
the label is clicked; remove the Label's onClick handler and rely on htmlFor to
forward clicks to the Checkbox (keep Checkbox's onCheckedChange as the single
source of truth), and ensure the Label retains htmlFor and appropriate classes
for accessibility and styling.

Comment on lines +92 to +104
<RadioGroupItem
value={filter}
id={filter}
onClick={() => recordFilterInput(filter)}
className="border-[#28282c] bg-[#141418] text-ox-purple transition data-[state=checked]:border-ox-purple data-[state=checked]:bg-ox-purple/20 data-[state=checked]:ring-2 data-[state=checked]:ring-ox-purple/50"
/>
<Label
htmlFor={filter}
onClick={() => recordFilterInput(filter)}
className="text-sm text-zinc-300 cursor-pointer transition-colors"
>
{filter}
</Label>
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify: Potential double-triggering in radio button mode.

Similar to the checkbox issue, both the RadioGroupItem and Label have click handlers:

  1. Line 95: RadioGroupItem has onClick={() => recordFilterInput(filter)}
  2. Lines 98-100: Label has both htmlFor={filter} AND onClick={() => recordFilterInput(filter)}

If this pattern existed in the original code and was working, it may be that the radio group implementation prevents double-firing. However, for consistency with the checkbox fix and to avoid potential issues, consider removing the redundant onClick from the label here as well.

Verify whether the radio button implementation was working correctly before this PR. If there were no issues, document why; otherwise, apply the same fix:

                   <Label
                     htmlFor={filter}
-                    onClick={() => recordFilterInput(filter)}
                     className="text-sm text-zinc-300 cursor-pointer transition-colors"
                   >
                     {filter}
                   </Label>

I'll help you verify this review comment. Let me gather information about the radio button implementation and compare it with the checkbox pattern.

Now let me examine the Filter.tsx file to understand the full context and see how the checkbox issue was handled:

#!/bin/bash
# Examine Filter.tsx around the radio button lines and look for checkbox pattern
fd -e tsx -e ts -path "*/Filter.tsx" -x cat {} | head -150

---

I need to gather more information to verify this concern properly.




🏁 Script executed:

#!/bin/bash
# Find and examine Filter.tsx file, focusing on radio and checkbox patterns
find . -name "Filter.tsx" -o -name "filter.tsx" 2>/dev/null | head -5 | xargs -I {} bash -c 'echo "=== File: {} ===" && cat {}'

Length of output: 4204



---

🌐 Web query:

```web
radix-ui RadioGroup RadioGroupItem onClick event handler

💡 Result:

Short answer

  • Use RadioGroup.Root's onValueChange to react to selection changes (it receives the selected value string). [1][2]
  • You can still add an onClick to individual RadioGroup.Item (it's rendered as a button), but selection logic / change events should come from Root (Item no longer has onCheckedChange). [1][2]

Example (React + Radix)

  • Preferred: handle selection at the group level
    const handleChange = (value: string) => console.log('selected', value);
    <RadioGroup.Root onValueChange={handleChange} defaultValue="a">
    <RadioGroup.Item value="a" id="a" />A
    <RadioGroup.Item value="b" id="b" />B
    </RadioGroup.Root>

  • Per-item click (allowed, but keep selection handling on Root)
    <RadioGroup.Item value="a" onClick={() => console.log('item A clicked')} />

Notes

  • Radix changed the API: onValueChange now receives the value string, and RadioGroup.Item's onCheckedChange prop was removed — prefer Root-level onValueChange for change handling. [2]

Sources
[1] Radix Radio Group docs. [2] Radix releases (Radio Group notes).


Remove duplicate onClick from Label in both Checkbox and RadioGroupItem sections.

Based on radix-ui documentation and the code inspection, I found that:

  1. RadioGroupItem pattern (lines 87–94): Both RadioGroupItem and Label have onClick={() => recordFilterInput(filter)}. When the label is clicked via htmlFor, the Label's onClick fires, and this likely causes recordFilterInput to be called.

  2. Confirmed issue in Checkbox pattern (lines 65–71): The same double-handler structure exists here too. The Checkbox has onCheckedChange (proper radix-ui event), but the Label also has onClick. When the label is clicked, both fire, causing a confirmed double-trigger.

  3. Standards alignment: Per radix-ui documentation, the preferred pattern is to use RadioGroup.Root's onValueChange handler for selection logic, not onClick on individual items. Similarly, Checkbox should rely solely on onCheckedChange.

Remove the onClick handler from the Label in both sections to prevent duplicate calls:

                  <Label
                    htmlFor={filter}
-                   onClick={() => recordFilterInput(filter)}
                    className="text-sm text-zinc-300 cursor-pointer transition-colors"
                  >

Apply this fix to:

  • Line 69 (Checkbox Label)
  • Line 92 (RadioGroupItem Label)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<RadioGroupItem
value={filter}
id={filter}
onClick={() => recordFilterInput(filter)}
className="border-[#28282c] bg-[#141418] text-ox-purple transition data-[state=checked]:border-ox-purple data-[state=checked]:bg-ox-purple/20 data-[state=checked]:ring-2 data-[state=checked]:ring-ox-purple/50"
/>
<Label
htmlFor={filter}
onClick={() => recordFilterInput(filter)}
className="text-sm text-zinc-300 cursor-pointer transition-colors"
>
{filter}
</Label>
<RadioGroupItem
value={filter}
id={filter}
onClick={() => recordFilterInput(filter)}
className="border-[#28282c] bg-[#141418] text-ox-purple transition data-[state=checked]:border-ox-purple data-[state=checked]:bg-ox-purple/20 data-[state=checked]:ring-2 data-[state=checked]:ring-ox-purple/50"
/>
<Label
htmlFor={filter}
className="text-sm text-zinc-300 cursor-pointer transition-colors"
>
{filter}
</Label>
🤖 Prompt for AI Agents
In apps/web/src/components/ui/Filter.tsx around lines 65–71 and 87–94
(specifically remove the Label onClick at line 69 for the Checkbox block and at
line 92 for the RadioGroupItem block): the Label currently duplicates click
handling already handled by the Checkbox (onCheckedChange) and
RadioGroupItem/RadioGroup.Root (onValueChange), causing double-triggered events;
remove the onClick={() => recordFilterInput(filter)} prop from both Label
elements so selection logic relies only on the input components' handlers (keep
htmlFor and styling intact).

@huamanraj
Copy link
Collaborator

hey @BARNALIXD could you please share a working screen recording also please look at the coderabbit reviews!
thanks

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