Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/danielitoCode/compose_svelted/llms.txt

Use this file to discover all available pages before exploring further.

This example walks through building a complete three-screen application with Compose Svelted’s navigation system. Starting from a Login screen, the user is taken to a Home screen where they can navigate forward to a Details screen that receives typed arguments — and then pop back through the stack. Every transition is handled by NavHost and rememberNavController, mirroring the Jetpack Compose Navigation API.
1

Define routes

Routes are plain TypeScript objects with a path string. Keeping them in a shared routes.ts module makes imports consistent across all screens and avoids magic strings.
// src/navigation/routes.ts
export const Login   = { path: "login" };
export const Home    = { path: "home" };
export const Details = { path: "details" };
Every composable() call in NavHost references one of these objects, so renaming a route is a single-file change.
2

Create the screens

Each screen is a plain Svelte component. Compose Svelted automatically injects two props into every routed component:
  • navController — the same NavController instance created in the host; use it to navigate() or popBackStack().
  • navBackStackEntry — the back-stack entry for the current destination; its .args property holds any arguments passed during navigation.
LoginScreen.svelte
<script lang="ts">
  import {
    Alignment,
    Arrangement,
    Button,
    Column,
    Modifier,
    Text,
  } from "@danielito1996/compose-svelted";

  export let navController;
</script>

<Column
  modifier={Modifier.fillMaxSize().padding(32)}
  verticalArrangement={Arrangement.Center}
  horizontalAlignment={Alignment.CenterVertically}
>
  <Text>Login Screen</Text>

  <Button
    modifier={Modifier.marginTop(24)}
    onClick={() => navController.navigate("home")}
  >
    Entrar
  </Button>
</Column>
HomeScreen.svelteThe Home screen demonstrates forward navigation with arguments. The object { id: 42 } is passed as the second argument to navigate() and becomes available via navBackStackEntry.args on the Details screen.
<script lang="ts">
  import {
    Alignment,
    Arrangement,
    Button,
    Column,
    Modifier,
    Text,
  } from "@danielito1996/compose-svelted";

  export let navController;
</script>

<Column
  modifier={Modifier.fillMaxSize().padding(32)}
  verticalArrangement={Arrangement.Center}
  horizontalAlignment={Alignment.CenterVertically}
>
  <Text>Home Screen</Text>

  <Button onClick={() => navController.navigate("details", { id: 42 })}>
    Ir a Details (id=42)
  </Button>

  <Button onClick={() => navController.popBackStack()}>
    Logout
  </Button>
</Column>
DetailsScreen.sveltenavBackStackEntry.args is destructured at the top of the script block. The nullish coalescing ?? {} guard keeps TypeScript happy when the entry is not yet hydrated.
<script lang="ts">
  import {
    Alignment,
    Arrangement,
    Button,
    Column,
    Modifier,
    Text,
  } from "@danielito1996/compose-svelted";

  export let navController;
  export let navBackStackEntry;

  const { id } = navBackStackEntry?.args ?? {};
</script>

<Column
  modifier={Modifier.fillMaxSize().padding(32)}
  verticalArrangement={Arrangement.Center}
  horizontalAlignment={Alignment.CenterVertically}
>
  <Text>Details Screen</Text>
  <Text>ID recibido: {id}</Text>

  <Button onClick={() => navController.popBackStack()}>
    Volver
  </Button>
</Column>
3

Wire NavHost

MainNavigationWrapper.svelte owns the NavController and declares the full route graph. rememberNavController() accepts the initial route path as its argument — here Home.path so the app opens directly on the home screen. Each composable() call maps a route object to a lazy screen factory () => ScreenComponent.
<script lang="ts">
  import {
    composable,
    Modifier,
    NavHost,
    rememberNavController,
  } from "@danielito1996/compose-svelted";

  import ProfesionalLogin      from "../ProfesionalLogin.svelte";
  import ProfesionalHomeScreen from "../ProfesionalHomeScreen.svelte";
  import DetailsScreen         from "./DetailsScreen.svelte";
  import { Details, Home, Login } from "./routes";

  export let modifier: Modifier = Modifier.empty();

  const navController = rememberNavController(Home.path);
</script>

<NavHost
  navController={navController}
  modifier={modifier.fillMaxSize()}
  routes={[
    composable(Login,   () => ProfesionalLogin),
    composable(Home,    () => ProfesionalHomeScreen),
    composable(Details, () => DetailsScreen),
  ]}
/>
Transition optionsNavHost accepts an optional transition prop. Import the transition helper and pass it directly:
<script lang="ts">
  import { fade } from "@danielito1996/compose-svelted";
</script>

<NavHost
  navController={navController}
  modifier={modifier.fillMaxSize()}
  transition={fade(300)}
  routes={[...]}
/>
The numeric argument is the duration in milliseconds. Omit transition entirely for an instant cut between screens.
4

Mount in App.svelte

Wrap the entire application in ComposeTheme and AppRoot. ComposeTheme provides the active colour scheme (light, dark, or automatic system detection) to every component in the tree. AppRoot sets up the root layout constraints.
<script>
  import {
    AppRoot,
    ComposeTheme,
  } from "@danielito1996/compose-svelted";

  import MainNavigationWrapper from "./navigation/MainNavigationWrapper.svelte";
</script>

<ComposeTheme mode="system">
  <AppRoot>
    <MainNavigationWrapper />
  </AppRoot>
</ComposeTheme>
With mode="system", ComposeTheme reads prefers-color-scheme from the browser and switches palettes automatically. Change to "light" or "dark" to pin the theme.
ProfesionalLoginWithAnimation.svelte in the playground shows how to combine this navigation setup with AnimatedVisibility to animate the login card appearing on mount. The card is wrapped in AnimatedVisibility with enter={fadeIn()} and exit={fadeOut()}, and a boolean state variable is set to true so the enter animation fires immediately on mount:
<script>
  import {
    AnimatedVisibility,
    fadeIn,
    fadeOut,
  } from "@danielito1996/compose-svelted";

  // Starts as true so the enter animation plays immediately on mount
  let showLogin = true;
</script>

<!-- Overlay Box -->
<Box
  contentAlignment={Alignment.Center}
  modifier={Modifier.fillMaxSize().background("rgba(0,0,0,0.45)")}
>
  <AnimatedVisibility visible={showLogin} enter={fadeIn()} exit={fadeOut()}>
    <Surface
      color={ColorScheme.Surface}
      modifier={Modifier.padding(24).clip(RoundedCornerShape(30))}
    >
      <!-- Brand, form, and action button -->
    </Surface>
  </AnimatedVisibility>
</Box>
scaleIn is also available as an enter animation and pairs well with fadeOut for a card-dismiss effect.
For the full NavHost API — including all supported transition types, nested navigation, and back-stack manipulation — see the NavHost reference.

Build docs developers (and LLMs) love