Padrões de tela
Foco em camadas
A assinatura do produto. Editar não acende um campo: afunda o resto. Quando um campo recebe foco, a tela recua em degraus e o bloco em edição sobe — ninguém precisa procurar onde estava.
globals.css6 atributosEditSurface + Field herdam
A demonstração é esta página
Toque no campo “Insumo” abaixo. A moldura do card e as linhas vizinhas recuam; o bloco levanta. Os atributos são os mesmos do app — nada aqui é figura.
Insumos
O cabeçalho é data-dim-keep: fura o véu e continua legível.
O bloco em edição é data-dim. Campo sem foco é data-field, a 0.70.
Buscar insumo…
Agulha 30Gem 5 fichasR$ 0,24/un
| Camada | O que acontece | Como |
|---|---|---|
| Fundo da tela (menu do app, rail) | recua | opacidade 0.65 |
| Superfície (card, seção da ficha) | recua junto | película de 40% por cima |
| Título da tela, cabeçalho do card | fica aceso | fura o véu (z-index 7) |
| O bloco em edição | sobe | ink-50 + --shadow-lift (z-index 8) |
| Campos do bloco sem foco | recuam | opacidade 0.70 |
O vocabulário
Seis atributos, aplicados no JSX. A regra mora em globals.css — nenhuma tela reimplementa o efeito.
| Atributo | Onde vai | O que faz no foco |
|---|---|---|
| data-dim | o bloco em edição (o tapete, a linha que virou form) | sobe acima das películas e ganha ink-50 + sombra |
| data-dim-solto | junto de data-dim, quando o form está SEMPRE aberto | a elevação vira pseudo-elemento: aparece sem empurrar layout |
| data-field | cada campo do formulário (já vem no Field) | o campo SEM foco recua pra 0.70; o em uso fica cheio |
| data-dim-veil | superfície que recua junto (seção, tabela) | película de 40% por cima; card já entra por data-slot |
| data-dim-keep | cabeçalho da superfície | fura a película e continua legível |
| data-dim-far | fundo da tela (sidebar do app, rail) | opacidade 0.65 — sem película |
o mínimo pra uma tela nova herdar tudo
<Card> {/* recebe a película por data-slot */}
<CardHeader data-dim-keep>…</CardHeader> {/* fura o véu */}
<CardContent>
<EditSurface> {/* já traz data-dim */}
<Field name="nome" label="Insumo" /> {/* já traz data-field */}
</EditSurface>
</CardContent>
</Card>Película, nunca opacidade no container
A escolha técnica que faz o padrão existir. Opacidade cria contexto de composição: o valor desce pra TUDO que está dentro e nenhum filho volta a 1.
Sim
/* película desenhada POR CIMA — irmã do conteúdo */
[data-dim-veil]::after { background: var(--veu); opacity: .4 }
[data-dim-keep] { z-index: 7 } /* fura */
[data-dim] { z-index: 8 } /* sobe */Quem precisa ficar aceso só sobe de camada. Nada herda nada.
Não
/* opacidade no container — desce pra tudo */
[data-dim-veil] { opacity: .6 }
[data-dim] { opacity: 1 } /* não volta: já é .6 do pai */Três tentativas morreram aqui: apagou o campo em edição, o rótulo dele e os botões Salvar/Cancelar.
Armadilhas já pagas
Cada uma custou uma rodada de ida e volta — ou fechou a porta pra um lugar onde o efeito atrapalharia. Estão presas na regra global e não reaparecem sozinhas.
aO gatilho é :focus
:focus-visible não serve: o formulário entrega o foco por código ao abrir a linha (autoFocus) e o dedo no celular nunca marca focus-visible. Nos dois casos o efeito não acontecia — justamente quando ele importa.bA película tem a cor da superfície
Branca sobre superfície branca, some. Branca sobre o cinza da faixa, vira um retângulo claro visível (apareceu como um “quadrado” em volta do rail). Onde o fundo não é
surface, recue por opacidade — é o caso do data-dim-far.cUm anel só em cena
O anel é do CAMPO. O bloco marca o lugar pela elevação, e o card devolve a borda neutra enquanto se edita. Anel dentro de anel dentro de anel é moldura, não hierarquia.
dForm sempre aberto não ganha tapete
Tapete permanente muda o desenho da tela em REPOUSO, não só no foco. Nesses blocos vai
data-dim-solto: a elevação entra por ::before com inset: -0.75rem e z-index: -1, então aparece e some sem mover um pixel.eLer não é editar
O tapete de LEITURA (o texto do documento aberto na lista) usa a mesma cor e NÃO leva
data-dim: marcá-lo faria a tela recuar sem ninguém preenchendo nada.fDiálogo já tem o seu véu
Gaveta e modal entram com scrim próprio. Empilhar o padrão ali dá dois escurecimentos brigando — e a busca de uma lista precisa mostrar a lista, não apagá-la.
Armadilha já pagaOrdem vence especificidade no minificador
A regra que desarma o tapete no
data-dim-solto precisa vir DEPOIS da regra de elevação: o minificador achata [data-dim][data-dim-solto] pra um atributo só, então quem decide é a ordem no arquivo, não a especificidade.NotaRegra solta em globals.css vence utility do Tailwind
Utilities vivem em
@layer utilities; regra fora de camada pesa mais. É o que permite o card devolver a borda sem !important — e o que exige cuidado: [data-slot="card"] { position: relative } sobrescreveria um sticky de classe, se algum card usasse.Onde vale
É contrato do sistema, não enfeite de uma tela: edição inline nova herda o padrão só de usar EditSurface e Field.
| Tela | O que recua | O que sobe |
|---|---|---|
| /ajustes/insumos | menu, rail, moldura do card, linhas vizinhas | a linha que virou formulário |
| /ajustes/custos | menu, rail, moldura dos cards | o tapete da despesa ou do equipamento; nos blocos de capacidade e impostos, o miolo dos campos |
| /ajustes/servicos | menu, rail, tabela e lista inteiras | a linha do preço, ou o serviço aberto pra editar |
| /ajustes/conhecimento | menu, rail, orçamento do agente, documentos vizinhos | o documento em escrita |
| /ajustes/horarios | menu, rail, os outros dias da grade | o dia em edição — e o miolo das regras de agendamento |
| /ajustes/clinica | menu, rail, seção da ficha | o dado que se está editando |
Onde NÃO vale
Não é falta de alcance: em cada um destes o efeito atrapalharia o que a pessoa foi fazer.
| Lugar | Por quê |
|---|---|
| Diálogos e gaveta | já entram com scrim próprio — dois escurecimentos brigam |
| Busca e barras de filtro | focar a busca serve pra VER a lista; apagá-la é o contrário do pedido |
| Entrevista de custos | uma pergunta por tela: já é foco total, não sobrou fundo pra recuar |
| Chat de teste do assistente | o campo vive em foco; apagar o histórico a cada clique seria hostil |
| Entrar, cadastro, 2FA, onboarding | a página inteira é o formulário — não há segundo plano |
| Perfil, senha, segurança, privacidade | um card só na tela: o véu não teria em quem pousar |
| Superfície que não é surface | a película branca vira retângulo claro — foi o caso dos painéis do Assistente, fora até ganharem card |
Antes de aplicar num lugar novo, a pergunta é uma só: existe um segundo plano que ATRAPALHA quem está preenchendo? Se não existe, o efeito não tem o que fazer.