Skip to content

ALEC-306: Bundle Feather styles so the UI survives the PrimeVue-based OpenNMS host - #172

Merged
joseanesONMS merged 5 commits into
release-3.xfrom
ja/alec-ui-bundle-feather-css
Aug 12, 2026
Merged

ALEC-306: Bundle Feather styles so the UI survives the PrimeVue-based OpenNMS host#172
joseanesONMS merged 5 commits into
release-3.xfrom
ja/alec-ui-bundle-feather-css

Conversation

@joseanesONMS

Copy link
Copy Markdown
Contributor

Jira: https://opennms.atlassian.net/browse/ALEC-306

Makes the UI extension's styling self-sufficient instead of relying on the host page's Feather CSS. The OpenNMS 37 web UI moved from FeatherDS to PrimeVue and ships no Feather CSS, which left the plugin rendering unstyled and partly unreadable in dark mode.

  • ui/src/feather-styles.ts (first import of main.ts) bundles every Feather component stylesheet into the extension's style.css (271 kB → 324 kB); on Feather-based hosts these duplicate identical rules.
  • When the page defines no --feather-* variables, the matching vendored theme is injected at runtime, keyed off the open-light/open-dark class the OpenNMS 37 host still stamps on <html>, and a MutationObserver follows the host's dark-mode toggle live.
  • On Feather hosts the variables already exist, so nothing is injected and the host theme (including dark mode) keeps working.
  • The vendored theme copies strip @font-face so 1.8 MB of .ttf files are not base64-inlined into the bundle.

Verified on a local OpenNMS 37: situation list and configuration render with correct Feather styling in light and dark mode; all 86 UI unit tests pass.

… OpenNMS host

The OpenNMS 37 web UI migrated from FeatherDS to PrimeVue and no longer
ships any Feather CSS. The extension relied on the host page for both the
Feather component base styles (.btn, inputs, tabs, ...) and the :root
--feather-* theme variables, so on the new host it rendered completely
unstyled.

- feather-styles.ts (first import of main.ts): bundles every Feather
  component stylesheet into the extension's style.css. On a Feather-based
  host these duplicate identical host rules, so they are harmless there.
- Theme variables: the new host defines no --feather-* vars but still
  stamps open-light/open-dark as a class on <html> and flips it with its
  dark-mode toggle. When no host theme is detected, inject the matching
  vendored theme at runtime and follow the class with a MutationObserver
  so dark mode tracks the host toggle. On Feather hosts (which do define
  the vars) nothing is injected and the host theme keeps working.
- The vendored theme copies strip @font-face: the referenced .ttf files
  (1.8MB) would be base64-inlined into the bundle, and the host already
  provides fonts.

https://opennms.atlassian.net/browse/ALEC-306
The ui package had eslint configured but no way to run it. Add lint and
lint:fix scripts and clear every error so they run clean:

- auto-fixes: quote style (utils.ts), inferrable type annotations
  (AlecService.ts, useUserStore.ts)
- tests/setup.ts: give the jsdom observer stubs explicit no-op bodies
- .eslintrc: allow the single-word Timeline component name instead of
  renaming a shipped component
- drop six unused imports flagged by no-unused-vars

The 38 vue-scoped-css/no-unused-selector warnings are left: the rule's
static analysis cannot see dynamically bound classes, and pruning shipped
selectors risks visual regressions. Regenerated bundles included.

https://opennms.atlassian.net/browse/ALEC-306
- Stamp feather-styles on the plugin root: @featherds/styles scopes its
  base rules (typography, sr-text, links) under that class, which Feather
  hosts put on <body> but the PrimeVue host never does — without it the
  bundled base CSS matched nothing in production. Scoping it to our root
  also keeps those rules off host pages.
- Vendor only the :root variable blocks of the themes: the full files
  also carry global spacing utilities (.mt-*, .p-*, ...) that the 37 host
  no longer ships but whose class names its templates still use, so
  injecting them document-wide restyled host pages (e.g. Provisioning).
- Pin @featherds/radio and @featherds/textarea exact (were ^0.10.17):
  a lockfile refresh could float them past the vendored 0.10.17 theme.
- Probe two sentinel vars (--feather-primary and --feather-background)
  so a stray single-var definition elsewhere can't suppress injection,
  and skip the <style> rewrite when the theme class did not change.

https://opennms.atlassian.net/browse/ALEC-306
Two contrast problems surfaced on the dark theme once the Feather chip CSS
was bundled:

- Severity filter chips keep a fixed light pastel background in both
  themes, but FeatherChip's label element sets the theme text color
  (near-white in dark mode) which beat the inherited black — white on
  pastel pink was unreadable. A global descendant rule keeps every
  severity chip label black in both themes.
- The severity text/border accents (-color classes) use the saturated
  light palette, which lacks contrast on dark surfaces (#cc0000 on
  #0a0c1b is about 2.4:1). Dark mode now lifts them to lighter variants
  keyed off the open-dark theme class the host stamps on <html>.

https://opennms.atlassian.net/browse/ALEC-306
@cgorantla
cgorantla requested a review from synqotik August 12, 2026 14:59
@joseanesONMS
joseanesONMS merged commit 7fefe5d into release-3.x Aug 12, 2026
6 checks passed
@joseanesONMS
joseanesONMS deleted the ja/alec-ui-bundle-feather-css branch August 12, 2026 15:31
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.

1 participant