Skip to content

Commit 2b2ec3e

Browse files
Thales-Chagasclaude
andcommitted
Contas: layout mobile responsivo (corrige pagina 'deszoomada' no celular)
Causa raiz: o grid dos blocos usava so lg:grid-cols-2 — sem grid-cols-1 a trilha implicita dimensiona pelo min-content das linhas (descricoes longas) e alarga a pagina alem da viewport; o navegador do celular afasta o zoom e tudo parece quebrado/estreito. grid-cols-1 (minmax 0) resolve. No celular a linha da conta vira dois andares: nome + valor em cima, vencimento/badge a esquerda e acoes a direita embaixo (botao Paguei/ Recebi agora com rotulo, alvo maior pro dedo). Filtros rolam de lado numa linha so, sem scrollbar. Desktop permanece identico. Verificado em 320/375/1280px: sem overflow horizontal e descricoes longas truncando. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 3bad1c6 commit 2b2ec3e

1 file changed

Lines changed: 48 additions & 33 deletions

File tree

src/App.jsx

Lines changed: 48 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2063,52 +2063,65 @@ function PaginaContas({ espaco, empresarial, acoes }) {
20632063
const grad = cat ? gradCat(cat) : gradPorId("grafite");
20642064
const venc = rotuloVencimento(t);
20652065
const nome = t.descricao || catNome(t.categoriaId);
2066+
// Ações e valor aparecem DUAS vezes (celular embaixo, desktop na direita) —
2067+
// uma some com hidden conforme o tamanho da tela.
2068+
const acoesLinha = (
2069+
<>
2070+
<button
2071+
onClick={() => acoes.marcarOk(t.id)}
2072+
title={t.tipo === "receita" ? "Marcar como recebido" : "Marcar como pago"}
2073+
className="flex items-center gap-1 rounded-lg border border-emerald-200 px-2 py-1.5 text-xs font-semibold text-emerald-700 transition hover:bg-emerald-50 dark:border-emerald-800 dark:text-emerald-300 dark:hover:bg-emerald-950"
2074+
>
2075+
<Check size={13} />
2076+
<span className="sm:inline">{t.tipo === "receita" ? "Recebi" : "Paguei"}</span>
2077+
</button>
2078+
<button
2079+
onClick={() => setForm(t)}
2080+
className="rounded-lg p-1.5 text-slate-400 transition hover:bg-slate-100 hover:text-slate-600 dark:hover:bg-slate-800"
2081+
aria-label="Editar"
2082+
>
2083+
<Pencil size={15} />
2084+
</button>
2085+
<button
2086+
onClick={() => setExcluindo(t)}
2087+
className="rounded-lg p-1.5 text-slate-400 transition hover:bg-red-50 hover:text-red-500 dark:hover:bg-red-950"
2088+
aria-label="Excluir"
2089+
>
2090+
<Trash2 size={15} />
2091+
</button>
2092+
</>
2093+
);
20662094
return (
2067-
<div className="group flex items-center gap-2.5 py-2.5 sm:gap-3">
2095+
<div className="group flex items-start gap-2.5 py-2.5 sm:items-center sm:gap-3">
20682096
<div
2069-
className="flex h-9 w-9 shrink-0 items-center justify-center rounded-xl text-sm font-bold text-white shadow-sm"
2097+
className="mt-0.5 flex h-9 w-9 shrink-0 items-center justify-center rounded-xl text-sm font-bold text-white shadow-sm sm:mt-0"
20702098
style={{ background: cssGrad(grad) }}
20712099
>
20722100
{(nome[0] || "?").toUpperCase()}
20732101
</div>
20742102
<div className="min-w-0 flex-1">
2075-
<p className="truncate text-sm font-medium text-slate-700 dark:text-slate-200">{nome}</p>
2103+
{/* celular: nome + valor lado a lado; desktop: só o nome (valor na direita) */}
2104+
<div className="flex items-baseline justify-between gap-2">
2105+
<p className="min-w-0 truncate text-sm font-medium text-slate-700 dark:text-slate-200">{nome}</p>
2106+
<span className="shrink-0 text-sm font-semibold tabular-nums text-slate-700 dark:text-slate-200 sm:hidden">
2107+
{fmtBRL(t.valor)}
2108+
</span>
2109+
</div>
20762110
<p className={"flex flex-wrap items-center gap-x-1.5 gap-y-0.5 text-xs " + venc.cor}>
20772111
{venc.texto}
20782112
{t.recorrencia && (
2079-
<span className="flex items-center gap-1 rounded-full bg-emerald-50 px-1.5 py-0.5 text-[10px] font-semibold text-emerald-600 dark:bg-emerald-950 dark:text-emerald-400">
2113+
<span className="flex items-center gap-1 whitespace-nowrap rounded-full bg-emerald-50 px-1.5 py-0.5 text-[10px] font-semibold text-emerald-600 dark:bg-emerald-950 dark:text-emerald-400">
20802114
<Repeat size={10} /> {rotuloRecorrencia(t.recorrencia)}
20812115
</span>
20822116
)}
20832117
</p>
2118+
{/* celular: ações na linha de baixo, com respiro pro dedo */}
2119+
<div className="mt-1.5 flex items-center gap-1 sm:hidden">{acoesLinha}</div>
20842120
</div>
2085-
<span className="text-right text-sm font-semibold tabular-nums text-slate-700 dark:text-slate-200">
2121+
<span className="hidden text-right text-sm font-semibold tabular-nums text-slate-700 dark:text-slate-200 sm:block">
20862122
{fmtBRL(t.valor)}
20872123
</span>
2088-
<div className="flex shrink-0 items-center gap-0.5">
2089-
<button
2090-
onClick={() => acoes.marcarOk(t.id)}
2091-
title={t.tipo === "receita" ? "Marcar como recebido" : "Marcar como pago"}
2092-
className="flex items-center gap-1 rounded-lg border border-emerald-200 px-2 py-1.5 text-xs font-semibold text-emerald-700 transition hover:bg-emerald-50 dark:border-emerald-800 dark:text-emerald-300 dark:hover:bg-emerald-950"
2093-
>
2094-
<Check size={13} />
2095-
<span className="hidden sm:inline">{t.tipo === "receita" ? "Recebi" : "Paguei"}</span>
2096-
</button>
2097-
<button
2098-
onClick={() => setForm(t)}
2099-
className="rounded-lg p-1.5 text-slate-400 transition hover:bg-slate-100 hover:text-slate-600 dark:hover:bg-slate-800"
2100-
aria-label="Editar"
2101-
>
2102-
<Pencil size={15} />
2103-
</button>
2104-
<button
2105-
onClick={() => setExcluindo(t)}
2106-
className="rounded-lg p-1.5 text-slate-400 transition hover:bg-red-50 hover:text-red-500 dark:hover:bg-red-950"
2107-
aria-label="Excluir"
2108-
>
2109-
<Trash2 size={15} />
2110-
</button>
2111-
</div>
2124+
<div className="hidden shrink-0 items-center gap-0.5 sm:flex">{acoesLinha}</div>
21122125
</div>
21132126
);
21142127
}
@@ -2229,15 +2242,15 @@ function PaginaContas({ espaco, empresarial, acoes }) {
22292242
</div>
22302243
</div>
22312244

2232-
{/* Filtros + criação */}
2245+
{/* Filtros + criação — no celular os filtros rolam de lado numa linha só */}
22332246
<div className="flex flex-wrap items-center justify-between gap-2">
2234-
<div className="flex flex-wrap gap-1 rounded-xl bg-slate-100 p-1 dark:bg-slate-800">
2247+
<div className="flex max-w-full flex-nowrap gap-1 overflow-x-auto rounded-xl bg-slate-100 p-1 [scrollbar-width:none] [&::-webkit-scrollbar]:hidden dark:bg-slate-800 sm:flex-wrap sm:overflow-visible">
22352248
{FILTROS.map(([v, r]) => (
22362249
<button
22372250
key={v}
22382251
onClick={() => setFiltro(v)}
22392252
className={
2240-
"rounded-lg px-2.5 py-1.5 text-xs font-semibold transition " +
2253+
"shrink-0 whitespace-nowrap rounded-lg px-2.5 py-1.5 text-xs font-semibold transition " +
22412254
(filtro === v
22422255
? "bg-white text-emerald-700 shadow-sm dark:bg-slate-700 dark:text-emerald-300"
22432256
: "text-slate-500 dark:text-slate-400")
@@ -2257,7 +2270,9 @@ function PaginaContas({ espaco, empresarial, acoes }) {
22572270
</div>
22582271
</div>
22592272

2260-
<div className="grid items-start gap-4 lg:grid-cols-2">
2273+
{/* grid-cols-1 (minmax 0) impede o min-content das linhas de alargar a
2274+
trilha no celular — sem ela o grid estoura a viewport e "deszooma" */}
2275+
<div className="grid grid-cols-1 items-start gap-4 lg:grid-cols-2">
22612276
<Bloco tipo="despesa" titulo="Contas a pagar" />
22622277
<Bloco tipo="receita" titulo="Contas a receber" />
22632278
</div>

0 commit comments

Comments
 (0)