Thank you for your interest in contributing to @zyxui! This guide will help you get started with contributing to our React UI component library.
- Node.js 18+
- pnpm 9+ (we use pnpm for package management)
- Git
-
Fork and Clone
git clone https://github.com/your-username/zyxui.git cd zyxui -
Install Dependencies
pnpm install
-
Start Development
pnpm dev
-
Build Packages
pnpm build:packages
zyxui/
βββ packages/
β βββ components/ # Individual component packages
β β βββ button/
β β βββ input/
β β βββ card/
β β βββ ...
β βββ lib/ # Shared utilities
β βββ theme/ # Theme system
β βββ config/ # Shared configurations
β βββ tsconfig/ # TypeScript configurations
βββ apps/
β βββ docs/ # Documentation site
β βββ web/ # Demo/playground app
βββ ...
-
Create Component Package
mkdir packages/components/my-component cd packages/components/my-component -
Setup Package Structure
my-component/ βββ package.json βββ tsup.config.ts βββ .eslintrc.js βββ src/ βββ index.ts βββ my-component.tsx -
Follow Component Template
'use client'; import { forwardRef, ReactNode } from 'react'; import { VariantProps, cva } from 'class-variance-authority'; import { cn } from '@zyxui/lib'; import { useTheme } from '@zyxui/theme'; const componentVariants = cva('base-classes', { variants: { variant: { default: 'default-classes', }, size: { sm: 'small-classes', md: 'medium-classes', lg: 'large-classes', }, }, defaultVariants: { variant: 'default', size: 'md', }, }); export type ComponentProps = { children: ReactNode; className?: string; } & React.HTMLAttributes<HTMLElement> & VariantProps<typeof componentVariants>; const Component = forwardRef<HTMLElement, ComponentProps>( ({ children, className, variant, size, ...props }, ref) => { const { config } = useTheme(); return ( <div ref={ref} className={cn(componentVariants({ variant, size }), className)} {...props} > {children} </div> ); }, ); Component.displayName = 'Component'; export default Component;
-
Accessibility First
- Use React Aria hooks when applicable
- Ensure proper ARIA attributes
- Support keyboard navigation
- Test with screen readers
-
TypeScript
- Full type safety
- Export all relevant types
- Use proper generic constraints
- Document complex types
-
Styling
- Use class-variance-authority for variants
- Follow Tailwind CSS conventions
- Support theme customization
- Responsive design by default
-
Performance
- Use forwardRef for ref forwarding
- Minimize re-renders
- Tree-shakeable exports
- Optimize bundle size
# Run all tests
pnpm test
# Run tests for specific package
pnpm test --filter=@zyxui/button
# Run tests in watch mode
pnpm test:watch# Lint all packages
pnpm lint
# Format code
pnpm format
# Fix linting issues
pnpm lint:fixEach component should include:
-
JSDoc Comments
/** * A versatile button component with multiple variants and states. * * @example * ```tsx * <Button variant="outlined" size="lg"> * Click me * </Button> * ``` */
-
README.md
- Installation instructions
- Basic usage examples
- API reference
- Accessibility notes
-
Storybook Stories (if applicable)
import type { Meta, StoryObj } from '@storybook/react'; import Button from './button'; const meta: Meta<typeof Button> = { title: 'Components/Button', component: Button, parameters: { layout: 'centered', }, }; export default meta; type Story = StoryObj<typeof meta>; export const Default: Story = { args: { children: 'Button', }, };
-
Create Feature Branch
git checkout -b feature/my-new-component
-
Make Changes
- Follow coding standards
- Add tests
- Update documentation
- Add changeset if needed
-
Add Changeset (for version bumps)
pnpm changeset
-
Commit Changes
git add . git commit -m "feat: add new component"
-
Push and Create PR
git push origin feature/my-new-component
-
Title: Use conventional commits format
feat:for new featuresfix:for bug fixesdocs:for documentationrefactor:for refactoringtest:for tests
-
Description:
- Clear description of changes
- Screenshots for UI changes
- Breaking changes noted
- Related issues linked
-
Checklist:
- Tests pass
- Documentation updated
- Changeset added (if needed)
- Accessibility tested
- Cross-browser tested
Use semantic color tokens:
/* Primary colors */
--primary: ... --primary-foreground: ... /* Semantic colors */ --success: ...
--warning: ... --error: ... /* Neutral colors */ --background: ...
--foreground: ... --muted: ... --border: ...;Follow consistent spacing:
--spacing-1: 0.25rem; /* 4px */
--spacing-2: 0.5rem; /* 8px */
--spacing-3: 0.75rem; /* 12px */
--spacing-4: 1rem; /* 16px */
/* ... */Use consistent typography:
--text-xs: 0.75rem;
--text-sm: 0.875rem;
--text-base: 1rem;
--text-lg: 1.125rem;
/* ... */When reporting bugs, please include:
-
Environment
- OS and version
- Browser and version
- Node.js version
- Package versions
-
Steps to Reproduce
- Clear, numbered steps
- Minimal code example
- Expected vs actual behavior
-
Additional Context
- Screenshots/videos
- Console errors
- Related issues
For new features:
- Check existing issues first
- Describe the problem you're solving
- Propose a solution with examples
- Consider alternatives and trade-offs
- Discuss breaking changes if any
// β
Good
interface ButtonProps {
variant?: 'solid' | 'outlined';
size?: 'sm' | 'md' | 'lg';
children: ReactNode;
}
// β Bad
interface ButtonProps {
variant?: string;
size?: string;
children: any;
}// β
Good - Use forwardRef
const Button = forwardRef<HTMLButtonElement, ButtonProps>(
({ children, ...props }, ref) => {
return (
<button ref={ref} {...props}>
{children}
</button>
);
},
);
// β
Good - Destructure props
const Button = ({ variant = 'solid', size = 'md', ...props }) => {
// ...
};
// β Bad - Don't use props object directly
const Button = (props) => {
return <button className={props.className}>{props.children}</button>;
};// β
Good - Use cn utility
className={cn(
'base-classes',
variants({ variant, size }),
className
)}
// β
Good - Logical grouping
className="flex items-center justify-center px-4 py-2 text-sm font-medium"
// β Bad - Random order
className="text-sm px-4 flex font-medium py-2 items-center justify-center"- Discord: Join our community
- GitHub Discussions: For questions and ideas
- Twitter: @zyxui for updates
By contributing to @zyxui, you agree that your contributions will be licensed under the MIT License.
Thank you for contributing to @zyxui! π