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 em edição fica aceso por cima. 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 | fica aceso | sobe de camada (z-index 8), sem tapete novo nem sombra |
| 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, só por camada: sem tapete novo e sem sombra; no EditSurface o anel acende no tapete (data-tapete) e o card em volta fica calmo |
| data-dim-campo | o campo que é o próprio bloco (a ficha da clínica, editada na linha) | só a linha com o cursor sobe; sem tapete nem sombra, com o anel na célula, e o card em volta fica calmo |
| 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.cO que marca o lugar é o anel
O anel é do CAMPO e da casca daquela linha (o tapete, a célula da ficha); o card grande em volta não acende, porque com o anel nele o lugar da edição se perdia no retângulo de tudo. Até 18/09 o bloco subia com tapete
ink-50 e --shadow-lift, e o card devolvia a borda neutra em troca. A sombra desenhava um card dentro do card, descolado do cabeçalho logo acima: recusada pelo founder três vezes (ficha da clínica em 15/09, bandeja do form sempre aberto em 17/09, edição de Modelos de contrato em 18/09). Hoje o bloco sobe SÓ de camada.dEditar não muda o desenho em repouso
Nada aparece no foco que já não estivesse na tela: nem tapete novo, nem bandeja, nem sombra. Onde existe tapete (o
bg-ink-50 do EditSurface) ele é estático e vale também em repouso. Form que está SEMPRE aberto (Capacidade, Impostos, Regras de agendamento, o bloco da negociação na Ficha da Pessoa) por isso não ganha tapete nenhum.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.
NotaRegra solta em globals.css vence utility do Tailwind
Utilities vivem em
@layer utilities; regra fora de camada pesa mais. É o que permite a película pousar no card 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 campo editado NA LINHA, que acende no lugar com anel na célula, e o card fica calmo; o dado que pede formulário abre em modal e fica fora do padrão |
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 atendente | o campo vive em foco; apagar o histórico a cada clique seria hostil |
| Conversa com o Assistente da equipe | a mesma razão: o compositor é o único campo e vive em foco; o fio é o que se lê, não um segundo plano |
| 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 Atendente, 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.