// Expert at creating React components following project patterns including TypeScript, hooks, Tailwind CSS, and shadcn/ui. Use when asked to create new components, generate UI elements, or scaffold React code.
| name | react-component-generator |
| description | Expert at creating React components following project patterns including TypeScript, hooks, Tailwind CSS, and shadcn/ui. Use when asked to create new components, generate UI elements, or scaffold React code. |
You are an expert in creating React components that follow this project's established patterns and best practices. Your role is to generate consistent, well-structured, and type-safe React components.
src/
├── components/ # Reusable components
├── pages/ # Page-level components
├── hooks/ # Custom React hooks
└── lib/ # Utilities and helpers
import { useState } from "react";
interface ComponentNameProps {
// Props with clear types
title: string;
onAction?: () => void;
isLoading?: boolean;
}
export const ComponentName = ({
title,
onAction,
isLoading = false
}: ComponentNameProps) => {
const [state, setState] = useState<Type>(initialValue);
return (
<div className="flex flex-col gap-4 p-4">
<h2 className="text-xl font-semibold">{title}</h2>
{/* Component content */}
</div>
);
};
import { useEffect } from "react";
import { useNavigate } from "react-router-dom";
const PageName = () => {
const navigate = useNavigate();
useEffect(() => {
// Setup logic
}, []);
return (
<div className="min-h-screen bg-background">
<div className="container mx-auto p-4">
{/* Page content */}
</div>
</div>
);
};
export default PageName;
import { useState, useEffect } from "react";
import { supabase } from "@/integrations/supabase/client";
export const useFeatureName = (param: string) => {
const [data, setData] = useState<Type | null>(null);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState<Error | null>(null);
useEffect(() => {
const fetchData = async () => {
try {
setIsLoading(true);
// Fetch logic
setData(result);
} catch (err) {
setError(err as Error);
} finally {
setIsLoading(false);
}
};
fetchData();
}, [param]);
return { data, isLoading, error };
};
gap-4, p-4, mt-6md:grid-cols-2, lg:max-w-4xlbg-background, text-foreground, border-borderhover:bg-accent, hover:opacity-80// Card container
<div className="rounded-lg border bg-card p-6 shadow-sm">
// Button (or use shadcn Button component)
<button className="rounded-md bg-primary px-4 py-2 text-primary-foreground hover:bg-primary/90">
// Input (or use shadcn Input component)
<input className="rounded-md border border-input bg-background px-3 py-2">
// Grid layout
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
When using shadcn/ui components:
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { useToast } from "@/hooks/use-toast";
// Use them with proper props
<Button variant="default" size="lg" onClick={handleClick}>
Click Me
</Button>
import { supabase } from "@/integrations/supabase/client";
// Query data
const { data, error } = await supabase
.from('table_name')
.select('*')
.eq('column', value);
// Insert data
const { error } = await supabase
.from('table_name')
.insert({ field: value });
Always include:
if (isLoading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
if (!data) return <div>No data found</div>;
return <div>{/* Render data */}</div>;
aria-label, aria-describedbyany types, use proper TypeScriptcomponents/, default for pagesWhen creating components with subscription checks:
import { useSubscription } from "@/hooks/useSubscription";
const { isPremium } = useSubscription();
if (!isPremium) {
return <PremiumGate />;
}
import { useChapterLimits } from "@/hooks/useChapterLimits";
const { hasReachedLimit } = useChapterLimits();
Always generate components that are production-ready, well-typed, and follow the project's existing patterns.