Screens and routing
Loom does not require a router. Most game UIs work best when C# owns the current game/UI mode and the Solid app renders the matching screen.
Screen state
Define a screen value on your bridge:
public enum GameScreen
{
Splash,
MainMenu,
Hud,
Pause
}
[Bridge]
public partial class UIBridge : LoomBridgeBase
{
public GameScreen CurrentScreen { get; set; } = GameScreen.Splash;
} After regenerating types, the UI receives a string-literal union for the screen value.
Render from state
In App.tsx, switch on bridge state:
import { Match, Switch } from 'solid-js';
import { useBridge } from '@loomgui/bridge';
import { Splash } from './screens/Splash';
import { MainMenu } from './screens/MainMenu';
import { Hud } from './screens/Hud';
import { Pause } from './screens/Pause';
export function App() {
const bridge = useBridge();
return (
<Switch>
<Match when={bridge.currentScreen === 'Splash'}>
<Splash />
</Match>
<Match when={bridge.currentScreen === 'MainMenu'}>
<MainMenu />
</Match>
<Match when={bridge.currentScreen === 'Hud'}>
<Hud />
</Match>
<Match when={bridge.currentScreen === 'Pause'}>
<Pause />
</Match>
</Switch>
);
} Change screens from C#
Gameplay code can update the bridge directly:
UIBridge.Instance.CurrentScreen = GameScreen.Hud; For UI-triggered transitions, expose an action:
[BridgeAction]
public void StartGame()
{
CurrentScreen = GameScreen.Hud;
} Organize screens
A simple structure scales well:
UI/src/
App.tsx
screens/
Splash.tsx
MainMenu.tsx
Hud.tsx
Pause.tsx
components/
Button.tsx
Panel.tsx Keep screen-level layout in screens, reusable controls in components, and
global tokens or resets in styles.css.