A ruby friend named Daniel emailed me a request for this feature:
Here’s my solution, Daniel:
- ✅ Collapsible sidebar
- ✅ Save state
- ✅ Elegant solution
First, create a stimulus controller to collapse sidebar. Write the current state to cookies
// app/javascript/controllers/sidebar_controller.js import { Controller } from "@hotwired/stimulus" export default class extends Controller { static targets = ["sidebarContainer"]; toggle(e) { e.preventDefault(); this.switchCurrentState(); } switchCurrentState() { const newState = this.element.dataset.expanded === "true" ? "false" : "true"; this.element.dataset.expanded = newState; document.cookie = `sidebar_expanded=${newState}`; // document.cookie = `sidebar_expanded=${newState}; path=/`; } }
The toggle can be triggered by a button like this:
<%= button_to "Toggle", nil, data: { action: "click->sidebar#toggle" }
Toggling the button will update cookies[:sidebar_expanded]
.
This is accessible in CSS via [[data-expanded=false]_&]:
. You can use it as a condition!
Here’s a sidebar that hides text like "Home"
& "Buttons"
when data-expanded=false
:
<!-- app/views/layouts/_sidebar.html.erb --> <nav class="bg-slate-400 hidden md:flex flex-col text-center p-4 justify-between sticky top-20 h-[calc(100vh-80px)]" data-controller="sidebar" data-expanded="<%= (cookies[:sidebar_expanded] || true) %>"> <div class="flex flex-col text-left"> <%= link_to root_path do %> <span>🏠</span> <span class="[[data-expanded=false]_&]:hidden">Home</span> <% end %> <%= link_to buttons_path do %> <span>🔘</span> <span class="[[data-expanded=false]_&]:hidden">Buttons</span> <% end %> </div> <div class="text-left"> <%= button_to nil, data: { action: "click->sidebar#toggle" } do %> <span class="[[data-expanded=true]_&]:hidden">➡️</span> <span class="[[data-expanded=false]_&]:hidden">⬅️</span> <span class="[[data-expanded=false]_&]:hidden">Toggle</span> <% end %> </div> </nav>
🤠 Voila!
Top comments (2)
spammer reported