chore: migrate `@rocket.chat/fuselage` from Fuselage

Merged
TA
6d ago
+67292-1439

Proposed changes (including videos or screenshots)

Moves @rocket.chat/fuselage from the Fuselage repo into packages/fuselage, continuing from the 0.96.0 release (Fuselage main at RocketChat/fuselage@84dbbbe). It still builds with Vite into the same dist/ layout: index.js picks fuselage.development.js or fuselage.production.js, and fuselage.css references fonts/InterVariable.woff2. Deep imports like @rocket.chat/fuselage/dist/fuselage.css keep working.

Compared with the published 0.96.0 tarball:

  • The font is byte-identical.
  • The .d.ts files describe the same types; the differences are formatting and import order.
  • The JS bundles differ only in module order, whitespace inside CSS template literals, and lint autofixes (?.(), dot notation, a duplicated RefAttributes removed from a type).
  • The production CSS differs only in how cssnano 9.0.5 (vs 9.0.4) merges rules.
  • tsdoc-metadata.json is gone, like the API report.

The package follows the earlier migrations:

  • Sources are reformatted to this repo's style. API Extractor, the README, lint-all and testing-utils are dropped; the one mock the specs need lives in mocks/.
  • Jest uses @rocket.chat/jest-presets/client, with a small local setup for toHaveCssInJsClass and the "no console errors" check.
  • @rocket.chat/css-in-js, @rocket.chat/fuselage-tokens, @rocket.chat/memo, @rocket.chat/fuselage-hooks, @rocket.chat/icons and @rocket.chat/storybook-dark-mode now resolve to the workspace.
  • All 19 workspaces that consumed ^0.95.0 now use workspace:~. Peer ranges (*) are unchanged.
  • A patch changeset records the move.

Specific to this package:

  • It keeps its own .storybook. @rocket.chat/storybook-config dev-depends on @rocket.chat/fuselage, so depending on it would create a turbo build cycle.
  • vite stays on ~8.2.2. With the repo's Vite 8.0.16, the 352 KB font gets inlined into the stylesheet as base64.
  • postcss is pinned to 8.5.26, the version the root resolutions force on Vite. With a different copy, the Vite config's PostCSS plugin types don't match and it fails to typecheck.
  • tsconfig.json sets target: es2024 and stripInternal, as Fuselage's base config did. That keeps class fields with define semantics and keeps the internal SCSS import out of index.d.ts.
  • The Meteor app now declares invariant, one of fuselage's runtime dependencies. The Meteor bundler resolves client modules only from the app's own node_modules. The npm copy of fuselage brought invariant along there; the workspace link doesn't.
  • The Vite dev client (dev:next) reads @rocket.chat/fuselage from dist, like @rocket.chat/fuselage-tokens. Compiling it from source would need fuselage's Sass, PostCSS and font handling.
  • The NavBar spec imports SSRProvider from @react-aria/ssr. This repo's react-aria patch drops it from the barrel; no runtime import is affected.
  • A scoped FIXME block in eslint.config.mjs turns 7 rules into warnings for packages/fuselage/src. They cover idioms Fuselage uses on purpose: Tag/Anchor component props, multi-component helper files, empty callbacks in stories.
  • Reformatting the css template literals changes the css-in-js class hashes. About 110 consumer snapshot files are regenerated. Every diff was checked: only rcx-css-* class names and React useId values change, never markup.

Separate commits on top:

  • fuselage.sh and the yarn fuselage script are removed. With fuselage here, the Fuselage repo publishes nothing this repo consumes.
  • A Test Visual Regression CI job replaces Fuselage's visual regression step. Fuselage relied on a persisted turbo cache to skip unchanged runs. Here a small job asks turbo ls --affected whether @rocket.chat/fuselage is affected: its own files, its workspace dependencies, or its locked external dependencies. Only then does a second job build Storybook and run Playwright in Docker. If the comparison base can't be resolved, turbo treats everything as affected and the tests run. It runs on an ARM runner, and โœ… Tests Done requires it; a skipped run counts as passing.
  • The visual regression baselines are regenerated with this repo's Playwright 1.52.0 image. Fuselage's were taken with 1.58.2, and five stories failed on text anti-aliasing. The Docker runner in @rocket.chat/visual-regression now always uses the linux/arm64 image, so snapshots come out the same on Apple Silicon machines and on CI's ARM runners. All 523 images were regenerated, and the 2 orphans whose stories no longer exist were dropped. 354 are pixel-identical to Fuselage's; the rest differ only in faint text and gradient shading.

Issue(s)

ARCH-2368

Steps to test or reproduce

  • yarn turbo run build --filter=@rocket.chat/fuselage
  • yarn workspace @rocket.chat/fuselage lint
  • yarn workspace @rocket.chat/fuselage typecheck
  • yarn workspace @rocket.chat/fuselage testunit
  • yarn workspace @rocket.chat/fuselage build-storybook
  • yarn workspace @rocket.chat/fuselage visual-regression (needs Docker)
  • yarn turbo run typecheck --filter='...^@rocket.chat/fuselage'

Further comments

Not in this PR:

  • The package still has to be removed from the Fuselage repo.
  • An org owner still has to repoint the npm trusted publisher for @rocket.chat/fuselage from RocketChat/fuselage to this repo, in the npm UI.
  • docs/bundle-optimization-react-aria.md still describes Fuselage as a dependency "you don't control". Fuselage can now import react-aria sub-packages directly, which would let the barrel patches go.

๐Ÿค– Generated with Claude Code