Đóng Góp
Cảm ơn bạn đã quan tâm đến việc đóng góp cho Galaxy UI! Hướng dẫn này sẽ giúp bạn bắt đầu.
Bắt Đầu
Yêu Cầu
- Node.js: 18.0.0 trở lên
- Package Manager: npm, pnpm, yarn, hoặc bun
- Git: Để quản lý phiên bản
Fork và Clone
Fork repository
Truy cập github.com/galaxy-nebula/galaxy-design và nhấp "Fork"
Clone fork của bạn
bashgit clone https://github.com/TEN_CUA_BAN/galaxy-design.git cd galaxy-designThêm upstream remote
bashgit remote add upstream https://github.com/galaxy-nebula/galaxy-design.git
Cài Đặt Dependencies
# Cài đặt dependencies
npm install
# hoặc
bun installCấu Trúc Dự Án
galaxy-design/
├── packages/
│ ├── cli/ # Mã nguồn công cụ CLI
│ │ ├── src/
│ │ │ ├── commands/ # Các lệnh CLI (init, add)
│ │ │ ├── utils/ # Các hàm tiện ích
│ │ │ └── registries/ # Registry của component
│ │ └── package.json
│ │
│ ├── react/ # Component React
│ │ └── src/components/
│ │
│ ├── vue/ # Component Vue
│ │ └── src/components/
│ │
│ └── angular/ # Component Angular
│ └── src/components/
│
├── docs/ # Tài liệu VitePress
│ ├── .vitepress/
│ ├── guide/
│ ├── components/
│ └── vi/ # Tài liệu tiếng Việt
│
└── examples/ # Các dự án ví dụ
├── react-example/
├── vue-example/
└── angular-example/Quy Trình Phát Triển
1. Tạo Branch
# Cập nhật branch main
git checkout main
git pull upstream main
# Tạo feature branch
git checkout -b feat/ten-tinh-nang-cua-ban
# hoặc cho bug fix
git checkout -b fix/mo-ta-loi2. Thực Hiện Thay Đổi
Tuân theo chuẩn code và quy ước commit của chúng tôi.
3. Kiểm Tra Thay Đổi
# Build CLI
npm run build
# Test CLI locally
cd examples/react-example
node ../../packages/cli/dist/bin.js add button
# Chạy dev server
npm run dev4. Commit Thay Đổi
git add .
git commit -m "feat: thêm variant nút mới"5. Push và Tạo PR
git push origin feat/ten-tinh-nang-cua-banSau đó tạo Pull Request trên GitHub.
Các Loại Đóng Góp
🐛 Sửa Lỗi
- Tìm kiếm issue hiện có để tránh trùng lặp
- Tạo issue mô tả lỗi
- Sửa lỗi và thêm test
- Gửi PR tham chiếu issue
✨ Tính Năng Mới
- Mở discussion cho các tính năng lớn
- Nhận phê duyệt trước khi bắt đầu
- Triển khai tính năng với test và docs
- Gửi PR với mô tả chi tiết
📝 Tài Liệu
- Xác định khoảng trống trong tài liệu
- Viết tài liệu rõ ràng, súc tích
- Thêm ví dụ code
- Gửi PR
🎨 Component Mới
Thêm component mới cần làm việc trên nhiều package:
Component React
# Tạo thư mục component
mkdir -p packages/react/src/components/new-component
# Tạo file component
touch packages/react/src/components/new-component/NewComponent.tsx
touch packages/react/src/components/new-component/index.tsNewComponent.tsx:
import * as React from 'react'
import { cn } from '@/lib/utils'
export interface NewComponentProps extends React.HTMLAttributes<HTMLDivElement> {
// Props đặc thù của component
}
const NewComponent = React.forwardRef<HTMLDivElement, NewComponentProps>(
({ className, ...props }, ref) => {
return (
<div
ref={ref}
className={cn('new-component-base-classes', className)}
{...props}
/>
)
}
)
NewComponent.displayName = 'NewComponent'
export { NewComponent }index.ts:
export * from './NewComponent'Component Vue
mkdir -p packages/vue/src/components/new-component
touch packages/vue/src/components/new-component/NewComponent.vue
touch packages/vue/src/components/new-component/index.tsNewComponent.vue:
<script setup lang="ts">
import { cn } from '@/lib/utils'
import { computed } from 'vue'
interface Props {
class?: string
}
const props = defineProps<Props>()
const className = computed(() => cn('new-component-base-classes', props.class))
</script>
<template>
<div :class="className">
<slot />
</div>
</template>Component Angular
mkdir -p packages/angular/src/components/new-component
touch packages/angular/src/components/new-component/new-component.component.ts
touch packages/angular/src/components/new-component/index.tsnew-component.component.ts:
import { Component, Input } from '@angular/core'
import { cn } from '@/lib/utils'
@Component({
selector: 'ui-new-component',
standalone: true,
template: `
<div [class]="className">
<ng-content />
</div>
`
})
export class NewComponentComponent {
@Input() class?: string
get className() {
return cn('new-component-base-classes', this.class)
}
}Cập Nhật Registry
Thêm component vào cả ba file registry:
packages/cli/src/registries/registry-react.json:
{
"new-component": {
"name": "NewComponent",
"type": "other",
"description": "Mô tả component mới",
"dependencies": [],
"devDependencies": [],
"registryDependencies": [],
"files": ["NewComponent.tsx", "index.ts"],
"category": "other"
}
}Lặp lại cho registry-vue.json và registry-angular.json.
Tạo Tài Liệu
touch docs/components/new-component.mdnew-component.md:
# New Component
Mô tả component và mục đích của nó.
## Import
::: code-group
```tsx [React]
import { NewComponent } from '@/components/ui/new-component'
```
```vue [Vue]
import { NewComponent } from '@/components/ui/new-component'
```
```typescript [Angular]
import { NewComponentComponent } from '@/components/ui/new-component'
```
:::
## Sử Dụng
::: code-group
```tsx [React]
export default function Example() {
return <NewComponent>Nội dung</NewComponent>
}
```
```vue [Vue]
<template>
<NewComponent>Nội dung</NewComponent>
</template>
```
```typescript [Angular]
@Component({
template: `<ui-new-component>Nội dung</ui-new-component>`
})
```
:::
## API
### Props
| Prop | Kiểu | Mặc định | Mô tả |
|------|------|---------|-------------|
| `class` | `string` | - | CSS class bổ sung |
## Ví Dụ
### Cơ Bản
[Thêm ví dụ ở đây]Cập Nhật Sidebar
Thêm component vào docs/.vitepress/config.ts:
{
text: 'Components',
items: [
// ... các item hiện có
{ text: 'New Component', link: '/components/new-component' },
],
}Chuẩn Code
TypeScript
- Sử dụng TypeScript cho mọi code
- Bật strict mode
- Thêm type cho tất cả props và function
- Tránh type
any
// ✅ Tốt
interface Props {
variant: 'default' | 'secondary'
onClick?: () => void
}
// ❌ Không tốt
interface Props {
variant: any
onClick: Function
}Style Component
- Sử dụng functional component
- Sử dụng React.forwardRef cho React component
- Export interface/type
- Thêm
displayNamecho React component
// ✅ Tốt
export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
variant?: 'default' | 'secondary'
}
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
({ variant = 'default', ...props }, ref) => {
return <button ref={ref} {...props} />
}
)
Button.displayName = 'Button'Styling
- Sử dụng Tailwind CSS classes
- Sử dụng cn() utility để merge class
- Hỗ trợ dark mode
// ✅ Tốt
<div className={cn('bg-background text-foreground', className)} />
// ❌ Không tốt
<div className={`bg-white text-black ${className}`} />Đặt Tên File
- React: PascalCase (Button.tsx)
- Vue: PascalCase (Button.vue)
- Angular: kebab-case (button.component.ts)
Quy Ước Commit
Chúng tôi tuân theo Conventional Commits:
<type>(<scope>): <description>
[body tùy chọn]
[footer tùy chọn]Types
feat: Tính năng mớifix: Sửa lỗidocs: Chỉ tài liệustyle: Style code (format, không thay đổi code)refactor: Refactor codetest: Thêm testchore: Công việc bảo trì
Ví Dụ
# Tính năng
feat(cli): thêm hỗ trợ pnpm package manager
# Sửa lỗi
fix(react): sửa style trạng thái disabled của nút
# Tài liệu
docs: cập nhật hướng dẫn cài đặt
# Breaking change
feat(vue)!: thay đổi API dialog để sử dụng composable
BREAKING CHANGE: Dialog giờ yêu cầu useDialog composableHướng Dẫn Pull Request
Tiêu Đề PR
Tuân theo quy ước commit:
feat(react): thêm component tooltip
fix(cli): giải quyết path alias trên Windows
docs: thêm hướng dẫn dark modeMô Tả PR
Sử dụng template này:
## Mô Tả
Mô tả ngắn gọn về thay đổi
## Loại Thay Đổi
- [ ] Sửa lỗi
- [ ] Tính năng mới
- [ ] Breaking change
- [ ] Cập nhật tài liệu
## Checklist
- [ ] Code tuân theo hướng dẫn style của dự án
- [ ] Đã tự review code
- [ ] Đã thêm/cập nhật test
- [ ] Đã thêm/cập nhật tài liệu
- [ ] Thay đổi không tạo cảnh báo mới
- [ ] Đã test ở cả ba framework (React, Vue, Angular)
## Screenshots (nếu có)
[Thêm screenshots]
## Issue Liên Quan
Fixes #123Quy Trình Review
- Kiểm tra tự động phải pass (linting, type checking)
- Review của maintainer - có thể yêu cầu thay đổi
- Phê duyệt - PR sẽ được merge
- Release - Thay đổi được đưa vào bản phát hành tiếp theo
Testing
Component Testing
Test component ở cả ba framework:
# React
cd examples/react-example
npm run dev
# Vue
cd examples/vue-example
npm run dev
# Angular
cd examples/angular-example
npm run devCLI Testing
# Build CLI
cd packages/cli
npm run build
# Test lệnh init
cd ../../examples/react-example
rm -rf components components.json
node ../../packages/cli/dist/bin.js init
# Test lệnh add
node ../../packages/cli/dist/bin.js add buttonTài Liệu
Hướng Dẫn Viết
- Rõ ràng và súc tích
- Sử dụng ví dụ code cho mọi tính năng
- Bao gồm tất cả framework (React, Vue, Angular)
- Thêm TypeScript type
- Hiển thị cả cách dùng cơ bản và nâng cao
Ví Dụ Code
Luôn cung cấp ví dụ cho tất cả framework:
::: code-group
\`\`\`tsx [React]
// Ví dụ React
\`\`\`
\`\`\`vue [Vue]
// Ví dụ Vue
\`\`\`
\`\`\`typescript [Angular]
// Ví dụ Angular
\`\`\`
:::Phát Triển Docs Cục Bộ
cd docs
npm install
npm run devTruy cập http://localhost:5173
Cộng Đồng
Nhận Hỗ Trợ
- GitHub Issues: Báo cáo lỗi và yêu cầu tính năng
- GitHub Discussions: Câu hỏi và thảo luận
- Discord: Chat thời gian thực (sắp ra mắt)
Quy Tắc Ứng Xử
Hãy tôn trọng và mang tính xây dựng. Chúng tôi tuân theo Contributor Covenant Code of Conduct.
Giấy Phép
Bằng việc đóng góp, bạn đồng ý rằng các đóng góp của bạn sẽ được cấp phép theo giấy phép MIT của dự án.
Có Câu Hỏi?
- Đọc tài liệu
- Tìm kiếm issue hiện có
- Mở discussion mới
Cảm ơn bạn đã đóng góp! 🎉
