Rails Notion-Like Multiselect
A beautiful, keyboard-navigable multiselect component for Rails applications, inspired by Notion's elegant UI/UX. This gem provides a fully-featured multiselect input with search, filtering, and the ability to create new items on the fly.
Features
- 🎨 Beautiful Notion-inspired UI - Clean, modern design that fits seamlessly into any application
- ⌨️ Full keyboard navigation - Arrow keys, Enter, Escape, Tab, and Backspace support
- 🔍 Real-time search/filtering - Quickly find items as you type
- ➕ Create new items - Optional ability to create new items inline
- 🎯 Smart selection display - Selected items appear as compact badges inside the input
- 🌈 Customizable colors - Multiple badge color options (blue, green, purple, yellow, red)
- 🌓 Dark mode support - Automatically adapts to light and dark themes
- 📱 Fully responsive - Works great on mobile and desktop
- ♿ Accessible - Proper ARIA attributes and keyboard support
- 🚀 Stimulus-powered - Built with Hotwire Stimulus for modern Rails apps
- 🎨 Tailwind CSS v4 - Styled with Tailwind CSS v4 for modern, customizable design
Requirements
- Rails 7.0 - 8.x
- Ruby 3.0+
- Stimulus.js ~> 1.0 (included as dependency)
- Tailwind CSS 4.x (included via tailwindcss-rails gem)
Installation
From RubyGems (when published)
Add this line to your application's Gemfile:
gem 'rails_notion_like_multiselect'
From GitHub
To use the latest version directly from GitHub, add this to your Gemfile:
gem 'rails_notion_like_multiselect', git: 'https://github.com/pageinteract/rails_notion_like_multiselect.git'
Or to use a specific version/tag:
gem 'rails_notion_like_multiselect', git: 'https://github.com/pageinteract/rails_notion_like_multiselect.git', tag: 'v0.3.0'
Or to use a specific branch:
gem 'rails_notion_like_multiselect', git: 'https://github.com/pageinteract/rails_notion_like_multiselect.git', branch: 'main'
Then execute:
bundle install
Setup
Quick Setup
After installation, run the generator to set up the component:
rails generate rails_notion_like_multiselect:install
This will:
- Copy the Stimulus controller to
app/javascript/controllers/rails_notion_multiselect_controller.js
- The controller is automatically registered by Stimulus auto-loading
- No additional configuration needed - it just works!
Why the JavaScript Controller is Copied
Modern Rails Architecture: In Rails 7+ with importmaps, gems cannot directly serve JavaScript files through the asset pipeline. The Stimulus controller must be in your app's app/javascript/controllers/
directory to be discovered by Stimulus's eagerLoadControllersFrom
auto-loading mechanism.
Gem Architecture:
Gem provides:
├── 💎 Ruby helper methods (multiselect_field)
├── 🛠️ Install generator
└── 📄 JavaScript controller template
Your app receives:
├── app/javascript/controllers/
│ └── rails_notion_multiselect_controller.js (copied & production-ready)
└── Enhanced views using multiselect_field helper
Prerequisites
The gem automatically includes tailwindcss-rails
as a dependency. If you haven't set up Tailwind CSS in your application yet, run:
rails tailwindcss:install
This will create the necessary Tailwind configuration files and set up the build process.
Important: Make sure to include the gem's view paths in your Tailwind configuration to ensure all classes are properly compiled:
// tailwind.config.js
module.exports = {
content: [
'./app/**/*.{erb,haml,html,slim,rb}',
'./node_modules/rails_notion_like_multiselect/**/*.{js,rb}',
// Or if using the gem directly:
'./vendor/bundle/ruby/*/gems/rails_notion_like_multiselect-*/**/*.{js,rb}'
],
// ... rest of your config
}
Manual Setup (if not using generator)
1. Import the JavaScript controller
In your app/javascript/controllers/index.js
:
import RailsNotionMultiselectController from "rails_notion_multiselect_controller"
application.register("rails-notion-multiselect", RailsNotionMultiselectController)
2. Include the helper in your application
The helper is automatically included when you install the gem.
Usage
Basic Usage
In your Rails form:
<%= form_with model: @game do |form| %>
<%= multiselect_field(
form,
:category_ids,
collection: @categories,
selected: @game.categories,
placeholder: "Search categories...",
label: "Categories"
) %>
<% end %>
With Create Capability
Allow users to create new items on the fly:
<%= multiselect_field(
form,
:tags,
collection: @existing_tags,
selected: @game.tags,
allow_create: true,
placeholder: "Search or create tags...",
label: "Tags",
help_text: "Type and press Enter to create new tags"
) %>
With Explicit Theme
Force a specific theme regardless of system settings:
<%= multiselect_field(
form,
:category_ids,
collection: @categories,
selected: @game.categories,
theme: "dark", # Options: "light", "dark", "auto"
label: "Categories"
) %>
With Custom Colors
Use different badge colors for different types of data:
<%= multiselect_field(
form,
:category_ids,
collection: @categories,
selected: @game.categories,
badge_color: "green", # Options: blue, green, purple, yellow, red
label: "Categories"
) %>
With API Endpoint
For server-side creation of new items:
<%= multiselect_field(
form,
:tags,
collection: @tags,
selected: @game.tags,
allow_create: true,
api_endpoint: "/api/tags",
item_type: "tag"
) %>
With Custom Attributes
For objects with custom attribute names:
<!-- Using objects with slug/title instead of id/name -->
<%= multiselect_field(
form,
:category_slugs,
collection: @categories, # Objects with .slug and .title methods
selected: @game.categories, # Selected objects
value_method: :slug, # Use slug for the value
text_method: :title, # Use title for display text
label: "Categories"
) %>
<!-- Using hash format with custom keys -->
<%= multiselect_field(
form,
:author_ids,
collection: [
{ author_id: 1, full_name: 'John Doe' },
{ author_id: 2, full_name: 'Jane Smith' }
],
selected: [{ author_id: 1, full_name: 'John Doe' }],
value_method: :author_id, # Use author_id for the value
text_method: :full_name, # Use full_name for display text
label: "Authors"
) %>
With Simple Strings
For simple string arrays:
<!-- Strings as both value and display text -->
<%= multiselect_field(
form,
:skills,
collection: ["Ruby", "JavaScript", "Python", "Go"],
selected: ["Ruby", "JavaScript"],
allow_create: true,
label: "Skills"
) %>
<!-- Selected values will be the strings themselves: ["Ruby", "JavaScript"] -->
Options
Option | Type | Default | Description |
---|---|---|---|
collection |
Array | [] |
Array of items to select from |
selected |
Array | [] |
Currently selected items |
allow_create |
Boolean | false |
Allow creating new items |
placeholder |
String | "Search or select..." |
Input placeholder text |
label |
String | Field name | Label for the field |
item_type |
String | Field singularized | Type of items (for create prompt) |
badge_color |
String | "blue" |
Color scheme for badges |
api_endpoint |
String | nil |
API endpoint for server-side creation |
help_text |
String | nil |
Help text below the field |
theme |
String | "auto" |
Theme mode: "light", "dark", or "auto" |
value_method |
Symbol | :id |
Method to call for the value/id |
text_method |
Symbol | :name |
Method to call for display text |
Keyboard Shortcuts
- ↓/↑ - Navigate through options
- Enter - Select highlighted option or create new item
- Escape - Close dropdown
- Backspace - Remove last selected item (when input is empty)
- Tab - Close dropdown and move to next field
- Any character - Open dropdown and start searching
Configuration
You can configure default settings in an initializer:
# config/initializers/rails_notion_like_multiselect.rb
RailsNotionLikeMultiselect.setup do |config|
config.default_badge_color = "green"
config.default_placeholder = "Type to search..."
config.enable_keyboard_navigation = true
end
Styling
The component is built with Tailwind CSS v4 and uses its utility classes for styling. The gem requires Tailwind CSS v4 to be properly installed in your Rails application for the component to render correctly.
Dark Mode Support
The multiselect component supports three theme modes:
-
"auto"
(default): Automatically adapts to your application's dark mode settings using Tailwind's dark mode classes -
"light"
: Forces light theme styling regardless of system settings -
"dark"
: Forces dark theme styling regardless of system settings
Theme behaviors:
- Light mode: Light colored badges with dark text, white background
- Dark mode: Dark colored badges with light text, dark background
- Automatic contrast: All elements adjust for optimal readability
To enable dark mode in your application, configure Tailwind CSS:
// tailwind.config.js
module.exports = {
darkMode: 'class', // or 'media' for system preference
// ... rest of your config
}
Custom Styling
If you need to customize the styles, you can override these classes in your Tailwind configuration or target them directly:
-
.rails-notion-multiselect-container
- Main container -
.rails-notion-multiselect-input
- Input field -
.rails-notion-multiselect-badge
- Selected item badges -
.rails-notion-multiselect-dropdown
- Dropdown container -
.rails-notion-multiselect-option
- Individual options
Examples
Categories with Predefined Options
<%= multiselect_field(
form,
:category_ids,
collection: Category.active.ordered,
selected: @product.categories,
placeholder: "Select categories...",
label: "Product Categories",
badge_color: "blue",
help_text: "Choose all applicable categories"
) %>
Tags with Creation
<%= multiselect_field(
form,
:tags,
collection: ["Ruby", "Rails", "JavaScript", "React", "Vue"],
selected: @post.tags || [],
allow_create: true,
placeholder: "Add tags...",
label: "Post Tags",
badge_color: "green",
item_type: "tag",
help_text: "Select existing tags or create new ones"
) %>
Users Assignment
<%= multiselect_field(
form,
:assigned_user_ids,
collection: User.active.map { |u| { id: u.id, name: u.full_name } },
selected: @task.assigned_users,
placeholder: "Assign team members...",
label: "Assigned To",
badge_color: "purple"
) %>
Controller Actions
If you're using the api_endpoint
option for server-side creation, implement a controller action like:
class TagsController < ApplicationController
def create
tag = Tag.find_or_create_by(name: params[:tag][:name])
render json: { id: tag.id, name: tag.name }
end
end
Browser Support
- Chrome (latest)
- Firefox (latest)
- Safari (latest)
- Edge (latest)
Development
After checking out the repo, run bin/setup
to install dependencies. Then, run rake spec
to run the tests. You can also run bin/console
for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install
. To release a new version, update the version number in version.rb
, and then run bundle exec rake release
, which will create a git tag for the version, push git commits and tags, and push the .gem
file to rubygems.org.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/pageinteract/rails_notion_like_multiselect. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the code of conduct.
How to Contribute
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'Add some amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
License
The gem is available as open source under the terms of the MIT License.
Note on Tailwind CSS Usage
This gem uses only open-source Tailwind CSS utility classes. No Tailwind UI/Plus components or proprietary code are used in this implementation. All styling is created using the freely available Tailwind CSS framework under the MIT license.
Acknowledgments
- Inspired by Notion's excellent multiselect component
- Built with Stimulus for modern Rails applications
- Styled with Tailwind CSS for beautiful, responsive design
Author
Sulman Baig
- GitHub: @sulmanweb
- Email: sulmanweb@gmail.com
Dependencies
- Rails - MIT License
- Stimulus - MIT License
- Tailwind CSS - MIT License (via tailwindcss-rails gem)