Dropdown Menu Rails Components
Dropdown menus with intelligent positioning, keyboard navigation, mobile support, and nested submenus. Perfect for navigation, user menus, and action lists.
Installation
1. Stimulus Controller Setup
Start by adding the following 3 stimulus controllers to your project:
This code is available to Pro users only.
// Hey curious person!
// You seem to be sneaking around the code...
// I hope you're enjoying the components!
// Have a great day!
class SecretMessage {
constructor() {
this.message = "Thanks for checking out Rails Blocks!";
this.compliment = "You're awesome!";
}
reveal() {
console.log(this.message);
return this.compliment;
}
}
const secret = new SecretMessage();
secret.reveal();
This code is available to Pro users only.
// Hey curious person!
// You seem to be sneaking around the code...
// I hope you're enjoying the components!
// Have a great day!
class SecretMessage {
constructor() {
this.message = "Thanks for checking out Rails Blocks!";
this.compliment = "You're awesome!";
}
reveal() {
console.log(this.message);
return this.compliment;
}
}
const secret = new SecretMessage();
secret.reveal();
This code is available to Pro users only.
// Hey curious person!
// You seem to be sneaking around the code...
// I hope you're enjoying the components!
// Have a great day!
class SecretMessage {
constructor() {
this.message = "Thanks for checking out Rails Blocks!";
this.compliment = "You're awesome!";
}
reveal() {
console.log(this.message);
return this.compliment;
}
}
const secret = new SecretMessage();
secret.reveal();
2. Floating UI Installation
The dropdown component relies on Floating UI for intelligent popover positioning. Choose your preferred installation method:
pin "@floating-ui/dom", to: "https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.7.0/+esm"
npm install @floating-ui/dom
yarn add @floating-ui/dom
Examples
Basic dropdown
A simple dropdown menu with navigation items and actions.
This code is available to Pro users only.
<!-- Hey curious person! -->
<!-- You seem to be sneaking around the code... -->
<!-- I hope you're enjoying the components! -->
<!-- Have a great day! -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Secret Message from Rails Blocks</title>
<style>
.secret-message {
font-family: 'Comic Sans MS', cursive;
text-align: center;
padding: 2rem;
background: linear-gradient(45deg, #ff6b6b, #4ecdc4);
border-radius: 10px;
box-shadow: 0 4px 15px rgba(0,0,0,0.2);
}
.wiggle { animation: wiggle 0.5s ease-in-out infinite; }
@keyframes wiggle {
0%, 100% { transform: rotate(0deg); }
25% { transform: rotate(1deg); }
75% { transform: rotate(-1deg); }
}
</style>
</head>
<body>
<div class="secret-message">
<h1>π Hello, Code Detective! π΅οΈ</h1>
<p>Thanks for checking out Rails Blocks!</p>
<p>You're clearly someone who pays attention to details.</p>
<p>That's exactly the kind of developer we love!</p>
<div class="cta-section">
<button class="awesome-btn wiggle">You're awesome!</button>
<p><small>Seriously, keep being curious! π</small></p>
</div>
<footer>
<p>Built with β€οΈ by the Rails Blocks team</p>
<p>Now go build something amazing!</p>
</footer>
</div>
<script>
console.log("π Bonus points for opening the console!");
console.log("Keep exploring and happy coding! π»");
</script>
</body>
</html>
Searchable dropdown
A dropdown with search functionality to filter through options. Requires the searchable-dropdown
controller.
This code is available to Pro users only.
<!-- Hey curious person! -->
<!-- You seem to be sneaking around the code... -->
<!-- I hope you're enjoying the components! -->
<!-- Have a great day! -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Secret Message from Rails Blocks</title>
<style>
.secret-message {
font-family: 'Comic Sans MS', cursive;
text-align: center;
padding: 2rem;
background: linear-gradient(45deg, #ff6b6b, #4ecdc4);
border-radius: 10px;
box-shadow: 0 4px 15px rgba(0,0,0,0.2);
}
.wiggle { animation: wiggle 0.5s ease-in-out infinite; }
@keyframes wiggle {
0%, 100% { transform: rotate(0deg); }
25% { transform: rotate(1deg); }
75% { transform: rotate(-1deg); }
}
</style>
</head>
<body>
<div class="secret-message">
<h1>π Hello, Code Detective! π΅οΈ</h1>
<p>Thanks for checking out Rails Blocks!</p>
<p>You're clearly someone who pays attention to details.</p>
<p>That's exactly the kind of developer we love!</p>
<div class="cta-section">
<button class="awesome-btn wiggle">You're awesome!</button>
<p><small>Seriously, keep being curious! π</small></p>
</div>
<footer>
<p>Built with β€οΈ by the Rails Blocks team</p>
<p>Now go build something amazing!</p>
</footer>
</div>
<script>
console.log("π Bonus points for opening the console!");
console.log("Keep exploring and happy coding! π»");
</script>
</body>
</html>
Radio dropdown
A dropdown with radio button options for single selection.
This code is available to Pro users only.
<!-- Hey curious person! -->
<!-- You seem to be sneaking around the code... -->
<!-- I hope you're enjoying the components! -->
<!-- Have a great day! -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Secret Message from Rails Blocks</title>
<style>
.secret-message {
font-family: 'Comic Sans MS', cursive;
text-align: center;
padding: 2rem;
background: linear-gradient(45deg, #ff6b6b, #4ecdc4);
border-radius: 10px;
box-shadow: 0 4px 15px rgba(0,0,0,0.2);
}
.wiggle { animation: wiggle 0.5s ease-in-out infinite; }
@keyframes wiggle {
0%, 100% { transform: rotate(0deg); }
25% { transform: rotate(1deg); }
75% { transform: rotate(-1deg); }
}
</style>
</head>
<body>
<div class="secret-message">
<h1>π Hello, Code Detective! π΅οΈ</h1>
<p>Thanks for checking out Rails Blocks!</p>
<p>You're clearly someone who pays attention to details.</p>
<p>That's exactly the kind of developer we love!</p>
<div class="cta-section">
<button class="awesome-btn wiggle">You're awesome!</button>
<p><small>Seriously, keep being curious! π</small></p>
</div>
<footer>
<p>Built with β€οΈ by the Rails Blocks team</p>
<p>Now go build something amazing!</p>
</footer>
</div>
<script>
console.log("π Bonus points for opening the console!");
console.log("Keep exploring and happy coding! π»");
</script>
</body>
</html>
Checkbox dropdown
A dropdown with checkbox options for multiple selections. Uses data-dropdown-popover-auto-close-value="false"
to prevent closing on selection.
This code is available to Pro users only.
<!-- Hey curious person! -->
<!-- You seem to be sneaking around the code... -->
<!-- I hope you're enjoying the components! -->
<!-- Have a great day! -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Secret Message from Rails Blocks</title>
<style>
.secret-message {
font-family: 'Comic Sans MS', cursive;
text-align: center;
padding: 2rem;
background: linear-gradient(45deg, #ff6b6b, #4ecdc4);
border-radius: 10px;
box-shadow: 0 4px 15px rgba(0,0,0,0.2);
}
.wiggle { animation: wiggle 0.5s ease-in-out infinite; }
@keyframes wiggle {
0%, 100% { transform: rotate(0deg); }
25% { transform: rotate(1deg); }
75% { transform: rotate(-1deg); }
}
</style>
</head>
<body>
<div class="secret-message">
<h1>π Hello, Code Detective! π΅οΈ</h1>
<p>Thanks for checking out Rails Blocks!</p>
<p>You're clearly someone who pays attention to details.</p>
<p>That's exactly the kind of developer we love!</p>
<div class="cta-section">
<button class="awesome-btn wiggle">You're awesome!</button>
<p><small>Seriously, keep being curious! π</small></p>
</div>
<footer>
<p>Built with β€οΈ by the Rails Blocks team</p>
<p>Now go build something amazing!</p>
</footer>
</div>
<script>
console.log("π Bonus points for opening the console!");
console.log("Keep exploring and happy coding! π»");
</script>
</body>
</html>
Nested dropdown with submenus
A dropdown with nested submenus that open on click. Perfect for complex navigation structures.
This code is available to Pro users only.
<!-- Hey curious person! -->
<!-- You seem to be sneaking around the code... -->
<!-- I hope you're enjoying the components! -->
<!-- Have a great day! -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Secret Message from Rails Blocks</title>
<style>
.secret-message {
font-family: 'Comic Sans MS', cursive;
text-align: center;
padding: 2rem;
background: linear-gradient(45deg, #ff6b6b, #4ecdc4);
border-radius: 10px;
box-shadow: 0 4px 15px rgba(0,0,0,0.2);
}
.wiggle { animation: wiggle 0.5s ease-in-out infinite; }
@keyframes wiggle {
0%, 100% { transform: rotate(0deg); }
25% { transform: rotate(1deg); }
75% { transform: rotate(-1deg); }
}
</style>
</head>
<body>
<div class="secret-message">
<h1>π Hello, Code Detective! π΅οΈ</h1>
<p>Thanks for checking out Rails Blocks!</p>
<p>You're clearly someone who pays attention to details.</p>
<p>That's exactly the kind of developer we love!</p>
<div class="cta-section">
<button class="awesome-btn wiggle">You're awesome!</button>
<p><small>Seriously, keep being curious! π</small></p>
</div>
<footer>
<p>Built with β€οΈ by the Rails Blocks team</p>
<p>Now go build something amazing!</p>
</footer>
</div>
<script>
console.log("π Bonus points for opening the console!");
console.log("Keep exploring and happy coding! π»");
</script>
</body>
</html>
Lazy loading dropdown
A dropdown that loads its content only when opened, improving performance for complex menus. Uses data-dropdown-popover-lazy-load-value="true"
.
This code is available to Pro users only.
<!-- Hey curious person! -->
<!-- You seem to be sneaking around the code... -->
<!-- I hope you're enjoying the components! -->
<!-- Have a great day! -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Secret Message from Rails Blocks</title>
<style>
.secret-message {
font-family: 'Comic Sans MS', cursive;
text-align: center;
padding: 2rem;
background: linear-gradient(45deg, #ff6b6b, #4ecdc4);
border-radius: 10px;
box-shadow: 0 4px 15px rgba(0,0,0,0.2);
}
.wiggle { animation: wiggle 0.5s ease-in-out infinite; }
@keyframes wiggle {
0%, 100% { transform: rotate(0deg); }
25% { transform: rotate(1deg); }
75% { transform: rotate(-1deg); }
}
</style>
</head>
<body>
<div class="secret-message">
<h1>π Hello, Code Detective! π΅οΈ</h1>
<p>Thanks for checking out Rails Blocks!</p>
<p>You're clearly someone who pays attention to details.</p>
<p>That's exactly the kind of developer we love!</p>
<div class="cta-section">
<button class="awesome-btn wiggle">You're awesome!</button>
<p><small>Seriously, keep being curious! π</small></p>
</div>
<footer>
<p>Built with β€οΈ by the Rails Blocks team</p>
<p>Now go build something amazing!</p>
</footer>
</div>
<script>
console.log("π Bonus points for opening the console!");
console.log("Keep exploring and happy coding! π»");
</script>
</body>
</html>
Turbo dropdown
In the following example, we're using the dropdown as a popover that loads content from another Rails partial only when opened, improving performance. Uses data-dropdown-popover-lazy-load-value="true"
& data-dropdown-popover-turbo-frame-src-value="<%= dropdown_content_path %>"
.
This code is available to Pro users only.
<!-- Hey curious person! -->
<!-- You seem to be sneaking around the code... -->
<!-- I hope you're enjoying the components! -->
<!-- Have a great day! -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Secret Message from Rails Blocks</title>
<style>
.secret-message {
font-family: 'Comic Sans MS', cursive;
text-align: center;
padding: 2rem;
background: linear-gradient(45deg, #ff6b6b, #4ecdc4);
border-radius: 10px;
box-shadow: 0 4px 15px rgba(0,0,0,0.2);
}
.wiggle { animation: wiggle 0.5s ease-in-out infinite; }
@keyframes wiggle {
0%, 100% { transform: rotate(0deg); }
25% { transform: rotate(1deg); }
75% { transform: rotate(-1deg); }
}
</style>
</head>
<body>
<div class="secret-message">
<h1>π Hello, Code Detective! π΅οΈ</h1>
<p>Thanks for checking out Rails Blocks!</p>
<p>You're clearly someone who pays attention to details.</p>
<p>That's exactly the kind of developer we love!</p>
<div class="cta-section">
<button class="awesome-btn wiggle">You're awesome!</button>
<p><small>Seriously, keep being curious! π</small></p>
</div>
<footer>
<p>Built with β€οΈ by the Rails Blocks team</p>
<p>Now go build something amazing!</p>
</footer>
</div>
<script>
console.log("π Bonus points for opening the console!");
console.log("Keep exploring and happy coding! π»");
</script>
</body>
</html>
This code is available to Pro users only.
# Hey curious person!
# You seem to be sneaking around the code...
# I hope you're enjoying the components!
# Have a great day!
class SecretMessage
def initialize
@message = "Thanks for checking out Rails Blocks!"
@compliment = "You're awesome!"
end
def reveal
puts @message
@compliment
end
end
secret = SecretMessage.new
secret.reveal
This code is available to Pro users only.
# Hey curious person!
# You seem to be sneaking around the code...
# I hope you're enjoying the components!
# Have a great day!
class SecretMessage
def initialize
@message = "Thanks for checking out Rails Blocks!"
@compliment = "You're awesome!"
end
def reveal
puts @message
@compliment
end
end
secret = SecretMessage.new
secret.reveal
AI Chatbot dropdown
A modern AI assistant chatbot interface using the dropdown component. Features a floating chat button with animations, message interface, and input area. Perfect for customer support or AI assistant implementations.
AI Assistant
Always here to help
Hello! π I'm your AI assistant. How can I help you today?
Here are some things I can help you with:
Just now
Can you help me with the dropdown component?
You β’ 2m ago
Powered by Rails Blocks AI
This code is available to Pro users only.
<!-- Hey curious person! -->
<!-- You seem to be sneaking around the code... -->
<!-- I hope you're enjoying the components! -->
<!-- Have a great day! -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Secret Message from Rails Blocks</title>
<style>
.secret-message {
font-family: 'Comic Sans MS', cursive;
text-align: center;
padding: 2rem;
background: linear-gradient(45deg, #ff6b6b, #4ecdc4);
border-radius: 10px;
box-shadow: 0 4px 15px rgba(0,0,0,0.2);
}
.wiggle { animation: wiggle 0.5s ease-in-out infinite; }
@keyframes wiggle {
0%, 100% { transform: rotate(0deg); }
25% { transform: rotate(1deg); }
75% { transform: rotate(-1deg); }
}
</style>
</head>
<body>
<div class="secret-message">
<h1>π Hello, Code Detective! π΅οΈ</h1>
<p>Thanks for checking out Rails Blocks!</p>
<p>You're clearly someone who pays attention to details.</p>
<p>That's exactly the kind of developer we love!</p>
<div class="cta-section">
<button class="awesome-btn wiggle">You're awesome!</button>
<p><small>Seriously, keep being curious! π</small></p>
</div>
<footer>
<p>Built with β€οΈ by the Rails Blocks team</p>
<p>Now go build something amazing!</p>
</footer>
</div>
<script>
console.log("π Bonus points for opening the console!");
console.log("Keep exploring and happy coding! π»");
</script>
</body>
</html>
Configuration
Basic Setup
To create a dropdown menu, wrap your trigger element with the dropdown-popover controller and add a dialog element as the menu:
This code is available to Pro users only.
<!-- Hey curious person! -->
<!-- You seem to be sneaking around the code... -->
<!-- I hope you're enjoying the components! -->
<!-- Have a great day! -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Secret Message from Rails Blocks</title>
<style>
.secret-message {
font-family: 'Comic Sans MS', cursive;
text-align: center;
padding: 2rem;
background: linear-gradient(45deg, #ff6b6b, #4ecdc4);
border-radius: 10px;
box-shadow: 0 4px 15px rgba(0,0,0,0.2);
}
.wiggle { animation: wiggle 0.5s ease-in-out infinite; }
@keyframes wiggle {
0%, 100% { transform: rotate(0deg); }
25% { transform: rotate(1deg); }
75% { transform: rotate(-1deg); }
}
</style>
</head>
<body>
<div class="secret-message">
<h1>π Hello, Code Detective! π΅οΈ</h1>
<p>Thanks for checking out Rails Blocks!</p>
<p>You're clearly someone who pays attention to details.</p>
<p>That's exactly the kind of developer we love!</p>
<div class="cta-section">
<button class="awesome-btn wiggle">You're awesome!</button>
<p><small>Seriously, keep being curious! π</small></p>
</div>
<footer>
<p>Built with β€οΈ by the Rails Blocks team</p>
<p>Now go build something amazing!</p>
</footer>
</div>
<script>
console.log("π Bonus points for opening the console!");
console.log("Keep exploring and happy coding! π»");
</script>
</body>
</html>
Targets
The dropdown popover controller uses the following targets:
Target | Controller | Description |
---|---|---|
button
|
dropdown-popover
|
The button that triggers the dropdown |
menu
|
dropdown-popover
|
The dialog element that contains the dropdown menu |
template
|
dropdown-popover
|
Template element for lazy loading content |
item
|
menu
|
Individual menu items for keyboard navigation |
Values
Configure the dropdown behavior with these data attributes:
Value | Type | Default | Description |
---|---|---|---|
autoClose
|
Boolean
|
true
|
Whether to close the menu when clicking on an item |
nested
|
Boolean
|
false
|
Enable nested dropdown behavior |
hover
|
Boolean
|
false
|
Open submenu on hover instead of click |
autoPosition
|
Boolean
|
true
|
Automatically position the menu using Floating UI |
lazyLoad
|
Boolean
|
false
|
Load menu content only when opened |
placement
|
String
|
"bottom-start"
|
Initial placement of the menu (Floating UI placement) |
Features
The dropdown includes the following features:
- Smart positioning: Automatically adjusts position using Floating UI to stay within viewport
- Keyboard navigation: Arrow keys, Enter, and Escape support with menu controller
- Nested submenus: Support for multi-level dropdown menus
- Auto-close: Closes when clicking outside or pressing Escape
- Lazy loading: Load content only when dropdown is opened
- Hover support: Open submenus on hover for faster navigation
- Text search: Type to search and focus menu items
- Form integration: Works with radio buttons, checkboxes, and form submissions
Accessibility
The dropdown is built with accessibility in mind:
- ARIA support: Proper
role="menu"
androle="menuitem"
attributes - Screen reader friendly: Semantic HTML structure with proper labeling
- Keyboard navigation: Full keyboard accessibility with arrow keys
- Escape handling: Close dropdown with Escape key
Nested Submenus
Create nested submenus using the dropdown-popover controller with data-dropdown-popover-nested-value="true"
:
This code is available to Pro users only.
<!-- Hey curious person! -->
<!-- You seem to be sneaking around the code... -->
<!-- I hope you're enjoying the components! -->
<!-- Have a great day! -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Secret Message from Rails Blocks</title>
<style>
.secret-message {
font-family: 'Comic Sans MS', cursive;
text-align: center;
padding: 2rem;
background: linear-gradient(45deg, #ff6b6b, #4ecdc4);
border-radius: 10px;
box-shadow: 0 4px 15px rgba(0,0,0,0.2);
}
.wiggle { animation: wiggle 0.5s ease-in-out infinite; }
@keyframes wiggle {
0%, 100% { transform: rotate(0deg); }
25% { transform: rotate(1deg); }
75% { transform: rotate(-1deg); }
}
</style>
</head>
<body>
<div class="secret-message">
<h1>π Hello, Code Detective! π΅οΈ</h1>
<p>Thanks for checking out Rails Blocks!</p>
<p>You're clearly someone who pays attention to details.</p>
<p>That's exactly the kind of developer we love!</p>
<div class="cta-section">
<button class="awesome-btn wiggle">You're awesome!</button>
<p><small>Seriously, keep being curious! π</small></p>
</div>
<footer>
<p>Built with β€οΈ by the Rails Blocks team</p>
<p>Now go build something amazing!</p>
</footer>
</div>
<script>
console.log("π Bonus points for opening the console!");
console.log("Keep exploring and happy coding! π»");
</script>
</body>
</html>
Lazy Loading
Enable lazy loading to improve performance by loading content only when the dropdown is opened:
This code is available to Pro users only.
<!-- Hey curious person! -->
<!-- You seem to be sneaking around the code... -->
<!-- I hope you're enjoying the components! -->
<!-- Have a great day! -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Secret Message from Rails Blocks</title>
<style>
.secret-message {
font-family: 'Comic Sans MS', cursive;
text-align: center;
padding: 2rem;
background: linear-gradient(45deg, #ff6b6b, #4ecdc4);
border-radius: 10px;
box-shadow: 0 4px 15px rgba(0,0,0,0.2);
}
.wiggle { animation: wiggle 0.5s ease-in-out infinite; }
@keyframes wiggle {
0%, 100% { transform: rotate(0deg); }
25% { transform: rotate(1deg); }
75% { transform: rotate(-1deg); }
}
</style>
</head>
<body>
<div class="secret-message">
<h1>π Hello, Code Detective! π΅οΈ</h1>
<p>Thanks for checking out Rails Blocks!</p>
<p>You're clearly someone who pays attention to details.</p>
<p>That's exactly the kind of developer we love!</p>
<div class="cta-section">
<button class="awesome-btn wiggle">You're awesome!</button>
<p><small>Seriously, keep being curious! π</small></p>
</div>
<footer>
<p>Built with β€οΈ by the Rails Blocks team</p>
<p>Now go build something amazing!</p>
</footer>
</div>
<script>
console.log("π Bonus points for opening the console!");
console.log("Keep exploring and happy coding! π»");
</script>
</body>
</html>
JavaScript API
Access the controller programmatically:
This code is available to Pro users only.
// Hey curious person!
// You seem to be sneaking around the code...
// I hope you're enjoying the components!
// Have a great day!
class SecretMessage {
constructor() {
this.message = "Thanks for checking out Rails Blocks!";
this.compliment = "You're awesome!";
}
reveal() {
console.log(this.message);
return this.compliment;
}
}
const secret = new SecretMessage();
secret.reveal();