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.
安装与使用
请根据来源仓库和你的 AI 工具说明安装此技能。先阅读技能文件和依赖要求,再添加到工作流。
查看来源 ↗使用指南技能说明
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
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:
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:
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:
// ✅ 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:
// ✅ 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:
<Button isLoading={isLoading} isDisabled={isLoading}>
Submit
</Button>
<Spinner size="sm" />
5. Icons
Use the project's Icon component with Lucide icons:
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:
// 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:
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
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/:
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()
})
})
使用示例
查看来源仓库中的使用示例与配置说明。
查看来源 ↗来源历史
- 收录时间
- 2026-01-20
- 索引更新时间
- 2026-02-02
- Branch
- main
收录与同步日期属于本站记录。源码修改历史请查看来源仓库。
GitHub ↗chat Comments (0)
Sign in to join the discussion and leave a comment.
No comments yet. Be the first to share your thoughts!