agentleFS
iwritec0deiwritec0de/app-dev/skills/tailwind/SKILL.md

tailwind

Skill3 starsChanged 7 months agoMITView on GitHub

This skill should be used when the user asks to "style a component with Tailwind", "set up dark mode", "create a responsive layout", "build a reusable UI component", "configure Tailwind", "use cn() utility", or mentions "tailwind", "tailwindcss", "utility class", "className", "dark mode", "responsive design", "tailwind-merge", "cva", "class variance authority", "shadcn", "tailwind v4", "CSS theme variables", "@theme", "@variant". Provides Tailwind CSS expertise for React and Next.js applications including utility patterns, responsive design, dark mode, component abstractions, and Tailwind v4 CSS-first configuration.

  • Installs packages

25 other projects use a version of this.

Adopted by

Most recently taken up by

Used with

Projects with it also use waapi, three and 10 more.

Other files people use alongside this one.

Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
  • anton-abyzovSkill

    waapi

    Web Animations API adapter patterns for HyperFrames. Use when authoring element.animate() motion, Animation currentTime seeking, document.getAnimations(), KeyframeEffect timing, fill modes, or native browser animations that must render deterministically in HyperFrames.

    Also in 5 projects that use this

  • anton-abyzovSkill

    three

    Three.js and WebGL adapter patterns for HyperFrames. Use when creating deterministic Three.js scenes, WebGL canvas layers, AnimationMixer timelines, camera motion, shader-driven visuals, or canvas renders that respond to HyperFrames hf-seek events.

    Also in 5 projects that use this

  • soilmassSkill

    lottie

    Lottie animation format specification and usage. Use when exporting animations as Lottie JSON, working with dotLottie packages, or understanding Lottie capabilities and limitations. References LAC Lottie Spec v1.0 and dotLottie v2.0.

    Also in 5 projects that use this

  • FldicoahkiinSkill

    contribute-catalog

    Author a new HyperFrames registry block (caption style, VFX block, transition, lower third) or component (text effect, overlay, snippet) and ship it as an upstream PR to the hyperframes repo. Use ONLY when the user wants to CONTRIBUTE to the public catalog — for in-project caption/transition authoring use the `hyperframes` skill, for installing existing registry items use the `hyperframes-registry` skill.

    Also in 3 projects that use this

  • software-mansion-labsSkill

    typegpu

    TypeGPU is type-safe WebGPU in TypeScript. Use whenever the user writes, debugs, or designs TypeGPU code: 'use gpu' shader functions, tgpu.fn, buffers, textures, bind groups, compute and render pipelines, command encoders, render passes, render bundles, vertex layouts, slots, accessors, @typegpu/react hooks (useRoot, useFrame, useUniform), React Native worklet rendering, and any TypeGPU API. Shader logic and CPU-side resources are tightly coupled - handle both sides here even if the user only mentions one (e.g. "how do I write a shader", "how do I create a buffer"). Trigger on any mention of typegpu, tgpu, "use gpu", TypedGPU, or WebGPU code written using TypeGPU's schema API (d.*, tgpu.*, std.*). Do NOT trigger for raw WebGPU (using GPUDevice/GPURenderPipeline directly without tgpu), WGSL-only questions, Three.js, Babylon.js, or WebGL.

    Also in 3 projects that use this

  • OpenAISkill

    gsap

    GSAP animation reference for HyperFrames. Covers gsap.to(), from(), fromTo(), easing, stagger, defaults, timelines (gsap.timeline(), position parameter, labels, nesting, playback), and performance (transforms, will-change, quickTo). Use when writing GSAP animations in HyperFrames compositions.

    Also in 7 projects that use this

  • +2 more from anton-abyzov

The file

We split this skill into the rules it gives an agent

1 rule. 0 are common, 1 is distinctive, and 0 are very specific to this project.

  • 0

    Common

    Most of the 22 edited versions we read keep these.

  • 1

    Distinctive

    This author's own choices. Worth a look.

  • 0

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Every project using Tailwind in React should have this helper:

    line 101

“Common” is measured: kept by at least 6 in 10 of the 22 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Tailwind CSS

Tailwind CSS utility-first patterns for React and Next.js applications.

Critical Rules

  1. Utility-first — compose styles from utility classes directly in markup; extract components, not CSS classes
  2. Never use @apply to build component classes — extract a React component instead; @apply defeats the purpose of utility-first and creates abstraction layers that are harder to maintain
  3. Use the cn() helper for conditional classes — combine clsx + tailwind-merge to handle conflicts and conditionals cleanly
  4. Mobile-first responsive — unprefixed utilities target mobile; use sm:, md:, lg:, xl:, 2xl: for larger screens
  5. Semantic color tokens — use design-system colors (bg-primary, text-muted-foreground) rather than raw scales (bg-blue-500) when a design system is in place
  6. Dark mode via dark: variant — pair light and dark utilities on the same element; never maintain separate component trees for themes

Setup with Next.js

Tailwind v4 (CSS-first configuration)

npm install tailwindcss @tailwindcss/postcss
/* app/globals.css */
@import "tailwindcss";
// postcss.config.ts
export default {
  plugins: {
    "@tailwindcss/postcss": {},
  },
};

Tailwind v4 uses CSS for configuration instead of tailwind.config.js. Define custom values with @theme:

/* app/globals.css */
@import "tailwindcss";

@theme {
  --color-primary: #2563eb;
  --color-primary-foreground: #ffffff;
  --color-muted: #f1f5f9;
  --color-muted-foreground: #64748b;
  --color-destructive: #ef4444;

  --font-sans: "Inter", sans-serif;
  --font-mono: "JetBrains Mono", monospace;

  --radius-lg: 0.75rem;
  --radius-md: 0.5rem;
  --radius-sm: 0.25rem;
}

These become utilities automatically: bg-primary, text-muted-foreground, font-sans, rounded-lg.

Tailwind v3 (JS configuration)

// tailwind.config.ts
import type { Config } from "tailwindcss";

const config: Config = {
  content: ["./app/**/*.{ts,tsx}", "./components/**/*.{ts,tsx}"],
  darkMode: "class",
  theme: {
    extend: {
      colors: {
        primary: { DEFAULT: "#2563eb", foreground: "#ffffff" },
        muted: { DEFAULT: "#f1f5f9", foreground: "#64748b" },
      },
    },
  },
};

export default config;

The cn() Utility

Every project using Tailwind in React should have this helper:

// lib/utils.ts
import { clsx, type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs));
}
npm install clsx tailwind-merge

Usage — twMerge resolves conflicting utilities so the last one wins:

import { cn } from "@/lib/utils";

<div className={cn(
  "rounded-lg border p-4",           // base styles
  isActive && "border-primary",       // conditional
  className,                          // prop override (wins over base)
)} />

Without twMerge, cn("p-4", "p-6") would produce "p-4 p-6" (both applied, unpredictable). With twMerge, it correctly produces "p-6".

Responsive Design

Mobile-first breakpoints — unprefixed utilities are the base (mobile):

PrefixMin-widthTarget
(none)0pxMobile (base)
sm:640pxLandscape phones
md:768pxTablets
lg:1024pxLaptops
xl:1280pxDesktops
2xl:1536pxLarge screens
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
  {items.map(item => <Card key={item.id} {...item} />)}
</div>

<h1 className="text-2xl font-bold md:text-3xl lg:text-4xl">
  Responsive heading
</h1>

Container pattern:

<div className="mx-auto w-full max-w-7xl px-4 sm:px-6 lg:px-8">
  {children}
</div>

Dark Mode

Class-based (recommended for Next.js)

Toggle the dark class on <html> — use next-themes for persistence:

npm install next-themes
// app/providers.tsx
"use client";
import { ThemeProvider } from "next-themes";

export function Providers({ children }: { children: React.ReactNode }) {
  return (
    <ThemeProvider attribute="class" defaultTheme="system" enableSystem>
      {children}
    </ThemeProvider>
  );
}
// Usage — pair light and dark utilities:
<div className="bg-white text-gray-900 dark:bg-gray-950 dark:text-gray-100">
  <p className="text-gray-600 dark:text-gray-400">Muted text</p>
</div>

CSS variable approach (scales with design systems)

@theme {
  --color-background: #ffffff;
  --color-foreground: #0a0a0a;
  --color-card: #ffffff;
  --color-card-foreground: #0a0a0a;
  --color-border: #e5e7eb;
}

.dark {
  --color-background: #0a0a0a;
  --color-foreground: #fafafa;
  --color-card: #111111;
  --color-card-foreground: #fafafa;
  --color-border: #27272a;
}

Then use bg-background, text-foreground, border-border — no dark: prefix needed because the variables themselves change.

Component Patterns

Reusable Button with Variants (CVA)

npm install class-variance-authority
// components/ui/button.tsx
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils";

const buttonVariants = cva(
  "inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50",
  {
    variants: {
      variant: {
        default: "bg-primary text-primary-foreground hover:bg-primary/90",
        secondary: "bg-muted text-muted-foreground hover:bg-muted/80",
        destructive: "bg-destructive text-white hover:bg-destructive/90",
        outline: "border border-border bg-transparent hover:bg-muted",
        ghost: "hover:bg-muted",
        link: "text-primary underline-offset-4 hover:underline",
      },
      size: {
        sm: "h-8 px-3 text-xs",
        default: "h-10 px-4",
        lg: "h-12 px-6 text-base",
        icon: "h-10 w-10",
      },
    },
    defaultVariants: {
      variant: "default",
      size: "default",
    },
  }
);

interface ButtonProps
  extends React.ButtonHTMLAttributes<HTMLButtonElement>,
    VariantProps<typeof buttonVariants> {}

export function Button({ className, variant, size, ...props }: ButtonProps) {
  return (
    <button
      className={cn(buttonVariants({ variant, size, className }))}
      {...props}
    />
  );
}

Card Component

// components/ui/card.tsx
import { cn } from "@/lib/utils";

export function Card({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
  return (
    <div
      className={cn("rounded-lg border border-border bg-card p-6 text-card-foreground shadow-sm", className)}
      {...props}
    />
  );
}

export function CardHeader({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
  return <div className={cn("mb-4 space-y-1.5", className)} {...props} />;
}

export function CardTitle({ className, ...props }: React.HTMLAttributes<HTMLHeadingElement>) {
  return <h3 className={cn("text-lg font-semibold leading-none", className)} {...props} />;
}

export function CardContent({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
  return <div className={cn("text-sm text-muted-foreground", className)} {...props} />;
}

Input Component

// components/ui/input.tsx
import { cn } from "@/lib/utils";

interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {}

export function Input({ className, ...props }: InputProps) {
  return (
    <input
      className={cn(
        "flex h-10 w-full rounded-md border border-border bg-transparent px-3 py-2 text-sm",
        "placeholder:text-muted-foreground",
        "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
        "disabled:cursor-not-allowed disabled:opacity-50",
        className,
      )}
      {...props}
    />
  );
}

Layout Patterns

Sticky Header + Scrollable Content

<div className="flex h-screen flex-col">
  <header className="sticky top-0 z-50 border-b border-border bg-background/80 backdrop-blur-sm">
    <nav className="mx-auto flex h-16 max-w-7xl items-center px-4">
      {/* nav content */}
    </nav>
  </header>
  <main className="flex-1 overflow-y-auto">
    {children}
  </main>
</div>

Sidebar Layout

<div className="flex h-screen">
  <aside className="hidden w-64 shrink-0 border-r border-border bg-muted/40 lg:block">
    {/* sidebar */}
  </aside>
  <main className="flex-1 overflow-y-auto p-6">
    {children}
  </main>
</div>

Centered Content

<div className="flex min-h-screen items-center justify-center">
  <div className="w-full max-w-md space-y-6 p-4">
    {/* login form, etc. */}
  </div>
</div>

Typography

{/* Heading hierarchy */}
<h1 className="text-4xl font-bold tracking-tight">Page title</h1>
<h2 className="text-2xl font-semibold tracking-tight">Section</h2>
<h3 className="text-xl font-semibold">Subsection</h3>

{/* Body text */}
<p className="leading-7 text-muted-foreground">Body copy with relaxed leading.</p>
<p className="text-sm text-muted-foreground">Small helper text.</p>

{/* Prose (for markdown/CMS content) */}
<article className="prose prose-gray dark:prose-invert max-w-none">
  {/* rendered markdown */}
</article>

The @tailwindcss/typography plugin provides the prose class for styling rendered HTML/markdown content.

Animation Utilities

{/* Built-in animations */}
<div className="animate-spin" />     {/* loading spinner */}
<div className="animate-pulse" />    {/* skeleton loader */}
<div className="animate-bounce" />   {/* attention indicator */}

{/* Transition utilities */}
<button className="transition-colors duration-200 hover:bg-primary">
  Smooth hover
</button>

<div className="transition-all duration-300 ease-out hover:scale-105 hover:shadow-lg">
  Card hover effect
</div>

For complex animations, use Framer Motion instead of Tailwind animation utilities.

Anti-Patterns

Anti-PatternCorrect Approach
@apply for component stylesExtract a React component
Raw color scales everywhere (bg-blue-500)Define semantic tokens (bg-primary)
Duplicating class strings across filesExtract a component or use CVA
className="..." with 20+ utilities on one lineBreak across multiple lines or use cn() with grouped strings
Inline style={} for spacing/colorsUse Tailwind utilities
Custom CSS file for simple layoutsCompose with flex/grid utilities
Forgetting dark: variantsAlways pair light and dark styles
Not using twMerge for overridable componentsAlways use cn() for components that accept className

For spacing, sizing, color, and typography reference tables, see reference/utility-reference.md. For form styling, table patterns, and advanced layout techniques, see reference/component-patterns.md.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.