Superfícies & cards¶
As superfícies são as caixas temáticas sobre as quais todo o resto do
tempest-core se apoia. No fundo há uma única primitiva — a Surface — e
tudo mais (Card, Sidebar, painéis) é ela mais um pouco de padding e um
arranjo de filhos. Todas resolvem seu Style da API de variantes Chakra
(variant / color_scheme / elevation) ancorada em Material 3: você
descreve a intenção de superfície e o resolver puro
resolve_surface_variant assa o Style concreto a partir dos tokens do
Theme. 🚀
O que você aprende aqui
- A primitiva
Surface(sem padding) e como oCardé só ela + padding +Column. - As três variantes
CardVariant(ELEVATED/FILLED/OUTLINED) e para qual tratamento M3 cada uma abaixa. - Por que a elevação é uma
Shadowmapeada do nível M3, nunca um campo deStylenovo. - Os itens de conteúdo (
ListTile,Avatar,Divider) e como eles leem cor e espaçamento do tema. - Os componentes de layout (
Grid,HStack,VStack,Scaffold,Sidebar) e ogappor passo de token. - Os helpers de composição:
merge_stylee os tokens de paleta padrão.
Superfícies¶
A superfície é a caixa temática crua. Surface não tem padding próprio;
StyledContainer adiciona um padding por passo de token sobre a Container
primitiva.
Surface¶
A primitiva de superfície sem padding: uma caixa de um filho só que carrega o
Style resolvido da variante, sem padding ou gap interno. É o que toda
superfície de nível mais alto (Card, cabeçalho de Accordion, …) constrói por
cima.
from tempest_core import Surface
from tempest_core import Text
superficie = Surface(child=Text(content="Olá"))
Esse Surface(child=…) já é uma superfície elevada, neutra — pronta para os
renderizadores. Escolha a variante e a família de cor pela intenção:
from tempest_core import Surface
from tempest_core import CardVariant
from tempest_core import Text
painel = Surface(
variant=CardVariant.OUTLINED, # (1)!
color_scheme="primary", # tonal *_container
elevation=0, # nível M3 explícito
child=Text(content="Painel"),
)
varianttambém aceita a string equivalente ("outlined"); o enumCardVariantdeixa a intenção explícita.
Props¶
| Prop | Tipo | Padrão | O que faz |
|---|---|---|---|
child |
Widget \| None |
None |
O widget envolvido (opcional). |
variant |
CardVariant |
ELEVATED |
O tratamento de superfície (elevated / filled / outlined). |
color_scheme |
str |
"neutral" |
A família de papéis M3 ("neutral" usa as roles de superfície planas; uma família usa as roles tonais *_container). |
elevation |
int \| None |
None |
Nível M3 explícito (0-5) que sobrepõe o padrão da variante. |
radius_step |
str |
"md" |
O passo da escala de forma para o raio dos cantos. |
theme |
Theme |
Theme() |
O tema cujos tokens resolvem a superfície. Não entra na IR. |
media |
MediaQueryData \| None |
None |
Snapshot de viewport (aceito por paridade; não usado aqui). |
Surface é a base sem padding; Card é Surface + padding + Column
Diferente do Card, a Surface não adiciona padding nem gap interno — ela
é a superfície nua, deixando o layout do conteúdo para o que ela envolve. Ela
resolve o Style da variante, mescla o style explícito do chamador por cima
(os campos setados vencem) e abaixa para uma Container de um filho só.
StyledContainer¶
Uma caixa de um filho só com padding por passo de token sobre a Container
primitiva. Dá ergonomia de design-system à primitiva sem mutá-la: o padding
aceita um nome de passo ("md" / "lg") resolvido contra a escala de
espaçamento do tema, ou um float cru para retrocompatibilidade.
from tempest_core import StyledContainer
from tempest_core import Text
caixa = StyledContainer(padding="lg", child=Text(content="Conteúdo folgado"))
Props¶
| Prop | Tipo | Padrão | O que faz |
|---|---|---|---|
child |
Widget \| None |
None |
O widget envolvido (opcional). |
padding |
float \| str |
"md" |
O padding interno — um nome de passo de token ("md") ou um float em pixels lógicos. |
theme |
Theme |
Theme() |
O tema cuja escala de espaçamento resolve o nome do passo. |
Passo de token ou float — os dois valem
Uma string ("md") resolve via Theme.space(...); um float cru
(padding=24.0) passa direto. Um style explícito é mesclado por cima do
padding resolvido.
Cards & itens¶
Blocos de apresentação clássicos que abaixam para primitivas. Com os tokens do
design-system, cada um lê cor e espaçamento do Theme em vez de hexadecimais
fixos.
Card¶
Uma superfície temática que agrupa uma pilha de filhos (card do Material 3). É
exatamente Surface + padding + Column: resolve o tratamento de
superfície de variant / color_scheme / elevation, adiciona seu próprio
padding e empilha os filhos numa Column.
from tempest_core import Card
from tempest_core import Text
cartao = Card(
children=[
Text(content="Título"),
Text(content="Corpo do card."),
]
)
Um Card(children=…) sem argumentos produz um card elevado, neutro. Escolha
a variante e ajuste os passos de espaçamento:
from tempest_core import Card
from tempest_core import CardVariant
from tempest_core import Text
destaque = Card(
variant=CardVariant.FILLED,
color_scheme="primary",
padding_step="lg", # padding interno
gap_step="md", # espaço entre os filhos
children=[Text(content="Plano Pro")],
)
Props¶
| Prop | Tipo | Padrão | O que faz |
|---|---|---|---|
children |
list[Widget] |
[] |
Os widgets empilhados verticalmente dentro do card. |
variant |
CardVariant |
ELEVATED |
O tratamento de superfície (elevated / filled / outlined). |
color_scheme |
str |
"neutral" |
A família de papéis M3 com que o card se tinge. |
elevation |
int \| None |
None |
Nível M3 explícito (0-5) sobrepondo o padrão. |
padding_step |
str |
"md" |
O passo de espaçamento para o padding interno. |
radius_step |
str |
"md" |
O passo da escala de forma para o raio dos cantos. |
gap_step |
str |
"sm" |
O passo de espaçamento para o gap entre os filhos. |
theme |
Theme |
Theme() |
O tema cujos tokens resolvem a superfície. Não entra na IR. |
media |
MediaQueryData \| None |
None |
Snapshot de viewport (aceito por paridade; não usado). |
As três variantes de CardVariant
CardVariant |
Tratamento M3 | Fundo | Sombra | Borda |
|---|---|---|---|---|
ELEVATED |
elevated card | surface |
elevação nível 1 | — |
FILLED |
filled card | surface_variant (tonal) |
— | — |
OUTLINED |
outlined card | surface |
— | outline (1px) |
O color_scheme decide qual família de cor pinta o tratamento: "neutral"
usa as roles de superfície planas; uma família ("primary", "error", …) usa
as roles tonais *_container.
Elevação é uma Shadow, não um campo de Style novo
Um nível de elevação M3 (0-5) é mapeado para uma Shadow (blur + deslocamento
para baixo) via _elevation_shadow — nunca um campo elevation no Style. Por
padrão ELEVATED sobe para o nível 1 e FILLED/OUTLINED ficam rentes (nível
0); passar elevation= sobrepõe esse padrão. O renderizador traduz a Shadow
resolvida para a elevação nativa (Compose Modifier.shadow / Qt
QGraphicsDropShadowEffect).
ListTile¶
Uma linha de lista: widgets leading/trailing opcionais em volta de um bloco
de título. O título usa ON_SURFACE, o subtítulo usa ON_SURFACE_VARIANT, e os
gaps/padding vêm da escala de espaçamento do tema.
from tempest_core import Avatar, ListTile
from tempest_core import IconButton
linha = ListTile(
title="Mauricio Benjamin",
subtitle="mauricio@exemplo.com",
leading=Avatar(initials="MB"),
trailing=IconButton(icon="chevron_right", label="Abrir"),
)
Props¶
| Prop | Tipo | Padrão | O que faz |
|---|---|---|---|
title |
str |
"" |
O texto primário da linha. |
subtitle |
str \| None |
None |
Uma segunda linha opcional, mostrada apagada sob o título. |
leading |
Widget \| None |
None |
Widget opcional antes do texto (ex.: um Avatar). |
trailing |
Widget \| None |
None |
Widget opcional depois do texto (ex.: um Button). |
color_scheme |
str \| None |
None |
Família M3 opcional que tinge o título; None mantém o ON_SURFACE neutro. |
theme |
Theme |
Theme() |
O tema cujos tokens fornecem cores e espaçamento. |
ListTile é apresentacional — sem on_click de linha
Como o handling de toque só existe no Button no conjunto de primitivas, a
linha não tem on_click. Coloque um Button (ou IconButton) no slot
trailing para ações. O bloco de título cresce (grow=1.0) e empurra o
trailing para a borda; a superfície de acessibilidade (semantics) é
preservada na linha.
Avatar¶
Um badge redondo mostrando iniciais curtas, tingido pelas roles de container. O
círculo se preenche com a role tonal *_container do color_scheme e as iniciais
usam a role on_*_container legível (segura para WCAG-AA por construção).
Props¶
| Prop | Tipo | Padrão | O que faz |
|---|---|---|---|
initials |
str |
"" |
O texto curto dentro do círculo (ex.: "MB"). |
size |
float |
40.0 |
O diâmetro do círculo em pixels lógicos. |
color_scheme |
str |
"primary" |
A família de papéis M3 com que o círculo se tinge. |
theme |
Theme |
Theme() |
O tema que resolve as cores do círculo. |
O raio segue o tamanho
O radius é fixado em size / 2.0 — sempre um círculo perfeito, seja qual for
o size. As cores saem do par (*_container, on_*_container) do esquema; um
esquema desconhecido cai no container primário.
Divider¶
Uma régua horizontal fina, tingida com a cor OUTLINE_VARIANT do Material 3. O
thickness aceita um nome de passo de token (resolvido contra a escala de forma)
ou um float cru.
from tempest_core import Divider
linha = Divider() # régua de 1px, outline-variant
grossa = Divider(thickness=2.0, color_scheme="primary")
Props¶
| Prop | Tipo | Padrão | O que faz |
|---|---|---|---|
thickness |
float \| str |
1.0 |
A altura da linha — um nome de passo de token ("xs") ou um float. |
color_scheme |
str \| None |
None |
Família M3 opcional para a cor da régua; None usa o OUTLINE_VARIANT neutro. |
theme |
Theme |
Theme() |
O tema cujos tokens fornecem a cor e o passo. |
Layout de componentes¶
Componentes de estrutura de página. Todos abaixam para árvores de Column /
Row / Container primitivas.
Grid¶
Uma grade de colunas fixas dispondo os filhos em células de largura igual, preenchidas da esquerda para a direita e de cima para baixo.
from tempest_core import Card, Grid
from tempest_core import Text
grade = Grid(
columns=3,
gap="md", # passo de token ou float
children=[Card(children=[Text(content=f"Item {i}")]) for i in range(6)],
)
Props¶
| Prop | Tipo | Padrão | O que faz |
|---|---|---|---|
children |
list[Widget] |
[] |
As células, preenchidas esquerda→direita, depois cima→baixo. |
columns |
int |
2 |
O número de colunas por linha (limitado a no mínimo 1). |
gap |
float \| str |
8.0 |
O espaço entre células — um nome de passo de token ("md") ou um float. |
theme |
Theme |
Theme() |
O tema cuja escala de espaçamento resolve o nome do passo. |
Células crescem para dividir a largura; a última linha é preenchida
Cada filho é envolvido numa Container que cresce (grow=1.0), então as
colunas dividem a largura igualmente (o flex). Linhas finais curtas são
completadas com células vazias para manter o alinhamento das colunas.
HStack¶
Uma pilha horizontal: filhos da esquerda para a direita com um gap por passo de
token. Um wrapper ergonômico estilo SwiftUI sobre a Row primitiva, com align
(eixo cruzado) e justify (eixo principal) na superfície.
from tempest_core import HStack
from tempest_core import JustifyContent
from tempest_core import Text
barra = HStack(
gap="sm",
justify=JustifyContent.SPACE_BETWEEN,
children=[Text(content="Esquerda"), Text(content="Direita")],
)
Props¶
| Prop | Tipo | Padrão | O que faz |
|---|---|---|---|
children |
list[Widget] |
[] |
Os filhos ordenados, dispostos da esquerda para a direita. |
gap |
float \| str |
"md" |
O espaço entre os filhos — um nome de passo de token ou um float. |
align |
AlignItems \| None |
CENTER |
O alinhamento no eixo cruzado (vertical) dos filhos. |
justify |
JustifyContent \| None |
None |
A distribuição no eixo principal (horizontal) dos filhos. |
theme |
Theme |
Theme() |
O tema cuja escala de espaçamento resolve o gap. |
VStack¶
O irmão vertical do HStack, sobre a Column primitiva: filhos de cima para
baixo com um gap por passo de token. Aqui align é o eixo cruzado (horizontal)
e justify é o eixo principal (vertical).
from tempest_core import VStack
from tempest_core import Text
coluna = VStack(
gap="lg",
children=[Text(content="Um"), Text(content="Dois"), Text(content="Três")],
)
Props¶
| Prop | Tipo | Padrão | O que faz |
|---|---|---|---|
children |
list[Widget] |
[] |
Os filhos ordenados, dispostos de cima para baixo. |
gap |
float \| str |
"md" |
O espaço entre os filhos — um nome de passo de token ou um float. |
align |
AlignItems \| None |
None |
O alinhamento no eixo cruzado (horizontal) dos filhos. |
justify |
JustifyContent \| None |
None |
A distribuição no eixo principal (vertical) dos filhos. |
theme |
Theme |
Theme() |
O tema cuja escala de espaçamento resolve o gap. |
gap por passo de token, sempre coerente
Nos dois stacks (e no Grid), um gap string ("md") resolve contra a escala
de espaçamento do tema via Theme.space(...); um float cru passa direto.
Preferir os passos mantém o ritmo vertical/horizontal consistente com o resto
do design-system.
Scaffold¶
O frame de página: uma app bar no topo, um corpo que cresce e uma bottom bar
opcional. O BACKGROUND do tema preenche o frame.
from tempest_core import Scaffold
from tempest_core import AppBar
from tempest_core import Text
pagina = Scaffold(
app_bar=AppBar(title="Início"),
body=Text(content="Conteúdo da página"),
scroll=True,
)
Props¶
| Prop | Tipo | Padrão | O que faz |
|---|---|---|---|
app_bar |
Widget \| None |
None |
A barra do topo (comumente um AppBar); omitida quando None. |
body |
Widget \| None |
None |
O conteúdo principal; vira uma coluna vazia quando None. |
bottom_bar |
Widget \| None |
None |
A barra de baixo (ex.: NavBar ou Footer); omitida quando None. |
scroll |
bool |
False |
Quando True, envolve o corpo numa ScrollView (conveniência do Qt). |
theme |
Theme |
Theme() |
O tema cuja role BACKGROUND preenche o frame. |
O corpo cresce; as barras ficam nas pontas
O Scaffold abaixa para uma Column que empilha, em ordem, a app bar, o corpo
(envolvido num container que cresce, grow=1.0, ou numa ScrollView quando
scroll=True) e a bottom bar. O corpo flex empurra as barras para o topo e a
base do frame.
Sidebar¶
Uma coluna lateral de largura fixa com widgets de navegação/conteúdo. A superfície
do painel é resolvida de variant / color_scheme / elevation, espelhando um
card; a largura e o padding fixos ficam inalterados.
from tempest_core import Sidebar
from tempest_core import Button
lateral = Sidebar(
width=280.0,
children=[
Button(label="Início", variant="ghost"),
Button(label="Ajustes", variant="ghost"),
],
)
Props¶
| Prop | Tipo | Padrão | O que faz |
|---|---|---|---|
children |
list[Widget] |
[] |
Os widgets empilhados de cima para baixo na sidebar. |
width |
float |
240.0 |
A largura fixa da sidebar em pixels lógicos. |
variant |
CardVariant |
ELEVATED |
O tratamento de superfície (elevated / filled / outlined). |
color_scheme |
str |
"neutral" |
A família de papéis M3 com que a sidebar se tinge. |
elevation |
int \| None |
None |
Nível M3 explícito (0-5) sobrepondo o padrão. |
theme |
Theme |
Theme() |
O tema cujos tokens resolvem a superfície do painel. Não entra na IR. |
media |
MediaQueryData \| None |
None |
Snapshot de viewport (aceito por paridade; encaminhado). |
Helpers de composição¶
Para construir componentes customizados no mesmo idioma, o pacote re-exporta o helper de mesclagem de estilo e uma pequena paleta escura padrão.
merge_style¶
Sobrepõe os campos setados de um override sobre um Style base. Só os
campos explicitamente não-None do override vencem; todo o resto mantém o padrão
do componente. Como Style é congelado, retorna uma cópia nova mesclada.
from tempest_core import merge_style
from tempest_core import Style
base = Style(padding=None, radius=8.0, gap=4.0)
final = merge_style(base, Style(radius=16.0)) # radius vence; gap e padding do base
Esse é exatamente o mecanismo que todo componente usa para deixar você
sobrescrever só os campos com que se importa: cada render monta um Style
default e chama merge_style(default, self.style). Passar override=None
devolve o base intocado.
Override sempre por cima, sem perder o default
É o mesmo idioma dos botões (o override vence nos campos que seta) aplicado às
superfícies e itens. Você nunca perde o estilo default do componente ao setar
um campo pontual pelo style.
Tokens de paleta padrão¶
Seis constantes Color — uma paleta escura contida que combina com os exemplos.
Servem como valores prontos ao montar componentes fora de um Theme completo.
from tempest_core import (
BACKGROUND,
SURFACE,
ACCENT,
MUTED,
ON_SURFACE,
ON_MUTED,
)
from tempest_core import Style
from tempest_core import Container, Text
caixa = Container(
style=Style(background=SURFACE),
child=Text(content="Rótulo", style=Style(color=ON_SURFACE)),
)
| Token | Hex | Papel |
|---|---|---|
BACKGROUND |
#0b0f14 |
Fundo da página / frame. |
SURFACE |
#1f2937 |
Superfície elevada (cards, painéis). |
ACCENT |
#2563eb |
Cor de destaque / ação. |
MUTED |
#374151 |
Superfície apagada / secundária. |
ON_SURFACE |
#f9fafb |
Conteúdo legível sobre SURFACE. |
ON_MUTED |
#9ca3af |
Conteúdo apagado sobre MUTED. |
Tokens são valores prontos, não um substituto do Theme
Eles dão a um AppBar ou Scaffold uma aparência intencional na largada. Para
temas completos e resolução por role (as roles M3 *_container, elevação, etc.),
passe um Theme — veja o tutorial do design-system.
Recapitulando¶
Surfaceé a primitiva sem padding;CardéSurface+ padding +Column. As duas resolvem viaresolve_surface_variantdevariant/color_scheme/elevation.CardVariant:ELEVATED(elevated card, sombra nível 1) →FILLED(tonalsurface_variant, sem sombra) →OUTLINED(bordaoutline, sem sombra).- Elevação é uma
Shadowmapeada do nível M3 (0-5), nunca um campo deStylenovo; o renderizador a traduz para a elevação nativa. StyledContainerdá padding por passo de token àContainerprimitiva sem mutá-la.- Itens de conteúdo —
ListTile(apresentacional, ação vai notrailing),Avatar(círculo tonal, raio =size / 2),Divider(réguaOUTLINE_VARIANT) — leem cor e espaçamento do tema. - Layout —
Grid(células que crescem para dividir a largura),HStack/VStack(stacks comgappor passo de token),Scaffold(corpo que cresce entre as barras),Sidebar(painel de largura fixa com superfície resolvida). - Helpers —
merge_stylesobrepõe os campos setados do override; os tokensBACKGROUND/SURFACE/ACCENT/MUTED/ON_SURFACE/ON_MUTEDsão valores prontos de paleta.