You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
109 lines
3.6 KiB
109 lines
3.6 KiB
<script lang="ts">
|
|
/**
|
|
* The testimonials mini-page: a grid of quotes with avatar fallbacks, plus a
|
|
* page floor.
|
|
*/
|
|
import { Testimonials } from '$blocks/testimonials';
|
|
import { Avatar } from '$uix/eidos/components/avatar';
|
|
import { Section } from '$uix/eidos/components/section';
|
|
import { Container } from '$uix/eidos/components/container';
|
|
import { Stack } from '$uix/eidos/components/stack';
|
|
import { Wrap } from '$uix/eidos/components/wrap';
|
|
import { Heading } from '$uix/eidos/components/heading';
|
|
import { Text } from '$uix/eidos/components/text';
|
|
|
|
let { layout = 'grid' as 'grid' | 'spotlight' }: { layout?: 'grid' | 'spotlight' } = $props();
|
|
|
|
type Quote = { quote: string; name: string; role: string; initials: string; color: string };
|
|
|
|
const quotes: Quote[] = [
|
|
{
|
|
quote: 'Migramos en una tarde y los números por fin cuadran con nuestra base de datos.',
|
|
name: 'Ana Ruiz',
|
|
role: 'CTO en Northwind',
|
|
initials: 'AR',
|
|
color: 'indigo'
|
|
},
|
|
{
|
|
quote: 'Las cohortes que antes tardaban un día ahora salen al instante, sin reprocesar.',
|
|
name: 'Marco Vidal',
|
|
role: 'Head of Growth en Umbra',
|
|
initials: 'MV',
|
|
color: 'teal'
|
|
},
|
|
{
|
|
quote: 'Configuramos una alerta y cazamos una fuga de conversión el mismo día.',
|
|
name: 'Lucía Peña',
|
|
role: 'Product Manager en Kessel',
|
|
initials: 'LP',
|
|
color: 'orange'
|
|
},
|
|
{
|
|
quote: 'Sin coste por asiento: por fin invité a todo el equipo al panel.',
|
|
name: 'Diego Sáez',
|
|
role: 'Fundador en Volta',
|
|
initials: 'DS',
|
|
color: 'green'
|
|
},
|
|
{
|
|
quote: 'El SSO y la auditoría pasaron la revisión de seguridad sin una sola fricción.',
|
|
name: 'Sofía Marín',
|
|
role: 'Engineering Lead en Marisol',
|
|
initials: 'SM',
|
|
color: 'plum'
|
|
}
|
|
];
|
|
|
|
// El spotlight lleva UNA cita — la que el equipo quiera destacar.
|
|
const shown = $derived(layout === 'spotlight' ? [quotes[1]] : quotes);
|
|
</script>
|
|
|
|
<Testimonials {layout}>
|
|
<Testimonials.Header>
|
|
<Heading level={2} align="center">Equipos de producto que ya no vuelan a ciegas</Heading>
|
|
<Text size="lg" color="muted" align="center">
|
|
Lo que cambia cuando los eventos entran crudos y salen en cohortes.
|
|
</Text>
|
|
</Testimonials.Header>
|
|
|
|
<Testimonials.Items>
|
|
<!-- El spotlight es UNA cita: la app decide cuál, el block sólo la coloca. -->
|
|
{#each shown as q (q.name)}
|
|
<Testimonials.Item>
|
|
{#snippet logo()}
|
|
<!-- La marca de quien firma la cita: lo que hace que se lea como
|
|
evidencia y no como una opinión. Aquí es una palabra compuesta con
|
|
el canon; una app real pondría su `Image`. -->
|
|
<Text size="lg" weight="semibold" color="muted">{q.role.split(' en ')[1] ?? ''}</Text>
|
|
{/snippet}
|
|
<Testimonials.Quote>«{q.quote}»</Testimonials.Quote>
|
|
<Testimonials.Author>
|
|
{#snippet avatar()}
|
|
<Avatar variant="solid" color={q.color}>
|
|
<Avatar.Fallback>{q.initials}</Avatar.Fallback>
|
|
</Avatar>
|
|
{/snippet}
|
|
<Testimonials.AuthorName>{q.name}</Testimonials.AuthorName>
|
|
<Testimonials.AuthorRole>{q.role}</Testimonials.AuthorRole>
|
|
</Testimonials.Author>
|
|
</Testimonials.Item>
|
|
{/each}
|
|
</Testimonials.Items>
|
|
</Testimonials>
|
|
|
|
<!-- A floor so the page reads as a page. -->
|
|
<Section size="lg">
|
|
<Container size="lg">
|
|
<Stack gap={4} align="center">
|
|
<Text size="sm" weight="medium" color="muted" align="center">
|
|
Con la confianza de equipos de producto en
|
|
</Text>
|
|
<Wrap gap={8} justify="center">
|
|
{#each ['Northwind', 'Umbra', 'Kessel', 'Volta', 'Marisol'] as brand (brand)}
|
|
<Text size="lg" weight="semibold" color="muted">{brand}</Text>
|
|
{/each}
|
|
</Wrap>
|
|
</Stack>
|
|
</Container>
|
|
</Section>
|