O botão das ofertas rola até o contato com o tipo marcado e não quebra mais as âncoras; ofertas com o que você recebe e primeiro passo, logo depois da vitrine; bloco de IA fora da home; cartão largo da SEV no hero do celular; separador da faixa de clientes só entre itens; favicon de 13 para 1,8 KB; pré-carregamento só no hover e nunca de /#... fora da home; X do menu e cabeçalho opaco; WhatsApp com "o case"; /ia com 3 passos e modelo de relatório ilustrativo; Sobre alinhado ao currículo; CSP Report-Only com os domínios do Ads.
87 lines
2.9 KiB
TypeScript
87 lines
2.9 KiB
TypeScript
import Image from "next/image";
|
|
import type { Testimonial } from "@/lib/proof";
|
|
import { textLink } from "./button-styles";
|
|
import HoverPrefetchLink from "./HoverPrefetchLink";
|
|
|
|
function initials(name: string) {
|
|
return name
|
|
.split(/\s+/)
|
|
.filter(Boolean)
|
|
.slice(0, 2)
|
|
.map((word) => word[0])
|
|
.join("")
|
|
.toUpperCase();
|
|
}
|
|
|
|
/**
|
|
* Depoimentos reais e autorizados (lib/proof.ts). Sem nenhum, a seção não existe:
|
|
* nada de depoimento de exemplo ou escrito em nome de alguém.
|
|
*/
|
|
export default function Testimonials({
|
|
items = [],
|
|
}: {
|
|
items?: Testimonial[];
|
|
}) {
|
|
if (items.length === 0) return null;
|
|
|
|
return (
|
|
<section
|
|
id="testimonials"
|
|
aria-labelledby="testimonials-title"
|
|
className="ds-section"
|
|
>
|
|
<div className="ds-section-shell">
|
|
<p className="ds-eyebrow">Depoimentos</p>
|
|
<h2 id="testimonials-title" className="ds-section-title max-w-[22ch]">
|
|
O que dizem os clientes.
|
|
</h2>
|
|
<ul className="mt-sp-8 grid gap-sp-6 md:grid-cols-2 xl:grid-cols-3">
|
|
{items.map((item) => (
|
|
<li key={`${item.company}-${item.name}`} className="flex">
|
|
<figure className="ds-card flex w-full flex-col justify-between gap-sp-6">
|
|
<blockquote className="font-display text-lg leading-8 text-[var(--ink)]">
|
|
<p>{`“${item.quote}”`}</p>
|
|
</blockquote>
|
|
<figcaption className="flex items-center gap-sp-4">
|
|
{item.photo ? (
|
|
<Image
|
|
src={item.photo}
|
|
alt=""
|
|
width={48}
|
|
height={48}
|
|
className="h-12 w-12 shrink-0 rounded-full object-cover"
|
|
/>
|
|
) : (
|
|
<span
|
|
aria-hidden="true"
|
|
className="flex h-12 w-12 shrink-0 items-center justify-center rounded-full bg-[var(--ink)] font-display text-sm font-semibold text-[var(--paper)]"
|
|
>
|
|
{initials(item.name)}
|
|
</span>
|
|
)}
|
|
<div className="min-w-0 font-display text-[15px] leading-6">
|
|
<p className="font-semibold text-[var(--ink)]">
|
|
{item.name}
|
|
</p>
|
|
<p className="text-[var(--meta)]">
|
|
{item.role}, {item.company}
|
|
</p>
|
|
{item.projectId && (
|
|
<HoverPrefetchLink
|
|
href={`/cases/${item.projectId}`}
|
|
className={`${textLink} !min-h-0 text-[var(--ink-80)]`}
|
|
>
|
|
Ver case
|
|
</HoverPrefetchLink>
|
|
)}
|
|
</div>
|
|
</figcaption>
|
|
</figure>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|