antd-stimulus
v1.0.0-alpha.1
Published
Wrap Ant Design React components using StimulusJS for seamless integration with Rails applications.
Maintainers
Readme
Antd Stimulus
Wrap Ant Design React components using StimulusJS for seamless integration with Rails applications.
Installation
npm install antd-stimulus turbo-mountDependencies
This library requires:
@hotwired/stimulus^3.0.0react^17.0.0 || ^18.0.0react-dom^17.0.0 || ^18.0.0antd^5.0.0turbo-mount^0.4.3
Features
- Complete Ant Design Integration: All 70+ components with full API support
- Zero Configuration: Works out of the box with sensible defaults
- TurboMount Integration: Efficient React component mounting/unmounting
- Rails Ready: Perfect integration with Rails and Hotwire
- Fully Customizable: Extend controllers for custom behavior
- Theme Support: Built-in Ant Design theme configuration
- Organized Structure: Clean separation of components and controllers in organized folders
- Easy Extension: Extend specific controller classes for custom behavior
- Modular: Import only what you need
Installation
npm install antd-stimulus turbo-mountQuick Start
1. Register Components
import { Application } from '@hotwired/stimulus';
import { initializeAndRegisterComponents } from 'antd-stimulus';
const application = Application.start();
// Register all components with optional theme
initializeAndRegisterComponents(application, {
prefix: 'rp', // Components will be rp-button, rp-input, etc.
theme: {
colorPrimary: '#1677ff',
colorSuccess: '#52c41a'
}
});2. Use in Rails Views
<!-- Button -->
<%= turbo_mount "rp-button", props: {
type: "primary",
children: "Click Me"
} %>
<!-- Input -->
<%= turbo_mount "rp-input", props: {
placeholder: "Enter text..."
} %>
<!-- Select -->
<%= turbo_mount "rp-select", props: {
options: [
{ value: 'option1', label: 'Option 1' },
{ value: 'option2', label: 'Option 2' }
]
} %>
<!-- Table -->
<%= turbo_mount "rp-table", props: {
dataSource: @users,
columns: [
{ title: 'Name', dataIndex: 'name' },
{ title: 'Email', dataIndex: 'email' }
]
} %>Available Components
All 70+ Ant Design components are included:
- Form: Button, Input, Select, Checkbox, Radio, Switch, DatePicker, TimePicker, Upload, Slider, Rate
- Display: Table, List, Card, Avatar, Badge, Tag, Tooltip, Popover, Progress, Tree, Calendar
- Feedback: Alert, Modal, Message, Notification, Spin, Result, Skeleton
- Navigation: Menu, Breadcrumb, Steps, Tabs, Pagination, Anchor, Dropdown
- Layout: Layout, Row, Col, Space, Flex, Divider, Affix, BackTop
- Advanced: Form, Transfer, TreeSelect, Mentions, Timeline, Tour, FloatButton
Component identifiers: {prefix}-{componentname} (e.g., rp-button, rp-table)
Custom Controllers
Extend any controller for custom behavior:
import { TurboMountController } from 'turbo-mount';
export default class CustomButtonController extends TurboMountController {
static targets = ['mount'];
get componentProps() {
return {
...super.componentProps,
onClick: this.handleClick.bind(this)
};
}
handleClick(event) {
console.log('Custom button clicked!');
this.dispatch('custom-click', { detail: { event } });
}
}
// Register your custom controller
import { registerComponent } from 'antd-stimulus';
registerComponent(application, 'rp-button', CustomButtonController);API Reference
initializeAndRegisterComponents(application, config?)
Register all components with optional configuration.
Config Options:
prefix- Component prefix (default: 'rp')theme- Ant Design theme objectcomponents- Array of components to register (default: all)
registerComponent(application, identifier, controller)
Register a custom controller.
updateTheme(newTheme)
Update theme at runtime.
Requirements
@hotwired/stimulus^3.0.0react^17.0.0 || ^18.0.0antd^5.0.0turbo-mount^0.4.3
License
MIT
Features
- Theme Configuration: Configure Ant Design theme tokens globally using
withThemeutility - Organized Structure: Clean separation of components and controllers in organized folders
- Easy Extension: Extend specific controller classes for custom behavior
- Base Classes:
BaseComponentControllerandwithThemeutility for consistent patterns - Modular: Import only what you need
- Rails Integration: Seamless integration with Rails and turbo-mount helper
Project Structure
src/
├── components/
│ ├── button/
│ │ ├── button_component.jsx # React component with theme
│ │ ├── button_controller.js # Stimulus controller
│ │ └── index.js # Exports
│ ├── select/
│ │ ├── select_component.jsx
│ │ ├── select_controller.js
│ │ └── index.js
│ └── input/
│ ├── input_component.jsx
│ ├── input_controller.js
│ └── index.js
├── utilities/
│ └── withTheme.jsx # HOC for theme integration
└── index.js # Main exports and initializationInstallation
npm install antd-stimulusUsage
Basic Setup
import { Application } from '@hotwired/stimulus';
import { initializeAndRegisterComponents, registerComponent } from 'antd-stimulus';
const application = Application.start();
// Initialize with theme configuration - registers Button, Input, Select by default
initializeAndRegisterComponents(application, {
theme: {
colorPrimary: '#1677ff',
colorSuccess: '#52c41a',
colorError: '#ff4d4f',
colorWarning: '#faad14',
colorInfo: '#1677ff',
},
prefix: 'rp', // CSS prefix for components
iconPrefix: 'rp-icon' // Icon prefix
});Extending Controllers
The clean way to customize behavior - extend TurboMountController directly:
// Import TurboMountController and React
import { TurboMountController } from 'turbo-mount';
import React from 'react';
import { SelectComponent } from 'antd-stimulus/src/components/select/select_component.jsx';
export default class CustomSelectController extends TurboMountController {
static targets = ['mount'];
// TurboMountController method - returns the React component
get component() {
return React.createElement(SelectComponent, this.componentProps);
}
// TurboMountController method - returns the component props
get componentProps() {
return {
...this.propsValue,
onChange: this.handleChange.bind(this),
onSearch: this.handleSearch.bind(this)
};
}
// Override the change handler
handleChange(value, option) {
// Your custom logic
console.log('Custom select logic:', { value, option });
// Update form fields
const hiddenInput = this.element.querySelector('input[type="hidden"]');
if (hiddenInput) {
hiddenInput.value = value;
}
// Emit standard event
this.dispatch('change', { detail: { value, option } });
}
handleSearch(searchValue) {
console.log('Searching for:', searchValue);
this.dispatch('search', { detail: { searchValue } });
}
}
// Register your custom controller
registerComponent(application, 'rp-select', CustomSelectController);Rails View Usage
Use any Ant Design component with the turbo-mount helper in your Rails views:
<!-- Button Component -->
<%= turbo_mount "rp-button", props: {
type: "primary",
size: "large",
children: "Click Me"
} do |controller_name| %>
<div data-<%= controller_name %>-target="mount"></div>
<% end %>
<!-- Input Component -->
<%= turbo_mount "rp-input", props: {
placeholder: "Enter your name...",
size: "large"
} do |controller_name| %>
<div data-<%= controller_name %>-target="mount"></div>
<% end %>
<!-- Select Component -->
<%= turbo_mount "rp-select", props: {
placeholder: "Choose an option",
options: [
{ value: 'option1', label: 'Option 1' },
{ value: 'option2', label: 'Option 2' }
]
} do |controller_name| %>
<div data-<%= controller_name %>-target="mount"></div>
<% end %>
<!-- Date Picker -->
<%= turbo_mount "rp-datepicker", props: {
placeholder: "Select date"
} do |controller_name| %>
<div data-<%= controller_name %>-target="mount"></div>
<% end %>
<!-- Table Component -->
<%= turbo_mount "rp-table", props: {
dataSource: @users,
columns: [
{ title: 'Name', dataIndex: 'name', key: 'name' },
{ title: 'Email', dataIndex: 'email', key: 'email' }
]
} do |controller_name| %>
<div data-<%= controller_name %>-target="mount"></div>
<% end %>Custom Controllers
Create custom controllers that extend TurboMountController for specific behavior:
import { TurboMountController } from 'turbo-mount';
import React from 'react';
import { ButtonComponent } from 'antd-stimulus/src/components/button/button_component.jsx';
export default class CustomButtonController extends TurboMountController {
static targets = ['mount'];
// TurboMountController method - returns the React component
get component() {
return React.createElement(ButtonComponent, this.componentProps);
}
// TurboMountController method - returns the component props
get componentProps() {
return {
...this.propsValue,
onClick: this.handleClick.bind(this),
};
}
handleClick(event) {
// Custom behavior
console.log('Custom click handler');
// Emit Rails-compatible event
this.dispatch('button-clicked', {
detail: { buttonId: this.data.get('id') }
});
}
}Creating New Components
To add a new component (e.g., Checkbox):
- Create the component file (
src/components/checkbox/checkbox_component.jsx):
import React from 'react';
import { Checkbox } from 'antd';
import { withTheme } from '../../utilities/withTheme.jsx';
export const CheckboxComponent = withTheme((props) => {
return <Checkbox {...props} />;
});- Create the controller (
src/components/checkbox/checkbox_controller.js):
import { TurboMountController } from 'turbo-mount';
import React from 'react';
import { CheckboxComponent } from './checkbox_component.jsx';
export default class CheckboxController extends TurboMountController {
static targets = ['mount'];
// TurboMountController method - returns the React component
get component() {
return React.createElement(CheckboxComponent, this.componentProps);
}
// TurboMountController method - returns the component props
get componentProps() {
return {
...this.propsValue,
onChange: this.handleChange.bind(this)
};
}
handleChange(event) {
const checked = event.target.checked;
this.dispatch('change', {
detail: { checked, event, timestamp: new Date().toISOString() }
});
}
}- Create index file (
src/components/checkbox/index.js):
export { CheckboxComponent } from './checkbox_component.jsx';
export { default as CheckboxController } from './checkbox_controller.js';- Update main index.js to include it in the controller mapping and default components.
API Reference
initializeAndRegisterComponents(application, config)
Initialize the library and register Ant Design components automatically.
Parameters:
application- Stimulus Application instanceconfig- Configuration objecttheme- Ant Design theme tokensprefix- CSS prefix for components (default: 'rp')iconPrefix- Icon prefix (default: 'rp-icon')components- Array of component names to register (optional, defaults to common components)
registerComponent(application, identifier, controller)
Register a custom controller for a specific component.
Parameters:
application- Stimulus Application instanceidentifier- Controller identifier (e.g., 'rp-button')controller- Custom Stimulus controller class
registerAntdComponent(application, componentName, identifier, prefix)
Register any Ant Design component dynamically.
Parameters:
application- Stimulus Application instancecomponentName- Ant Design component name (e.g., 'Button', 'Transfer')identifier- Custom controller identifier (optional)prefix- Prefix for controller identifier (optional, defaults to 'rp')
updateTheme(newTheme)
Update the global theme configuration.
Parameters:
newTheme- Object containing new theme tokens
GenericComponentController
Base controller class that can mount any Ant Design component. Available for advanced usage.
Available Components
All Ant Design components are automatically available! Common ones include:
- Form Controls: Button, Input, Select, Checkbox, Radio, Switch, DatePicker, TimePicker, Slider
- Data Display: Table, List, Card, Avatar, Badge, Tag, Tooltip, Popover, Statistic
- Feedback: Alert, Modal, Message, Notification, Progress, Spin, Result
- Navigation: Menu, Breadcrumb, Steps, Tabs, Pagination, Anchor
- Layout: Layout, Grid, Space, Divider, Affix, BackTop
- Other: Form, Upload, Transfer, Tree, Calendar, Carousel, Collapse, and many more!
Component identifiers follow the pattern: {prefix}-{componentname} (e.g., rp-button, rp-datepicker, rp-table).
Theme Configuration
The library uses Ant Design's ConfigProvider to apply themes globally. You can configure:
colorPrimary- Primary colorcolorSuccess- Success colorcolorError- Error colorcolorWarning- Warning colorcolorInfo- Info color- Custom prefix and icon prefix
Contributing
- Fork the repository
- Create your feature branch
- Add your component in
src/components/ - Update the component registry in
src/index.js - Submit a pull request
License
MIT
