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".
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
// 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
- React (named imports)
- Third-party libraries
- Router/navigation
- Local API/utils
- Components
- Context/state
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, neverany) - Union types for variants/states
- Optional props with
?
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
// 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
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
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
@applyas 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
const user = data?.user?.name ?? "Guest";
User-Facing Errors
try {
await performAction();
} catch (err: any) {
alert(`Error: ${err.message ?? "Something went wrong"}`);
}
Accessibility Props
<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/orcomponents/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
anyexcept external data)
Method Size Limit
Keep logic methods under 20 lines. Extract helpers if needed:
// 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
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
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.
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.
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.
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.
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.
handoff
Compact the current conversation into a handoff document for another agent to pick up.
Didn't find tool you were looking for?