Build consistent, scalable UIs with Tailwind CSS, custom plugins, and component libraries in Next.js.
# Next.js with Tailwind Design System
Build scalable design systems with Next.js and Tailwind CSS using Google Antigravity IDE. This comprehensive guide covers component architecture, theming, and accessibility patterns.
## Why Tailwind Design Systems?
Tailwind provides utility-first CSS with excellent customization. Google Antigravity IDE's Gemini 3 engine suggests component patterns and accessibility improvements.
## Theme Configuration
```typescript
// tailwind.config.ts
import type { Config } from "tailwindcss";
const config: Config = {
content: ["./src/**/*.{js,ts,jsx,tsx,mdx}"],
darkMode: "class",
theme: {
extend: {
colors: {
primary: {
50: "#eff6ff",
100: "#dbeafe",
200: "#bfdbfe",
300: "#93c5fd",
400: "#60a5fa",
500: "#3b82f6",
600: "#2563eb",
700: "#1d4ed8",
800: "#1e40af",
900: "#1e3a8a",
},
neutral: {
50: "#fafafa",
100: "#f5f5f5",
200: "#e5e5e5",
300: "#d4d4d4",
400: "#a3a3a3",
500: "#737373",
600: "#525252",
700: "#404040",
800: "#262626",
900: "#171717",
},
},
fontFamily: {
sans: ["Inter", "system-ui", "sans-serif"],
mono: ["JetBrains Mono", "monospace"],
},
spacing: {
"4.5": "1.125rem",
"18": "4.5rem",
},
borderRadius: {
"4xl": "2rem",
},
animation: {
"fade-in": "fadeIn 0.2s ease-in-out",
"slide-up": "slideUp 0.3s ease-out",
},
keyframes: {
fadeIn: {
"0%": { opacity: "0" },
"100%": { opacity: "1" },
},
slideUp: {
"0%": { transform: "translateY(10px)", opacity: "0" },
"100%": { transform: "translateY(0)", opacity: "1" },
},
},
},
},
plugins: [
require("@tailwindcss/forms"),
require("@tailwindcss/typography"),
],
};
export default config;
```
## Base Button Component
```typescript
// components/ui/Button.tsx
import { forwardRef, ButtonHTMLAttributes } from "react";
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils";
const buttonVariants = cva(
"inline-flex items-center justify-center rounded-lg font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
{
variants: {
variant: {
primary: "bg-primary-600 text-white hover:bg-primary-700 focus-visible:ring-primary-500",
secondary: "bg-neutral-100 text-neutral-900 hover:bg-neutral-200 focus-visible:ring-neutral-500 dark:bg-neutral-800 dark:text-neutral-100",
outline: "border border-neutral-300 bg-transparent hover:bg-neutral-100 focus-visible:ring-neutral-500 dark:border-neutral-700 dark:hover:bg-neutral-800",
ghost: "hover:bg-neutral-100 dark:hover:bg-neutral-800",
destructive: "bg-red-600 text-white hover:bg-red-700 focus-visible:ring-red-500",
link: "text-primary-600 underline-offset-4 hover:underline",
},
size: {
sm: "h-8 px-3 text-sm",
md: "h-10 px-4 text-sm",
lg: "h-12 px-6 text-base",
icon: "h-10 w-10",
},
},
defaultVariants: {
variant: "primary",
size: "md",
},
}
);
interface ButtonProps
extends ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {
loading?: boolean;
}
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant, size, loading, children, disabled, ...props }, ref) => {
return (
<button
ref={ref}
className={cn(buttonVariants({ variant, size }), className)}
disabled={disabled || loading}
{...props}
>
{loading && (
<svg
className="mr-2 h-4 w-4 animate-spin"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
>
<circle
className="opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor"
strokeWidth="4"
/>
<path
className="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"
/>
</svg>
)}
{children}
</button>
);
}
);
Button.displayName = "Button";
```
## Input Component
```typescript
// components/ui/Input.tsx
import { forwardRef, InputHTMLAttributes } from "react";
import { cn } from "@/lib/utils";
interface InputProps extends InputHTMLAttributes<HTMLInputElement> {
label?: string;
error?: string;
hint?: string;
}
export const Input = forwardRef<HTMLInputElement, InputProps>(
({ className, label, error, hint, id, ...props }, ref) => {
const inputId = id || props.name;
return (
<div className="w-full">
{label && (
<label
htmlFor={inputId}
className="mb-1.5 block text-sm font-medium text-neutral-700 dark:text-neutral-300"
>
{label}
</label>
)}
<input
ref={ref}
id={inputId}
className={cn(
"flex h-10 w-full rounded-lg border bg-white px-3 py-2 text-sm",
"placeholder:text-neutral-400",
"focus:outline-none focus:ring-2 focus:ring-offset-2",
error
? "border-red-500 focus:ring-red-500"
: "border-neutral-300 focus:ring-primary-500 dark:border-neutral-700",
"disabled:cursor-not-allowed disabled:opacity-50",
"dark:bg-neutral-900 dark:text-white",
className
)}
aria-invalid={error ? "true" : "false"}
aria-describedby={error ? `${inputId}-error` : hint ? `${inputId}-hint` : undefined}
{...props}
/>
{error && (
<p id={`${inputId}-error`} className="mt-1.5 text-sm text-red-600">
{error}
</p>
)}
{hint && !error && (
<p id={`${inputId}-hint`} className="mt-1.5 text-sm text-neutral-500">
{hint}
</p>
)}
</div>
);
}
);
Input.displayName = "Input";
```
## Card Component
```typescript
// components/ui/Card.tsx
import { HTMLAttributes, forwardRef } from "react";
import { cn } from "@/lib/utils";
const Card = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(
({ className, ...props }, ref) => (
<div
ref={ref}
className={cn(
"rounded-xl border border-neutral-200 bg-white shadow-sm",
"dark:border-neutral-800 dark:bg-neutral-900",
className
)}
{...props}
/>
)
);
const CardHeader = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(
({ className, ...props }, ref) => (
<div ref={ref} className={cn("p-6 pb-0", className)} {...props} />
)
);
const CardContent = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(
({ className, ...props }, ref) => (
<div ref={ref} className={cn("p-6", className)} {...props} />
)
);
export { Card, CardHeader, CardContent };
```
## Best Practices
- Use CVA for variant management
- Apply proper dark mode support
- Implement accessible form controls
- Create consistent spacing tokens
- Use semantic color naming
- Add proper focus indicators
Google Antigravity IDE provides Tailwind component suggestions and automatically ensures accessibility compliance in your design system.This Next.js prompt is ideal for developers working on:
By using this prompt, you can save hours of manual coding and ensure best practices are followed from the start. It's particularly valuable for teams looking to maintain consistency across their next.js implementations.
Yes! All prompts on Antigravity AI Directory are free to use for both personal and commercial projects. No attribution required, though it's always appreciated.
This prompt works excellently with Claude, ChatGPT, Cursor, GitHub Copilot, and other modern AI coding assistants. For best results, use models with large context windows.
You can modify the prompt by adding specific requirements, constraints, or preferences. For Next.js projects, consider mentioning your framework version, coding style, and any specific libraries you're using.