App

The App component is the root container that defines your application's overall structure and layout. It provides a complete UI framework with built-in navigation, header, footer, and content areas that work together seamlessly.

Essential features:

  • Layout templates: Choose from 7 predefined layouts (horizontal, vertical, condensed, etc.) with sticky navigation options
  • Routing: Built-in page routing via the Pages component

Behaviors

This component supports the following behaviors:

BehaviorProperties
Bookmarkbookmark, bookmarkLevel, bookmarkTitle, bookmarkOmitFromToc
Publish/SubscribesubscribeToTopic
Styling Variantvariant

Properties

autoDetectTone

default: false

This boolean property enables automatic detection of the system theme preference. When set to true and no defaultTone is specified, the app will automatically use "light" or "dark" tone based on the user's system theme setting. The app will also respond to changes in the system theme preference.

defaultTheme

This property sets the app's default theme.

defaultTone

This property sets the app's default tone ("light" or "dark").

Available values: light, dark

layout

This property sets the layout template of the app. This setting determines the position and size of the app parts (such as header, navigation bar, footer, etc.) and the app's scroll behavior.

Available values:

ValueDescription
verticalThis layout puts the navigation bar on the left side and displays its items vertically. The main content is aligned to the right (including the header and the footer), and its content is a single scroll container; every part of it moves as you scroll the page. This layout does not display the logo in the app header.
vertical-stickySimilar to vertical, the header and the navigation bar dock to the top of the main content's viewport, while the footer sticks to the bottom. This layout does not display the logo in the app header.
vertical-full-headerSimilar to vertical-sticky. However, the header and the navigation bar dock to the top of the app's window, while the footer sticks to the bottom.
condensedSimilar to horizontal. However, the header and the navigation bar are in a single header block. (default)
condensed-stickyHowever, the header and the navigation bar are in a single header block.
horizontalThis layout stacks the layout sections in a single column in this order: header, navigation bar, main content, and footer. The application is a single scroll container; every part moves as you scroll the page.
horizontal-stickySimilar to horizontal, the header and the navigation bar dock to the top of the viewport, while the footer sticks to the bottom.
desktopThis layout is designed for desktop applications with a fixed viewport structure. The app fills the entire browser viewport (100vw × 100vh) with zero padding and margins. The header remains fixed at the top, the footer remains fixed at the bottom, and the main content dynamically fills all remaining vertical space between them. When the content overflows, only the main content area scrolls while the header and footer remain visible. This creates a classic desktop application layout with persistent header and footer regions.

Here are a few samples demonstrating the usage of the layout property. All samples use this markup, except the value of App's layout and a few marked code snippets:

<App layout="(specific layout value)">
  <!-- AppHeader omitted for "vertical" and "vertical-sticky" -->
  <AppHeader>
    <property name="logoTemplate">
      <Heading level="h3" value="Example App"/>
    </property>
  </AppHeader>
  <NavPanel>
    <NavLink label="Home" to="/" icon="home"/>
    <NavLink label="Page 1" to="/page1"/>
    <NavLink label="Page 2" to="/page2"/>
  </NavPanel>
  <Pages fallbackPath="/">
    <Page url="/">
      <List data="https://api.spacexdata.com/v3/history">
        <property name="itemTemplate">
          <Card title="{$item.title}" subtitle="{$item.details}"/>
        </property>
      </List>
    </Page>
    <Page url="/page1">
      <Text value="Page 1" />
    </Page>
    <Page url="/page2">
      <Text value="Page 2" />
    </Page>
  </Pages>
  <Footer>Powered by XMLUI</Footer>
</App>

horizontal

Example: 'horizontal' layout

horizontal-sticky

Example: 'horizontal-sticky' layout

condensed

Example: 'condensed' layout

condensed-sticky

Example: 'condensed-sticky' layout

vertical

Example: 'vertical' layout

vertical-sticky

Example: 'vertical-sticky' layout

vertical-full-header

Example: 'vertical-full-header' layout

desktop

Example: 'desktop' layout

The desktop layout is designed for full-screen desktop applications. It stretches the app to fill the entire browser viewport with zero padding and margins. The header (if present) docks to the top, the footer (if present) docks to the bottom, and the main content area stretches to fill all remaining vertical and horizontal space. This layout ignores all max-width constraints and scrollbar gutter settings to ensure edge-to-edge display.

loggedInUser

Stores information about the currently logged-in user. By not defining this property, you can indicate that no user is logged in.

Stores information about the currently logged in user. Currently, there is no restriction on what the user data must look like.

<App loggedInUser="{{ name: 'Joe', token: '1234' }}">
  <NavPanel>
    <NavLink label="Home" to="/" icon="home"/>
  </NavPanel>
  <Pages fallbackPath="/">
    <Page url="/">
      <Text value="User name: {loggedInUser.name}" />
      <Text value="User token: {loggedInUser.token}" />
    </Page>
  </Pages>
</App>
Example: loggedInUser
<App loggedInUser="{{ name: 'Joe', token: '1234' }}">
  <NavPanel>
    <NavLink label="Home" to="/" icon="home"/>
  </NavPanel>
  <Pages fallbackPath="/">
    <Page url="/">
      <Text value="User name: {loggedInUser.name}" />
      <Text value="User token: {loggedInUser.token}" />
    </Page>
  </Pages>
</App>

Optional logo path

logo-dark

Optional logo path in dark tone

logo-light

Optional logo path in light tone

logoTemplate

Optional template of the app logo

name

Optional application name (visible in the browser tab). When you do not define this property, the tab name falls back to the one defined in the app's configuration. If the name is not configured, "XMLUI App" is displayed in the tab.

noScrollbarGutters

default: false

This boolean property specifies whether the scrollbar gutters should be hidden.

scrollWholePage

default: true

This boolean property specifies whether the whole page should scroll (true) or just the content area (false). The default value is true.

This boolean property specifies whether the whole page should scroll (true) or just the content area (false). The default value is true.

<App scrollWholePage="false">
  <NavPanel>
    <NavLink label="Home" to="/" icon="home"/>
  </NavPanel>
  <Pages fallbackPath="/">
    <Page url="/">
      <Text>
        Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed 
        do eiusmod tempor incididunt ut labore et dolore magna aliqua. 
        Ut enim ad minim veniam, quis nostrud exercitation ullamco 
        laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure 
        dolor in reprehenderit in voluptate velit esse cillum dolore eu 
        fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, 
        sunt in culpa qui officia deserunt mollit anim id est laborum.
      </Text>
    </Page>
  </Pages>
</App>
Example: scrollWholePage='false'
<App scrollWholePage="false">
  <NavPanel>
    <NavLink label="Home" to="/" icon="home"/>
  </NavPanel>
  <Pages fallbackPath="/">
    <Page url="/">
      <Text>
        Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed 
        do eiusmod tempor incididunt ut labore et dolore magna aliqua. 
        Ut enim ad minim veniam, quis nostrud exercitation ullamco 
        laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure 
        dolor in reprehenderit in voluptate velit esse cillum dolore eu 
        fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, 
        sunt in culpa qui officia deserunt mollit anim id est laborum.
      </Text>
    </Page>
  </Pages>
</App>

When scrollWholePage is set to false, the main content panel's height is stretched to the remaining height of the viewport between the header and the footer. When you use star sizing, it calculates the effective height from the main content's height:

<App layout="horizontal" scrollWholePage="false">
  <AppHeader>
    Horizontal Splitter Example
  </AppHeader>
  <CHStack height="*" backgroundColor="lightblue">1/4</CHStack>
  <CHStack height="3*" backgroundColor="lightcoral">3/4</CHStack>
  <Footer>
    Footer Content
  </Footer>
</App>
Example: scrollWholePage='false' (star-sizing)
<App layout="horizontal" scrollWholePage="false">
  <AppHeader>
    Horizontal Splitter Example
  </AppHeader>
  <CHStack height="*" backgroundColor="lightblue">1/4</CHStack>
  <CHStack height="3*" backgroundColor="lightcoral">3/4</CHStack>
  <Footer>
    Footer Content
  </Footer>
</App>

Here is a more complex example built on star-sizing:

<App layout="horizontal" scrollWholePage="false">
  <AppHeader>
    Horizontal Splitter Example
  </AppHeader>
  <HSplitter height="*" minPrimarySize="180px" maxPrimarySize="-180px">
    <List
      id="myList"
      data="{ Array.from({ length: 100 }).map((_, i) => i) }"
    >
      <Card title="Item #{$item}" />
    </List>
    <Card title="Details" />
  </HSplitter>
  <Footer>
    Footer Content
  </Footer>
</App>
Example: scrollWholePage='false' (with Splitter)
<App layout="horizontal" scrollWholePage="false">
  <AppHeader>
    Horizontal Splitter Example
  </AppHeader>
  <HSplitter height="*" minPrimarySize="180px" maxPrimarySize="-180px">
    <List
      id="myList"
      data="{ Array.from({ length: 100 }).map((_, i) => i) }"
    >
      <Card title="Item #{$item}" />
    </List>
    <Card title="Details" />
  </HSplitter>
  <Footer>
    Footer Content
  </Footer>
</App>

Events

didNavigate

This event fires after the app has completed any navigation (including Link clicks, browser back/forward, and programmatic navigation).

Signature: (to: string | number, queryParams?: Record<string, any>) => Promise<void>

  • to: The path that was navigated to.
  • queryParams: Query parameters (only available for programmatic navigation).

keyDown

This event fires when a key is pressed while the App has focus or when the event reaches the app level without being consumed by a child component.

Signature: (event: KeyboardEvent) => void

  • event: The keyboard event object.

keyUp

This event fires when a key is released while the App has focus or when the event reaches the app level without being consumed by a child component.

Signature: (event: KeyboardEvent) => void

  • event: The keyboard event object.

messageReceived

This event fires when the App component receives a message from another window or iframe via the window.postMessage API.

Signature: (data: any) => void

  • data: The data sent from the other window via postMessage.

The event handler method has two parameters. The first is the message sent; the second is the entire native event object.

<App 
  var.message = "<none>" 
  onMessageReceived="(msg, ev) => {
    message = JSON.stringify(msg);
    console.log('Message event received:', ev);
  }">
  <Button label="Send a message"
    onClick="window.postMessage({type: 'message', messages:'Here you are!'})" />
  <Text>Message received: {message}</Text>
</App>
Example: messageReceived
<App 
  var.message = "<none>" 
  onMessageReceived="(msg, ev) => {
    message = JSON.stringify(msg);
    console.log('Message event received:', ev);
  }">
  <Button label="Send a message"
    onClick="window.postMessage({type: 'message', messages:'Here you are!'})" />
  <Text>Message received: {message}</Text>
</App>

ready

This event fires when the App component finishes rendering on the page.

Signature: () => void

This event fires when the App component finishes rendering on the page. Use it as onReady when inlining it on the component.

<App onReady="isAppReady = true">
  <variable name="isAppReady" value="{false}"/>
  <Text value="{isAppReady ? 'App is ready' : 'Sadly, App is not ready'}" />
</App>
Example: ready
<App onReady="isAppReady = true">
  <variable name="isAppReady" value="{false}"/>
  <Text value="{isAppReady ? 'App is ready' : 'Sadly, App is not ready'}" />
</App>

willNavigate

This event fires before the app is about to navigate programmatically via navigate() or Actions.navigate(). The event handler receives the target path and optional query parameters. Returning false cancels the navigation; returning null, undefined, or any other value proceeds with normal navigation. Note: This event does NOT fire for Link clicks or browser back/forward navigation due to React Router limitations (event handlers are async, but router blocking is synchronous).

Signature: (to: string | number, queryParams?: Record<string, any>) => Promise<false | void | null | undefined>

  • to: The target path or history delta (e.g., -1 for back) to navigate to.
  • queryParams: Optional query parameters to include in the navigation.

Exposed Methods

This component does not expose any methods.

Styling

Theme Variables

VariableDefault Value (Light)Default Value (Dark)
backgroundColor-AppHeadernonenone
backgroundColor-content-App$backgroundColor$backgroundColor
backgroundColor-navPanel-App$backgroundColor$backgroundColor
borderBottom-AppHeadernonenone
borderLeft-content-Appnonenone
borderRight-navPanelWrapper-App1px solid $borderColor1px solid $borderColor
boxShadow-header-Appnonenone
boxShadow-navPanel-Appnonenone
maxWidth-App$maxWidth-content$maxWidth-content
maxWidth-content-App$maxWidth-content$maxWidth-content
maxWidth-content-App--withTocnonenone
width-navPanel-App$space-64$space-64
width-navPanel-collapsed-App48px48px

Variable Explanations

Theme VariableDescription
maxWidth-content-AppThis theme variable defines the maximum width of the main content. If the main content is broader, the engine adds margins to keep the expected maximum size.
boxShadow‑header‑AppThis theme variable sets the shadow of the app's header section.
boxShadow‑navPanel‑AppThis theme variable sets the shadow of the app's navigation panel section (visible only in vertical layouts).
width‑navPanel‑AppThis theme variable sets the width of the navigation panel when the app is displayed with one of the vertical layouts.