Skip to main content

react-component-development

Guide for creating React components using HeroUI in the DEVS platform. Use this when asked to create new UI components, pages, or modify existing React code.

소스 정보

저장소
codename-co/devs
최근 소스 활동
2026년 1월 16일 23:22
감지된 SKILL.md 언어
영어
스타
53
포크
2

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
react-component-development
description
Guide for creating React components using HeroUI in the DEVS platform. Use this when asked to create new UI components, pages, or modify existing React code.
# React Component Development for DEVS When creating React components in the DEVS platform, follow these patterns using HeroUI and project conventions. ## Component Structure Components are organized as: - `src/components/` - Shared/reusable components - `src/pages/` - Route-based page components - `src/features/{feature}/components/` - Feature-specific components ## Component Template ```tsx import { useState, useCallback } from 'react' import { Button, Card, CardBody, Spinner } from '@heroui/react' import { useTranslation } from 'react-i18next' import { Icon } from '@/components/Icon' interface MyComponentProps { title: string onAction?: () => void isDisabled?: boolean children?: React.ReactNode } export function MyComponent({ title, onAction, isDisabled = false, children, }: MyComponentProps) { const { t } = useTranslation() const [isLoading, setIsLoading] = useState(false) const handleAction = useCallback(async () => { if (!onAction) return setIsLoading(true) try { await onAction() } finally { setIsLoading(false) } }, [onAction]) return ( <Card> <CardBody className="gap-4"> <h2 className="text-lg font-semibold">{title}</h2> {children} <Button color="primary" isDisabled={isDisabled || isLoading} isLoading={isLoading} onPress={handleAction} > {t('common.submit')} </Button> </CardBody> </Card> ) } ``` ## HeroUI Component Usage Always import from `@heroui/react`: ```tsx import { Button, Card, CardBody, CardHeader, CardFooter, Modal, ModalContent, ModalHeader, ModalBody, ModalFooter, Input, Textarea, Select, SelectItem, Chip, Badge, Avatar, Spinner, Progress, Tooltip, Popover, PopoverTrigger, PopoverContent, Dropdown, DropdownTrigger, DropdownMenu, DropdownItem, Table, TableHeader, TableBody, TableColumn, TableRow, TableCell, Tabs, Tab, Accordion, AccordionItem, Divider, Switch, Checkbox, } from '@heroui/react' ``` ## Critical Patterns ### 1. Internationalization (i18n) All user-facing strings must be translatable: ```tsx import { useTranslation } from 'react-i18next' function MyComponent() { const { t } = useTranslation() return <Button>{t('agents.create')}</Button> } ``` Use curly apostrophe `'` (not `'`) in translation strings. ### 2. Path Aliases Always use `@/` prefix for imports: ```tsx // ✅ Correct import { Agent } from '@/types' import { Icon } from '@/components/Icon' // ❌ Wrong import { Agent } from '../../types' ``` ### 3. Event Handlers Use HeroUI's `onPress` instead of `onClick` for buttons: ```tsx // ✅ Correct <Button onPress={handleClick}>Click me</Button> // ❌ Avoid for HeroUI buttons <Button onClick={handleClick}>Click me</Button> ``` ### 4. Loading States Use HeroUI's built-in loading props: ```tsx <Button isLoading={isLoading} isDisabled={isLoading}> Submit </Button> <Spinner size="sm" /> ``` ### 5. Icons Use the project's Icon component with Lucide icons: ```tsx import { Icon } from '@/components/Icon' <Icon name="Plus" size={20} /> <Icon name="Settings" className="text-default-500" /> ``` ### 6. Styling Use Tailwind CSS classes. Common patterns: ```tsx // Flex layouts <div className="flex items-center gap-2"> <div className="flex flex-col gap-4"> // Spacing <div className="p-4 m-2"> <div className="px-4 py-2"> // Text styling <span className="text-sm text-default-500"> <h2 className="text-lg font-semibold"> ``` ## Store Integration Use Zustand stores with selectors for performance: ```tsx import { useAgentStore } from '@/stores/agentStore' function AgentList() { // ✅ Good - select only what you need const agents = useAgentStore((state) => state.agents) const isLoading = useAgentStore((state) => state.isLoading) // ❌ Bad - subscribes to entire store const store = useAgentStore() } ``` ## Modal Pattern ```tsx import { Modal, ModalContent, ModalHeader, ModalBody, ModalFooter, Button, useDisclosure, } from '@heroui/react' function MyModal() { const { isOpen, onOpen, onOpenChange } = useDisclosure() return ( <> <Button onPress={onOpen}>Open Modal</Button> <Modal isOpen={isOpen} onOpenChange={onOpenChange}> <ModalContent> {(onClose) => ( <> <ModalHeader>Title</ModalHeader> <ModalBody>Content</ModalBody> <ModalFooter> <Button variant="light" onPress={onClose}> Cancel </Button> <Button color="primary" onPress={onClose}> Confirm </Button> </ModalFooter> </> )} </ModalContent> </Modal> </> ) } ``` ## Testing Component tests go in `src/test/components/`: ```tsx import { render, screen } from '@testing-library/react' import { describe, it, expect } from 'vitest' import { MyComponent } from '@/components/MyComponent' describe('MyComponent', () => { it('renders title correctly', () => { render(<MyComponent title="Test Title" />) expect(screen.getByText('Test Title')).toBeInTheDocument() }) }) ```
GitHub에서 보기