Superfície e layout¶
O kit de ação e entrada deu ergonomia aos controles. Agora falta a moldura: os cartões, as superfícies e os espaçadores que organizam a tela. O tempestroid traz essa camada com a mesma API de variantes que você já conhece — só que aqui o eixo é a elevação Material 3, não a ênfase do botão.

O exemplo examples/h3gallery no simulador Qt: as três variantes de Card, um
painel tingido com ListTile + Divider, e uma Surface crua.
Onde os nomes moram
Tudo desta página é importado de tempestroid: os widgets (Card,
Surface, HStack, VStack, Spacer, Divider, ListTile), o enum
CardVariant e o Theme/Color. tempest_core é só o motor por baixo —
você não importa ele.
Card e as três variantes Material 3¶
Um Card agrupa conteúdo numa superfície com cantos arredondados e padding
interno. A prop variant (enum CardVariant) escolhe o tratamento M3 — e, como
no Button, o motor resolve o Style a partir do theme, sem você fixar cor
nenhuma:
CardVariant |
Tratamento |
|---|---|
ELEVATED |
superfície + sombra (a elevação vira um Shadow) — o padrão |
FILLED |
preenchimento tonal (surface_variant), sem sombra |
OUTLINED |
borda fina na cor outline, fundo da superfície |
from tempestroid import Card, CardVariant, Text, Widget
def cards(theme) -> Widget: # theme: Theme
return Card(
variant=CardVariant.ELEVATED,
theme=theme,
children=[
Text(content="Título"),
Text(content="Conteúdo do cartão"),
],
)
Os passos de espaçamento vêm do tema
Card carrega padding_step / radius_step / gap_step (padrão "md" /
"md" / "sm") — passos da escala 4dp do tema, não pixels soltos. Troque
para "sm" ou "lg" e o cartão respira de acordo com o resto do app.
Tingindo um cartão com color_scheme¶
Um Card aceita color_scheme para tingir a superfície num
papel de cor (o padrão é "neutral").
Útil para destacar um painel sem sair do tema:
from tempestroid import Card, CardVariant, Text, Widget
def painel(theme) -> Widget: # theme: Theme
return Card(
variant=CardVariant.ELEVATED,
color_scheme="primary", # superfície tingida no acento
theme=theme,
children=[Text(content="Painel em destaque")],
)
Surface — a primitiva crua¶
Card é uma conveniência sobre Surface: a Surface aplica a mesma
resolução de variante (ELEVATED/FILLED/OUTLINED + color_scheme +
radius_step), mas sem o padding interno e segurando um único filho
(child, não children). Use quando você quer controlar o espaçamento por conta
própria:
from tempestroid import CardVariant, Surface, Text, Widget
def superficie(theme) -> Widget: # theme: Theme
return Surface(
variant=CardVariant.FILLED,
theme=theme,
child=Text(content="Superfície preenchida, sem padding interno"),
)
Card constrói sobre Surface
Pense no Card como Surface + padding + um Column dos seus children.
Quando o padding embutido do Card não serve, desça para a Surface e monte
o miolo você mesmo.
Helpers de pilha: HStack, VStack, Spacer¶
Para o arranjo do dia a dia, os helpers de pilha são Row/Column com gaps
nomeados do tema em vez de um número de pixels. HStack empilha na horizontal,
VStack na vertical; o gap aceita um passo da escala de espaçamento
("xs"/"sm"/"md"/"lg"/"xl"):
from tempestroid import HStack, Spacer, Text, VStack, Widget
def barra(theme) -> Widget: # theme: Theme
return HStack(
gap="md",
theme=theme,
children=[
Text(content="Início"),
Spacer(), # empurra o que vem depois para a borda oposta
Text(content="Configurações"),
],
)
def coluna(theme) -> Widget: # theme: Theme
return VStack(
gap="sm",
theme=theme,
children=[Text(content="Linha 1"), Text(content="Linha 2")],
)
Spacer é o espaço elástico: ele cresce para preencher o eixo principal, então
um Spacer entre dois filhos de um HStack joga o segundo para a borda
contrária. Controle a proporção com flex (padrão 1.0).
Divider e ListTile temáticos¶
Divider é uma régua fina que segue a cor outline do tema (ou um
color_scheme que você passe); ListTile é a linha clássica de lista — title
+ subtitle + slots leading/trailing (que aceitam qualquer widget, como um
Avatar):
from tempestroid import Avatar, Divider, ListTile, VStack, Widget
def lista(theme) -> Widget: # theme: Theme
return VStack(
gap="xs",
theme=theme,
children=[
ListTile(
title="Maria Silva",
subtitle="maria@example.com",
leading=Avatar(label="MS"),
theme=theme,
),
Divider(theme=theme),
ListTile(title="João Souza", subtitle="joao@example.com", theme=theme),
],
)
Exemplo completo: a galeria de superfície¶
examples/h3gallery/app.py junta tudo — as três variantes de Card lado a lado,
um cartão tingido com ListTile + Divider + uma linha de ação que usa Spacer
para empurrar o botão à borda, e uma Surface crua:
No aparelho, o mesmo view/make_state carrega no host Compose: como Card,
Surface, HStack, VStack, Divider e ListTile são componentes
compostos (descem a primitivos via Component.render), eles renderizam pelos
seus filhos primitivos nos dois renderizadores — sem um ramo Kotlin dedicado.
Divergência de superfície
A sombra do ELEVATED vira um Shadow resolvido pela elevação M3 e segue os
dois tradutores Style. A geometria (raio, padding) sai dos passos do tema —
idêntica nos dois renderizadores. Veja a
cobertura de renderizadores para a tabela
completa.
Recapitulando¶
Cardagrupa conteúdo numa superfície M3;variantescolheELEVATED(sombra) /FILLED(tonal) /OUTLINED(borda) e o motor resolve oStyledo tema.padding_step/radius_step/gap_stepvêm da escala 4dp do tema, não de pixels soltos;color_schemetinge a superfície num papel de cor.Surfaceé a primitiva crua que oCardusa — mesma resolução de variante, sem padding e com umchild.HStack/VStacksãoRow/Columncom gap nomeado do tema;Spacercresce para empurrar os vizinhos.Divider/ListTileseguem o tema (linha + a clássica linha de lista comleading/trailing).- Tudo é componente composto → renderiza pelos primitivos nos dois renderizadores.
A seguir: data display e feedback — Alert/Banner, a família
Badge/Chip/Tag, Stat, ProgressStepper e os color_schemes de status.