Skip to content

feat: add Favorite Phrases Category Tags & Search - #1165

Merged
itzzavdhesh merged 1 commit into
itzzavdhesh:mainfrom
hrshjswniii:feature/Favorite-Phrases-Category-Search
Aug 6, 2026
Merged

feat: add Favorite Phrases Category Tags & Search#1165
itzzavdhesh merged 1 commit into
itzzavdhesh:mainfrom
hrshjswniii:feature/Favorite-Phrases-Category-Search

Conversation

@hrshjswniii

@hrshjswniii hrshjswniii commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

🚀 Program

GSSoC

📝 Description

This PR implements Favorite Phrases Category Tags & Search in FavoriteMessages.jsx. It equips non-verbal AAC users managing 20+ pinned phrases with category filter chips (All, Greetings, Needs, Questions, Social) and an inline live search input to instantly find essential phrases in fast-moving conversations.

Key additions:

  1. Category Tag Chips: Rendered interactive category filter chips (All, Greetings, Needs, Questions, Social) at the top of the Pinned Phrases board.
  2. Intent & Keyword Inference (getPhraseCategory): Built smart category inference classifying phrase intent based on question marks (?), urgent needs ("help/water/food/doctor"), greetings ("hello/thanks/bye"), and social phrases.
  3. Inline Live Search Bar: Embedded a compact search input with a Search icon and X clear button filtering pinned items in real time.
  4. Preserved Click-to-Speak Actions: Retained click-to-speak (onReuse) and unpin (onUnpin) actions on all filtered phrase chips.
  5. Unit Tests (FavoriteMessages.test.js): Added Vitest assertions for category inference and phrase classification logic.

🔗 Related Issue

Closes #1134

🔄 Type of Change

  • 🐛 Bug fix
  • ✨ New feature
  • 🔍 SEO improvement
  • 🎨 Style / UI improvement
  • ♿ Accessibility improvement
  • 📝 Documentation
  • ⚙️ CI / configuration
  • 🧹 Refactor / cleanup

🧪 How to Test

  1. Open http://localhost:5173 in a browser.
  2. Pin several phrases (e.g. "Hello good morning", "I need water please", "Where are we going?").
  3. Click category chips (Greetings, Needs, Questions) in the Pinned Phrases bar and verify filter switching.
  4. Type in the inline search bar and click X to clear search results.
  5. Run client tests: npm run test --workspace client and verify all tests pass.

✅ Checklist

  • I am contributing under GSSoC
  • My code follows the project's existing style
  • I have tested my changes in a browser
  • I have linked the related issue above
  • My PR title follows Conventional Commits format (e.g. feat: add favorite phrases category tags and search)

Summary by cubic

Adds category tags and live search to pinned phrases in FavoriteMessages so users can filter and find phrases quickly. Includes intent inference to auto-categorize phrases plus small UI and accessibility tweaks.

  • New Features
    • Category chips: All, Greetings, Needs, Questions, Social; filters without removing click-to-speak or unpin.
    • Inline live search with icon and clear button; filters results in real time.
    • getPhraseCategory infers categories from question marks and common keywords; defaults to social; unit tests added.
    • UI/accessibility: shows pinned count, FEW_SHOWN set to 6, “show more” respects filters, improved ARIA roles and labels.

Written for commit a692f13. Summary will update on new commits.

Review in cubic

@vercel

vercel Bot commented Jul 26, 2026

Copy link
Copy Markdown

@hrshjswniii is attempting to deploy a commit to the itzzavdhesh's projects Team on Vercel.

A member of the Team first needs to authorize it.

@github-actions

Copy link
Copy Markdown

✍️ DCO Sign-off Needed

Hey @hrshjswniii! 👋 One or more commits in this PR are missing a Signed-off-by: line.

Warning

  • a692f13 feat: add Favorite Phrases Category Tags & Search

How to fix:

For the latest commit:

git commit --amend --signoff
git push --force-with-lease

For multiple commits, replace N with the number to update:

git rebase --signoff HEAD~N
git push --force-with-lease

This comment will update automatically after you push.


🤖 VoiceForge Automation · Updates automatically on edits

@coderabbitai

coderabbitai Bot commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@hrshjswniii, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 54 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

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.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 2c12be95-0b76-4248-b022-281582c7ed9f

📥 Commits

Reviewing files that changed from the base of the PR and between e915118 and a692f13.

📒 Files selected for processing (2)
  • client/src/components/FavoriteMessages.jsx
  • client/src/components/FavoriteMessages.test.js
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@github-actions

github-actions Bot commented Jul 26, 2026

Copy link
Copy Markdown

🎉 PR Ready for Mentor Review

Hey @hrshjswniii! 👋 Your PR passed all checks and is now in the GSSoC review queue.

Note

🔗 Closing: #1134 · 📐 196 lines across 2 file(s) · 📬 Already requested or no eligible reviewer found

@sabeenaviklar @Anushreebasics @itsdakshjain @snehkris @1754riya @Mrigakshi-Rathore @Itzzavdheshh @Nitya-003 @4f4d @lovestaco, this PR is ready for your review — please confirm scope, check behavior and tests, then approve or request changes.

Important

This is not an approval. Please wait for mentor feedback before expecting a merge. If changes are requested, push them to this same branch and keep the PR focused on the linked issue.


🤖 VoiceForge Automation · Updates automatically on edits

@github-actions
github-actions Bot requested a review from lovestaco July 26, 2026 15:56

@cubic-dev-ai cubic-dev-ai Bot 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.

3 issues found across 2 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="client/src/components/FavoriteMessages.jsx">

<violation number="1" location="client/src/components/FavoriteMessages.jsx:2">
P3: Unused `Filter` import from lucide-react. The `Filter` icon is imported but never rendered anywhere in the component. Dead imports increase bundle size unnecessarily and add noise for future readers.</violation>

<violation number="2" location="client/src/components/FavoriteMessages.jsx:76">
P2: The search `<input>` has no accessible label. It relies solely on the `placeholder` attribute for its name, which is not a reliable accessible label — screen readers may announce it inconsistently or skip it entirely in some browsing modes. Adding an `aria-label` ensures the input is always identifiable to assistive technology.</violation>

<violation number="3" location="client/src/components/FavoriteMessages.jsx:121">
P3: The empty-state message only mentions "in this category" but the empty result could also come from the search filter (or both). If the user has the "All" category selected and types a search that matches nothing, the message "No pinned phrases found in this category" is misleading — the issue is the search query, not the category. Consider a dynamic message that reflects which filter(s) are active.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment on lines +76 to +82
<input
type="text"
value={search}
onChange={(e) => setSearch(e.target.value)}
placeholder="Search pinned..."
className="w-full rounded-full border border-amber-200 bg-white py-1 pl-7 pr-6 text-xs text-amber-900 placeholder:text-amber-400/80 outline-none focus:ring-1 focus:ring-amber-400 dark:border-amber-500/30 dark:bg-surface dark:text-amber-200 dark:placeholder:text-amber-500/60"
/>

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.

P2: The search <input> has no accessible label. It relies solely on the placeholder attribute for its name, which is not a reliable accessible label — screen readers may announce it inconsistently or skip it entirely in some browsing modes. Adding an aria-label ensures the input is always identifiable to assistive technology.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At client/src/components/FavoriteMessages.jsx, line 76:

<comment>The search `<input>` has no accessible label. It relies solely on the `placeholder` attribute for its name, which is not a reliable accessible label — screen readers may announce it inconsistently or skip it entirely in some browsing modes. Adding an `aria-label` ensures the input is always identifiable to assistive technology.</comment>

<file context>
@@ -1,64 +1,159 @@
+        {/* Compact Search Bar */}
+        <div className="relative flex items-center min-w-[140px] max-w-[200px]">
+          <Search size={12} className="pointer-events-none absolute left-2 text-amber-500" aria-hidden="true" />
+          <input
+            type="text"
+            value={search}
</file context>
Suggested change
<input
type="text"
value={search}
onChange={(e) => setSearch(e.target.value)}
placeholder="Search pinned..."
className="w-full rounded-full border border-amber-200 bg-white py-1 pl-7 pr-6 text-xs text-amber-900 placeholder:text-amber-400/80 outline-none focus:ring-1 focus:ring-amber-400 dark:border-amber-500/30 dark:bg-surface dark:text-amber-200 dark:placeholder:text-amber-500/60"
/>
<input
type="text"
value={search}
onChange={(e) => setSearch(e.target.value)}
placeholder="Search pinned..."
aria-label="Search pinned phrases"
className="w-full rounded-full border border-amber-200 bg-white py-1 pl-7 pr-6 text-xs text-amber-900 placeholder:text-amber-400/80 outline-none focus:ring-1 focus:ring-amber-400 dark:border-amber-500/30 dark:bg-surface dark:text-amber-200 dark:placeholder:text-amber-500/60"
/>

{/* Pinned Phrase List */}
<div className="flex flex-wrap items-center gap-1.5" role="list" aria-label="Pinned phrases">
{displayed.length === 0 ? (
<p className="text-xs italic text-amber-700/70 dark:text-amber-400/70 py-1">

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.

P3: The empty-state message only mentions "in this category" but the empty result could also come from the search filter (or both). If the user has the "All" category selected and types a search that matches nothing, the message "No pinned phrases found in this category" is misleading — the issue is the search query, not the category. Consider a dynamic message that reflects which filter(s) are active.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At client/src/components/FavoriteMessages.jsx, line 121:

<comment>The empty-state message only mentions "in this category" but the empty result could also come from the search filter (or both). If the user has the "All" category selected and types a search that matches nothing, the message "No pinned phrases found in this category" is misleading — the issue is the search query, not the category. Consider a dynamic message that reflects which filter(s) are active.</comment>

<file context>
@@ -1,64 +1,159 @@
+      {/* Pinned Phrase List */}
+      <div className="flex flex-wrap items-center gap-1.5" role="list" aria-label="Pinned phrases">
+        {displayed.length === 0 ? (
+          <p className="text-xs italic text-amber-700/70 dark:text-amber-400/70 py-1">
+            No pinned phrases found in this category.
+          </p>
</file context>

import React, { useState } from "react";
import { Pin, X } from "lucide-react";
import React, { useMemo, useState } from "react";
import { Pin, X, Search, Filter } from "lucide-react";

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.

P3: Unused Filter import from lucide-react. The Filter icon is imported but never rendered anywhere in the component. Dead imports increase bundle size unnecessarily and add noise for future readers.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At client/src/components/FavoriteMessages.jsx, line 2:

<comment>Unused `Filter` import from lucide-react. The `Filter` icon is imported but never rendered anywhere in the component. Dead imports increase bundle size unnecessarily and add noise for future readers.</comment>

<file context>
@@ -1,64 +1,159 @@
-import React, { useState } from "react";
-import { Pin, X } from "lucide-react";
+import React, { useMemo, useState } from "react";
+import { Pin, X, Search, Filter } from "lucide-react";
 
-const FEW_SHOWN = 5;
</file context>
Suggested change
import { Pin, X, Search, Filter } from "lucide-react";
import { Pin, X, Search } from "lucide-react";

@Nitya-003 Nitya-003 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@hrshjswniii Resolve the conflicts.

@github-actions github-actions Bot added mentor:Nitya-003 Applied by mentor automation needs revision labels Jul 27, 2026
@github-actions

Copy link
Copy Markdown

🔄 Changes Requested

Hey @hrshjswniii! 👋 A mentor has reviewed your PR and requested some changes.

Warning

Please review the feedback above, update this same branch, and keep the PR focused on the linked issue.

Once you push your updates, the review flow will continue automatically on this same PR.


🤖 VoiceForge Automation · Updates automatically on edits

@itsdakshjain itsdakshjain left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

resolve the merge conflicts and address the code review feedback from cubic-dev-ai.

@github-actions github-actions Bot added the mentor:itsdakshjain GSSoC: Mentor-@itsdakshjain label Jul 27, 2026
@itzzavdhesh
itzzavdhesh merged commit 9675f10 into itzzavdhesh:main Aug 6, 2026
22 of 23 checks passed
@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown

🎊 PR Merged Successfully

Hey @hrshjswniii! 👋 Congratulations and thank you for your contribution to VoiceForge!

Note

🔗 Linked issue(s): #1134 · ✅ Marked as merged and complete

Maintainers may still handle final cleanup, release notes, or follow-up tracking after the merge.


🤖 VoiceForge Automation · Updates automatically on edits

@itzzavdhesh itzzavdhesh added SSoC26 SSOC Hard hard ELUSOC ELUSOC VETERAN VETERAN type:feature type:feature type:refactor type:refactor mentor:Anushreebasics GSSoC: Mentor-@Anushreebasics mentor:sabeenaviklar GSSoC: Mentor-@sabeenaviklar labels Aug 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: Favorite Phrases Category Tags & Search

4 participants