Skip to Content
styled-cva 0.5.3 is available šŸŽ‰
Examples

Usage Examples

Common patterns and real-world examples using styled-cva.

Buttons

Basic Button with Variants

A standard button component with intent and size variants.

import tw from "@styled-cva/react"; const Button = tw.button.cva( "inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none ring-offset-background", { variants: { $variant: { default: "bg-primary text-primary-foreground hover:bg-primary/90", destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90", outline: "border border-input hover:bg-accent hover:text-accent-foreground", secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80", ghost: "hover:bg-accent hover:text-accent-foreground", link: "underline-offset-4 hover:underline text-primary", }, $size: { default: "h-10 py-2 px-4", sm: "h-9 px-3 rounded-md", lg: "h-11 px-8 rounded-md", icon: "h-10 w-10", }, }, defaultVariants: { $variant: "default", $size: "default", }, }, ); export default function ButtonExample() { return ( <div className="flex flex-wrap gap-4 p-4"> <Button>Default</Button> <Button $variant="secondary">Secondary</Button> <Button $variant="destructive">Destructive</Button> <Button $variant="outline">Outline</Button> <Button $variant="ghost">Ghost</Button> <Button $variant="link">Link</Button> </div> ); }

Form Elements

Input with Validation States

An input component that handles error, success, and disabled states.

import tw from "@styled-cva/react"; const Input = tw.input.cva( "flex h-10 w-full rounded-md border bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50", { variants: { $state: { default: "border-input focus-visible:ring-ring", error: "border-red-500 focus-visible:ring-red-500 text-red-900 placeholder:text-red-300", success: "border-green-500 focus-visible:ring-green-500 text-green-900", }, }, defaultVariants: { $state: "default", }, }, ); export default function InputExample() { return ( <div className="grid w-full max-w-sm items-center gap-4"> <Input placeholder="Default input" /> <Input $state="error" placeholder="Error state" defaultValue="Invalid input" /> <Input $state="success" placeholder="Success state" defaultValue="Valid input" /> <Input disabled placeholder="Disabled input" /> </div> ); }

Interactive Components

Toggle Switch

A switch component using aria-pressed or a custom prop for state.

import { useState } from "react"; import tw from "@styled-cva/react"; const SwitchRoot = tw.button.cva( "peer inline-flex h-[24px] w-[44px] shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50", { variants: { $checked: { true: "bg-primary", false: "bg-input", }, }, }, ); const SwitchThumb = tw.span.cva( "pointer-events-none block h-5 w-5 rounded-full bg-background shadow-lg ring-0 transition-transform", { variants: { $checked: { true: "translate-x-5", false: "translate-x-0", }, }, }, ); export default function SwitchExample() { const [checked, setChecked] = useState(false); return ( <SwitchRoot $checked={checked} onClick={() => setChecked(!checked)} role="switch" aria-checked={checked} > <SwitchThumb $checked={checked} /> </SwitchRoot> ); }

Layouts

Card

A composed card component.

import tw from "@styled-cva/react"; const Card = tw.div`rounded-lg border bg-card text-card-foreground shadow-sm`; const CardHeader = tw.div`flex flex-col space-y-1.5 p-6`; const CardTitle = tw.h3`text-2xl font-semibold leading-none tracking-tight`; const CardDescription = tw.p`text-sm text-muted-foreground`; const CardContent = tw.div`p-6 pt-0`; const CardFooter = tw.div`flex items-center p-6 pt-0`; export default function CardExample() { return ( <Card className="w-[350px]"> <CardHeader> <CardTitle>Create project</CardTitle> <CardDescription>Deploy your new project in one-click.</CardDescription> </CardHeader> <CardContent> <p>Project details form goes here...</p> </CardContent> <CardFooter className="flex justify-between"> <button className="text-sm">Cancel</button> <button className="bg-primary rounded px-4 py-2 text-white"> Deploy </button> </CardFooter> </Card> ); }

Polymorphic Components

Using the $as prop to render a button as a link.

import Link from "next/link"; import tw from "@styled-cva/react"; const Button = tw.button.cva( "inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 bg-primary text-primary-foreground hover:bg-primary/90 h-10 px-4 py-2", ); export default function PolymorphicExample() { return ( <div className="flex gap-4"> {/* Renders as <button> */} <Button onClick={() => alert("Clicked!")}>Button</Button> {/* Renders as <a> */} <Button $as="a" href="https://github.com/alanrsoares/styled-cva" target="_blank" rel="noreferrer" > GitHub Link </Button> {/* Renders as Next.js Link */} <Button $as={Link} href="/getting-started"> Get Started </Button> </div> ); }

Advanced Composition

Extending Components

Styling a custom component or extending an existing one.

import tw from "@styled-cva/react"; // Base component const BaseBox = tw.div`p-4 border rounded`; // Extended component overrides styles const WarningBox = tw(BaseBox)`border-yellow-500 bg-yellow-50 text-yellow-900`; // Custom React Component const UserProfile = ({ className, name, }: { className?: string; name: string; }) => ( <div className={className}> <span className="font-bold">{name}</span> </div> ); // Styled Custom Component const StyledProfile = tw( UserProfile, )`flex items-center gap-2 p-2 bg-gray-100 rounded-full`; export default function AdvancedCompositionExample() { return ( <div className="flex flex-col gap-4"> <BaseBox>Base Box</BaseBox> <WarningBox>Warning Box</WarningBox> <StyledProfile name="John Doe" /> </div> ); }

Default Props

Pre-configuring Components

Using .withProps() to set default attributes and variant values.

import tw from "@styled-cva/react"; const IconButton = tw.button .cva( "inline-flex items-center justify-center rounded-full p-2 transition-colors", { variants: { $variant: { primary: "bg-blue-600 text-white hover:bg-blue-700", ghost: "hover:bg-gray-100 text-gray-600", }, }, }, ) .withProps({ type: "button", $variant: "primary", "aria-label": "Icon button", }); export default function DefaultPropsExample() { return ( <div className="flex gap-4"> {/* Uses all defaults */} <IconButton> <span className="size-4">šŸš€</span> </IconButton> {/* Overrides default variant */} <IconButton $variant="ghost"> <span className="size-4">āš™ļø</span> </IconButton> {/* Overrides default aria-label */} <IconButton aria-label="Settings"> <span className="size-4">šŸ› ļø</span> </IconButton> </div> ); }
Last updated on