Skip to content

NIFI-16009 refactor theming#11322

Open
scottyaslan wants to merge 4 commits into
apache:mainfrom
scottyaslan:NIFI-16009
Open

NIFI-16009 refactor theming#11322
scottyaslan wants to merge 4 commits into
apache:mainfrom
scottyaslan:NIFI-16009

Conversation

@scottyaslan

@scottyaslan scottyaslan commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Summary

NIFI-16009
Refactor frontend theming to eliminate the centralized *component-theme.scss + global mixin
registration pattern, replacing it with per-component style ownership and a single
material.scss orchestrator.

Background

The NiFi Angular frontend themes components through a two-part pattern: a
_*.component-theme.scss file alongside each component containing a generate-theme() mixin,
and an html {} block in each app's styles.scss that @uses every theme file and @includes
every mixin. This pattern has two structural problems.
Redundancy. Angular Material v15+ (MDC) expresses all theming through CSS custom properties
(--mat-sys-*, --nf-*). These cascade to all descendants automatically and already rebind for
dark mode in material.scss. There is no scenario in which calling
@include canvas.generate-theme() inside html {} produces a different result than those same
styles placed in canvas.component.scss. The styles.scss mixin registry was emitting the same
CSS twice — once for light mode, and again redundantly for dark mode via a double-call pattern.
Scalability. Bundling all component styles into the eager styles.scss bundle prevents
Angular's code-splitting from delivering component styles alongside their lazy-loaded feature
modules.

What Changed

Shared library (libs/shared/src/assets/)

  • Deleted the styles/ directory (_app.scss, _listing-table.scss, _prism-theme.scss,
    _tailwind-theme.scss)
  • themes/material.scss absorbs structural resets and semantic color utilities from the former
    _app.scss, becoming the sole eager global orchestrator
  • themes/components/_table.scss (new) — merged from _listing-table.scss; all @extend
    directives converted to inline CSS custom properties (@extend cannot cross Sass module
    boundaries)
  • themes/components/_prism-theme.scss (new) — moved from styles/
  • themes/_tailwind-theme.scss (new) — moved from styles/
  • themes/purple.scss deleted (unused alternative theme)
  • themes/README.md updated to document the new architecture and ::ng-deep decision criteria

Apps

  • 25 _*.component-theme.scss files deleted across apps/nifi,
    apps/nifi-jolt-transform-ui, apps/standard-content-viewer, and apps/update-attribute;
    each component's styles migrated into its own *.component.scss
  • styles.scss in all four apps reduced from 80–105 lines with 20+ component registrations
    to ~30 lines: Tailwind, flowfont, material.scss, Font Awesome — no html {} block, no
    component mixin calls
  • connector-canvas.component.scss created (component previously lacked a stylesheet);
    styleUrl added to connector-canvas.component.ts

::ng-deep audit

All migrated styles that target DOM not created by Angular's template compiler use
:host ::ng-deep with an inline comment explaining why. Styles targeting template-defined
elements (Angular Material host elements, CDK directive classes, Material density mixins that
emit CSS custom properties) do not use ::ng-deep.

Frontend (manual testing — no automated SCSS tests exist)

Run each app in development mode and verify light mode and dark mode:
apps/nifi

  • Canvas: component borders, labels, connection paths visible and correctly colored
  • Birdseye / navigation control: minimap SVG renders without missing styles
  • Search and canvas-header-search: results panel opens with correct background, shadow,
    and spacing
  • Provenance / lineage: SVG graph elements correctly colored
  • Status history: chart axes, labels, and controls render correctly
  • Documentation: expansion panel header title and description styled correctly
  • Navigation bar: secondary background, on-secondary text and icon colors correct
    apps/nifi-jolt-transform-ui
  • Editor height and button density correct
    apps/standard-content-viewer
  • Button density correct
    apps/update-attribute
  • Drag-and-drop list clears background color when dragging

Issue Tracking

Pull Request Tracking

  • Pull Request title starts with Apache NiFi Jira issue number, such as NIFI-16009
  • Pull Request commit message starts with Apache NiFi Jira issue number, as such NIFI-16009
  • Pull request contains commits signed with a registered key indicating Verified status

Pull Request Formatting

  • Pull Request based on current revision of the main branch
  • Pull Request refers to a feature branch with one commit containing changes

Verification

Please indicate the verification steps performed prior to pull request creation.

Build

  • Build completed using ./mvnw clean install -P contrib-check
    • JDK 21
    • JDK 25

Licensing

  • New dependencies are compatible with the Apache License 2.0 according to the License Policy
  • New dependencies are documented in applicable LICENSE and NOTICE files

Documentation

  • Documentation formatting appears as expected in rendered files

@scottyaslan scottyaslan added the ui Pull requests for work relating to the user interface label Jun 10, 2026
@rfellows

Copy link
Copy Markdown
Contributor

Will review...

@rfellows rfellows left a comment

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.

Thanks for tackling this — the core direction (kill the centralized @include registry + the redundant .darkMode double-emit, co-locate styles with components) is clearly right, and I verified the redundancy and code-splitting arguments hold up. A few inline notes below, plus two things that don't have a natural code anchor:

Missing .cursor/rules/ng-deep.mdc. The PR description says this file is added, but git show --name-only doesn't list it. The same criteria are in themes/README.md, but if the intent was a standalone rule file for AI agents to pick up automatically, it looks like it didn't make the commit.

Pre-existing bug worth fixing while you're in the fileapps/nifi/src/app/ui/common/status-history/status-history.component.scss lines 104–106:

:host ::ng-deep #status-history-chart-container text,
#status-history-chart-control-container text { ... }

Angular's view-encapsulation processor only applies the :host ::ng-deep prefix to the first selector in a comma-separated list. The second selector gets compiled with attribute scoping (#status-history-chart-control-container[_ngcontent-xxx] text[_ngcontent-xxx]) and never matches the D3-created <text> elements, so the control chart's labels silently don't pick up the intended font. One-line fix: repeat :host ::ng-deep in front of the second selector.

NiFi's `canvas.component.scss` and `birdseye.component.scss` only contain structural layout rules
inside `::ng-deep`. Colors use `--mat-sys-*` and `--nf-*` CSS custom properties that already
resolve correctly for both light and dark mode. No `.darkMode` block is needed inside `::ng-deep`
for these components.

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.

Heads up: apps/nifi/src/app/ui/common/canvas/canvas.component.scss and apps/nifi/src/app/ui/common/birdseye/birdseye.component.scss (the new shared replacements introduced by NIFI-15951 and consumed by connector-canvas) still use the old @mixin styles(); @mixin generate-theme(); :host ::ng-deep { @include styles(); @include generate-theme(); .darkMode { @include generate-theme(); } } pattern — including the redundant double-include for .darkMode. They weren't touched by this PR.

That means the pattern this PR is "removing" actually still ships in the codebase, just relocated. Ideally these get migrated alongside the legacy pages/flow-designer/... versions you already moved. If you'd rather defer it, please mention the exception in the PR description and add a note here so the next maintainer doesn't think the pattern is fully gone.

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.

Both files cleaned up — redundant .darkMode double-call removed, comments updated to explain why it's not needed.

Comment thread nifi-frontend/src/main/frontend/libs/shared/src/assets/themes/README.md Outdated
Comment thread nifi-frontend/src/main/frontend/libs/shared/src/assets/themes/README.md Outdated
Comment thread nifi-frontend/src/main/frontend/libs/shared/src/assets/themes/README.md Outdated
// Shadows should always be darker. We explicitly set this so the SVG shadows are correct in both modes.
$drop-shadow-color: black;

:host ::ng-deep svg.canvas-svg {

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.

Cosmetic: this is a second :host ::ng-deep svg.canvas-svg { … } block — there's already one at line 46. Now that they're co-located in the same file, worth merging into a single block. Easier to scan and avoids the impression that they have different scoping intent.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ui Pull requests for work relating to the user interface

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants