Skip to main content

Layouts

Create layouts programmatically and use them in your Python notebooks.

What is a layout?

A layout in Foxglove is a data visualization environment configured to support a particular robot or simulation. Layouts include an arrangement of panels, their configurations, and any global variables or user scripts necessary to visualize your data.

Layouts use JSON configuration under the hood. Generally, you would create and configure layouts using the app. To create a layout programmatically, use the Layout class in the foxglove-sdk package.

from foxglove.layouts import *

# Create a layout with a single Markdown panel and a global variable
layout = Layout(
content=MarkdownPanel(
config=MarkdownConfig(markdown="Hello, world!"),
),
variables={
"my_variable": 1,
}
)

The content of a layout can be any panel or panel container.

Panel containers

Layouts typically include multiple panels. There are three containers for arranging panels in a layout:

  • Splits arrange children side-by-side in a row or column
  • Tabs arrange children in tabs, with one child visible at a time
  • Stacks arrange children in a vertically-scrolling list

Split container

A SplitContainer arranges its children in a row or column based on its direction parameter. The children are represented as a list of SplitItem objects, each of which has a proportion and a content.

The space each split item takes up is determined by dividing an item's proportion by the sum of all proportions of all items in the container. For example, if a Split had three children whose proportion values were 4, 6, and 10, then the children would take up 20%, 30%, and 50% of the space, respectively.

tip

When creating a SplitItem, the proportion defaults to 1 if not specified. This will evenly distribute the space between all items if none of the proportions are specified.

tip

Layouts can get complex quickly. If they become deeply-nested, consider extracting sub-sections into named variables and then combining them into a single layout.

from foxglove.layouts import *

# Create a row of panels where the width is evenly distributed between the two panels
split = SplitContainer(
direction="row",
items=[
SplitItem(content=MarkdownPanel(
config=MarkdownConfig(markdown="Hello, world!"),
)),
SplitItem(content=MarkdownPanel(
config=MarkdownConfig(markdown="Hello, world!"),
)),
]
)

layout = Layout(
content=split,
)

Tab container

Use the TabContainer to create a set of tabs, allowing you to quickly switch between different sections of the layout. The container has a list of TabItem objects, each of which has a title and content, and a selected tab index which defaults to 0.

from foxglove.layouts import *

# Create a tab container with two tabs
tabs = TabContainer(
selected_tab_index=1, # Select the second tab
tabs=[
TabItem(
title="Tab 1",
content=MarkdownPanel(
config=MarkdownConfig(markdown="Hello, world!"),
),
),
TabItem(
title="Tab 2",
content=MarkdownPanel(
config=MarkdownConfig(markdown="Hello, world!"),
),
),
]
)

layout = Layout(
content=tabs,
)

Stack container

Use the StackContainer to create a scrollable list of panels. The container has a title and a list of StackItem, each of which has a panel and a size. The size is represented as a fraction of the height of the stack container (for example, 0.5 is 50% of the height of the stack container).

from foxglove.layouts import *

# Create a stack container with two panels
stack = StackContainer(
title="Stack",
panels=[
StackItem(
panel=MarkdownPanel(
config=MarkdownConfig(markdown="Hello, world!"),
),
size=0.25,
),
StackItem(
panel=MarkdownPanel(
config=MarkdownConfig(markdown="Hello, world!"),
),
size=0.25,
),
]
)

layout = Layout(
content=stack,
)

Nesting containers

You can nest the SplitContainer and TabContainer inside each other, and nest the StackContainer inside a SplitContainer or TabContainer.

This enables you to create more complex layouts with multiple levels of nesting.

from foxglove.layouts import *

# Create a tab container with a single tab
# The content of the tab is a 2x2 grid of markdown panels

column1 = SplitContainer(
direction="column",
items=[
SplitItem(content=MarkdownPanel(
config=MarkdownConfig(markdown="Hello, world!"),
)),
SplitItem(content=MarkdownPanel(
config=MarkdownConfig(markdown="Hello, world!"),
)),
]
)

column2 = SplitContainer(
direction="column",
items=[
SplitItem(content=MarkdownPanel(
config=MarkdownConfig(markdown="Hello, world!"),
)),
SplitItem(content=MarkdownPanel(
config=MarkdownConfig(markdown="Hello, world!"),
)),
]
)

row = SplitContainer(
direction="row",
items=[
SplitItem(content=column1),
SplitItem(content=column2),
]
)

tabs = TabContainer(
tabs=[
TabItem(title="Grid", content=row)
]
)

layout = Layout(
content=tabs,
)