Agent skill

atomic-components

Create atomic components (atoms) - basic, reusable UI building blocks following React/TypeScript best practices with Tailwind v4 styling. Use when creating fundamental UI elements like buttons, inputs, labels, icons, or other single-responsibility components. Triggers on requests like "create a button component", "add an input atom", "build a reusable icon wrapper", or "create atomic UI elements".

Stars 0
Forks 0

Install this agent skill to your Project

npx add-skill https://github.com/felixAnhalt/spotify-playlist-extractor/tree/main/.opencode/skill/atomic-components

SKILL.md

Atomic Components

Create atomic components (atoms) - the fundamental building blocks of your UI with proper TypeScript interfaces and Tailwind v4 styling.

Component Structure Template

typescript
// ComponentName.tsx
// Brief description of component purpose

// always named imports from React
import { ReactNode, ReactElement, useState } from "react";

export interface ComponentNameProps {
  children: ReactNode;
  variant?: "primary" | "secondary"; // Variant types
  size?: "small" | "medium" | "large"; // Size types
  disabled?: boolean;
  // Additional props
}

/**
 * ComponentName component.
 * Detailed description of what it does.
 */
export const ComponentName = ({
  children,
  variant = "primary",
  size = "medium",
  disabled = false,
}: ComponentNameProps): ReactElement => {
  // 1. Local state (if needed)
  const [isActive, setIsActive] = useState(false);

  // 2. Event handlers (if needed)
  const handleClick = (): void => {
    if (!disabled) setIsActive(!isActive);
  };

  // 3. Computed variant/size classes
  const getVariantClasses = (): string => {
    switch (variant) {
      case "secondary":
        return "bg-secondary-500 text-white";
      case "primary":
      default:
        return "bg-primary-500 text-white";
    }
  };

  const getSizeClasses = (): string => {
    switch (size) {
      case "small":
        return "px-3 py-1 text-sm";
      case "large":
        return "px-6 py-3 text-lg";
      case "medium":
      default:
        return "px-4 py-2 text-base";
    }
  };

  // 4. Compose final classes
  const baseClasses = `
    rounded-lg transition-all duration-200
    ${disabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer"}
    ${getVariantClasses()}
    ${getSizeClasses()}
  `;

  return (
    <div className={baseClasses} onClick={handleClick}>
      {children}
    </div>
  );
}

export default ComponentName;

What Are Atoms?

Atoms are the basic building blocks of your UI - fundamental, reusable components with single responsibility.

Characteristics:

  • Single responsibility (one thing, well)
  • No dependencies on other components
  • Highly reusable across the application
  • Minimal props (typically 3-7)
  • Pure presentational logic

Common Examples:

  • Button with variants (primary, secondary, disabled states)
  • Input field with validation states
  • Typography components (Heading, Paragraph, Label)
  • Icon wrapper
  • Card container
  • Container layout

Not Atoms (compose atoms instead):

  • FormField (Label + Input + Error) → compose atoms into a molecule
  • SearchBox (Input + Button) → compose atoms into a molecule
  • NavigationBar (multiple atoms + logic) → compose atoms into an organism

Code Style Requirements

Import Order

  1. React (named imports)
  2. Third-party libraries
  3. Router/navigation
  4. Local API/utils
  5. Components
  6. Context/state
typescript
import { ReactNode, useState } from "react";
import { motion } from "framer-motion";
import { useNavigate } from "react-router-dom";
import { formatDate } from "../utils/dates";
import { useAuth } from "../context/AuthContext";

Type Definitions

  • Always export interface for props
  • Use explicit types (string | null, never any)
  • Union types for variants/states
  • Optional props with ?
typescript
export interface ButtonProps {
  children: ReactNode;
  onClick?: () => void;
  variant?: "primary" | "secondary" | "spotify";
  size?: "small" | "medium" | "large";
  disabled?: boolean;
  type?: "button" | "submit" | "reset";
  ariaLabel?: string;
}

Naming Conventions

  • PascalCase: Components, interfaces
  • camelCase: Functions, variables, props
  • UPPER_SNAKE_CASE: Constants
  • Prop naming: onClick, isActive, hasError (verb prefixes for booleans)

Component Structure Order

typescript
// 1. Props interface
export interface ComponentProps { }

// 2. Component function with JSDoc
/**
 * ComponentName brief description.
 * Longer description if needed.
 */
export const ComponentName = (props: ComponentProps): ReactElement => {
  // 3. State declarations
  const [state, setState] = useState();
  
  // 4. Event handlers
  const handleEvent = (): void => { };
  
  // 5. Computed values/classes
  const classes = computeClasses();
  
  // 6. Return JSX
  return <div>{children}</div>;
}

// 7. Export
export default ComponentName;

Styling with Tailwind v4

Core Principles

  • Use Tailwind classes, avoid inline styles
  • Group related classes together
  • Use template literals for conditional classes
  • Extract repeated patterns into helper functions

Pattern: Variant Classes

typescript
const getVariantClasses = (): string => {
  switch (variant) {
    case "spotify":
      return "bg-accent-500 text-primary-900 border-accent-700";
    case "secondary":
      return "bg-secondary-200 text-primary-900 border-secondary-700";
    case "primary":
    default:
      return "bg-primary-500 text-primary-50 border-primary-700";
  }
};

Pattern: Conditional Styling

typescript
const baseClasses = `
  rounded-lg font-bold transition-all duration-200
  ${disabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer hover:scale-105"}
  ${isActive && "bg-active-500"}
  ${getVariantClasses()}
  ${getSizeClasses()}
`;

Avoid v3 Patterns

Tailwind v4 Guidelines (vs v3):

  • Avoid v3-era abstraction patterns
  • Don't use @apply as a component or styling system (escape hatch only)
  • Don't use theme() — Tailwind v4 exposes design tokens via CSS variables
  • Don't over-invest in tailwind.config.js; v4 is CSS-first, config is optional

Preferred v4 approach:

  • Use utility classes directly in markup
  • Use React components for reuse, not CSS abstraction
  • Use CSS variables for theming when needed

Rule of thumb: If you're writing CSS to avoid utilities, you're fighting Tailwind v4.

Error Handling & Accessibility

Optional Chaining

typescript
const user = data?.user?.name ?? "Guest";

User-Facing Errors

typescript
try {
  await performAction();
} catch (err: any) {
  alert(`Error: ${err.message ?? "Something went wrong"}`);
}

Accessibility Props

typescript
<button
  type={type}
  onClick={onClick}
  disabled={disabled}
  aria-label={ariaLabel}
  aria-pressed={isPressed}
>
  {children}
</button>

Quick Reference

File Naming & Organization

  • ComponentName.tsx (PascalCase)
  • Place in components/ or components/atoms/ directory
  • One component per file

Component Checklist

  • Props interface exported
  • Default prop values set
  • JSDoc comment present
  • Tailwind v4 classes used
  • Accessibility props included
  • Error boundaries where needed
  • Type safety (no any except external data)

Method Size Limit

Keep logic methods under 20 lines. Extract helpers if needed:

typescript
// Bad: 30-line render method with complex logic
export const Component = () => {
  return (
    <div>
      {/* 30 lines of conditional rendering */}
    </div>
  );
}

// Good: Extracted to helper
export const Component = () => {
  return <div>{renderContent()}</div>;
}

function renderContent(): ReactElement {
  // Complex logic extracted
}

Assets

Component template available at assets/templates/AtomicComponent.tsx

Expand your agent's capabilities with these related and highly-rated skills.

felixAnhalt/spotify-playlist-extractor

frontend-design

Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, artifacts, posters, or applications (examples include websites, landing pages, dashboards, React components, HTML/CSS layouts, or when styling/beautifying any web UI). Generates creative, polished code and UI design that avoids generic AI aesthetics.

0 0
Explore
felixAnhalt/spotify-playlist-extractor

skill-creator

Guide for creating effective skills. This skill should be used when users want to create a new skill (or update an existing skill) that extends Claude's capabilities with specialized knowledge, workflows, or tool integrations.

0 0
Explore
felixAnhalt/opencode-worktree-session

add-new-file

Guide for adding new files to this codebase while respecting architectural principles including Separation of Concerns, Common Closure Principle, small composable functions (max 20 lines), and externalizing constants. Use when creating new modules, utilities, or any new source files in the project.

26 0
Explore
felixAnhalt/opencode-worktree-session

skill-creator

Guide for creating effective skills. This skill should be used when users want to create a new skill (or update an existing skill) that extends Claude's capabilities with specialized knowledge, workflows, or tool integrations.

26 0
Explore
mattpocock/skills

obsidian-vault

Search, create, and manage notes in the Obsidian vault with wikilinks and index notes. Use when user wants to find, create, or organize notes in Obsidian.

111,310 9,758
Explore
mattpocock/skills

handoff

Compact the current conversation into a handoff document for another agent to pick up.

111,310 9,758
Explore

Didn't find tool you were looking for?

Be as detailed as possible for better results