(
+ (
+ {
+ variant = 'solid',
+ size = 'md',
+ loading = false,
+ icon,
+ iconPosition = 'left',
+ fullWidth = false,
+ children,
+ className,
+ ...rest
+ },
+ ref,
+ ) => {
+ const cls = [styles.btn, LOADING_MAP[variant], className]
+ .filter(Boolean)
+ .join(' ')
+
+ return (
+
+ )
+ },
+)
+
+Button.displayName = 'Button'
diff --git a/src/components/Button/index.md b/src/components/Button/index.md
new file mode 100644
index 0000000..07f1ce6
--- /dev/null
+++ b/src/components/Button/index.md
@@ -0,0 +1,77 @@
+---
+nav: 组件
+group: 通用
+title: Button 按钮
+description: 用于触发操作的按钮组件。
+---
+
+## 代码演示
+
+### 基础用法
+
+```tsx | pure
+/**
+ * title: 基础按钮
+ * description: 使用 `variant` 切换按钮风格。
+ */
+import { Button } from '@nova/ui/components/Button'
+
+export default () => (
+
+)
+```
+
+### 变体
+
+```tsx | pure
+/**
+ * title: 变体
+ * description: 四种按钮风格。
+ */
+import { Button } from '@nova/ui/components/Button'
+
+export default () => (
+
+
+
+
+
+
+)
+```
+
+### 尺寸
+
+```tsx | pure
+/**
+ * title: 尺寸
+ */
+import { Button } from '@nova/ui/components/Button'
+
+export default () => (
+
+
+
+
+
+
+
+)
+```
+
+### 加载状态
+
+```tsx | pure
+/**
+ * title: 加载状态
+ */
+import { Button } from '@nova/ui/components/Button'
+
+export default () =>
+```
+
+## API
+
+
diff --git a/src/components/Button/index.ts b/src/components/Button/index.ts
new file mode 100644
index 0000000..25e893d
--- /dev/null
+++ b/src/components/Button/index.ts
@@ -0,0 +1,4 @@
+import { Button } from './Button'
+export type { ButtonProps } from './Button'
+export default Button
+export { Button }
diff --git a/src/index.ts b/src/index.ts
new file mode 100644
index 0000000..dd6b946
--- /dev/null
+++ b/src/index.ts
@@ -0,0 +1,2 @@
+export { Button } from './components/Button'
+export type { ButtonProps } from './components/Button'
diff --git a/test-setup.ts b/test-setup.ts
new file mode 100644
index 0000000..c44951a
--- /dev/null
+++ b/test-setup.ts
@@ -0,0 +1 @@
+import '@testing-library/jest-dom'
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000..1ed222f
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,28 @@
+{
+ "compilerOptions": {
+ "target": "ES2020",
+ "module": "ESNext",
+ "moduleResolution": "bundler",
+ "jsx": "react-jsx",
+ "strict": true,
+ "declaration": true,
+ "declarationMap": true,
+ "sourceMap": true,
+ "outDir": "dist",
+ "rootDir": "src",
+ "allowSyntheticDefaultImports": true,
+ "esModuleInterop": true,
+ "skipLibCheck": true,
+ "forceConsistentCasingInFileNames": true,
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "noEmit": true,
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
+ "baseUrl": ".",
+ "paths": {
+ "@nova/ui/*": ["src/components/*"]
+ }
+ },
+ "include": ["src", "docs", ".dumirc.ts", ".fatherrc.ts"],
+ "exclude": ["node_modules", "dist"]
+}
diff --git a/vitest.config.ts b/vitest.config.ts
new file mode 100644
index 0000000..5eae4e2
--- /dev/null
+++ b/vitest.config.ts
@@ -0,0 +1,17 @@
+import { defineConfig } from 'vitest/config'
+
+export default defineConfig({
+ test: {
+ environment: 'jsdom',
+ globals: true,
+ setupFiles: ['./test-setup.ts'],
+ include: ['src/**/*.test.{ts,tsx}'],
+ coverage: {
+ provider: 'v8',
+ include: ['src/components/**/*.tsx'],
+ thresholds: {
+ functions: 80,
+ },
+ },
+ },
+})