Skip to content

ENG-2890: Extend message and notification APIs to use Carbon icons#7582

Merged
gilluminate merged 24 commits intomainfrom
gill/ENG-2890/message-notification-carbon-icons
Mar 9, 2026
Merged

ENG-2890: Extend message and notification APIs to use Carbon icons#7582
gilluminate merged 24 commits intomainfrom
gill/ENG-2890/message-notification-carbon-icons

Conversation

@gilluminate
Copy link
Copy Markdown
Contributor

@gilluminate gilluminate commented Mar 5, 2026

Ticket ENG-2890

Dependency: Requires #7569 to be merged first (modal Carbon icons)

Description Of Changes

Extend the Carbon icon wrapping pattern from #7569 to cover Ant Design's message and notification APIs. All three feedback APIs (modal, message, notification) now automatically inject Carbon icons for info, success, error, and warning methods when consumed through the FidesUI provider hooks.

The message API's loading method intentionally keeps Ant's default spinner, and open/destroy are inherited unchanged.

Also migrates two admin-ui components that were using Ant's notification directly to go through the provider's useNotification() hook, ensuring consistent icon rendering.

Code Changes

  • clients/fidesui/src/lib/carbon-icon-defaults.tsx - Add message (16px + 8px margin) and notification (24px) icon maps with getter functions
  • clients/fidesui/src/FidesUIProvider.tsx - Wrap messageApi and notificationApi with Carbon icon defaults; handle message API's dual call signature (string vs object form)
  • clients/admin-ui/src/features/privacy-assessments/AssessmentTaskStatusIndicator.tsx - Migrate from notification.useNotification() to provider's useNotification() hook; remove Fragment wrapper
  • clients/admin-ui/src/features/privacy-experience/preview/Preview.tsx - Migrate from static notification.warning() to provider's useNotification() hook

Steps to Confirm

  1. Run Storybook in clients/fidesui/ (npm run storybook)
    • Navigate to Feedback > Message Methods - each type (info, success, error, warning) should show correct Carbon icon with proper color
    • Navigate to Feedback > Notification Methods - each type should show correct Carbon icon with proper color
    • Loading message should still show Ant's default spinner (no Carbon icon)
  2. Run admin-ui dev server (npm run dev in clients/admin-ui/)
    • Trigger a notification (e.g., on the privacy experience preview page with a TCF overlay and no vendors, a warning notification should appear with a Carbon WarningFilled icon)
    • Verify messages and notifications throughout the app render with Carbon icons

Pre-Merge Checklist

  • Issue requirements met
  • All CI pipelines succeeded
  • CHANGELOG.md updated
    • Updates unreleased work already in Changelog, no new entry necessary
  • UX feedback:
    • All UX related changes have been reviewed by a designer
  • Followup issues:
    • No followup issues
  • Database migrations:
    • No migrations
  • Documentation:
    • No documentation updates required

Summary by CodeRabbit

  • New Features

    • Message and notification components now display Carbon icons automatically for improved visual consistency and better user feedback.
  • Refactor

    • Improved notification system architecture by enhancing message and notification APIs to support Carbon icon integration through the FidesUI provider.

gilluminate and others added 10 commits March 4, 2026 16:00
Wrap the useModal hook in FidesUIProvider to inject Carbon icon
equivalents (InformationFilled, CheckmarkFilled, WarningFilled, Misuse)
as defaults for info, success, warning, error, and confirm modals.
Callers can still override with icon prop or suppress with icon: null.

Add Modal Methods Storybook stories for visual verification.

ENG-2889

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add useEffect dependencies and destroy() cleanup in stories
- Use public import path for CarbonIconType
- Add hideIcon default arg to all stories, remove standalone NoIcon story

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add Carbon icon defaults for message (16px) and notification (24px) APIs,
matching the existing modal pattern. Wrap both APIs in FidesUIProvider to
automatically inject icons for info/success/error/warning methods while
preserving loading's default spinner. Migrate admin-ui call sites from
direct antd notification usage to the provider's useNotification hook.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown
Contributor

vercel bot commented Mar 5, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

2 Skipped Deployments
Project Deployment Actions Updated (UTC)
fides-plus-nightly Ignored Ignored Preview Mar 9, 2026 4:46pm
fides-privacy-center Ignored Ignored Mar 9, 2026 4:46pm

Request Review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 5, 2026

📝 Walkthrough

Walkthrough

This PR extends message and notification APIs to use Carbon icons via the FidesUI provider. It refactors carbon-icon-defaults to support message and notification feedback types with corresponding icon maps, updates FidesUIProvider to wrap message and notification methods with automatic default icons, and modifies components to use the new useNotification hook-based API instead of direct notification imports.

Changes

Cohort / File(s) Summary
Changelog
changelog/7582-message-notification-carbon-icons.yaml
Added changelog entry documenting the extension of message and notification APIs to use Carbon icons.
FidesUI Core Provider
clients/fidesui/src/FidesUIProvider.tsx
Integrated message and notification API wrapping with automatic Carbon icon injection; wraps message methods (info, success, error, warning) and notification methods with default icons; exports wrapped APIs via provider context.
Icon Utilities
clients/fidesui/src/lib/carbon-icon-defaults.tsx
Introduced public types FeedbackType and ModalType; refactored icon maps to support message and notification icons separately; added getDefaultMessageIcon and getDefaultNotificationIcon getters; updated getDefaultModalIcon signature to use typed parameter.
Component Notification Refactoring
clients/admin-ui/src/features/privacy-assessments/AssessmentTaskStatusIndicator.tsx, clients/admin-ui/src/features/privacy-experience/preview/Preview.tsx
Replaced direct notification imports with useNotification hook from fidesui; updated notification calls to use the hook-based API (notificationApi.success/error/warning); added notificationApi to effect dependency arrays.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • kruulik
  • speaker-ender

Poem

🐰 Carbon icons now dance through messages bright,
With notifications adorned in visual light,
The FidesUI provider wraps each call,
Icons for all feedback types, big and small! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'ENG-2890: Extend message and notification APIs to use Carbon icons' clearly and concisely summarizes the main change: adding Carbon icon support to Ant Design's message and notification APIs.
Description check ✅ Passed The PR description comprehensively covers all template sections: ticket link, detailed description of changes, specific code changes, verification steps, and a completed pre-merge checklist addressing migrations, documentation, and UX review.
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.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch gill/ENG-2890/message-notification-carbon-icons

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

@gilluminate gilluminate marked this pull request as ready for review March 5, 2026 22:21
@gilluminate gilluminate requested a review from a team as a code owner March 5, 2026 22:21
@gilluminate gilluminate requested review from speaker-ender and removed request for a team March 5, 2026 22:21
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 5, 2026

Greptile Summary

This PR extends the Carbon icon injection pattern (previously applied only to Ant Design's Modal API in #7569) to cover the message and notification APIs as well. The implementation introduces per-API static icon maps and getter functions in carbon-icon-defaults.tsx, then wraps the APIs with Carbon icon defaults inside FidesUIProvider before exposing them through the existing useMessage() and useNotification() hooks. Two admin-ui components are also migrated from direct Ant Design notification usage to the provider-based hook, ensuring consistent icon rendering throughout the app.

  • carbon-icon-defaults.tsx: Adds MESSAGE_ICON_MAP (16px icons with 8px right margin) and NOTIFICATION_ICON_MAP (24px icons) alongside the existing MODAL_ICON_MAP; renames the private icon helper to modalIcon and introduces a shared inlineIcon helper for the two new maps.
  • FidesUIProvider.tsx: Adds wrapMessageMethod to handle Ant Design's dual call signature for message methods (bare string/ReactNode vs. ArgsProps object), then wraps messageApi and notificationApi in useMemo similarly to how modalApi was already wrapped. Imports internal types from antd/lib/message/interface.
  • AssessmentTaskStatusIndicator.tsx: Migrates from notification.useNotification() to the provider's useNotification(), removing the now-unnecessary Fragment wrapper and notificationHolder since the provider manages its own holder.
  • Preview.tsx: Replaces the static notification.warning() call with the provider hook; notification is added to the useEffect dependency array, which is technically correct but creates a subtle dependency on reference stability of the API object returned by the context.

Confidence Score: 4/5

  • This PR is safe to merge with minor caveats around a subtle useEffect dependency and an internal antd type import path.
  • The implementation is consistent, well-factored, and follows the established pattern from the parent branch. No logic bugs were found. Two minor style concerns were noted: (1) notification being in the useEffect deps in Preview.tsx creates a silent re-fire risk if the context is ever recreated; and (2) the import from antd/lib/message/interface is an internal path that could break across releases. Neither is a blocker for the current use case given Ant Design's stable hook references.
  • clients/admin-ui/src/features/privacy-experience/preview/Preview.tsx — verify the notification deps-array addition behaves as expected when the provider context re-renders.

Important Files Changed

Filename Overview
clients/fidesui/src/lib/carbon-icon-defaults.tsx Clean extension of the existing modal icon pattern to add message (16px) and notification (24px) static icon maps. The new inlineIcon helper is well-factored and the exported getter functions follow the established getDefaultModalIcon convention.
clients/fidesui/src/FidesUIProvider.tsx Adds wrapMessageMethod to handle Ant Design's dual call signature (string vs ArgsProps object) and wraps messageApi and notificationApi with Carbon icon defaults via useMemo. The type import from antd/lib/message/interface is an internal antd path, which is consistent with how other types are imported in the file but is worth noting.
clients/admin-ui/src/features/privacy-assessments/AssessmentTaskStatusIndicator.tsx Clean migration from notification.useNotification() to the provider's useNotification() hook. Removes the now-unnecessary Fragment wrapper and notificationHolder since the provider manages the holder in its own tree.
clients/admin-ui/src/features/privacy-experience/preview/Preview.tsx Migrates from the static notification.warning() call to the provider's useNotification() hook. notification is correctly added to the useEffect dependency array, though this creates a subtle dependency on the stability of the notification API reference returned by the provider context.
changelog/7582-message-notification-carbon-icons.yaml Correct changelog entry with type "Changed", accurate description, and matching PR number.

Last reviewed commit: 241a318

Copy link
Copy Markdown
Contributor

@speaker-ender speaker-ender left a comment

Choose a reason for hiding this comment

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

Overall looks good. Left some comments but don't need to be addressed now.

Comment on lines +29 to +51
const wrapMessageMethod = (
method: MessageTypeOpen,
type: string,
): MessageTypeOpen => {
const defaultIcon = getDefaultMessageIcon(type);
return (content, duration?, onClose?) => {
if (isMessageArgsProps(content)) {
// ArgsProps form - inject icon as default, caller can override
return method({ icon: defaultIcon, ...content });
}
// JointContent (string/ReactNode) - convert to ArgsProps to inject icon
const args: MessageArgsProps = { content, icon: defaultIcon };
if (typeof duration === "number") {
args.duration = duration;
} else if (typeof duration === "function") {
args.onClose = duration;
}
if (onClose) {
args.onClose = onClose;
}
return method(args);
};
};
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.

Any thoughts on just picking one method for using messages?
It's a little much to expect devs to pick between the two.
If we leave in we should leave a recommendation/explanation of when to use each.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think it's fine to keep both. Devs should be getting direction from design on which feedback pattern to use for a given interaction, so the choice shouldn't fall on them to figure out independently.

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.

@gilluminate To be clear I'm talking about the two styles of function calls

  1. message.success(content, [duration], onClose)
  2. message.success(config)
    This is more of a technical/code style decision imo

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Ah my bad. That makes more sense, I thought you were talking about only using message OR notification. Hmmmm...yeah, I'm torn on this one. Notification ONLY supports the config style, so it kind of makes sense to restrict to only use that for message. On the other hand, we have 70+ instances of message only using the content style so that'd be a major overhaul. Keeping both in the wrapper is ~15 lines of logic to avoid touching 70+ files.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Added a JSDoc to wrapMessageMethod recommending the string form as the default. Happy to collapse to one style if we find a strong reason to later.

gilluminate and others added 10 commits March 6, 2026 14:38
- Type icon map keys with FeedbackType and ModalType unions
- Remove nullish coalescing from getter functions
- Update wrapMessageMethod to use FeedbackType param

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wrap the useModal hook in FidesUIProvider to inject Carbon icon
equivalents (InformationFilled, CheckmarkFilled, WarningFilled, Misuse)
as defaults for info, success, warning, error, and confirm modals.
Callers can still override with icon prop or suppress with icon: null.

Add Modal Methods Storybook stories for visual verification.

ENG-2889

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add useEffect dependencies and destroy() cleanup in stories
- Use public import path for CarbonIconType
- Add hideIcon default arg to all stories, remove standalone NoIcon story

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove unnecessary modalApi spread in FidesUIProvider
- Nest modal method stories under Feedback/Modal/Methods
- Add Primary story pattern with type control disabled on variants

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@gilluminate gilluminate force-pushed the gill/ENG-2889/modal-carbon-icons branch from cbbe49d to 2666242 Compare March 6, 2026 21:39
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Base automatically changed from gill/ENG-2889/modal-carbon-icons to main March 9, 2026 16:34
@gilluminate gilluminate enabled auto-merge March 9, 2026 16:45
Copy link
Copy Markdown

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@clients/fidesui/src/FidesUIProvider.tsx`:
- Around line 46-48: The spread `{ icon: defaultIcon, ...content }` lets callers
pass icon: undefined and overwrite the injected default; change the logic in the
isMessageArgsProps branch to set icon only when the incoming icon is undefined
(e.g., determine icon = content.icon === undefined ? defaultIcon : content.icon)
and pass that computed icon into method instead of relying on the spread, and
apply the exact same undefined-only check to the success, error, and warning
notification handlers so null remains a valid explicit opt-out while undefined
preserves the defaultIcon.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 104fec4b-af2a-4d0c-9b15-a856646f9c96

📥 Commits

Reviewing files that changed from the base of the PR and between e4e9986 and b07261f.

📒 Files selected for processing (5)
  • changelog/7582-message-notification-carbon-icons.yaml
  • clients/admin-ui/src/features/privacy-assessments/AssessmentTaskStatusIndicator.tsx
  • clients/admin-ui/src/features/privacy-experience/preview/Preview.tsx
  • clients/fidesui/src/FidesUIProvider.tsx
  • clients/fidesui/src/lib/carbon-icon-defaults.tsx

Comment on lines +46 to +48
if (isMessageArgsProps(content)) {
// ArgsProps form - inject icon as default, caller can override
return method({ icon: defaultIcon, ...content });
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
sed -n '44,49p' clients/fidesui/src/FidesUIProvider.tsx
sed -n '123,141p' clients/fidesui/src/FidesUIProvider.tsx

node <<'NODE'
const cases = [
  {
    label: 'message/object form',
    value: { icon: 'default', ...{ icon: undefined, content: 'Saved' } },
  },
  {
    label: 'notification/object form',
    value: { icon: 'default', ...{ icon: undefined, message: 'Saved' } },
  },
  {
    label: 'explicit null opt-out',
    value: { icon: 'default', ...{ icon: null, message: 'Saved' } },
  },
];
for (const { label, value } of cases) {
  console.log(label, value);
}
NODE

Repository: ethyca/fides

Length of output: 1242


Don't let icon: undefined overwrite the injected default.

In { icon: defaultIcon, ...content } and the notification handlers, when callers pass an optional icon field that resolves to undefined, the spread operator overwrites the default icon. This breaks the automatic icon injection behavior. Use an explicit undefined check to preserve the default only when icon is not explicitly provided, while still allowing null as an intentional opt-out.

🛠️ Suggested change
     if (isMessageArgsProps(content)) {
       // ArgsProps form - inject icon as default, caller can override
-      return method({ icon: defaultIcon, ...content });
+      return method({
+        ...content,
+        icon: content.icon === undefined ? defaultIcon : content.icon,
+      });
     }
       info: (props: Parameters<typeof notificationApi.info>[0]) =>
         notificationApi.info({
-          icon: getDefaultNotificationIcon("info"),
           ...props,
+          icon:
+            props.icon === undefined
+              ? getDefaultNotificationIcon("info")
+              : props.icon,
         }),

Apply the same pattern to success, error, and warning notification handlers.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@clients/fidesui/src/FidesUIProvider.tsx` around lines 46 - 48, The spread `{
icon: defaultIcon, ...content }` lets callers pass icon: undefined and overwrite
the injected default; change the logic in the isMessageArgsProps branch to set
icon only when the incoming icon is undefined (e.g., determine icon =
content.icon === undefined ? defaultIcon : content.icon) and pass that computed
icon into method instead of relying on the spread, and apply the exact same
undefined-only check to the success, error, and warning notification handlers so
null remains a valid explicit opt-out while undefined preserves the defaultIcon.

@gilluminate gilluminate added this pull request to the merge queue Mar 9, 2026
Merged via the queue into main with commit 4791199 Mar 9, 2026
50 checks passed
@gilluminate gilluminate deleted the gill/ENG-2890/message-notification-carbon-icons branch March 9, 2026 17:12
mfbrown pushed a commit that referenced this pull request Mar 12, 2026
…7582)

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
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