Files
aperonight/docs/creating-shadcn-react-components.md
Kevin BATAILLE 30f3ecc6ad refactor(events): replace parties concept with events throughout the application
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

This commit refactors the entire application to replace the 'parties' concept with 'events'. All controllers, models, views, and related files have been updated to reflect this change. The parties table has been replaced with an events table, and all related functionality has been updated accordingly.
2025-08-28 13:20:51 +02:00

289 lines
6.3 KiB
Markdown
Executable File

# Creating New Shadcn and React Components
This guide explains how to create new Shadcn (UI) components and React components in this Rails application with React frontend.
## Overview
This project uses:
- **Shadcn/ui** for UI components (built on Radix UI and Tailwind CSS)
- **React** for frontend components
- **Rails** as the backend framework
- **esbuild** for JavaScript bundling
## Directory Structure
```
app/
├── javascript/
│ ├── components/
│ │ └── ui/ # Shadcn components
│ └── controllers/ # React controllers
├── views/
│ └── components/ # Rails view components
└── docs/ # Documentation
```
## Creating Shadcn Components
### 1. Using the Shadcn CLI
The easiest way to add new Shadcn components is using the CLI:
```bash
# Navigate to the project root
cd /home/acid/Documents/aperonight
# Add a new component (example: adding a card)
npx shadcn-ui@latest add card
```
This will:
- Install the component to `app/javascript/components/ui/`
- Update the components.json configuration
- Create the necessary TypeScript/JavaScript files
### 2. Manual Component Creation
If the CLI is not available, create components manually:
#### Create the component file
```bash
# Create a new component (example: button.jsx)
touch app/javascript/components/ui/button.jsx
```
#### Basic component structure
```javascript
// app/javascript/components/ui/button.jsx
import * as React from "react"
import { cn } from "@/lib/utils"
const Button = React.forwardRef(({ className, ...props }, ref) => {
return (
<button
className={cn(
"inline-flex items-center justify-center rounded-md text-sm font-medium",
className
)}
ref={ref}
{...props}
/>
)
})
Button.displayName = "Button"
export { Button }
```
## Creating React Components
### 1. Controller-Based Components
For components that need Rails integration:
#### Create controller file
```bash
# Create a new controller
touch app/javascript/controllers/my_component_controller.js
```
#### Basic controller structure
```javascript
// app/javascript/controllers/my_component_controller.js
import { Controller } from "@hotwired/stimulus"
import React from "react"
import ReactDOM from "react-dom/client"
export default class extends Controller {
static targets = ["container"]
connect() {
const root = ReactDOM.createRoot(this.containerTarget)
root.render(<MyComponent />)
}
}
```
### 2. Standalone React Components
For reusable React components:
#### Create component file
```bash
# Create a new React component
touch app/javascript/components/MyNewComponent.jsx
```
#### Component structure
```javascript
// app/javascript/components/MyNewComponent.jsx
import React from "react"
const MyNewComponent = ({ title, description }) => {
return (
<div className="p-4 border rounded-lg">
<h2 className="text-lg font-semibold">{title}</h2>
<p className="text-gray-600">{description}</p>
</div>
)
}
export default MyNewComponent
```
## Integration Patterns
### 1. Using in Rails Views
To use components in Rails views:
#### Create partial
```erb
<!-- app/views/components/_my_component.html.erb -->
<div data-controller="my-component">
<div data-my-component-target="container"></div>
</div>
```
#### Include in page
```erb
<!-- app/views/pages/home.html.erb -->
<%= render "components/my_component" %>
```
### 2. Direct React Rendering
For pages that are primarily React:
#### Create page component
```javascript
// app/javascript/components/pages/HomePage.jsx
import React from "react"
import { Button } from "@/components/ui/button"
const HomePage = () => {
return (
<div className="container mx-auto">
<h1>Welcome</h1>
<Button>Get Started</Button>
</div>
)
}
export default HomePage
```
## Configuration Updates
### 1. Update components.json
```json
{
"style": "default",
"rsc": false,
"tsx": false,
"tailwind": {
"config": "tailwind.config.js",
"css": "app/assets/stylesheets/application.postcss.css",
"baseColor": "slate",
"cssVariables": true
},
"aliases": {
"components": "app/javascript/components",
"utils": "app/javascript/lib/utils"
}
}
```
### 2. Update JavaScript entry point
```javascript
// app/javascript/application.js
import "./components"
import "./controllers"
```
## Naming Conventions
### Shadcn Components
- Use kebab-case for filenames: `button.jsx`, `card.jsx`
- Use PascalCase for exports: `export { Button }`
- Follow Radix UI naming patterns
### React Components
- Use PascalCase for filenames: `MyComponent.jsx`
- Use PascalCase for components: `const MyComponent = () => {}`
- Use camelCase for props: `myProp`, `onClick`
## Testing Components
### 1. Create test file
```bash
# Create test file
touch test/components/my_component_test.rb
```
### 2. Write component test
```javascript
// test/components/my_component_test.jsx
import { render, screen } from "@testing-library/react"
import MyComponent from "../../app/javascript/components/MyComponent"
test("renders component", () => {
render(<MyComponent title="Test" />)
expect(screen.getByText("Test")).toBeInTheDocument()
})
```
## Common Patterns
### 1. Props Pattern
```javascript
// Pass Rails data as props
const MyComponent = ({ user, config }) => {
return <div>{user.name}</div>
}
```
### 2. Event Handling
```javascript
// Handle events from Rails
const MyComponent = ({ onAction }) => {
return <button onClick={onAction}>Click me</button>
}
```
### 3. Styling Integration
```javascript
// Use Tailwind classes
const MyComponent = () => {
return <div className="bg-white dark:bg-gray-800">Content</div>
}
```
## Troubleshooting
### Common Issues
1. **Component not rendering**: Check controller connection
2. **Styling issues**: Verify Tailwind classes
3. **Props not passing**: Check data-controller attributes
4. **Import errors**: Verify alias paths in components.json
### Debug Steps
1. Check browser console for errors
2. Verify component file exists in correct location
3. Check import paths in application.js
4. Verify Rails view includes correct data attributes
## Example created for testing purpose
```html
<!-- Shadcn Button Test -->
<div data-controller="shadcn-test" class="mt-4">
<div data-shadcn-test-target="container"></div>
</div>
```