Files

138 lines
4.8 KiB
TypeScript

'use client'
import React from "react";
import { motion } from "@/components/motion";
import { MessageSquare, Users, Edit, GamepadIcon, ChartBar, Code, Heart } from "lucide-react";
import { View, YStack, XStack } from '@hanzo/ui'
import { Grid } from '@hanzo/ui/grid'
import { Line } from '@/components/type'
import { Chip, Lede, Title, Leaf } from '@hanzo/ui/marketing'
interface UseCaseCardProps {
icon: React.ElementType;
title: string;
description: string;
index: number;
}
/**
* The tile a use case sits in.
*
* `Leaf` is the site's card-whose-edge-lifts-on-approach: it owns the resting
* edge, the hover and the reduced-motion opt-out, which is the one thing a style
* attribute cannot say. Its three custom properties are what varies, so this
* states those and nothing else about the edge.
*
* `display` is overridden because `Leaf` is a block and gui's `Text` is
* `display: inline` — the title and the paragraph would share a line unless each
* is a flex item.
*/
const CARD = { p: 24, borderColor: "var(--neutral-800)", display: "flex", flexDirection: "column", backgroundImage: "linear-gradient(to bottom right, var(--neutral-900), var(--background))", bg: "transparent", hoverStyle: { borderColor: "color-mix(in oklab, var(--pure-white) 30%, transparent)" } } as const
/** The badge over the section head. `Chip` owns the outline and the gap. */
const BADGE = { mb: 24, px: 12, py: 4, bg: "color-mix(in oklab, var(--primary) 10%, transparent)", borderColor: "color-mix(in oklab, var(--pure-white) 30%, transparent)" } as const
const UseCaseCard: React.FC<UseCaseCardProps> = ({ icon: Icon, title, description, index }) => {
return (
<Leaf
render={<motion.div initial={{ opacity: 0, y: 20 }} whileInView={{ opacity: 1, y: 0 }} viewport={{ once: true }} transition={{ duration: 0.5, delay: 0.1 * index }} />}
{...CARD}
hoverStyle={{ borderColor: "color-mix(in oklab, var(--pure-white) 30%, transparent)" }}
>
<XStack
width={40}
height={40}
items="center"
justify="center"
mb={16}
rounded="var(--radius-full)"
bg="$raised"
>
<Icon width={20} height={20} color="var(--foreground)" />
</XStack>
<Line render="h3" size="lg" weight="600" marginBottom={8}>{title}</Line>
<Line render="p" size="sm" tone="muted">{description}</Line>
</Leaf>
);
};
const UseCases = () => {
const useCases = [
{
icon: MessageSquare,
title: "Chat Applications",
description: "Build messaging apps with real-time delivery, typing indicators, and read receipts."
},
{
icon: Users,
title: "Collaborative Workspaces",
description: "Create shared workspaces where multiple users can collaborate simultaneously."
},
{
icon: Edit,
title: "Collaborative Editing",
description: "Several people editing one document, each of them seeing the others' changes land as they happen."
},
{
icon: GamepadIcon,
title: "Multiplayer Games",
description: "Develop low-latency multiplayer games with synchronized game state across players."
},
{
icon: ChartBar,
title: "Live Dashboards",
description: "Build dashboards that update in real-time as new data becomes available."
},
{
icon: Code,
title: "Dev Tooling",
description: "Create collaborative coding environments with real-time changes and execution."
}
];
return (
<YStack
render="section"
py={80}
px={16}
$sm={{ px: 24 }}
$lg={{ px: 32 }}
background="linear-gradient(to bottom, var(--background), color-mix(in oklab, var(--pure-white) 10%, transparent))"
>
<YStack width="100%" maxW={1280} mx="auto">
<View
render={<motion.div initial={{ opacity: 0, y: 20 }} whileInView={{ opacity: 1, y: 0 }} viewport={{ once: true }} transition={{ duration: 0.5 }} />}
display="block"
mb={64}
$platform-web={{ textAlign: 'center' }}
>
<Chip {...BADGE}>
<Heart width={16} height={16} color="var(--foreground)" />
<span>Popular Use Cases</span>
</Chip>
<Title quiet mb={16}>
Build Interactive Experiences
</Title>
<Lede maxW={768} mx="auto" mt="$3.5">
Hanzo Realtime powers a wide range of applications that demand immediate data updates
</Lede>
</View>
<Grid columns={{ min: 300, max: 3 }} gap={24} mb={48}>
{useCases.map((useCase, index) => (
<UseCaseCard
key={index}
icon={useCase.icon}
title={useCase.title}
description={useCase.description}
index={index}
/>
))}
</Grid>
</YStack>
</YStack>
);
};
export default UseCases;