Visibility and Responsive Display

Every XMLUI component supports a when attribute that controls whether the component is rendered. Extending this, a family of responsive when-* attributes lets you show or hide components based on the current viewport size.

The when attribute

when is not a visibility toggle — it controls whether XMLUI processes the component at all. When when evaluates to a falsy value, the component and every one of its nested children are skipped: no component output is rendered, no child nodes are created, and no visible lifecycle runs. The component simply does not exist on the page until when becomes truthy again.

This is distinct from merely hiding a component. A hidden-but-rendered component still occupies memory, its event handlers are still active, and it can still affect the layout of the surrounding elements. A component with when="false" has none of that rendered subtree overhead.

Set when to false (or any expression that evaluates falsy) to opt out of rendering:

<Text when="{user.isLoggedIn}">Welcome back!</Text>

When when is omitted or evaluates to true, the component renders normally.

<Spinner when="{isLoading}" />
<Text when="{!isLoading}">Data loaded.</Text>

when and lifecycle events

onMount and onUnmount respond to when transitions. When when switches from false to true, onMount fires. When when switches from true to false, onUnmount fires. This lets you perform setup and teardown logic tied to a component's visibility.

The older onInit and onCleanup names still work as compatibility aliases for onMount and onUnmount.

<App var.showPanel="{false}">
  <Button label="Toggle panel" onClick="showPanel = !showPanel" />
  <Card
    when="{showPanel}"
    onMount="console.log('panel appeared')"
    onUnmount="console.log('panel removed')"
  >
    <Text>Panel content</Text>
  </Card>
</App>

One subtlety: if when starts as false, onMount does not fire at that point. It fires the first time when transitions from false to true — that is, when the component first becomes visible. Each subsequent false -> true transition fires onMount again; the matching true -> false transition fires onUnmount.

Reactivity of when

when is a reactive binding expression. XMLUI re-evaluates it when the XMLUI variables, component state, or context values it reads change. The result controls whether the component subtree exists.

Keep when expressions focused on explicit state:

<Stack when="{user.loaded}">
  <Text>{user.value.name}</Text>
</Stack>

When a condition depends on fetched data, prefer DataSource status properties such as loaded, inProgress, and error. For a one-off payload check, reading a deep path directly is fine; XMLUI member access is optional by default. When the condition is reused or has business meaning, store that named decision in a local var from onLoaded.

<App var.showBillingPanel="{false}">
  <DataSource
    id="user"
    url="/api/users/me"
    onLoaded="data => showBillingPanel = !!data.billing.address"
  />

  <Stack when="{showBillingPanel}">
    <Text>Billing address is available.</Text>
  </Stack>
</App>

Deep payload checks are valid expressions. Use a named boolean when it makes the rendering rule easier to read or when the same decision appears in multiple places.

Responsive when-* attributes

The responsive variants follow a mobile-first (min-width) convention. Each attribute name is when- followed by a breakpoint name:

AttributeApplies from
when-xsAll screens (≥ 0 px)
when-smSmall screens (≥ 576 px)
when-mdMedium screens (≥ 768 px)
when-lgLarge screens (≥ 992 px)
when-xlExtra-large screens (≥ 1200 px)
when-xxlExtra-extra-large screens (≥ 1400 px)

How the active value is resolved

At any given viewport width, XMLUI looks for the most specific rule that applies, by walking from the current breakpoint downward:

  • At md it tries when-md, then when-sm, then when-xs.
  • The first defined value wins.
  • If no rule matches (no rule is defined at or below the current breakpoint), the fallback depends on whether base when is set:
    • when is explicitly set → its value is used as-is.
    • when is absent → the base visibility is inferred as the opposite of the lowest defined when-* rule. A truthy lowest rule implies the component is opt-in (hidden by default below the breakpoint); a falsy lowest rule implies it is opt-out (visible by default below the breakpoint).

This inference makes single-attribute patterns convenient:

  • when-md="true" → visible at md and above, hidden below (inferred base = opposite of true).
  • when-md="false" → hidden at md and above, visible below (inferred base = opposite of false).

Examples

Visible only from md upward:

At md and above when-md="true" applies. Below md the walk finds no rule; since when is absent, the base is inferred as the opposite of true — hidden. The shorthand and the explicit form are equivalent:

<!-- shorthand: inferred base -->
<Text when-md="true" value="Only on medium screens and above" />

<!-- explicit: same effect, intent is stated -->
<Text when="false" when-md="true" value="Only on medium screens and above" />

Hidden from md upward, visible below:

<Text when-md="false" value="Hidden on medium screens and above" />

At xs and sm the walk finds no rule; since when is absent, the base is inferred as the opposite of false — visible. At md and above, when-md="false" applies.

Different content for small and large screens:

<App>
  <Text when-md="false" value="Compact summary" />
  <Text when="false" when-md="true" value="Full detail view" />
</App>

Visible only in a specific breakpoint range — sm through lg:

<Text
  when="false"
  when-sm="true"
  when-xl="false"
  value="Only visible between sm and lg"
/>
  • Below sm: falls back to when=false → hidden.
  • smxl: when-sm=true applies → visible; until xl overrides with false.
  • xl and above: when-xl=false applies → hidden.

Combining responsive attributes with when

The base when is only consulted when the walk from the current breakpoint downward finds no matching responsive rule. Once any responsive rule applies, the base when is ignored for that breakpoint.

When no rule matches and when is absent, the base visibility is inferred as the opposite of the lowest defined when-* rule (see above).

whenwhen-xswhen-mdResult at xsResult at md
(absent)(absent)(absent)visiblevisible
false(absent)(absent)hiddenhidden
(absent)(absent)truehidden (inferred: opposite of true)visible
(absent)(absent)falsevisible (inferred: opposite of false)hidden
(absent)true(absent)visiblevisible (inherits when-xs)
(absent)truefalsevisiblehidden
(absent)falsetruehiddenvisible
false(absent)truehidden (explicit when)visible
true(absent)falsevisible (explicit when)hidden