Build consistent scalable design systems with Tailwind CSS in Google Antigravity including tokens components and variants
# Tailwind CSS Design System Patterns for Google Antigravity
Design systems provide consistency and accelerate development by establishing reusable patterns. This guide establishes patterns for building design systems with Tailwind CSS in Google Antigravity projects, enabling Gemini 3 to generate cohesive, maintainable UI implementations.
## Design Token Configuration
Extend Tailwind with custom design tokens:
```typescript
// tailwind.config.ts
import type { Config } from "tailwindcss";
const config: Config = {
content: ["./src/**/*.{js,ts,jsx,tsx,mdx}"],
theme: {
extend: {
colors: {
brand: {
50: "#f0f9ff",
100: "#e0f2fe",
200: "#bae6fd",
300: "#7dd3fc",
400: "#38bdf8",
500: "#0ea5e9",
600: "#0284c7",
700: "#0369a1",
800: "#075985",
900: "#0c4a6e",
950: "#082f49",
},
semantic: {
success: "#22c55e",
warning: "#f59e0b",
error: "#ef4444",
info: "#3b82f6",
},
},
spacing: {
"4.5": "1.125rem",
"18": "4.5rem",
"88": "22rem",
},
fontSize: {
"2xs": ["0.625rem", { lineHeight: "0.75rem" }],
},
borderRadius: {
"4xl": "2rem",
},
boxShadow: {
"soft": "0 2px 15px -3px rgba(0, 0, 0, 0.07), 0 10px 20px -2px rgba(0, 0, 0, 0.04)",
"glow": "0 0 20px rgba(14, 165, 233, 0.3)",
},
animation: {
"fade-in": "fadeIn 0.3s ease-in-out",
"slide-up": "slideUp 0.4s ease-out",
"pulse-soft": "pulseSoft 2s infinite",
},
keyframes: {
fadeIn: {
"0%": { opacity: "0" },
"100%": { opacity: "1" },
},
slideUp: {
"0%": { opacity: "0", transform: "translateY(10px)" },
"100%": { opacity: "1", transform: "translateY(0)" },
},
pulseSoft: {
"0%, 100%": { opacity: "1" },
"50%": { opacity: "0.7" },
},
},
},
},
plugins: [require("@tailwindcss/forms"), require("@tailwindcss/typography")],
};
export default config;
```
## Component Variants with CVA
Create flexible component variants:
```typescript
// components/ui/Button.tsx
import { cva, type VariantProps } from "class-variance-authority";
import { forwardRef } from "react";
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-brand-600 text-white hover:bg-brand-700 focus-visible:ring-brand-500",
secondary: "bg-gray-100 text-gray-900 hover:bg-gray-200 focus-visible:ring-gray-500",
outline: "border-2 border-brand-600 text-brand-600 hover:bg-brand-50 focus-visible:ring-brand-500",
ghost: "text-gray-600 hover:bg-gray-100 hover:text-gray-900",
danger: "bg-red-600 text-white hover:bg-red-700 focus-visible:ring-red-500",
link: "text-brand-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",
xl: "h-14 px-8 text-lg",
icon: "h-10 w-10",
},
fullWidth: {
true: "w-full",
},
},
defaultVariants: {
variant: "primary",
size: "md",
},
}
);
interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {
isLoading?: boolean;
}
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant, size, fullWidth, isLoading, children, ...props }, ref) => {
return (
<button
ref={ref}
className={cn(buttonVariants({ variant, size, fullWidth, className }))}
disabled={isLoading || props.disabled}
{...props}
>
{isLoading && (
<svg className="mr-2 h-4 w-4 animate-spin" viewBox="0 0 24 24">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" fill="none" />
<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";
```
## Utility Function
Merge class names safely:
```typescript
// lib/utils.ts
import { clsx, type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
```
## Form Components
Build accessible form elements:
```typescript
// components/ui/Input.tsx
import { forwardRef } from "react";
import { cn } from "@/lib/utils";
interface InputProps extends React.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="space-y-1.5">
{label && (
<label htmlFor={inputId} className="block text-sm font-medium text-gray-700">
{label}
{props.required && <span className="text-red-500 ml-1">*</span>}
</label>
)}
<input
ref={ref}
id={inputId}
className={cn(
"block w-full rounded-lg border px-3 py-2 text-gray-900 shadow-sm transition-colors",
"placeholder:text-gray-400",
"focus:border-brand-500 focus:outline-none focus:ring-2 focus:ring-brand-500/20",
"disabled:cursor-not-allowed disabled:bg-gray-50 disabled:text-gray-500",
error
? "border-red-500 focus:border-red-500 focus:ring-red-500/20"
: "border-gray-300",
className
)}
aria-invalid={!!error}
aria-describedby={error ? `${inputId}-error` : hint ? `${inputId}-hint` : undefined}
{...props}
/>
{error && (
<p id={`${inputId}-error`} className="text-sm text-red-600">{error}</p>
)}
{hint && !error && (
<p id={`${inputId}-hint`} className="text-sm text-gray-500">{hint}</p>
)}
</div>
);
}
);
Input.displayName = "Input";
```
## Best Practices
1. **Design tokens**: Centralize colors, spacing, typography in config
2. **CVA for variants**: Use class-variance-authority for flexible components
3. **Utility merging**: Use clsx + tailwind-merge for class composition
4. **Accessibility**: Include ARIA attributes and focus states
5. **Consistent naming**: Follow naming conventions across componentsThis Tailwind CSS 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 tailwind css 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 Tailwind CSS projects, consider mentioning your framework version, coding style, and any specific libraries you're using.