Files
hanzo.ai/components/blockchain/surface.tsx

82 lines
2.8 KiB
TypeScript

'use client'
/**
* The surface every `/blockchain` page is drawn on, stated once: the three
* inks, the hairline tile, the disc a mark sits on, and a card's two lines.
*
* Four pages under this route each declared their own copy of these and they
* had drifted — the disc was `pure-white` at 10% on three and at 5% on the
* fourth. A value with four homes is four values wearing one name.
*
* The grounds are token mixes, which gui's colour type does not take, so they
* ride `$platform-web`; everything else is a prop.
*/
import type { ComponentProps, ReactNode } from 'react'
import { Box, Text, XStack } from '@hanzo/ui'
/** The three strengths of the foreground these pages draw in. */
export const INK = 'var(--foreground)'
export const DIM = 'var(--muted-foreground)'
/** A share of the foreground. */
export const ink = (pct: number) => `color-mix(in oklab, var(--foreground) ${pct}%, transparent)`
export const SOFT = ink(80)
/** A share of pure white, for a disc, an edge or a wash. */
export const white = (pct: number) => `color-mix(in oklab, var(--pure-white) ${pct}%, transparent)`
/** The ground the tiles sit on: the secondary surface at half strength. */
export const GROUND = 'color-mix(in oklab, var(--secondary) 50%, transparent)'
/** The hairline tile these pages set everything in. Padding is the caller's. */
export function Card({ children, ...p }: { children?: ReactNode } & ComponentProps<typeof Box>) {
return (
<Box
rounded="var(--radius-xl)"
borderWidth={1}
borderColor="var(--border)"
{...p}
$platform-web={{ backgroundColor: GROUND, ...p['$platform-web'] }}
>
{children}
</Box>
)
}
/** The disc a mark sits on, at the size the caller states. */
export function Tile({ size, children, ...p }: { size: number; children?: ReactNode } & ComponentProps<typeof XStack>) {
return (
<XStack
width={size}
height={size}
shrink={0}
items="center"
justify="center"
rounded="var(--radius-lg)"
{...p}
$platform-web={{ backgroundColor: white(10), ...p['$platform-web'] }}
>
{children}
</XStack>
)
}
type TextProps = ComponentProps<typeof Text>
/** A card's name: the browser's h3 rung, on the page's 20px line. */
export function CardTitle({ children, ...p }: { children: ReactNode } & Omit<TextProps, 'children'>) {
return (
<Text render="h3" display="block" mb={4} fontSize={16.38} lineHeight="1.25rem" fontWeight="600" color={INK} {...p}>
{children}
</Text>
)
}
/** The paragraph under a card's name. */
export function CardBody({ children, ...p }: { children: ReactNode } & Omit<TextProps, 'children'>) {
return (
<Text render="p" display="block" fontSize="$2" lineHeight="1.1607rem" color={DIM} {...p}>
{children}
</Text>
)
}