Skip to content

Commit

Permalink
dropdown controller
Browse files Browse the repository at this point in the history
  • Loading branch information
naofumi committed Sep 3, 2024
1 parent 5a9cc90 commit f45c543
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 21 deletions.
67 changes: 67 additions & 0 deletions app/javascript/controllers/dropdown_controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
# Dropdown controller
* The menu appears on a mouseenter event on the trigger element.
* The menu disappears on a mouseleave event on the div surrounding the trigger and the menu.
The HTML should be like the following
<!-- Profile dropdown -->
<div class="relative ml-3" data-controller="dropdown" data-action="mouseleave->dropdown#hide">
<div data-action="mouseenter->dropdown#show">
<button type="button">
[button that will cause the dropdown menu to appear.
</button>
</div>
<div data-dropdown-target="menu" class="absolute right-0 z-10 mt-2 w-48 origin-top-right rounded-md bg-white py-1 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none transform opacity-0 scale-95" role="menu" aria-orientation="vertical" aria-labelledby="user-menu-button" tabindex="-1">
[The dropdown menu that appears]
</div>
</div>
Targets
* menuTargets: The menus that will be shown and hidden in response to the show() and hide() actions.
Classes
* showClasses, hideClasses: The classes added/removed from the menu in the show() and hide() actions.
* */

import {Controller} from "@hotwired/stimulus"
import {classTokenize} from "../utlitilies";

const DefaultShowClasses = classTokenize("transform opacity-100 scale-100 visible transition-all ease-out duration-200")
const DefaultHideClasses = classTokenize("transform opacity-0 scale-95 collapse transition-all ease-in duration-75")

// Connects to data-controller="dropdown"
export default class DropdownController extends Controller {
static targets = ["menu"]
static classes = ["show", "hide"]

connect() {
}

show() {
this.menuTargets.forEach(target => {
target.classList.remove(...this.#hideClasses())
target.classList.add(...this.#showClasses())
})
}

hide() {
this.menuTargets.forEach(target => {
target.classList.remove(...this.#showClasses())
target.classList.add(...this.#hideClasses())
})
}

#showClasses() {
return this.showClasses.length
? this.showClasses
: DefaultShowClasses
}

#hideClasses() {
return this.hideClasses.length
? this.hideClasses
: DefaultHideClasses
}
}
3 changes: 3 additions & 0 deletions app/javascript/controllers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

import { application } from "./application"

import DropdownController from "./dropdown_controller"
application.register("dropdown", DropdownController)

import HelloController from "./hello_controller"
application.register("hello", HelloController)

Expand Down
3 changes: 3 additions & 0 deletions app/javascript/utlitilies.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function classTokenize(string, separator=" ") {
return string.split(separator).filter(i => i)
}
22 changes: 10 additions & 12 deletions app/views/components/_template.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,16 @@
<% content_for(:title, "#{title} | Tailwind, ERB & Stimulus") %>

<div class="container mx-auto px-4 my-6 sm:px-6 lg:px-8">
<div class="divide-y divide-gray-200 overflow-hidden rounded-lg bg-white shadow">
<div class="px-4 py-5 sm:px-6">
<h1 class="font-light text-6xl text-center">
<%= title %>
</h1>
<p class="mt-6 leading-6 text-lg text-center">
<%= description %>
</p>
</div>
<div class="px-4 py-5 sm:p-6 text-center h-96">
<%= yield %>
</div>
<div class="px-4 py-5 sm:px-6">
<h1 class="font-light text-6xl text-center">
<%= title %>
</h1>
<p class="mt-6 leading-6 text-lg text-center">
<%= description %>
</p>
</div>
<div class="px-4 py-5 sm:p-6 text-center h-96">
<%= yield %>
</div>
</div>

25 changes: 16 additions & 9 deletions app/views/components/navigation.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,27 @@
<%= render 'template',
title: "Navigation",
description: "" do %>

<div class="mb-6 text-left">
This is a Navigation bar. This contains multiple Stimulus controllers.
<ul class="list-disc ml-4">
<li>A <code>tablist</code> controller for the tabs.</li>
<li>A <code>dropdown</code> controller for the account dropdown menu.</li>
<li>A <code>hamburger</code> controller for the mobile menu.</li>
</ul>
</div>
<nav class="bg-white shadow">
<div class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
<div class="flex h-16 justify-between">
<div class="flex">
<div class="flex flex-shrink-0 items-center">
<img class="h-8 w-auto" src="https://tailwindui.com/img/logos/mark.svg?color=indigo&shade=600" alt="Your Company">
</div>
<div class="hidden sm:ml-6 sm:flex sm:space-x-8">
<div class="hidden sm:ml-6 sm:flex sm:space-x-8" data-controller="tablist">
<!-- Current: "border-indigo-500 text-gray-900", Default: "border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700" -->
<a href="javascript:void(0)" class="inline-flex items-center border-b-2 border-indigo-500 px-1 pt-1 text-sm font-medium text-gray-900" aria-current="page">Dashboard</a>
<a href="javascript:void(0)" class="inline-flex items-center border-b-2 border-transparent px-1 pt-1 text-sm font-medium text-gray-500 hover:border-gray-300 hover:text-gray-700">Team</a>
<a href="javascript:void(0)" class="inline-flex items-center border-b-2 border-transparent px-1 pt-1 text-sm font-medium text-gray-500 hover:border-gray-300 hover:text-gray-700">Projects</a>
<a href="javascript:void(0)" class="inline-flex items-center border-b-2 border-transparent px-1 pt-1 text-sm font-medium text-gray-500 hover:border-gray-300 hover:text-gray-700">Calendar</a>
<a href="javascript:void(0)" data-action="click->tablist#select" class="inline-flex items-center border-b-2 border-transparent px-1 pt-1 text-sm font-medium text-gray-900" aria-current="page">Dashboard</a>
<a href="javascript:void(0)" data-action="click->tablist#select" class="inline-flex items-center border-b-2 border-transparent px-1 pt-1 text-sm font-medium text-gray-500 hover:border-gray-300 hover:text-gray-700">Projects</a>
<a href="javascript:void(0)" data-action="click->tablist#select" class="inline-flex items-center border-b-2 border-transparent px-1 pt-1 text-sm font-medium text-gray-500 hover:border-gray-300 hover:text-gray-700">Team</a>
<a href="javascript:void(0)" data-action="click->tablist#select" class="inline-flex items-center border-b-2 border-transparent px-1 pt-1 text-sm font-medium text-gray-500 hover:border-gray-300 hover:text-gray-700">Calendar</a>
</div>
</div>
<div class="hidden sm:ml-6 sm:flex sm:items-center">
Expand All @@ -29,8 +36,8 @@
</button>

<!-- Profile dropdown -->
<div class="relative ml-3">
<div>
<div class="relative ml-3" data-controller="dropdown" data-action="mouseleave->dropdown#hide">
<div data-action="mouseenter->dropdown#show">
<button type="button" class="relative flex rounded-full bg-white text-sm focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2" id="user-menu-button" aria-expanded="false" aria-haspopup="true">
<span class="absolute -inset-1.5"></span>
<span class="sr-only">Open user menu</span>
Expand All @@ -48,7 +55,7 @@
From: "transform opacity-100 scale-100"
To: "transform opacity-0 scale-95"
-->
<div class="absolute right-0 z-10 mt-2 w-48 origin-top-right rounded-md bg-white py-1 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none" role="menu" aria-orientation="vertical" aria-labelledby="user-menu-button" tabindex="-1">
<div data-dropdown-target="menu" class="absolute right-0 z-10 mt-2 w-48 origin-top-right rounded-md bg-white py-1 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none transform opacity-0 collapse scale-95" role="menu" aria-orientation="vertical" aria-labelledby="user-menu-button" tabindex="-1">
<!-- Active: "bg-gray-100", Not Active: "" -->
<a href="#" class="block px-4 py-2 text-sm text-gray-700" role="menuitem" tabindex="-1" id="user-menu-item-0">Your Profile</a>
<a href="#" class="block px-4 py-2 text-sm text-gray-700" role="menuitem" tabindex="-1" id="user-menu-item-1">Settings</a>
Expand Down

0 comments on commit f45c543

Please sign in to comment.