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.
150 lines
5.3 KiB
150 lines
5.3 KiB
<script lang="ts">
|
|
/**
|
|
* The feature-split mini-page: alternating rows with real product copy and
|
|
* `Mockup`-framed media (browser + phone chrome), plus a page floor.
|
|
*/
|
|
import { FeatureSplit } from '$blocks/feature-split';
|
|
import { Mockup } from '$uix/eidos/components/mockup';
|
|
import { Section } from '$uix/eidos/components/section';
|
|
import { Container } from '$uix/eidos/components/container';
|
|
import { Stack } from '$uix/eidos/components/stack';
|
|
import { Group } from '$uix/eidos/components/group';
|
|
import { Grid } from '$uix/eidos/components/grid';
|
|
import { Box } from '$uix/eidos/components/box';
|
|
import { Surface } from '$uix/eidos/components/surface';
|
|
import { Heading } from '$uix/eidos/components/heading';
|
|
import { Text } from '$uix/eidos/components/text';
|
|
import { Badge } from '$uix/eidos/components/badge';
|
|
import { Button } from '$uix/eidos/components/button';
|
|
import { Link } from '$uix/eidos/components/link';
|
|
import * as Icon from '$uix/eidos/components/icon';
|
|
|
|
let {
|
|
count = 3,
|
|
startReversed = false
|
|
}: {
|
|
count?: number;
|
|
startReversed?: boolean;
|
|
} = $props();
|
|
|
|
const chart = ['3rem', '5rem', '3.6rem', '6.4rem', '4.4rem', '7.4rem', '5.6rem'];
|
|
|
|
const rows = [
|
|
{
|
|
eyebrow: 'Analítica',
|
|
title: 'Cohortes al día, sin configurar pipelines',
|
|
text: 'Los eventos llegan crudos y salen en cohortes: qué hicieron, cuándo dejaron de hacerlo y qué cambió la semana en que lanzaste.',
|
|
features: [
|
|
'Sin muestreo — los números cuadran',
|
|
'Ventanas sin reprocesar',
|
|
'Embudos y retención al vuelo'
|
|
],
|
|
cta: 'Ver la analítica',
|
|
media: 'browser' as const
|
|
},
|
|
{
|
|
eyebrow: 'En el bolsillo',
|
|
title: 'Las alertas que importan, donde las lees',
|
|
text: 'Un umbral sobre cualquier métrica y el canal —o el móvil— donde de verdad lo ves. Sin abrir el panel.',
|
|
features: ['Push al móvil', 'Reglas por segmento', 'Silencio en horario'],
|
|
cta: 'Configurar alertas',
|
|
media: 'phone' as const
|
|
},
|
|
{
|
|
eyebrow: 'Automatizaciones',
|
|
title: 'Reglas que reaccionan solas al flujo',
|
|
text: 'Una condición sobre los eventos y una acción: avisar a un canal, mover a un segmento, abrir un ticket. Se escribe una vez.',
|
|
features: ['Sin código', 'Traza de cada ejecución', 'Reintentos y límites'],
|
|
cta: 'Crear una regla',
|
|
media: 'browser' as const
|
|
}
|
|
];
|
|
|
|
const shown = $derived(rows.slice(0, count));
|
|
</script>
|
|
|
|
<FeatureSplit>
|
|
<!--
|
|
The section names itself (A-110): the `h2` is the header's and each row
|
|
hangs at `h3`. Before the part existed, three rows meant three sibling
|
|
`h2`s and a section with no name at all.
|
|
-->
|
|
<FeatureSplit.Header>
|
|
<Heading level={2}>Del evento crudo a la decisión</Heading>
|
|
<Text color="muted" size="lg">Tres capacidades, cada una al lado de lo que hace.</Text>
|
|
</FeatureSplit.Header>
|
|
{#each shown as row, i (row.title)}
|
|
<FeatureSplit.Row reversed={i % 2 === (startReversed ? 0 : 1)}>
|
|
{#snippet media()}
|
|
{#if row.media === 'phone'}
|
|
<Mockup chrome="phone">
|
|
<Surface variant="solid" color="primary" height="24rem" padding={5}>
|
|
<Stack gap={4}>
|
|
<Text size="sm" weight="semibold" color="on-solid">09:41</Text>
|
|
<Surface variant="soft" color="primary" rounded height="3rem" />
|
|
<Surface variant="soft" color="primary" rounded height="3rem" />
|
|
<Surface variant="soft" color="primary" rounded height="3rem" />
|
|
</Stack>
|
|
</Surface>
|
|
</Mockup>
|
|
{:else}
|
|
<Mockup chrome="browser" url="acme.app/{row.eyebrow.toLowerCase()}">
|
|
<Box padding={4}>
|
|
<Stack gap={5}>
|
|
<Group gap={2} align="center" justify="end">
|
|
<Badge size="xs" variant="soft" color="primary">en vivo</Badge>
|
|
</Group>
|
|
<Grid columns={7} gap={3} align="end">
|
|
{#each chart as h, j (j)}
|
|
<Surface
|
|
variant="solid"
|
|
color={j === 5 ? 'primary' : 'neutral'}
|
|
rounded
|
|
height={h}
|
|
/>
|
|
{/each}
|
|
</Grid>
|
|
<Grid templateColumns="1fr 20%" gap={3} align="center">
|
|
<Surface variant="solid" color="neutral" rounded height="0.5rem" />
|
|
<Surface variant="solid" color="neutral" rounded height="0.5rem" />
|
|
</Grid>
|
|
</Stack>
|
|
</Box>
|
|
</Mockup>
|
|
{/if}
|
|
{/snippet}
|
|
|
|
<FeatureSplit.Eyebrow>{row.eyebrow}</FeatureSplit.Eyebrow>
|
|
<FeatureSplit.Title>{row.title}</FeatureSplit.Title>
|
|
<FeatureSplit.Text>{row.text}</FeatureSplit.Text>
|
|
<FeatureSplit.Features>
|
|
{#each row.features as feature (feature)}
|
|
<FeatureSplit.Feature>{feature}</FeatureSplit.Feature>
|
|
{/each}
|
|
</FeatureSplit.Features>
|
|
<FeatureSplit.Actions>
|
|
<Button variant="solid" size="md">
|
|
{#snippet endIcon()}<Icon.ArrowRight size="xs" />{/snippet}
|
|
{#snippet child({ props, content })}
|
|
<a href="#{row.eyebrow.toLowerCase()}" {...props}>{@render content()}</a>
|
|
{/snippet}
|
|
{row.cta}
|
|
</Button>
|
|
</FeatureSplit.Actions>
|
|
</FeatureSplit.Row>
|
|
{/each}
|
|
</FeatureSplit>
|
|
|
|
<!-- A floor so the page reads as a page. -->
|
|
<Section size="lg">
|
|
<Container size="lg">
|
|
<Stack gap={4}>
|
|
<Heading level={2}>Todo desde un solo SDK</Heading>
|
|
<Text color="muted" measure="wide">
|
|
Un evento entra una vez y alimenta cohortes, alertas y automatizaciones — sin pegamento
|
|
entre servicios.
|
|
</Text>
|
|
</Stack>
|
|
</Container>
|
|
</Section>
|