Conversation
84fae89 to
feb4960
Compare
|
There was a problem hiding this comment.
skimmed through the PR and mostly left questions, not change requests since i'm not familiar with the first iteration at all
i'm not really sure about the name "stroke" for the new icon variants, since it's a small technical detail about them, not really important for neither us and especially not for the end user. i think a more semantic differentiation could be better but that's just my 2 cents
as someone who is not familiar with how the icons are generated, from where and why, the structure feels very complicated to me and i'm not really looking forward to maintain this in the future. i think it would really benefit us in the long run to come up with something that's easier to wrap our heads around
also with the old icons we also provided the raw svg values along with the react components (in the docs page). are those not needed anymore? I'm not against it, just asking if that is intentional
docs/guides/upgrade-guide.md
Outdated
| InstUI has switched to a new icon set based on [Lucide](https://lucide.dev/icons/). We are still keeping some Instructure-specific icons, like product logos. We have a codemod that will help you migrate your code to the new icon set (see below). | ||
|
|
||
| ### Lucide Icons Package | ||
| ### Stroke-Based Icons Package |
There was a problem hiding this comment.
where is this name coming from? did design come up with it? it's a bit confusing for me what it means (and how this is different from other icons. others are store based too, no?)
There was a problem hiding this comment.
This is not an issue anymore, I removed the 'filled', 'stroke' names.
| const __dirname = path.dirname(__filename) | ||
| const require = createRequire(import.meta.url) | ||
|
|
||
| // Use CommonJS require to load ui-themes to avoid ES module resolution issues |
There was a problem hiding this comment.
is this a new issue? or was it not working before?
There was a problem hiding this comment.
It was caused by the local Node 22.6 issue. I fixed it.
There was a problem hiding this comment.
Is there a reason this is in a separate dir and not under Icons?
There was a problem hiding this comment.
Yes, old icons will be shown on a separate page than new icons.
| * Stroke width is automatically derived from size for consistent visual weight. | ||
| * Numeric and custom CSS values are not supported. | ||
| */ | ||
| export function wrapStrokeIcon( |
There was a problem hiding this comment.
wouldn't wrapLucideIcon actually be an appropriate name here? since this is actually for wrapping just the lucide library icons
There was a problem hiding this comment.
It is, I restored it during refactoring.
There was a problem hiding this comment.
is this a build file? seems like it has the same svg data as svg/Custom/.... or what's the difference?
There was a problem hiding this comment.
This file is generated by the generateCustomIndex script. It contains all the custom icons that developers can import.
packages/ui-icons/src/index.ts
Outdated
| // Re-export all generated SVG icons and Lucide icons | ||
| // Main entry point - exports all icons for backwards compatibility | ||
| export * from './lucide' | ||
| export * from './custom' |
There was a problem hiding this comment.
could this (in theory) cause a naming conflict if a custom icon has a same name as a lucide icon? is that even a problem?
There was a problem hiding this comment.
Naming conflicts are handled in generateLucideIndex (lines 69-88). Custom icons shadow Lucide icons of the same name.
There was a problem hiding this comment.
isn't this the canvas logo?
There was a problem hiding this comment.
I copied this icon from the old icon build system. Yeah it looks like the canvas logo and canvas.svg looks pretty similar. I reach out to designers whether they want to keep this under this name.
| const MyIcon = () => { | ||
| return ( | ||
| <${iconName} size={'2xl'} color='successColor'/> | ||
| <${icon.name} size={'2xl'} color='successColor' /> |
There was a problem hiding this comment.
nitpick: double quotes and string primitive would be nicer here
|
|
||
| function getUsageInfo(iconName: string) { | ||
| return `import { ${iconName} } from '@instructure/ui-icons' | ||
| // Get all stroke icons |
There was a problem hiding this comment.
this section is a bit overcomplicated. you are getting the keys of each icon type to convert an object list to a string array and then you are converting it back to an object while accessing each item in the original list again. this is resource heavy and with lots of icons could cause perf issue.
There was a problem hiding this comment.
Refactored IconsGallery entirely, this is no longer an issue.
| ...strokeIconNames.map((name) => ({ | ||
| name, | ||
| component: (StrokeIcons as any)[name], | ||
| source: 'stroke' as const, |
There was a problem hiding this comment.
I don't like it either but it is needed for the type IconInfo otherwise ts throws an error.
packages/ui-icons/src/stroke/wrapStrokeIcon/createIconWrapper.tsx
Outdated
Show resolved
Hide resolved
balzss
left a comment
There was a problem hiding this comment.
also it seems like the custom icons with ai color have a border around them:
<div>
<IconButton><SparklesInstUIIcon size="2xl" color="ai"/></IconButton>
<IconButton><Sparkles2InstUIIcon size="2xl" color="ai" /></IconButton>
</div>
is this intentional?
also the new icons docs page have a border around which doesn't seem necessary and the focus ring is cut off from the input field:
the custom filled ai button is black in the avatar example, this also seems like a bug:
290e31a to
f72f6cb
Compare
b41e5e2 to
f3dfb7f
Compare
| // write legacy-icons-data.json for the docs gallery | ||
| const legacyIconsData = generateLegacyIconsData() | ||
| const legacyOutputDir = path.join(process.cwd(), 'lib/legacy/') | ||
| fs.mkdirSync(legacyOutputDir, { recursive: true }) | ||
| const legacyOutputPath = path.join( | ||
| legacyOutputDir, | ||
| 'legacy-icons-data.json' | ||
| ) | ||
| fs.writeFileSync( | ||
| `${config.destination}icons-data.json`, | ||
| JSON.stringify(iconsData) | ||
| legacyOutputPath, | ||
| JSON.stringify(legacyIconsData, null, 2), | ||
| 'utf8' | ||
| ) | ||
| info(`Generated ${legacyOutputPath} (${legacyIconsData.length} icons)`) |
There was a problem hiding this comment.
hmm I dont understand this part. This json is only generated for the docs page? Why not use the icons itself in the docs app, that way we are also checking that they work OK. Why not just take them from the buil;d __build__ folder?
There was a problem hiding this comment.
We discussed this already but legacy icons are shown and exposed as svg too. This json is needed for the docs file. It can be removed when we remove all legacy icons in a future release.
f3dfb7f to
5a671d2
Compare
docs/patterns/UsingIcons.md
Outdated
| Icons from `@instructure/ui-icons` are available as `<Name>InstUIIcon` components — browse them | ||
| in the [Icons gallery](#icons). Legacy class-component icons (`IconHeartLine`, `IconSearchLine`, | ||
| etc.) are still available for backwards compatibility but are deprecated — see | ||
| [Legacy Icons](#legacy-icons) below. |
There was a problem hiding this comment.
I would also write about compatibility:
- Components with the new theme ONLY accept new icons
- what happens if you use a component with the old theme and a new icon?
There was a problem hiding this comment.
I added a sentence about the first part. The second part will be answered once the docs multi-version support is available and I’ve tested it thoroughly with all the components. The new icons worked with some old components on my local branch.
| --- | ||
|
|
||
| ## Adding and Modifying Icons | ||
| ## Adding Custom Icons |
There was a problem hiding this comment.
I would also mention in this doc how to update and add Lucide icons (IMO this is a much better place, than the package README files, those are read very rarely)
balzss
left a comment
There was a problem hiding this comment.
I've reviewed the code itself and left comments but i wasn't able to test it because the updates from last time weren't deployed to gh pages and i get errors when i try to run the branch locally, so i will finish the review when those are working again
| name, | ||
| component: component as React.ComponentType<any>, | ||
| source: 'lucide' as const, | ||
| importPath: '@instructure/ui-icons' |
There was a problem hiding this comment.
if source and importPath are static data, why add it every time when the page is rendered instead of including these with the orignal data?
There was a problem hiding this comment.
It is safe to be there, it is only called during module load not during render.
There was a problem hiding this comment.
what does only called during module load mean? i've just tested and this is runs on every render. also as I said earlier, I think static data should not be added runtime if it can just be included with the original data
| canvasHighContrast, | ||
| rebrandDark, | ||
| rebrandLight | ||
| } from '@instructure/ui-themes' |
There was a problem hiding this comment.
I put them back, I mistakenly removed them because of my local Node 22.6 issue.
There was a problem hiding this comment.
i see. i would add them back to the same place to not update git history unnecessarily
packages/ui-icons/package.json
Outdated
| "require": "./lib/index.js", | ||
| "default": "./es/index.js" | ||
| }, | ||
| "./InstructureIcons-Solid.css": "./src/__build__/icon-font/Solid/InstructureIcons-Solid.css", |
There was a problem hiding this comment.
i just don't really understand why did it work with the previous icon system and why did it break with the current that made this line required?
f2a5a27 to
de5e92b
Compare
@balzss We don't expose svgs or icon fonts of new icons in the new system. |
| @@ -1,4 +1,4 @@ | |||
| #!/usr/bin/env node | |||
| #!/usr/bin/env -S node --experimental-strip-types | |||
There was a problem hiding this comment.
@balzss comment on this: We discussed with Matyi that it would be good to convert all the JS files in ui-scripts to TS soon, so as a good first step I added the --experimental-strip-types Node feature, and the new generator scripts are written in TS.
balzss
left a comment
There was a problem hiding this comment.
first half of my review. i'll continue on monday
packages/ui-scripts/package.json
Outdated
| "fantasticon": "^3.0.0", | ||
| "svgo": "^3.3.2" | ||
| "svgo": "^3.3.2", | ||
| "svgson": "^5.3.1" |
There was a problem hiding this comment.
why is this new lib needed? what process our old pipeline is not capable of?
There was a problem hiding this comment.
My reasoning to add this lib:
- I did not want to write a custom svg parser
svgohas an svg parser but it has no public API, I could import it from svgo/lib/parser.js but it would be an antipattern, the lib's internals might change later- I could use the
optimizefunction call fromsvgobut it does a lot of other things than just parsing svg (invokePlugins(), stringifySvg(), etc.) and it has no option to make attributes camelCase; it is a very ugly solution to call theoptimizefunction with a plugin that filters attributes, extracts IconNodes and do camelCase conversion - I chose
svgsonbecause the Lucide library uses it, I trust it, it is a known support library. I followed what they are doing: first they parse svgs and convert them into IconNodes (we need to convert custom svg into IconNodes to be able to change colors). It can also convert attribute names to camelCase, which React needs - as soon as we throw out the old icon system,
svgocan be thrown out too
There was a problem hiding this comment.
you don't have to write a custom svg parser, we already have and use one for the legacy icon pipeline at packages/ui-scripts/lib/icons/svg2jsx.js. I would prefer using that to adding a new lib
| canvasHighContrast, | ||
| rebrandDark, | ||
| rebrandLight | ||
| } from '@instructure/ui-themes' |
There was a problem hiding this comment.
i see. i would add them back to the same place to not update git history unnecessarily
03d3694 to
6810da0
Compare
6810da0 to
ef85acd
Compare
…build-time JSX components Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…with flexbox Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…hey are all deprecated
31e63df to
75cdd1d
Compare
matyasf
left a comment
There was a problem hiding this comment.
Looks good now, just 2 small remarks
| <path d="..." fill="#2D3B45" /> | ||
| </svg> | ||
| ``` | ||
| Custom icons live in `packages/ui-icons/svg/Custom/` and are consumed directly by the build script (`scripts/generateCustomIndex.ts`). |
There was a problem hiding this comment.
This is called now ui-scripts/lib/generate-custom-index.ts
| const ICON_IMPORT_PATHS = [ | ||
| '@instructure/ui-icons', | ||
| '@instructure/ui-icons/es/svg' | ||
| ] | ||
| const NEW_ICON_IMPORT_PATH = '@instructure/ui-icons' |
There was a problem hiding this comment.
In a later PR (can you please make a ticket?) this codemod should also handle if the icon is imported from the ui package
|
@joyenjoyer my commits are logically separated so i think those should remain as is, but your first 3 commit should be squashed and a more descriptive commit message added. can you cherry pick those to have a nicer git history? |

Summary
svg/Custom/, each exported as<Name>InstUIIconalongside the existing Lucide iconswrapCustomIcon— a runtime wrapper that owns the<svg>, adds a similar API thanwrapLucideIcongenerateCustomIndexbuild script — parses SVGs at build time into [tagName, attrs][] tuples (Lucide's IconNode format, it is needed for color handling)migrateToNewIconscodemod inui-codemodsfor migrating legacy iconsTest plan
pnpm run test:vitest ui-codemods-> codemod fixtures passpnpm run test:vitest ui-icons-> IconPropsProvider tests passHow to check the regression page manually