Skip to content

fix: Enable validation feedback for Canned Response Tags field#38723

Open
sezallagwal wants to merge 2 commits intoRocketChat:developfrom
sezallagwal:fix/canned-response-tags-validation
Open

fix: Enable validation feedback for Canned Response Tags field#38723
sezallagwal wants to merge 2 commits intoRocketChat:developfrom
sezallagwal:fix/canned-response-tags-validation

Conversation

@sezallagwal
Copy link

@sezallagwal sezallagwal commented Feb 15, 2026

Proposed changes

This PR fixes an issue where the Tags field in the Canned Responses form was disconnected from the form's validation system. Previously, if validation rules were applied to the Tags field, no visual feedback (red border or error message) was displayed to the user, leading to confusing "silent failures" on form submission.

Changes:

  • CannedResponseForm: Updated the Tags Controller to pass errors.tags and render a <FieldError> component, aligning with the pattern used for Shortcut and Message.
  • Tags Component: Updated to accept an error prop and propagate it to its children (TextInput or CurrentChatTags).
  • CurrentChatTags: Updated to accept the error prop and pass it as a boolean to PaginatedMultiSelectFiltered, ensuring the UI correctly reflects the error state.

Issue(s)

N/A (Addressed inline TODO: // TODO: refactor Tags field validation)

Verification Steps

Since the Tags field is currently optional, you must temporarily enforce a rule to verify the fix:

  1. In client/views/omnichannel/cannedResponses/components/CannedResponseForm.tsx, temporarily add a rule to the Tags Controller:
    rules={{ required: true }}
  2. Go to Canned Responses and attempt to save a new response without tags.
  3. Verify: The Tags field turns red and displays the "Required field" error message.

Screenshots

image

Types of changes

  • Bugfix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation Update (if none of the other choices apply)

Checklist

  • I have read the CONTRIBUTING doc
  • I have flagged this PR as "Ready for Review" or "WIP"
  • I have updated all the related documentation
  • Lint and unit tests pass locally with my changes
  • I have added tests that prove my fix is effective or that my feature works
  • I have added necessary documentation (if appropriate)
  • Any dependent changes have been merged and published in downstream modules

Summary by CodeRabbit

  • Bug Fixes
    • Tag validation errors in omnichannel forms now display inline on tag fields, providing clear per-field feedback.
    • Current chat tag controls will surface validation error messages when present, improving form usability.

@sezallagwal sezallagwal requested a review from a team as a code owner February 15, 2026 23:47
@dionisio-bot
Copy link
Contributor

dionisio-bot bot commented Feb 15, 2026

Looks like this PR is not ready to merge, because of the following issues:

  • This PR is missing the 'stat: QA assured' label
  • This PR is missing the required milestone or project

Please fix the issues and try again

If you have any trouble, please check the PR guidelines

@changeset-bot
Copy link

changeset-bot bot commented Feb 15, 2026

⚠️ No Changeset found

Latest commit: b142066

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 15, 2026

Walkthrough

CurrentChatTags now accepts an optional error?: string prop (not forwarded internally). Tags forwards an error prop into CurrentChatTags. CannedResponseForm passes errors.tags?.message to Tags and renders a FieldError when errors.tags exists.

Changes

Cohort / File(s) Summary
CurrentChatTags
apps/meteor/client/views/omnichannel/additionalForms/CurrentChatTags.tsx
Added optional error?: string to CurrentChatTags props and destructuring; did not change internal usage or forwarding to AutoCompleteTagsMultiple.
Tags component
apps/meteor/client/views/omnichannel/components/Tags.tsx
Now passes an error prop into CurrentChatTags when rendering tag values.
CannedResponseForm validation
apps/meteor/client/views/omnichannel/cannedResponses/components/CannedResponseForm.tsx
Updated Tags field to pass error={errors.tags?.message} and added a FieldError block to display per-field validation feedback when errors.tags exists.

Sequence Diagram(s)

(none — changes are prop additions and validation rendering without new multi-component control flow requiring a sequence diagram.)

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Suggested labels

type: bug

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main objective: enabling validation feedback (error messages and visual indicators) for the Tags field in the Canned Response form, which is reflected across all three modified files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


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.

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

No issues found across 3 files

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.

🧹 Nitpick comments (2)
apps/meteor/client/views/omnichannel/cannedResponses/components/CannedResponseForm.tsx (2)

102-113: Accessibility: Tags field doesn't follow the same aria-* pattern as Shortcut and Message.

The Shortcut and Message fields use useId() to generate a unique field ID, then wire up aria-describedby={${id}-error}, aria-required, and aria-invalid on the input, with the matching id on FieldError. The Tags field instead hardcodes id='tags-error' and doesn't pass aria-describedby or aria-invalid to Tags/its inputs. This breaks screen-reader association between the input and its error message and risks ID collisions.

Consider generating a tagsField ID via useId() and threading it through like the other fields.

Suggested approach
  const departmentField = useId();
+ const tagsField = useId();

Then in the Controller render:

- <Tags handler={onChange} tags={value} error={errors.tags?.message} />
+ <Tags handler={onChange} tags={value} error={errors.tags?.message} aria-describedby={`${tagsField}-error`} aria-invalid={Boolean(errors.tags)} />

And for the FieldError:

- <FieldError aria-live='assertive' id='tags-error'>
+ <FieldError aria-live='assertive' id={`${tagsField}-error`}>

(This would also require Tags to forward aria-describedby/aria-invalid to its underlying inputs.)


14-14: Consider removing or updating the TODO comment.

The TODO // TODO: refactor Tags field to get proper validation appears to be partially addressed by this PR. Either update it to reflect remaining work or remove it if this PR fully resolves the validation gap. As per coding guidelines, code comments should be avoided in the implementation.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 11e1c51 and 1f5d3ce.

📒 Files selected for processing (3)
  • apps/meteor/client/views/omnichannel/additionalForms/CurrentChatTags.tsx
  • apps/meteor/client/views/omnichannel/cannedResponses/components/CannedResponseForm.tsx
  • apps/meteor/client/views/omnichannel/components/Tags.tsx
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

**/*.{ts,tsx,js}: Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests
Avoid code comments in the implementation

Files:

  • apps/meteor/client/views/omnichannel/components/Tags.tsx
  • apps/meteor/client/views/omnichannel/additionalForms/CurrentChatTags.tsx
  • apps/meteor/client/views/omnichannel/cannedResponses/components/CannedResponseForm.tsx
🧠 Learnings (1)
📚 Learning: 2025-09-18T17:32:33.969Z
Learnt from: aleksandernsilva
Repo: RocketChat/Rocket.Chat PR: 36974
File: apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/forms/MessageForm/MessageForm.tsx:124-129
Timestamp: 2025-09-18T17:32:33.969Z
Learning: The ARIA mismatch issue in MessageForm's template field (where FieldError id used templateId instead of messageFormId) was addressed in PR `#36972` through refactoring the template field into a separate TemplateField component, which uses consistent templateFieldId for both aria-describedby and FieldError id.

Applied to files:

  • apps/meteor/client/views/omnichannel/cannedResponses/components/CannedResponseForm.tsx
🔇 Additional comments (2)
apps/meteor/client/views/omnichannel/components/Tags.tsx (1)

76-85: LGTM! The error prop is correctly forwarded to both the CurrentChatTags and TextInput branches, ensuring validation feedback works regardless of which input variant is rendered.

Also applies to: 88-101

apps/meteor/client/views/omnichannel/additionalForms/CurrentChatTags.tsx (1)

6-12: LGTM! The error prop is properly typed as an optional string, destructured separately, and coerced to boolean before passing to AutoCompleteTagsMultiple, which is the expected pattern for toggling visual error states.

Also applies to: 14-14, 28-28

@KevLehman KevLehman added the valid A valid contribution where maintainers will review based on priority label Feb 16, 2026
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: 1

Caution

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

⚠️ Outside diff range comments (1)
apps/meteor/client/views/omnichannel/additionalForms/CurrentChatTags.tsx (1)

14-21: ⚠️ Potential issue | 🟠 Major

Error prop is destructured but not forwarded to AutoCompleteTagsMultiple.

The error prop is accepted in the component signature but never passed to AutoCompleteTagsMultiple. This means validation feedback won't be displayed when using the CurrentChatTags path. AutoCompleteTagsMultiple inherits the error prop from PaginatedMultiSelectFiltered, so the prop must be explicitly forwarded.

🐛 Proposed fix
-	return <AutoCompleteTagsMultiple {...props} onChange={handler} value={value} department={department} viewAll={viewAll} />;
+	return <AutoCompleteTagsMultiple {...props} onChange={handler} value={value} department={department} viewAll={viewAll} error={error} />;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/meteor/client/views/omnichannel/additionalForms/CurrentChatTags.tsx`
around lines 14 - 21, The CurrentChatTags component destructures an error prop
but never forwards it to AutoCompleteTagsMultiple; update the return in
CurrentChatTags to pass the error prop through (alongside existing props like
value, handler/onChange, department, viewAll) so AutoCompleteTagsMultiple (and
its PaginatedMultiSelectFiltered) can display validation feedback.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/meteor/client/views/omnichannel/components/Tags.tsx`:
- Line 2: The import line in Tags.tsx is malformed: the import of useEffectEvent
from '@rocket.chat/fuselage-hooks' has a URL concatenated to it (merge artifact)
which causes a syntax error; open the Tags.tsx file, locate the import statement
referencing useEffectEvent and remove the trailing URL/merge-conflict text so
the line is a clean import (import { useEffectEvent } from
'@rocket.chat/fuselage-hooks';), then save and run the build/test to verify the
component (Tags component and any usages) compile correctly.

---

Outside diff comments:
In `@apps/meteor/client/views/omnichannel/additionalForms/CurrentChatTags.tsx`:
- Around line 14-21: The CurrentChatTags component destructures an error prop
but never forwards it to AutoCompleteTagsMultiple; update the return in
CurrentChatTags to pass the error prop through (alongside existing props like
value, handler/onChange, department, viewAll) so AutoCompleteTagsMultiple (and
its PaginatedMultiSelectFiltered) can display validation feedback.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1f5d3ce and b142066.

📒 Files selected for processing (2)
  • apps/meteor/client/views/omnichannel/additionalForms/CurrentChatTags.tsx
  • apps/meteor/client/views/omnichannel/components/Tags.tsx
📜 Review details
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

**/*.{ts,tsx,js}: Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests
Avoid code comments in the implementation

Files:

  • apps/meteor/client/views/omnichannel/components/Tags.tsx
  • apps/meteor/client/views/omnichannel/additionalForms/CurrentChatTags.tsx
🧠 Learnings (2)
📓 Common learnings
Learnt from: sampaiodiego
Repo: RocketChat/Rocket.Chat PR: 39003
File: apps/meteor/client/lib/chats/flows/sendMessage.ts:39-45
Timestamp: 2026-02-24T19:16:35.307Z
Learning: In apps/meteor/client/lib/chats/flows/sendMessage.ts, when sdk.call('sendMessage', ...) throws an error, the message is intentionally left with temp: true (not deleted or cleaned up) to support a future retry UI feature. This allows users to retry sending failed messages rather than losing them.
📚 Learning: 2025-11-17T15:07:13.273Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 37398
File: packages/fuselage-ui-kit/src/surfaces/FuselageSurfaceRenderer.tsx:357-363
Timestamp: 2025-11-17T15:07:13.273Z
Learning: In packages/fuselage-ui-kit/src/surfaces/FuselageSurfaceRenderer.tsx, IconElement is a presentational, non-actionable element that does not require wrapping in AppIdProvider, similar to plain_text and mrkdwn renderers. Only actionable elements (those with actions, actionId, or interactive behavior) should be wrapped in AppIdProvider.

Applied to files:

  • apps/meteor/client/views/omnichannel/components/Tags.tsx
🔇 Additional comments (1)
apps/meteor/client/views/omnichannel/components/Tags.tsx (1)

12-20: LGTM! Error prop propagation is correctly implemented.

The error prop is properly typed in TagsProps and passed to both CurrentChatTags and TextInput components, ensuring validation feedback can be displayed in both code paths.

Also applies to: 76-85, 88-101

@@ -1,5 +1,5 @@
import { TextInput, Chip, Button, FieldLabel, FieldRow } from '@rocket.chat/fuselage';
import { useEffectEvent } from '@rocket.chat/fuselage-hooks';
import { useEffectEvent } from '@rocket.chat/fuselage-hooks';https://github.com/RocketChat/Rocket.Chat/pull/38723/conflict?name=apps%252Fmeteor%252Fclient%252Fviews%252Fomnichannel%252FadditionalForms%252FCurrentChatTags.tsx&ancestor_oid=e298f3cb3dbc49d0e2bdcd928013aee0d2e22440&base_oid=d7bc69afc620395b2bddd53c4da0accc5750597f&head_oid=0df8f5d14a2ec04cd58afc296f8c9cde98a6b6f4
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: Malformed import statement with concatenated URL.

Line 2 contains a URL appended to the import statement, which is a syntax error that will break compilation. This appears to be a merge conflict artifact or copy-paste error.

🐛 Proposed fix
-import { useEffectEvent } from '@rocket.chat/fuselage-hooks';https://github.com/RocketChat/Rocket.Chat/pull/38723/conflict?name=apps%252Fmeteor%252Fclient%252Fviews%252Fomnichannel%252FadditionalForms%252FCurrentChatTags.tsx&ancestor_oid=e298f3cb3dbc49d0e2bdcd928013aee0d2e22440&base_oid=d7bc69afc620395b2bddd53c4da0accc5750597f&head_oid=0df8f5d14a2ec04cd58afc296f8c9cde98a6b6f4
+import { useEffectEvent } from '@rocket.chat/fuselage-hooks';
📝 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
import { useEffectEvent } from '@rocket.chat/fuselage-hooks';https://github.com/RocketChat/Rocket.Chat/pull/38723/conflict?name=apps%252Fmeteor%252Fclient%252Fviews%252Fomnichannel%252FadditionalForms%252FCurrentChatTags.tsx&ancestor_oid=e298f3cb3dbc49d0e2bdcd928013aee0d2e22440&base_oid=d7bc69afc620395b2bddd53c4da0accc5750597f&head_oid=0df8f5d14a2ec04cd58afc296f8c9cde98a6b6f4
import { useEffectEvent } from '@rocket.chat/fuselage-hooks';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/meteor/client/views/omnichannel/components/Tags.tsx` at line 2, The
import line in Tags.tsx is malformed: the import of useEffectEvent from
'@rocket.chat/fuselage-hooks' has a URL concatenated to it (merge artifact)
which causes a syntax error; open the Tags.tsx file, locate the import statement
referencing useEffectEvent and remove the trailing URL/merge-conflict text so
the line is a clean import (import { useEffectEvent } from
'@rocket.chat/fuselage-hooks';), then save and run the build/test to verify the
component (Tags component and any usages) compile correctly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type: bug valid A valid contribution where maintainers will review based on priority

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants