Skip to content

Conversation

@zamoore
Copy link
Contributor

@zamoore zamoore commented Dec 9, 2025

πŸ“Œ Summary

DO NOT MERGE - This PR is a spike with the goal of figuring out the best way to import Carbon icons in to HDS

πŸ› οΈ Detailed description

πŸ“Έ Screenshots

πŸ”— External links

Jira ticket: HDS-XXX
Figma file: [if it applies]


πŸ‘€ Component checklist

πŸ’¬ Please consider using conventional comments when reviewing this PR.

πŸ“‹ PCI review checklist
  • If applicable, I've documented a plan to revert these changes if they require more than reverting the pull request.
  • If applicable, I've worked with GRC to document the impact of any changes to security controls.
    Examples of changes to controls include access controls, encryption, logging, etc.
  • If applicable, I've worked with GRC to ensure compliance due to a significant change to the in-scope PCI environment.
    Examples include changes to operating systems, ports, protocols, services, cryptography-related components, PII processing code, etc.

@vercel
Copy link

vercel bot commented Dec 9, 2025

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

Project Deployment Review Updated (UTC)
hds-showcase Ready Ready Preview Dec 20, 2025 0:12am
hds-website Ready Ready Preview Dec 20, 2025 0:12am

Copy link
Contributor

@didoo didoo left a comment

Choose a reason for hiding this comment

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

Did a general review of the PR. We're definitely in the right direction, there are still a few things I want to discuss with you to better understand (when you're back).

@zamoore
Copy link
Contributor Author

zamoore commented Dec 16, 2025

Did a general review of the PR. We're definitely in the right direction, there are still a few things I want to discuss with you to better understand (when you're back).

What do you think of the changes? I believe I've addressed everything.

@zamoore zamoore requested a review from didoo December 16, 2025 22:16
Copy link
Contributor

@didoo didoo left a comment

Choose a reason for hiding this comment

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

I think the overall architecture and implementation clicks now. There are a few small things to tweak/fix here and there, but nothing major. We're in a very good spot now, I think.

The next steps for me, before opening a proper PR (or a set of stacked PRs, to ease code reviewing/approval) are:

  • address the latest comments
  • stress-test a bit more the implementation (I remember in the other PR you had this huge grid of all the HDS icon with a switcher on top, we could add it to the component/icon page)
  • stress-test in a couple of consumer app (HCP/Cloud UI and TFC/Atlas, I would say)

When we're sure that everything works (there may be things we didn't think of) we can start to write down the proposed solution in the RFC, so we can gather feedback from our consumers (I would also ask the FEF team and @meirish for feedback)

What do you think? It's a plan?

Copy link
Contributor

Choose a reason for hiding this comment

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

FYI @jorytindall is working on a script that generates a JSON with these mappsings, later we can use his JSON as "source of truth" so design and engineering are in sync

}
}

// Generate Registry (JS + Types)
Copy link
Contributor

Choose a reason for hiding this comment

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

Not sure if this comment I've found in Carbon is relevant for us, but I wanted to share it with you just in case: https://github.com/carbon-design-system/carbon/blob/main/packages/icon-build-helpers/src/builders/react/builder.js#L75-L84

Copy link
Contributor

@didoo didoo left a comment

Choose a reason for hiding this comment

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

I haven't fully reviewed generateBundleSymbolJS.ts but everything else yes, but everything is great πŸ‘ and I think at this point we can start to think how to open the "official" PR (or PRs, if you think you can split it somehow). Branching from the PR #3237 so you can use directly the hdsTheming service instead of the hdsCarbon service

const { name } = this.args;
const registryEntry = IconRegistry[name as HdsIconName];

if (this.hdsCarbon.carbonModeEnabled && registryEntry?.carbon) {
Copy link
Contributor

Choose a reason for hiding this comment

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

[note] below it's registryEntry.carbon (without ?), which one is correct?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

They're both correct. The second instance just has an assertion above it.

Copy link
Contributor

Choose a reason for hiding this comment

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

@zamoore OK, this lead me to another observation: you dont' need at all to set the viewport to 32px: because of how SVG works, the important thing is that the <symbol> has the correct viewport (32px) for the Carbon icons, here you can leave the standard viewport; which means you can get rid of this whole getter and just use 0 0 ${this.size} ${this.size} directly in the template as we did before

import type { SafeString } from '@ember/template';
import type { IconName } from '@hashicorp/flight-icons/svg';
import type Owner from '@ember/owner';
import type { HdsIconModule, HdsIconName } from '@hashicorp/flight-icons/symbol-js/registry.ts';
Copy link
Contributor

Choose a reason for hiding this comment

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

[note] The fact that we have IconName and HdsIconName may lead to confusion, what other name can we think of, for the HdsIconName imported from the registry?

or could we use a Partial of the IconName for the IconRegistry type?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We can use IconName directly which cleans up some of the typing. Good suggestion.


const loader = shouldUseCarbon
? registryEntry.carbon
: registryEntry.flight[size];
Copy link
Contributor

Choose a reason for hiding this comment

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

[praise] Neat! ❀️

if (loader) {
this.iconModule = await loader();
} else {
assert(`Size "${size}" not found for icon "${name}"`);
Copy link
Contributor

Choose a reason for hiding this comment

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

Mmm, are we sure this is the correct error message for this condition? Probably we can add a bit of logic here to differentiate the different messages for the different cases/errors/fails?

carbon: (() => Promise<HdsIconModule>) | null;
}

export declare const IconRegistry: Record<string, HdsIconRegistryEntry>;
Copy link
Contributor

Choose a reason for hiding this comment

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

[praise] so much simpler than the previous version! πŸ‘

@didoo
Copy link
Contributor

didoo commented Dec 18, 2025

@zamoore FYI this will be soon merged: #3444 and then I'll rebase #3237 on main so if you branch and start to work on the final PR(s) for this work, you can do it directly in .gts format

Copy link
Member

@alex-ju alex-ju left a comment

Choose a reason for hiding this comment

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

Some general consideration on my end – started a few days ago, but took me a while to re-assess today as many of my suggestions were no longer relevant/valid.

The refactored registry structure is a major improvement (grouping icons by base name with nested size loaders reduces registry size in half and creates much clearer separation between size-specific Flight icons and universal Carbon icons. Moving from bundled files to separate /symbol-js/flight/ and /symbol-js/carbon/ folders completely addresses my initial network overhead concern. With HTTP/2 multiplexing and individual file caching, this dynamic loading approach should actually be more efficient than bundled sprites. The simplified regex-based SVG processing and universal 32px Carbon icons with dynamic viewBox adjustment are both elegant solutions.

I think this is now production-ready pending stress testing (ideally with some basic performance metrics). I would personally look for any potential FOUC during async icon loads.

I would also recommend explicitly documenting the fallback behaviour (e.g. when Carbon mode is enabled but no Carbon equivalent exists).

Overall, the architecture is sound, backward compatibility is maintained, and the approach is well-suited for modern HTTP/2 environments. Great work @zamoore and @didoo!

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.

4 participants