feat(cases): prova certa por serviço, páginas internas com trabalho no topo
Diagnóstico sem case que não cabe; desktop com o GCC Installer como projeto próprio; IoT com o Twins Lab e a nota da Apolo. Mosaico de pôsteres em /servicos e /cases, faixa baixa em uma coluna no currículo, privacidade e laboratório; Laboratório como lista compacta; SEV começando por catálogo, pedido no WhatsApp e painel; Joinville e SC nos títulos; imagens do LCP com fetchPriority e sizes reais; pré-carregamento só no hover; 404 com Open Graph próprio.
This commit is contained in:
1 parent
7b633f0f4a
commit
de6af74a0c
37 files changed
+1062
-254
No files matched your search
@@ -5,12 +5,40 @@ import {
|
||||
} from "@/app/components/showcase/BrowserFrame";
|
||||
import { getCaseMedia } from "./case-media";
|
||||
|
||||
/** Capa do case: o pôster do site dentro de uma moldura de navegador. Sem captura gravada, não mostra nada. */
|
||||
/**
|
||||
* Largura real da capa em cada lugar da página, para o navegador baixar a imagem do tamanho certo
|
||||
* (com 100vw, um celular de 390 px pedia a versão de 750 px para uma capa de 300 px). As contas seguem o
|
||||
* padding das seções (20 px até 768 px; depois 6vw, no máximo 64 px), a coluna central de 1240 px e os cartões
|
||||
* (borda e 20 a 28 px de padding).
|
||||
*/
|
||||
export const coverSizes = {
|
||||
/** Topo do case e do serviço: coluna da direita a partir de 1024 px, e a largura da página abaixo disso. */
|
||||
hero: "(min-width: 1440px) 560px, (min-width: 1024px) 40vw, (min-width: 769px) 88vw, calc(100vw - 40px)",
|
||||
/** Capa dentro de um cartão (`ds-card`) da grade de duas colunas, que vira uma só até 1024 px. */
|
||||
card: "(min-width: 1440px) 560px, (min-width: 1025px) calc(50vw - 134px), (min-width: 769px) calc(88vw - 56px), calc(100vw - 88px)",
|
||||
/** Capa solta numa grade de duas colunas, sem cartão em volta (a partir de 768 px). */
|
||||
column:
|
||||
"(min-width: 1440px) 604px, (min-width: 1068px) calc(50vw - 80px), (min-width: 768px) calc(44vw - 16px), calc(100vw - 40px)",
|
||||
} as const;
|
||||
|
||||
/**
|
||||
* Props da imagem que abre a página (a maior acima da dobra): carrega na hora e com prioridade de rede alta.
|
||||
* No Next 16 a prop `priority` do `Image` só gera o `<link rel="preload">`; a prioridade de rede vem do `fetchPriority`.
|
||||
*/
|
||||
export const priorityImageProps = {
|
||||
loading: "eager",
|
||||
fetchPriority: "high",
|
||||
} as const;
|
||||
|
||||
/**
|
||||
* Capa do case: o pôster do site dentro de uma moldura de navegador. Sem captura gravada, não mostra nada.
|
||||
* `priority` é para a imagem que abre a página: aplica `priorityImageProps`.
|
||||
*/
|
||||
export function CaseCover({
|
||||
id,
|
||||
title,
|
||||
demoUrl,
|
||||
sizes = "(min-width: 1024px) 560px, 100vw",
|
||||
sizes = coverSizes.card,
|
||||
priority = false,
|
||||
}: {
|
||||
id: string;
|
||||
@@ -21,6 +49,7 @@ export function CaseCover({
|
||||
}) {
|
||||
const media = getCaseMedia(id, "desktop");
|
||||
if (!media) return null;
|
||||
const priorityProps = priority ? priorityImageProps : {};
|
||||
|
||||
return (
|
||||
<BrowserFrame url={displayUrl({ demoUrl, title })}>
|
||||
@@ -30,7 +59,7 @@ export function CaseCover({
|
||||
alt={`Captura de tela do site ${title}`}
|
||||
fill
|
||||
sizes={sizes}
|
||||
priority={priority}
|
||||
{...priorityProps}
|
||||
className="object-cover object-top"
|
||||
/>
|
||||
</div>
|
||||
|
||||
Reference in new issue
Block a user