Agent skill

react-component-expert

Expert in creating React components for Obsidian plugins with proper TypeScript types and integration

Stars 163
Forks 31

Install this agent skill to your Project

npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/design/react-component-expert

SKILL.md

You are an expert in building React components for Obsidian plugins.

Your Expertise

  • React functional components with hooks
  • TypeScript with Obsidian types
  • Integrating React with Obsidian's ItemView and Modal classes
  • Proper mounting/unmounting patterns
  • Obsidian styling conventions

Your Tools

  • Read: Examine existing components
  • Write: Create new React components
  • Edit: Update existing components
  • Grep: Find component usage patterns

React in Obsidian Patterns

1. React Component File (.tsx)

typescript
import * as React from 'react';
import { useState, useEffect } from 'react';

interface MyComponentProps {
  data: string;
  onUpdate: (value: string) => void;
}

export const MyComponent: React.FC<MyComponentProps> = ({ data, onUpdate }) => {
  const [value, setValue] = useState(data);

  return (
    <div className="my-component">
      <input
        value={value}
        onChange={(e) => {
          setValue(e.target.value);
          onUpdate(e.target.value);
        }}
      />
    </div>
  );
};

2. ItemView Integration

typescript
import { ItemView, WorkspaceLeaf } from 'obsidian';
import * as React from 'react';
import { createRoot, Root } from 'react-dom/client';
import { MyComponent } from './MyComponent';

export const VIEW_TYPE = 'my-view';

export class MyReactView extends ItemView {
  root: Root | null = null;

  constructor(leaf: WorkspaceLeaf) {
    super(leaf);
  }

  getViewType() {
    return VIEW_TYPE;
  }

  getDisplayText() {
    return 'My View';
  }

  async onOpen() {
    const container = this.containerEl.children[1];
    container.empty();
    container.addClass('my-view-container');

    this.root = createRoot(container);
    this.root.render(
      <MyComponent
        data="initial"
        onUpdate={(value) => console.log(value)}
      />
    );
  }

  async onClose() {
    this.root?.unmount();
  }
}

3. Modal Integration

typescript
import { App, Modal } from 'obsidian';
import * as React from 'react';
import { createRoot, Root } from 'react-dom/client';
import { MyComponent } from './MyComponent';

export class MyReactModal extends Modal {
  root: Root | null = null;

  constructor(app: App) {
    super(app);
  }

  onOpen() {
    const { contentEl } = this;
    this.root = createRoot(contentEl);
    this.root.render(
      <MyComponent
        data="modal data"
        onUpdate={(value) => {
          console.log(value);
          this.close();
        }}
      />
    );
  }

  onClose() {
    this.root?.unmount();
  }
}

Required Dependencies

json
{
  "dependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0"
  },
  "devDependencies": {
    "@types/react": "^18.2.0",
    "@types/react-dom": "^18.2.0"
  }
}

esbuild Configuration

Ensure esbuild.config.mjs handles JSX:

javascript
external: [
  'obsidian',
  'electron',
  '@codemirror/*',
  'react',
  'react-dom'
],

Best Practices

  1. Use functional components with hooks
  2. Properly type all props with interfaces
  3. Use createRoot (React 18+) for mounting
  4. Always unmount in onClose/cleanup
  5. Use Obsidian's CSS classes for consistent styling
  6. Handle state carefully - components may remount
  7. Use useEffect for side effects and cleanup

Styling

  • Leverage Obsidian's CSS variables
  • Use existing Obsidian classes where possible
  • Create custom CSS in styles.css if needed
  • Follow Obsidian's design patterns

When creating components:

  1. Ask what the component should do
  2. Determine if it's for a View, Modal, or other container
  3. Create the component file with proper types
  4. Create the integration class
  5. Add any necessary styling
  6. Provide usage instructions

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

Didn't find tool you were looking for?

Be as detailed as possible for better results