react-composition

from front-depiction/claude-setup

Reusable Claude Code configuration for Effect TypeScript projects with specialized agents and skills

10 stars4 forksUpdated Jan 19, 2026
npx skills add https://github.com/front-depiction/claude-setup --skill react-composition

SKILL.md

React Composition Skill

Build React UIs using compositional patterns, Effect Atom for state management, and the component module pattern. Use this skill when creating React applications that integrate with Effect's ecosystem.

When to Use This Skill

  • Building React components that integrate with Effect Atom state
  • Refactoring components away from boolean prop anti-patterns
  • Implementing complex UIs through composition of simple pieces
  • Creating reusable component libraries with flexible APIs
  • Managing shared state across multiple React components
  • Lifting state to appropriate levels in component trees

Core Principles

1. Composition over Configuration

Build complex UIs from simple, composable pieces rather than configuring behavior through props.

Anti-Pattern: Boolean Props

// L WRONG - Configuration through boolean props
interface FormProps {
  isUpdate?: boolean
  hideWelcome?: boolean
  showEmail?: boolean
  redirectOnSuccess?: boolean
  enableValidation?: boolean
}

function UserForm({
  isUpdate,
  hideWelcome,
  showEmail,
  redirectOnSuccess,
  enableValidation
}: FormProps) {
  return (
    <form>
      {!hideWelcome && <WelcomeMessage />}
      <NameField />
      {showEmail && <EmailField />}
      <button type="submit">
        {isUpdate ? "Update" : "Create"}
      </button>
    </form>
  )
}

// Usage becomes unreadable
<UserForm
  isUpdate
  hideWelcome
  showEmail
  redirectOnSuccess
/>

Correct Pattern: Composition

//  CORRECT - Compose specific forms from atomic pieces
export namespace UserForm {
  export const Frame: React.FC<{ children: React.ReactNode }> =
    ({ children }) => <form className="user-form">{children}</form>

  export const WelcomeMessage: React.FC = () =>
    <div className="welcome">Welcome!</div>

  export const NameField: React.FC = () =>
    <input name="name" placeholder="Name" />

  export const EmailField: React.FC = () =>
    <input type="email" name="email" placeholder="Email" />

  export const SubmitButton: React.FC<{ children: React.ReactNode }> =
    ({ children }) => <button type="submit">{children}</button>
}

// Create specific forms through composition
function CreateUserForm() {
  return (
    <UserForm.Frame>
      <UserForm.WelcomeMessage />
      <UserForm.NameField />
      <UserForm.EmailField />
      <UserForm.SubmitButton>Create</UserForm.SubmitButton>
    </UserForm.Frame>
  )
}

function UpdateUserForm() {
  return (
    <UserForm.Frame>
      <UserForm.NameField />
      <UserForm.SubmitButton>Update</UserForm.SubmitButton>
    </UserForm.Frame>
  )
}

// Usage is clear and explicit (in JSX context):
// <CreateUserForm />
// <UpdateUserForm />

2. Component Module Pattern

Treat components like Effect modules with namespace imports and exported sub-components.

// components/Composer/Composer.tsx
import * as React from "react"

/**
 * Composer state interface
 */
export interface ComposerState {
  readonly content: string
  readonly attachments: ReadonlyArray<Attachment>
  readonly isSubmitting: boolean
}

/**
 * Composer context for sharing state
 */
const ComposerContext = React.createContext<ComposerState | null>(null)

/**
 * Hook to access composer state
 * @throws when used outside Provider
 */
export const useComposer = (): ComposerState => {
  const context = React.useContext(ComposerContext)
  if (!context) {
    throw new Error("useComposer must be used within Composer.Provider")
  }
  return context
}

/**
 * Provider component for composer state
 */
export const Provider: React.FC<{
  children: React.ReactNode
  state: ComposerState
}> = ({ children, state }) => (
  <ComposerContext.Provider value={state}>
    {children}
  </ComposerContext.Provider>
)

/**
 * Frame component for layout
 */
export const Frame: React.FC<{
  children: React.ReactNode
}> = ({ children }) => (
  <div className="composer-frame">
    {children}
  </div>
)

/**
 * Input component for message content
 */
export const Input: React.FC = () => {
  const { content } = useComposer()
  return (
    <textarea
      value={content}
      className="composer-input"
      placeholder="Type a message..."
    />
  )
}

/**
 * Footer component for actions
 */
export const Footer: React.FC<{
  children: React.ReactNode
}> = ({ children }) => (
  <div className="composer-footer">
    {children}
  </div>
)

/**
 * Submit button component
 */
export const Submit: React.FC = () => {
  const { isSubmitting } = useComposer()
  return (
    <button
      type="submit"
      disabled={isSubmitting}
      className="composer-submit"
    >
      {isSubmitting ? "Sending..." : "Send"}
    </button>
  )
}

Usage with Namespace Import

import * as Composer from "@/components/Composer"

function MessageComposer() {
  const [state, setState] = useState<Composer.ComposerState>({
    content: "",
    attachments: [],
    isSubmitting: false
  })

  return (
    <Composer.Provider state={state}>
      <Comp

...
Read full content

Repository Stats

Stars10
Forks4