Skip to main content

Layout

This section explains the fundamental rule Komplete UI's layout system uses:

Parent proposes size. Child chooses size. Parent positions child.

Consider the following example component, where a Text component is layered on top of a Rectangle using a ZStack.

component Example {
ZStack {
Rectangle(color: Color(0xFFFF0000))
Text("Text")
}
with { Frame(width: 200, height: 200) }
}

The following image demonstrates the resulting layout:

layout_algorithm_example.svg

To understand how this layout is created we can consider the following dialog between the components:

Frame: "Hi ZStack, I propose you 200 pixels of width, and 200 pixels of height."

ZStack: "Hmmm, before I'll let you know my size, I'll ask my children what size they want."

ZStack: "Hey Rectangle, You could be 200 pixels wide, and 200 tall."

Rectangle: "OK, I would like to fill the entire space."

ZStack: "Hey Text, You could be 200 pixels wide, and 200 tall."

Text: "Hey, ZStack I only need enough to display my text."

ZStack: “Fair enough, I'll put you in the center.”

ZStack: "Hey Frame, since Rectangle wants to fill the entire area I’ve decided that my size is also going to be 200 pixels wide, and 200 pixels tall."

Z-Level Stacking of Components

In this section you'll learn three different ways how to stack components on top of each other.

Overlay

The Overlay modifier allows you to layer components in front of another one. In difference to the ZStack the size of the background component is unchanged and will be used as suggestion for the overlayed components.

Consider the following example where a Text is overlayed on top of a Rectangle bound by 100x100 pixels:

import { Rectangle, Text, Frame, Overlay } from ui

export var main = Rectangle(color: Color(0xFFDFDFDF)) with {
Frame(width: 100, height: 100)
Overlay {
Text("Hello Long Text")
}
}

overlay_example.png

You can see that the text is wrapped, because it doesn't fit into the suggested area driven by the Frame. Here's the same example using a ZStack instead:

import { Rectangle, ZStack, Text, Frame } from ui

export var main = ZStack {
Rectangle(color: Color(0xFF565656)) with { Frame(width: 100, height: 100) }
Text("Hello Long Text", color: Color(0xFFFFFFFF))
}

overlay_example_zstack.png

In the case of the ZStack the text doesn't have to fit into the Rectangle. The ZStack considers all children equally to determine its final size.

Background

The Background modifier does the opposite of Overlay and instead layers components behind another one. The size of the foreground component will be suggested to the background components.

Consider the following example where a Rectangle is put behind some Text:

import { Rectangle, Background, Text, Frame } from ui

export var main = Text("Hello World", color: Color(0xFFFFFFFF)) with {
Background {
Rectangle(color: Color(0xFF565656))
}
}

background_example.png

You can see that in this case the Text is the driver of the background size, which is why the Rectangle fills out the area spanned up by the Text.

Here's the same example with a ZStack:

import { Rectangle, ZStack, Text, Frame } from ui

export var main = ZStack {
Rectangle(color: Color(0xFF565656))
Text("Hello World", color: Color(0xFFFFFFFF))
}

background_example_zstack.png

In this case, the ZStack considers all children equally and will fill the entire area of the window, because its child Rectangle wants to fill everything that's available.