Passagens com fade e 32 px, cena anterior termina em opacidade 0, sem visibility nem clip-path. 3D do hero como fundo ambiente, sob demanda e desligado em toque, aparelho fraco, saveData e movimento reduzido. Lenis fora do toque e salto direto em âncoras distantes. Vitrine só de clientes, até 3 capítulos, fixa só no desktop e carrossel no celular; vídeo só do projeto em cena com preload metadata. Rótulos mono a partir de 12 px e limão só no contato.
72 lines
2.0 KiB
TypeScript
72 lines
2.0 KiB
TypeScript
import type { CSSProperties, ReactNode } from "react";
|
|
|
|
/**
|
|
* Endereço mostrado na barra: o domínio real do site publicado (`demoUrl`). Sem demonstração, só o nome do
|
|
* projeto: o endereço do código nunca aparece (nada de github.com na interface).
|
|
*/
|
|
export function displayUrl(project: {
|
|
title?: string | null;
|
|
demoUrl?: string | null;
|
|
}): { text: string; secure: boolean } | null {
|
|
if (project.demoUrl) {
|
|
try {
|
|
const url = new URL(project.demoUrl);
|
|
if (!/(^|\.)github\.com$/i.test(url.hostname)) {
|
|
const path =
|
|
url.pathname === "/" ? "" : url.pathname.replace(/\/$/, "");
|
|
return {
|
|
text: `${url.host.replace(/^www\./, "")}${path}`,
|
|
secure: url.protocol === "https:",
|
|
};
|
|
}
|
|
} catch {}
|
|
}
|
|
return project.title ? { text: project.title, secure: false } : null;
|
|
}
|
|
|
|
/**
|
|
* Janela de navegador em volta da captura: três pontos, barra com o endereço real e a tela.
|
|
* A barra é decoração (aria-hidden); o endereço também aparece como texto no próprio card.
|
|
*/
|
|
export function BrowserFrame({
|
|
url,
|
|
children,
|
|
className = "",
|
|
style,
|
|
}: {
|
|
url: { text: string; secure: boolean } | null;
|
|
children: ReactNode;
|
|
className?: string;
|
|
style?: CSSProperties;
|
|
}) {
|
|
return (
|
|
<div className={`ds-bframe ${className}`.trim()} style={style}>
|
|
<div className="ds-bframe-bar" aria-hidden="true">
|
|
<span className="ds-bframe-dots">
|
|
<i />
|
|
<i />
|
|
<i />
|
|
</span>
|
|
<span className="ds-bframe-url">
|
|
{url?.secure && (
|
|
<svg
|
|
viewBox="0 0 12 12"
|
|
width="10"
|
|
height="10"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
strokeWidth="1.4"
|
|
aria-hidden="true"
|
|
>
|
|
<rect x="2.5" y="5.5" width="7" height="5" />
|
|
<path d="M4 5.5V4a2 2 0 0 1 4 0v1.5" />
|
|
</svg>
|
|
)}
|
|
<span>{url?.text ?? "pré-visualização"}</span>
|
|
</span>
|
|
</div>
|
|
{children}
|
|
</div>
|
|
);
|
|
}
|