PO

porting-tools-to-fluent

Framework-assisted migration of legacy Babylon.js tools to Fluent UI.

Install

mkdir -p .claude/skills/porting-tools-to-fluent && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/10397" && unzip -o skill.zip -d .claude/skills/porting-tools-to-fluent && rm skill.zip

Installs to .claude/skills/porting-tools-to-fluent

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Guide for porting Babylon.js tools from legacy shared-ui-components to Fluent UI using MakeModularTool. Use when: port to fluent, migrate to fluent, fluent migration, porting tool UI.
183 chars · catalog description✓ has a “when” trigger
Advanced

Key capabilities

  • Replace legacy UI bootstrapping with MakeModularTool
  • Migrate layout from custom containers to IShellService
  • Update UI components to Fluent primitives
  • Convert styling from SCSS/CSS to makeStyles
  • Replace FontAwesome icons with Fluent UI icons
  • Configure Vite and tsconfig for Fluent UI dependencies

How it works

The skill guides the replacement of four UI layers: bootstrapping, layout, components, and styling, along with icons, by using MakeModularTool and Fluent UI primitives.

Inputs & outputs

You give it
Legacy Babylon.js tool UI code, package.json, Vite config, tsconfig.json
You get back
Babylon.js tool UI ported to Fluent UI with MakeModularTool, updated dependencies, and Fluent styling

When to use porting-tools-to-fluent

  • Porting legacy UI to Fluent
  • Migrating Babylon.js tools
  • Modernizing UI component architecture

About this skill

Porting Babylon.js Tools to Fluent UI

Guide for porting Babylon.js tools (NME, NGE, NPE, NRGE, Playground, etc.) from the legacy shared-ui-components to Fluent UI using the MakeModularTool framework from shared-ui-components/modularTool/.

Reference implementation: packages/tools/viewer-configurator/ (fully ported).

Design guidelines: For the shared design system these ports target — color schema, shell/panel structure, component and styling conventions — see .github/design-guidelines.md.


Overview

A Fluent port replaces four layers:

  1. Bootstrapping — from ad-hoc createRoot + <App /> to MakeModularTool (provides theming, settings, shell layout)
  2. Layout — from hand-rolled split containers / panes to IShellService (central content, side panes, toolbars)
  3. Components — from legacy shared-ui-components to shared-ui-components/fluent/ primitives and HOCs
  4. Styling — from raw SCSS/CSS to makeStyles from @fluentui/react-components
  5. Icons — from FontAwesome to @fluentui/react-icons

1. Dependencies

Add

// package.json devDependencies
"@fluentui/react-components": "^9.x", // for makeStyles, tokens, low-level Fluent components
"@fluentui/react-icons": "^2.x"       // for all icons

Note: @dev/shared-ui-components should already be a dependency. It contains both the Fluent primitives (fluent/) and the ModularTool framework (modularTool/). No dependency on @dev/inspector is needed.

Remove

"@fortawesome/fontawesome-svg-core": "...",
"@fortawesome/free-solid-svg-icons": "...",
"@fortawesome/free-regular-svg-icons": "...",
"@fortawesome/react-fontawesome": "...",
"sass": "...",
"sass-loader": "..."   // if no other SCSS remains

Vite config

Ensure the shared-ui-components alias is present:

commonDevViteConfiguration({
    aliases: {
        "shared-ui-components": path.resolve("../../dev/sharedUiComponents/src"),
        // ... other aliases as needed
    },
});

tsconfig.json

Ensure the shared-ui-components path mapping is present (no inspector mapping needed):

"paths": {
    "shared-ui-components/*": ["../../dev/sharedUiComponents/src/*"]
}

2. Bootstrapping with MakeModularTool

Replace the old entry point:

// BEFORE
const root = createRoot(document.getElementById("root")!);
root.render(<App />);

// AFTER
import { MakeModularTool } from "shared-ui-components/modularTool/modularTool";
MakeModularTool({
    namespace: "MyToolName",
    containerElement: document.getElementById("root")!,
    serviceDefinitions: [
        /* your service definitions */
    ],
    toolbarMode: "compact", // "compact" for minimal toolbar, "full" for full toolbar
    showThemeSelector: true, // adds theme toggle to toolbar
    // Do NOT pass extensionFeeds to disable the extensions dialog
});

MakeModularTool automatically provides:

  • FluentProvider + theme (light/dark)
  • SettingsStore (persisted user preferences)
  • ThemeService + optional ThemeSelectorService
  • ShellService (layout: central content, side panes, toolbars)
  • ToastProvider + IToastService for toast notifications (consume ToastServiceIdentity — do not roll your own container)
  • IDialogService (consume DialogServiceIdentity) for modal alert/confirm dialogs — replaces ad-hoc MessageDialog

Cross-window / popup hosting

MakeModularTool derives targetDocument from containerElement.ownerDocument. If your tool's entry function (e.g. Show(options)) hosts the editor in a popup window, just pass the popup body as containerElement — Fluent/Griffel/Theme plumb cross-window automatically.

  • For a fully-Fluent popup, use OpenPopupWindow from shared-ui-components/fluent/hoc/popupWindow.
  • If part of your tool still ships traditional CSS/SCSS (e.g. shared-ui-components/nodeGraphSystem/'s graph canvas), keep the legacy CreatePopup from shared-ui-components/popupHelper — it copies stylesheets into the popup. Fluent and CreatePopup coexist fine.

3. Service Architecture

Each tool should define its own services that populate the shell. A service is a ServiceDefinition<Produces, Consumes> with:

  • friendlyName — human-readable name for debugging
  • produces — array of service identity symbols this service provides
  • consumes — array of service identity symbols this service depends on
  • factory(…consumedServices) — returns an object satisfying the produced contracts + optional IDisposable

Defining a service identity and contract

export const MyServiceIdentity = Symbol("MyService");

export interface IMyService extends IService<typeof MyServiceIdentity> {
    readonly someData: SomeType | undefined;
    readonly onStateChanged: IReadonlyObservable<void>;
}

Service factory pattern

export const MyServiceDefinition: ServiceDefinition<[IMyService], [IShellService]> = {
    friendlyName: "My Service",
    produces: [MyServiceIdentity],
    consumes: [ShellServiceIdentity],
    factory: (shellService) => {
        const onStateChanged = new Observable<void>();
        let someData: SomeType | undefined;

        // Register shell content
        const registration = shellService.addCentralContent({
            key: "MyContent",
            component: () => <MyComponent />,
        });

        return {
            get someData() {
                return someData;
            },
            onStateChanged,
            dispose: () => {
                onStateChanged.clear();
                registration.dispose();
            },
        } satisfies IMyService & IDisposable;
    },
};

Shell service APIs

  • shellService.addCentralContent({ key, component }) — main content area
  • shellService.addSidePane({ key, title, icon, horizontalLocation, verticalLocation, teachingMoment, content }) — side pane
  • shellService.addToolbarItem({ key, horizontalLocation, verticalLocation, teachingMoment, component }) — toolbar button

All return IDisposable — clean up in your service's dispose().

Reactive state with useObservableState

Use the useObservableState hook from shared-ui-components/modularTool/ to subscribe to service state in React components:

import { useObservableState } from "shared-ui-components/modularTool/hooks/observableHooks";

const myData = useObservableState(
    () => myService.someData, // getter
    myService.onStateChanged // observable to subscribe to
);

4. Component Mapping

Legacy → Fluent shared component mapping

Legacy ComponentFluent ReplacementImport Path
LineContainerComponentAccordionSectionshared-ui-components/fluent/primitives/accordion
Side pane containerAccordion (or ExtensibleAccordion)shared-ui-components/fluent/primitives/accordion
CheckBoxLineComponentSwitch (primitive) or SwitchPropertyLine (with label)shared-ui-components/fluent/primitives/switch or .../hoc/propertyLines/switchPropertyLine
SliderLineComponentSyncedSliderInput (primitive) or SyncedSliderPropertyLine (with label)shared-ui-components/fluent/primitives/syncedSlider or .../hoc/propertyLines/syncedSliderPropertyLine
OptionsLineDropdown (primitive) or StringDropdownPropertyLine (with label)shared-ui-components/fluent/primitives/dropdown or .../hoc/propertyLines/dropdownPropertyLine
ButtonLineComponentButton (primitive)shared-ui-components/fluent/primitives/button
TextInputLineComponent (single-line)TextInput (primitive) or TextInputPropertyLine (with label)shared-ui-components/fluent/primitives/textInput or .../hoc/propertyLines/inputPropertyLine
TextInputLineComponent (multiline)Fluent Textarea + slot props@fluentui/react-components
MessageLineComponentMessageBarshared-ui-components/fluent/primitives/messageBar
Color4LineComponentColorPickerPopup (primitive) or Color4PropertyLine (with label)shared-ui-components/fluent/primitives/colorPicker or .../hoc/propertyLines/colorPropertyLine
LockObjectNot needed (Fluent property lines don't use it)
FontAwesomeIconButtonButton with icon propshared-ui-components/fluent/primitives/button

Content truncated.

When not to use it

  • When not porting Babylon.js tools to Fluent UI
  • When not migrating from legacy shared-ui-components
  • When not using MakeModularTool framework

Limitations

  • Specific to Babylon.js tools
  • Focuses on migration to Fluent UI
  • Requires familiarity with MakeModularTool

How it compares

This skill provides a structured, layer-by-layer guide for migrating Babylon.js tools to Fluent UI, offering specific dependency changes and code examples, unlike general UI migration advice.

Compared to similar skills

porting-tools-to-fluent side by side with the closest alternatives in the catalog.

SkillInstallsUpdatedSafetyDifficulty
porting-tools-to-fluent (this skill)01moNo flagsAdvanced
scroll-experience1016moNo flagsIntermediate
anthropic-frontend-design126moNo flagsIntermediate
infographic-structure-creator15moNo flagsIntermediate

Try saying

Example prompts that trigger this skill in your AI assistant.

You might also like

scroll-experience

davila7

Expert in building immersive scroll-driven experiences - parallax storytelling, scroll animations, interactive narratives, and cinematic web experiences. Like NY Times interactives, Apple product pages, and award-winning web experiences. Makes websites feel like experiences, not just pages. Use when: scroll animation, parallax, scroll storytelling, interactive story, cinematic website.

101142

anthropic-frontend-design

chaibuilder

Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, artifacts, posters, or applications (examples include websites, landing pages, dashboards, React components, HTML/CSS layouts, or when styling/beautifying any web UI). Generates creative, polished code and UI design that avoids generic AI aesthetics.

1237

infographic-structure-creator

antvis

Generate or update infographic Structure components for this repo (TypeScript/TSX in src/designs/structures). Use when asked to design, implement, or modify structure layouts (list/compare/sequence/hierarchy/relation/geo/chart), including layout logic, component composition, and registration.

110

logo-with-variants

crafter-station

Create logo components with multiple variants (icon, wordmark, logo) and light/dark modes. Use when the user provides logo SVG files and wants to create a variant-based logo component following the Clerk pattern in the Elements project.

47

design-context

WellApp-ai

Refresh UI/UX context from design system, Storybook, and codebase

17

threejs-postprocessing

CloudAI-X

Three.js post-processing - EffectComposer, bloom, DOF, screen effects. Use when adding visual effects, color grading, blur, glow, or creating custom screen-space shaders.

17

Search skills

Search the agent skills registry