import * as React from "react"; import { cva, type VariantProps } from "class-variance-authority"; import { cn } from "@/lib/utils"; /** * TextPair — WealthX * * A strong line with a quiet line under it: section heading + subject, list item * + metadata, field label + captured value. Owns the gap between them so the * relationship is defined once (--spacing-text-pair) instead of per screen. */ // min-w-0 + break-words: without both, an unbroken string (a long email, a // pasted reference) blows the parent flex item out and scrolls the document. const textPairVariants = cva("flex min-w-0 flex-col gap-text-pair"); const primaryVariants = cva("break-words text-foreground", { variants: { size: { sm: "text-label-small", md: "text-label-medium", lg: "text-h5", }, }, defaultVariants: { size: "md" }, }); const secondaryVariants = cva("break-words text-muted-foreground", { variants: { size: { sm: "text-caption", md: "text-body-small", lg: "text-body-small", }, }, defaultVariants: { size: "md" }, }); export type TextPairProps = Omit, "children"> & VariantProps & { primary: React.ReactNode; secondary?: React.ReactNode; primaryClassName?: string; secondaryClassName?: string; }; function TextPair({ primary, secondary, size, className, primaryClassName, secondaryClassName, ...props }: TextPairProps) { // `x={cond && value}` yields `false`, which is not null and not "". Without the // boolean check that renders an empty span and leaks the gap. `0` must survive. const isRenderable = (v: React.ReactNode) => v !== null && v !== undefined && v !== "" && typeof v !== "boolean"; const hasPrimary = isRenderable(primary); const hasSecondary = isRenderable(secondary); return (
{hasPrimary ? ( {primary} ) : null} {hasSecondary ? ( {secondary} ) : null}
); } export { TextPair, textPairVariants };