Skip to content

[icons] Add opt-in next-gen static icon components#8065

Draft
ggdouglas wants to merge 14 commits intodevelopfrom
gd/icons-next
Draft

[icons] Add opt-in next-gen static icon components#8065
ggdouglas wants to merge 14 commits intodevelopfrom
gd/icons-next

Conversation

@ggdouglas
Copy link
Copy Markdown
Contributor

@ggdouglas ggdouglas commented Apr 16, 2026

Warning

🚧 This content is WIP 🏗️

Summary

Adds a new, opt-in icon system at @blueprintjs/icons/next. Icons use a unified 16x16 viewBox, support outlined and filled variants, and work as both static imports and dynamic string-based lookups. The existing @blueprintjs/icons entrypoint is unchanged.

Screenshot 2026-04-16 at 22 53 31@2x Screenshot 2026-04-16 at 22 55 08@2x

What's included

New static icon entrypoint (@blueprintjs/icons/next)

  • React icon components for outlined variants (<DownloadIcon />) and filled variants where available (<PlayFilledIcon />)
  • Codegen pipeline (generate-next-icon-components.mjs) reads SVGs from resources/icons/next/ and emits components + path modules + manifests
  • SvgIconContainerNext with fixed viewBox="0 0 16 16"
  • icons-next.json manifest
  • Proxy next/package.json for moduleResolution: "node" compatibility

Dynamic loading (IconsNext + <IconNext>)

  • IconsNext loader with outlined/filled variant support
  • Generated paths/*.ts modules for dynamic import() loading
  • <IconNext> component in @blueprintjs/core with variant prop and automatic filled-to-outlined fallback

Storybook + docs

  • Side-by-side comparison stories for all icon-accepting core components
  • Icon gallery and IconNext demo stories
  • Docs page (next-icons.mdx) with searchable icon gallery

Design decisions

No exports field. Adding exports to package.json broke Vitest's async icon loading in core (the splitPathsBySizeLoader dynamic import stopped resolving within act()). A proxy next/package.json provides the same subpath import without side effects.

Reuse IconName type. The next icon set is a strict subset of the current set (differing only by "blank"). Sharing the type avoids friction when migrating <Icon> to <IconNext>.

Filled fallback. variant="filled" silently falls back to outlined when unavailable, with a dev-mode console warning.

No fillRule="evenodd" on paths. New icons use the nonzero fill rule (SVG default). Color is inherited via .bp6-icon > svg:not([fill]) { fill: currentColor }.

Consumer-specified size for some components. Alert, NonIdealState, and TagInput (large) render icons at non-default sizes internally. We can't inject size into an opaque JSX element without cloneElement, so the consumer passes size on their icon element.

Internal icon usages (future work)

8 core components use current static icons internally (not via props). Not addressed here:

Dialog (SmallCross), Drawer (SmallCross), MenuItem (CaretRight, SmallTick), NumericInput (ChevronDown/Up), Section (ChevronDown/Up), Tag (SmallCross), Toast (Cross), TreeNode (ChevronRight), Breadcrumbs (chevron-right via CSS svg-icon())


Auxiliary: component fixes for static icon elements

Included here for testing convenience. Will be cherry-picked into separate preflight PRs and rebased out.

When a component receives a JSX element for its icon prop, the element passes through <Icon> unchanged, dropping any className, intent, or size the component would normally apply. Fixes for 7 components:

Component Fix What was lost
Tabs Wrap in <span class="bp6-tab-icon"> Spacing
Tree Wrap in <span class="bp6-tree-node-icon"> Spacing
Section Wrap in <span class="bp6-text-muted"> Muted color
EntityTitle Wrap in <span class="bp6-text-muted"> Muted color
Alert Wrap in <span class="bp6-icon bp6-intent-*">, CSS > .bp6-icon Intent color, spacing
NonIdealState Wrap in <span class="bp6-icon bp6-icon-muted"> Muted/outlined style
TagInput Wrap in <span class="bp6-tag-input-icon">, display: flex Muted color, spacing

All backwards compatible. String icons hit the same code paths as before.

@changelog-app
Copy link
Copy Markdown

changelog-app Bot commented Apr 16, 2026

Generate changelog in packages/core/changelog/@unreleased

Type (Select exactly one)

  • Feature (Adding new functionality)
  • Improvement (Improving existing functionality)
  • Fix (Fixing an issue with existing functionality)
  • Break (Creating a new major version by breaking public APIs)
  • Deprecation (Removing functionality in a non-breaking way)
  • Migration (Automatically moving data/functionality to a new system)

Description

[icons] Add opt-in next-gen static icon components


Generate changelog in packages/icons/changelog/@unreleased

Type (Select exactly one)

  • Feature (Adding new functionality)
  • Improvement (Improving existing functionality)
  • Fix (Fixing an issue with existing functionality)
  • Break (Creating a new major version by breaking public APIs)
  • Deprecation (Removing functionality in a non-breaking way)
  • Migration (Automatically moving data/functionality to a new system)

Description

[icons] Add opt-in next-gen static icon components


Check the box to generate changelog(s)

  • Generate changelog entry

@blueprint-previews
Copy link
Copy Markdown

Add stories

Build artifact links for this commit: documentation | landing | table | demo | storybook

This is an automated comment from the deploy-preview CircleCI job.

@blueprint-previews
Copy link
Copy Markdown

fix(tag-input): apply icon spacing and color to static icon elements

Build artifact links for this commit: documentation | landing | table | demo | storybook

This is an automated comment from the deploy-preview CircleCI job.

@blueprint-previews
Copy link
Copy Markdown

fix(tag-input): apply icon spacing and color to static icon elements

Build artifact links for this commit: documentation | landing | table | demo | storybook

This is an automated comment from the deploy-preview CircleCI job.

@blueprint-previews
Copy link
Copy Markdown

fix(tag-input): apply icon spacing and color to static icon elements

Build artifact links for this commit: documentation | landing | table | demo | storybook

This is an automated comment from the deploy-preview CircleCI job.

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.

1 participant