Adding a Component
Reusable UI components live in app/components/.
Component Guidelines
- Directory Structure: Create a dedicated directory:
app/components/ComponentName/. - Implementation: Implement the component in
app/components/ComponentName/index.tsx. - Props Typing: Always declare explicit TypeScript
interfacetypes for component props (noany). - HeroUI v3: Use compound component dot notation (e.g.
<Card.Header>,<Tooltip.Trigger>) and accessible interactive primitives. - Icons: Use named imports from
lucide-reactor@icons-pack/react-simple-iconswith Tailwindsize-*orh-* w-*classes. - Server vs. Client: Keep components as Server Components by default. Add
"use client"only when managing state, effects, or browser events. - Unit Testing: Add a corresponding unit test file under
tests/unit/components/ComponentName/index.test.tsx.
Example Component
import { Card } from "@heroui/react";
import { Sparkles } from "lucide-react";
interface InfoCardProps {
title: string;
description: string;
}
export function InfoCard({ title, description }: InfoCardProps) {
return (
<Card className="p-6">
<Card.Header className="flex items-center gap-2">
<Sparkles className="size-5 text-primary" aria-hidden="true" />
<Card.Title className="text-lg font-semibold">{title}</Card.Title>
</Card.Header>
<Card.Content>
<p className="text-muted-foreground">{description}</p>
</Card.Content>
</Card>
);
}Adding Unit Tests
Create tests/unit/components/InfoCard/index.test.tsx:
import { render, screen } from "@testing-library/react";
import { describe, expect, it } from "vitest";
import { InfoCard } from "@/components/InfoCard";
describe("InfoCard", () => {
it("renders title and description", () => {
render(<InfoCard title="Test Title" description="Test Description" />);
expect(screen.getByText("Test Title")).toBeInTheDocument();
expect(screen.getByText("Test Description")).toBeInTheDocument();
});
});Last updated on