Dock elements to panel edges

Use dock on Stack children to build fixed-height panels with pinned headers, scrollable middle content, and bottom action bars.

A common case is a panel or dialog section with a long, scrollable body and buttons that must remain visible at the bottom. Put the scrollable region in a child with dock="stretch" and the actions in a child with dock="bottom". The parent Stack must have an explicit height.

<App scrollWholePage="false">
  <Stack height="100%" borderWidth="1px" borderColor="$color-surface-200" gap="0">
    <HStack
      dock="top"
      padding="$space-2 $space-3"
      backgroundColor="$color-surface-100"
      borderBottom="1px solid $color-surface-200"
    >
      <Text variant="strong">Preview events</Text>
    </HStack>
    <ScrollViewer dock="stretch" showScrollerFade="{false}">
      <VStack padding="$space-2" gap="$space-2">
        <Text>Community forum at the library</Text>
        <Text>Neighborhood cleanup on Saturday</Text>
        <Text>Summer concert in the park</Text>
        <Text>Transit board meeting</Text>
        <Text>Farmers market opening day</Text>
        <Text>After-school robotics demo</Text>
        <Text>Public art walk downtown</Text>
        <Text>Book club at the branch library</Text>
        <Text>Tenant association meeting</Text>
        <Text>Neighborhood potluck in the park</Text>
        <Text>Open studio night at the arts center</Text>
        <Text>Community bike ride kickoff</Text>
      </VStack>
    </ScrollViewer>
    <HStack
      dock="bottom"
      padding="$space-2"
      gap="$space-2"
      horizontalAlignment="end"
      backgroundColor="$color-surface-0"
      borderTop="1px solid $color-surface-200"
    >
      <Button label="Back" variant="ghost" />
      <Button label="Add Feed" />
    </HStack>
  </Stack>
</App>
Scrollable panel with bottom actions
<App scrollWholePage="false">
  <Stack height="100%" borderWidth="1px" borderColor="$color-surface-200" gap="0">
    <HStack
      dock="top"
      padding="$space-2 $space-3"
      backgroundColor="$color-surface-100"
      borderBottom="1px solid $color-surface-200"
    >
      <Text variant="strong">Preview events</Text>
    </HStack>
    <ScrollViewer dock="stretch" showScrollerFade="{false}">
      <VStack padding="$space-2" gap="$space-2">
        <Text>Community forum at the library</Text>
        <Text>Neighborhood cleanup on Saturday</Text>
        <Text>Summer concert in the park</Text>
        <Text>Transit board meeting</Text>
        <Text>Farmers market opening day</Text>
        <Text>After-school robotics demo</Text>
        <Text>Public art walk downtown</Text>
        <Text>Book club at the branch library</Text>
        <Text>Tenant association meeting</Text>
        <Text>Neighborhood potluck in the park</Text>
        <Text>Open studio night at the arts center</Text>
        <Text>Community bike ride kickoff</Text>
      </VStack>
    </ScrollViewer>
    <HStack
      dock="bottom"
      padding="$space-2"
      gap="$space-2"
      horizontalAlignment="end"
      backgroundColor="$color-surface-0"
      borderTop="1px solid $color-surface-200"
    >
      <Button label="Back" variant="ghost" />
      <Button label="Add Feed" />
    </HStack>
  </Stack>
</App>

The next example uses all four edges at once — a toolbar at the top, a status bar at the bottom, a navigation tree on the left, a properties panel on the right, and a scrollable editor region in the middle:

<App scrollWholePage="false">
  <Stack 
    height="100%" 
    borderWidth="1px" 
    borderColor="$color-surface-200"
    gap="0"
  >
    <HStack
      dock="top"
      padding="$space-3 $space-2"
      backgroundColor="$color-surface-100"
    >
      <Icon name="layout" />
      <Text variant="strong">Editor</Text>
    </HStack>
    <VStack
      dock="left"
      width="150px"
      padding="$space-2"
      backgroundColor="$color-primary-100"
    >
      <Text variant="strong">Files</Text>
      <Text>index.xmlui</Text>
      <Text>App.xmlui</Text>
      <Text>Card.xmlui</Text>
    </VStack>
    <VStack
      dock="right"
      width="140px"
      padding="$space-2"
      backgroundColor="$color-warn-100"
    >
      <Text variant="strong">Properties</Text>
      <Text>width: auto</Text>
      <Text>height: 100%</Text>
    </VStack>
    <VStack dock="stretch" padding="$space-3">
      <Text>…editor content…</Text>
    </VStack>
    <HStack
      dock="bottom"
      padding="$space-1 $space-3"
      backgroundColor="$color-surface-100"
    >
      <Text>Ln 12, Col 4</Text>
      <SpaceFiller />
      <Text>UTF-8</Text>
    </HStack>
  </Stack>
</App>
All four dock edges
<App scrollWholePage="false">
  <Stack 
    height="100%" 
    borderWidth="1px" 
    borderColor="$color-surface-200"
    gap="0"
  >
    <HStack
      dock="top"
      padding="$space-3 $space-2"
      backgroundColor="$color-surface-100"
    >
      <Icon name="layout" />
      <Text variant="strong">Editor</Text>
    </HStack>
    <VStack
      dock="left"
      width="150px"
      padding="$space-2"
      backgroundColor="$color-primary-100"
    >
      <Text variant="strong">Files</Text>
      <Text>index.xmlui</Text>
      <Text>App.xmlui</Text>
      <Text>Card.xmlui</Text>
    </VStack>
    <VStack
      dock="right"
      width="140px"
      padding="$space-2"
      backgroundColor="$color-warn-100"
    >
      <Text variant="strong">Properties</Text>
      <Text>width: auto</Text>
      <Text>height: 100%</Text>
    </VStack>
    <VStack dock="stretch" padding="$space-3">
      <Text>…editor content…</Text>
    </VStack>
    <HStack
      dock="bottom"
      padding="$space-1 $space-3"
      backgroundColor="$color-surface-100"
    >
      <Text>Ln 12, Col 4</Text>
      <SpaceFiller />
      <Text>UTF-8</Text>
    </HStack>
  </Stack>
</App>

Key points

DockPanel mode activates automatically: As soon as any direct child of a Stack receives a dock prop, the parent switches to DockPanel layout. No extra mode attribute is needed on the parent:

dock valueBehaviour
"top"Anchored to the top edge, full container width
"bottom"Anchored to the bottom edge, full container width
"left"Anchored to the left edge, full height of the middle row
"right"Anchored to the right edge, full height of the middle row
"stretch"Fills all remaining space in the middle row

dock="stretch" is the fill region: Exactly one child should have dock="stretch". It takes all space not claimed by top, bottom, left, and right children. Omitting it leaves the middle row at zero height:

<Stack height="400px">
  <HStack dock="top">…header…</HStack>
  <VStack dock="stretch">…scrollable content…</VStack>
  <HStack dock="bottom">…action bar…</HStack>
</Stack>

dock="stretch" is the usual place for a ScrollViewer when the middle region should scroll while the action row remains fixed:

<Stack height="400px" gap="0">
  <ScrollViewer dock="stretch">…long content…</ScrollViewer>
  <HStack dock="bottom">…buttons…</HStack>
</Stack>

Parent height is required for dock="bottom" to take effect: Without an explicit height the outer container collapses to content size and the bottom-docked child simply follows the content instead of anchoring to the edge:

<Stack height="100%">   <!-- or height="400px" -->
  <VStack dock="stretch"></VStack>
  <HStack dock="bottom"></HStack>
</Stack>

gap="0" removes the default spacing between docked regions: By default Stack applies a gap between its children. In a DockPanel layout this creates visible gaps between the toolbar, side panels, and content area. Set gap="0" on the parent Stack when the docked children carry their own borders or background colors and you want the regions to meet flush:

<Stack height="100%" gap="0">
  <HStack dock="top">…toolbar…</HStack>
  <VStack dock="left" width="160px">…sidebar…</VStack>
  <VStack dock="stretch">…content…</VStack>
</Stack>

Use dock="bottom" for parent-owned action bars, not ScrollViewer.footerTemplate: footerTemplate belongs to the scroll container itself. When you need a panel or dialog section with a scrollable body and a bottom action row, make the action row a sibling in the parent Stack and dock it to the bottom:

<Stack height="400px" gap="0">
  <ScrollViewer dock="stretch">…body…</ScrollViewer>
  <HStack dock="bottom">…Back / Save…</HStack>
</Stack>

Children without a dock prop: Undocked children participate in the middle row alongside the stretch child, distributed by normal flex rules.

Nesting DockPanels: A dock="stretch" child can itself contain another Stack with docked children — giving you an outer shell with a toolbar at the top and an inner panel that splits into a scrollable list and a status bar at the bottom.


See also