Skip to content

Consolidate custom icons to Carbon design system equivalents#7738

Merged
gilluminate merged 30 commits intomainfrom
gill/icon-audit
Mar 25, 2026
Merged

Consolidate custom icons to Carbon design system equivalents#7738
gilluminate merged 30 commits intomainfrom
gill/icon-audit

Conversation

@gilluminate
Copy link
Copy Markdown
Contributor

@gilluminate gilluminate commented Mar 24, 2026

Ticket ENG-3081

Description Of Changes

Audit and migrate custom icon components to their Carbon design system (Icons.*) equivalents, removing ~25 unused or redundant icon components. Brand logos (AWS, Okta, Slack, Twilio, Mailgun) are consolidated under admin-ui/features/common/logos/ with a consistent size prop API. The remaining custom SVGs that have no Carbon equivalent (ArrowDownRight, Compass, ManualSetup, Monitor, Sparkle) are rewritten as plain forwardRef components in fidesui, dropping the Chakra createIcon dependency.

Icon migration PR 1 of 2

Code Changes

  • Replace ~20 custom fidesui icons with Carbon equivalents (e.g., GreenCheckCircleIcon -> Icons.CheckmarkFilled, TrashCanSolidIcon -> Icons.TrashCan, EyeIcon -> Icons.View, MoreIcon -> Icons.OverflowMenuVertical, etc.)
  • Move brand logos from scattered locations (features/messaging/icons/, features/common/Icon/, features/privacy-assessments/) into a single features/common/logos/ directory with named exports and consistent size props
  • Rewrite 4 remaining custom SVG icons as React.forwardRef components with displayName, currentColor support, and a size prop -- see clients/fidesui/src/icons/
  • Delete the entire features/common/Icon/ directory (Globe, database icons, arrow icons, etc.) and features/common/HorizontalStepper.tsx which depended on removed icons
  • Add a Storybook gallery story for the remaining custom icons -- see clients/fidesui/src/icons/icons.stories.tsx
  • Add a dev-only Icon Migration reference page at /poc/icon-migration for designer review of remaining non-Carbon icons

Sample migration sites for review:

  • Carbon icon usage in tables: FidesTable.tsx (Icons.OverflowMenuVertical, Icons.ExpandAll, Icons.CollapseAll)
  • Carbon icon in form input: inputs.tsx (Icons.View / Icons.ViewOff)
  • Logo consolidation: AwsSesMessagingForm.tsx (AwsSesLogo + Icons.CheckmarkFilled)
  • Config wizard with logo props: AddSystem.tsx (AWSLogo, OktaLogo, ManualSetupIcon)
  • System configure page: [id]/index.tsx (Icons.Settings replacing GearLightIcon)

Steps to Confirm

  1. Navigate to Add Systems page and verify AWS, Okta, and Manual Setup icons render correctly (top left of those old cards)
  2. Navigate to Notifications > Providers and verify messaging provider logos (Twilio, Mailgun, AWS SES) render in the table
  3. Open any messaging provider (Notifications) edit form and verify the logo appears in the header and the green checkmark renders on successful verification
  4. Navigate to the system configure page and verify the "Integrations" button has a gear icon

Pre-Merge Checklist

  • Issue requirements met
  • All CI pipelines succeeded
  • CHANGELOG.md updated
    • Add a db-migration This indicates that a change includes a database migration label to the entry if your change includes a DB migration
    • Add a high-risk This issue suggests changes that have a high-probability of breaking existing code label to the entry if your change includes a high-risk change (i.e. potential for performance impact or unexpected regression) that should be flagged
    • Updates unreleased work already in Changelog, no new entry necessary
  • UX feedback:
    • All UX related changes have been reviewed by a designer
    • No UX review needed
  • Followup issues:
    • Followup issues created
    • No followup issues
  • Database migrations:
    • Ensure that your downrev is up to date with the latest revision on main
    • Ensure that your downgrade() migration is correct and works
      • If a downgrade migration is not possible for this change, please call this out in the PR description!
    • No migrations
  • Documentation:
    • Documentation complete, PR opened in fidesdocs
    • Documentation issue created in fidesdocs
    • If there are any new client scopes created as part of the pull request, remember to update public-facing documentation that references our scope registry
    • No documentation updates required

@vercel
Copy link
Copy Markdown
Contributor

vercel bot commented Mar 24, 2026

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

Project Deployment Actions Updated (UTC)
fides-plus-nightly Ready Ready Preview, Comment Mar 25, 2026 3:33pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
fides-privacy-center Ignored Ignored Mar 25, 2026 3:33pm

Request Review

@gilluminate gilluminate marked this pull request as ready for review March 24, 2026 02:17
@gilluminate gilluminate requested a review from a team as a code owner March 24, 2026 02:17
@gilluminate gilluminate requested review from speaker-ender and removed request for a team March 24, 2026 02:17
Copy link
Copy Markdown

@claude claude bot left a comment

Choose a reason for hiding this comment

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

Code Review — Icon Audit Migration (PR #7738)

This is a solid, well-scoped cleanup. The migration from createIcon/createChakraIcon to either Carbon Icons.* equivalents or plain React.forwardRef SVGs is consistent throughout, and the consolidation of brand logos under common/logos/ with a uniform size prop API is a clear improvement. No correctness or security issues. Findings are all suggestions/visual checks.

Suggestions

OktaLogo.tsx — duplicate clipPath ID (flagged inline)
The <clipPath id="clip0_3116_111154"> is a hardcoded static ID. If multiple OktaLogo instances appear on the same page simultaneously (e.g., a table with multiple Okta rows), the DOM will have duplicate IDs. All other logo components in this PR avoid this issue. Worth fixing with useId() or by dropping the clip entirely if the paths are already correctly bounded.

inputs.tsx — dropped boxSize="full" from password toggle icon (flagged inline)
The old EyeIcon was explicitly sized to fill its container (boxSize="full"). The new Carbon icons have their own default dimensions. Verify the icon renders correctly at the small button size.

[id]/index.tsx — Integrations button lost size="small" (flagged inline)
The size="small" prop was removed from the Integrations tab button alongside the icon swap. If this is an intentional UX change, fine — but if not, it's a visual regression bundled into this icon-only PR.

SlackLogo.tsx — default size increased from 20→24px (flagged inline)
Call sites that don't pass an explicit size will get a slightly larger icon than before.

EditDrawer.tsxTrashCanOutlineIcon fontSize="small" dropped (flagged inline)
Icons.TrashCan renders at its default Carbon size. Quick visual check recommended.

Nice to Have

  • Logo accessibility: The new components in common/logos/ (AWSLogo, OktaLogo, SlackLogo, etc.) don't accept an aria-label or include a <title> element, and don't spread ...props to the <svg>. This makes it impossible for screen readers to identify the logo. The fidesui icon rewrites (ArrowDownRight, Compass, ManualSetup, Monitor) do spread ...props via forwardRef, which allows callers to pass aria-label. Consider aligning the logo components to the same pattern, or at minimum adding role="img" and aria-label at the usage sites where they appear without accompanying text.

  • Logo export style inconsistency: AWSLogo, OktaLogo, SlackLogo, TwilioLogo use inline arrow function exports (export const Foo = ...) without React.forwardRef, while AwsSesLogo and MailgunLogo (renames of the old AwsIcon/MailgunIcon) are function declarations that also don't forward refs. The fidesui icon rewrites all use forwardRef. Brand logos likely don't need ref forwarding, but a consistent pattern would be cleaner.

Overall this is a well-executed migration — the deletions are justified, the Carbon replacements are appropriate, and the forwardRef rewrites for the remaining custom icons are a clear improvement over createChakraIcon.

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.

Minor nit/comment but approving as is.
Looking good!

Comment on lines +30 to +44
export const Gallery: Story = {
render: () => (
<List
dataSource={icons}
renderItem={(item) => (
<List.Item>
<Flex align="center" gap={16}>
<item.component size={24} />
<Typography.Text code>{item.name}</Typography.Text>
</Flex>
</List.Item>
)}
/>
),
};
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.

Since we are already making stories for each individual icon, I think this might be unnecessary.
I do like the idea of seeing them all in one place.
That is where the docs plugin will start coming into play (once added)

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.

This one is for custom icons. There'll be another gallery for all the icons. Once everything is merged in we can take another look and figure out what makes sense. I almost think the individual icon stories are what should go away.

@gilluminate gilluminate added this pull request to the merge queue Mar 25, 2026
@gilluminate gilluminate removed this pull request from the merge queue due to a manual request Mar 25, 2026
@gilluminate gilluminate enabled auto-merge March 25, 2026 15:29
@gilluminate gilluminate added this pull request to the merge queue Mar 25, 2026
Merged via the queue into main with commit da90478 Mar 25, 2026
47 of 49 checks passed
@gilluminate gilluminate deleted the gill/icon-audit branch March 25, 2026 15:53
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.

3 participants