Files
zeekay 6c65e3e941 @hanzo/app 0.2.0: the app SDK, renamed from @hanzo/rooms
Every import, the catalog pin and the docs name @hanzo/app and
github.com/hanzoai/app. lib/rooms.ts is lib/app.ts and
components/rooms.tsx is components/app.tsx.
2026-10-22 19:07:20 -07:00

84 lines
2.5 KiB
TypeScript

'use client'
import React from "react";
import { motion } from "@/components/motion";
import { LucideIcon } from "lucide-react";
import { BrandColor } from "@/lib/constants/brand";
import { Text, XStack } from '@hanzo/ui'
import { Leaf, Line } from '@hanzo/ui/marketing'
import { mix } from '@hanzo/app/lib/mix'
/**
* NO TAILWIND AND NO STYLE OBJECTS. The card is `Leaf` — @hanzo/ui's component
* for a card whose edge lifts on approach — and everything inside it is gui
* props over @hanzo/design's tokens.
*/
interface FeatureCardProps {
title: string;
description: string;
icon: LucideIcon;
color?: BrandColor;
delay?: number;
}
/** The card's edge at rest and on approach, and the room inside it. */
const LEAF = {
p: 24,
borderColor: 'var(--border)',
hoverStyle: { borderColor: 'color-mix(in oklab, var(--pure-white) 40%, transparent)' },
} as const
/** The wash behind it, at the two strengths `color` picks between. */
const wash = (to: string): string =>
`linear-gradient(to bottom right in oklab, color-mix(in oklab, var(--pure-white) 20%, transparent), ${to})`
const PRIMARY = wash('color-mix(in oklab, var(--pure-white) 5%, transparent)')
const SECONDARY = wash('color-mix(in oklab, var(--pure-white) 10%, transparent)')
/**
* Reusable feature card with consistent brand styling.
* Use this instead of duplicating card patterns across components.
*/
const FeatureCard: React.FC<FeatureCardProps> = ({
title,
description,
icon: Icon,
color = "primary",
delay = 0,
}) => {
const isPrimary = color === "primary";
return (
<Leaf
render={<motion.div initial={{ opacity: 0, y: 20 }} whileInView={{ opacity: 1, y: 0 }} viewport={{ once: true }} transition={{ duration: 0.4, delay }} />}
backgroundImage={isPrimary ? PRIMARY : SECONDARY}
{...LEAF}
>
<XStack
items="center"
justify="center"
width={48}
height={48}
mb="$4"
rounded="var(--radius-lg)"
bg="$raised"
>
<Icon
width={24}
height={24}
color={isPrimary ? 'var(--foreground)' : 'color-mix(in oklab, var(--foreground) 70%, transparent)'}
/>
</XStack>
<Line render="h3" display="block" mb={8} fontSize="$6" fontWeight="700" color="var(--white)" lineHeight="1.4">
{title}
</Line>
<Text render="p" display="block" color={mix('var(--foreground)', 80)}>
{description}
</Text>
</Leaf>
);
};
export default FeatureCard;