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.
6.3 KiB
Executable File
6.3 KiB
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:
# 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
# Create a new component (example: button.jsx)
touch app/javascript/components/ui/button.jsx
Basic component structure
// 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
# Create a new controller
touch app/javascript/controllers/my_component_controller.js
Basic controller structure
// 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
# Create a new React component
touch app/javascript/components/MyNewComponent.jsx
Component structure
// 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
<!-- app/views/components/_my_component.html.erb -->
<div data-controller="my-component">
<div data-my-component-target="container"></div>
</div>
Include in page
<!-- app/views/pages/home.html.erb -->
<%= render "components/my_component" %>
2. Direct React Rendering
For pages that are primarily React:
Create page component
// 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
{
"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
// 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
# Create test file
touch test/components/my_component_test.rb
2. Write component test
// 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
// Pass Rails data as props
const MyComponent = ({ user, config }) => {
return <div>{user.name}</div>
}
2. Event Handling
// Handle events from Rails
const MyComponent = ({ onAction }) => {
return <button onClick={onAction}>Click me</button>
}
3. Styling Integration
// Use Tailwind classes
const MyComponent = () => {
return <div className="bg-white dark:bg-gray-800">Content</div>
}
Troubleshooting
Common Issues
- Component not rendering: Check controller connection
- Styling issues: Verify Tailwind classes
- Props not passing: Check data-controller attributes
- Import errors: Verify alias paths in components.json
Debug Steps
- Check browser console for errors
- Verify component file exists in correct location
- Check import paths in application.js
- Verify Rails view includes correct data attributes
Example created for testing purpose
<!-- Shadcn Button Test -->
<div data-controller="shadcn-test" class="mt-4">
<div data-shadcn-test-target="container"></div>
</div>