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.zipInstalls 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.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
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:
- Bootstrapping — from ad-hoc
createRoot+<App />toMakeModularTool(provides theming, settings, shell layout) - Layout — from hand-rolled split containers / panes to
IShellService(central content, side panes, toolbars) - Components — from legacy shared-ui-components to
shared-ui-components/fluent/primitives and HOCs - Styling — from raw SCSS/CSS to
makeStylesfrom@fluentui/react-components - 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+ optionalThemeSelectorServiceShellService(layout: central content, side panes, toolbars)ToastProvider+IToastServicefor toast notifications (consumeToastServiceIdentity— do not roll your own container)IDialogService(consumeDialogServiceIdentity) for modal alert/confirm dialogs — replaces ad-hocMessageDialog
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
OpenPopupWindowfromshared-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 legacyCreatePopupfromshared-ui-components/popupHelper— it copies stylesheets into the popup. Fluent andCreatePopupcoexist 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 debuggingproduces— array of service identity symbols this service providesconsumes— array of service identity symbols this service depends onfactory(…consumedServices)— returns an object satisfying the produced contracts + optionalIDisposable
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 areashellService.addSidePane({ key, title, icon, horizontalLocation, verticalLocation, teachingMoment, content })— side paneshellService.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 Component | Fluent Replacement | Import Path |
|---|---|---|
LineContainerComponent | AccordionSection | shared-ui-components/fluent/primitives/accordion |
| Side pane container | Accordion (or ExtensibleAccordion) | shared-ui-components/fluent/primitives/accordion |
CheckBoxLineComponent | Switch (primitive) or SwitchPropertyLine (with label) | shared-ui-components/fluent/primitives/switch or .../hoc/propertyLines/switchPropertyLine |
SliderLineComponent | SyncedSliderInput (primitive) or SyncedSliderPropertyLine (with label) | shared-ui-components/fluent/primitives/syncedSlider or .../hoc/propertyLines/syncedSliderPropertyLine |
OptionsLine | Dropdown (primitive) or StringDropdownPropertyLine (with label) | shared-ui-components/fluent/primitives/dropdown or .../hoc/propertyLines/dropdownPropertyLine |
ButtonLineComponent | Button (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 |
MessageLineComponent | MessageBar | shared-ui-components/fluent/primitives/messageBar |
Color4LineComponent | ColorPickerPopup (primitive) or Color4PropertyLine (with label) | shared-ui-components/fluent/primitives/colorPicker or .../hoc/propertyLines/colorPropertyLine |
LockObject | Not needed (Fluent property lines don't use it) | — |
FontAwesomeIconButton | Button with icon prop | shared-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.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| porting-tools-to-fluent (this skill) | 0 | 1mo | No flags | Advanced |
| scroll-experience | 101 | 6mo | No flags | Intermediate |
| anthropic-frontend-design | 12 | 6mo | No flags | Intermediate |
| infographic-structure-creator | 1 | 5mo | No flags | Intermediate |
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.
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.
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.
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.
design-context
WellApp-ai
Refresh UI/UX context from design system, Storybook, and codebase
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.