
Security News
PolinRider: North Korea-Linked Supply Chain Campaign Expands Across Open Source Ecosystems
PolinRider expands across npm, Packagist, Go modules, and Chrome extensions, using hidden loaders to target developer environments.
@huaiyou/ui
Advanced tools
共享的 React UI 组件库,提供常用的基础组件。
pnpm add @huaiyou/ui react react-dom
import { Button, Card, Input } from '@huaiyou/ui';
function App() {
return (
<Card title="Welcome">
<Input label="Email" placeholder="Enter your email" />
<Button variant="primary">Submit</Button>
</Card>
);
}
可定制的按钮组件,支持多种样式和尺寸。
import { Button } from '@huaiyou/ui';
// 基础用法
<Button>Default Button</Button>
// 不同样式
<Button variant="primary">Primary</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="danger">Danger</Button>
// 不同尺寸
<Button size="small">Small</Button>
<Button size="medium">Medium</Button>
<Button size="large">Large</Button>
// 加载状态
<Button loading>Loading...</Button>
// 禁用状态
<Button disabled>Disabled</Button>
Props:
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| variant | 'primary' | 'secondary' | 'danger' | 'primary' | 按钮样式 |
| size | 'small' | 'medium' | 'large' | 'medium' | 按钮尺寸 |
| loading | boolean | false | 加载状态 |
| disabled | boolean | false | 禁用状态 |
内容容器组件,支持标题和额外操作。
import { Card, Button } from '@huaiyou/ui';
// 基础用法
<Card title="Card Title">
<p>Card content goes here</p>
</Card>
// 带额外操作
<Card
title="User Profile"
extra={<Button size="small">Edit</Button>}
>
<p>User information...</p>
</Card>
// 无标题
<Card>
<p>Simple card without title</p>
</Card>
Props:
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| title | string | - | 卡片标题 |
| extra | ReactNode | - | 右上角额外操作 |
| children | ReactNode | - | 卡片内容 |
| className | string | - | 自定义类名 |
表单输入组件,支持标签、错误提示和辅助文本。
import { Input } from '@huaiyou/ui';
import { useState } from 'react';
function Form() {
const [value, setValue] = useState('');
const [error, setError] = useState('');
return (
<>
{/* 基础用法 */}
<Input label="Username" value={value} onChange={(e) => setValue(e.target.value)} />
{/* 带错误提示 */}
<Input label="Email" type="email" error="Invalid email format" />
{/* 带辅助文本 */}
<Input label="Password" type="password" helperText="Must be at least 8 characters" />
{/* 占位符 */}
<Input label="Phone" placeholder="Enter your phone number" />
</>
);
}
Props:
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| label | string | - | 输入框标签 |
| error | string | - | 错误提示信息 |
| helperText | string | - | 辅助文本 |
| className | string | - | 自定义类名 |
继承所有原生 <input> 属性。
组件使用 Tailwind CSS 类名,确保你的项目已配置 Tailwind:
// tailwind.config.js
module.exports = {
content: ['./src/**/*.{js,ts,jsx,tsx}', './node_modules/@huaiyou/ui/dist/**/*.{js,mjs}'],
theme: {
extend: {},
},
plugins: [],
};
通过 className 属性添加自定义样式:
<Button className="my-custom-button">
Custom Button
</Button>
<Card className="shadow-2xl rounded-xl">
Custom Card
</Card>
/* 全局样式文件 */
.my-custom-button {
@apply bg-gradient-to-r from-purple-500 to-pink-500;
}
import { Button, Input, Card } from '@huaiyou/ui';
import { useState } from 'react';
function LoginForm() {
const [formData, setFormData] = useState({
email: '',
password: '',
});
const [errors, setErrors] = useState<Record<string, string>>({});
const [loading, setLoading] = useState(false);
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setLoading(true);
try {
// 验证
const newErrors: Record<string, string> = {};
if (!formData.email) {
newErrors.email = 'Email is required';
}
if (!formData.password) {
newErrors.password = 'Password is required';
}
if (Object.keys(newErrors).length > 0) {
setErrors(newErrors);
return;
}
// 提交表单
await login(formData);
} finally {
setLoading(false);
}
};
return (
<Card title="Login">
<form onSubmit={handleSubmit} className="space-y-4">
<Input
label="Email"
type="email"
value={formData.email}
onChange={(e) => setFormData({ ...formData, email: e.target.value })}
error={errors.email}
/>
<Input
label="Password"
type="password"
value={formData.password}
onChange={(e) => setFormData({ ...formData, password: e.target.value })}
error={errors.password}
/>
<Button type="submit" loading={loading} className="w-full">
Login
</Button>
</form>
</Card>
);
}
import { Button, Card } from '@huaiyou/ui';
function Dashboard() {
return (
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<Card title="Total Users" extra={<Button size="small">View All</Button>}>
<div className="text-4xl font-bold">1,234</div>
<p className="text-gray-500">+12% from last month</p>
</Card>
<Card title="Revenue" extra={<Button size="small">Details</Button>}>
<div className="text-4xl font-bold">$12,345</div>
<p className="text-gray-500">+8% from last month</p>
</Card>
<Card title="Active Projects" extra={<Button size="small">Manage</Button>}>
<div className="text-4xl font-bold">42</div>
<p className="text-gray-500">5 completed this week</p>
</Card>
</div>
);
}
src/ 目录创建组件文件src/index.ts 中导出// src/NewComponent.tsx
import React from 'react';
export interface NewComponentProps {
title: string;
children?: React.ReactNode;
}
export function NewComponent({ title, children }: NewComponentProps) {
return (
<div>
<h2>{title}</h2>
{children}
</div>
);
}
# 运行测试
pnpm test
# 监听模式
pnpm test:watch
# 测试覆盖率
pnpm test:coverage
# UI 模式
pnpm test:ui
# 构建组件库
pnpm build
# 开发模式(stub)
pnpm dev
所有组件都有完整的测试覆盖,使用 Vitest + React Testing Library。
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { Button } from './Button';
it('should handle click events', async () => {
const handleClick = vi.fn();
render(<Button onClick={handleClick}>Click me</Button>);
await userEvent.click(screen.getByText('Click me'));
expect(handleClick).toHaveBeenCalledTimes(1);
});
欢迎添加新组件或改进现有组件!请确保:
MIT
FAQs
Shared React UI component library
The npm package @huaiyou/ui receives a total of 4 weekly downloads. As such, @huaiyou/ui popularity was classified as not popular.
We found that @huaiyou/ui demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
PolinRider expands across npm, Packagist, Go modules, and Chrome extensions, using hidden loaders to target developer environments.

Security News
Open source attacks are accelerating as AI coding agents pull in dependencies faster, with less human review.

Research
/Security News
Malicious Chrome and Firefox extensions posed as free VPNs while stealing clipboard data through later extension updates.