From f45c543e5ea0179f8232057727be49dafa08f595 Mon Sep 17 00:00:00 2001 From: Naofumi Kagami Date: Tue, 3 Sep 2024 10:54:51 +0900 Subject: [PATCH] dropdown controller --- .../controllers/dropdown_controller.js | 67 +++++++++++++++++++ app/javascript/controllers/index.js | 3 + app/javascript/utlitilies.js | 3 + app/views/components/_template.html.erb | 22 +++--- app/views/components/navigation.html.erb | 25 ++++--- 5 files changed, 99 insertions(+), 21 deletions(-) create mode 100644 app/javascript/controllers/dropdown_controller.js create mode 100644 app/javascript/utlitilies.js diff --git a/app/javascript/controllers/dropdown_controller.js b/app/javascript/controllers/dropdown_controller.js new file mode 100644 index 0000000..b5e8faa --- /dev/null +++ b/app/javascript/controllers/dropdown_controller.js @@ -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 + + +
+
+ +
+ + +
+ +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 + } +} diff --git a/app/javascript/controllers/index.js b/app/javascript/controllers/index.js index 4722524..5008096 100644 --- a/app/javascript/controllers/index.js +++ b/app/javascript/controllers/index.js @@ -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) diff --git a/app/javascript/utlitilies.js b/app/javascript/utlitilies.js new file mode 100644 index 0000000..fe727f9 --- /dev/null +++ b/app/javascript/utlitilies.js @@ -0,0 +1,3 @@ +export function classTokenize(string, separator=" ") { + return string.split(separator).filter(i => i) +} diff --git a/app/views/components/_template.html.erb b/app/views/components/_template.html.erb index 5391c5a..2e962a5 100644 --- a/app/views/components/_template.html.erb +++ b/app/views/components/_template.html.erb @@ -3,18 +3,16 @@ <% content_for(:title, "#{title} | Tailwind, ERB & Stimulus") %>
-
-
-

- <%= title %> -

-

- <%= description %> -

-
-
- <%= yield %> -
+
+

+ <%= title %> +

+

+ <%= description %> +

+
+
+ <%= yield %>
diff --git a/app/views/components/navigation.html.erb b/app/views/components/navigation.html.erb index dd94475..f080ee3 100644 --- a/app/views/components/navigation.html.erb +++ b/app/views/components/navigation.html.erb @@ -3,7 +3,14 @@ <%= render 'template', title: "Navigation", description: "" do %> - +
+ This is a Navigation bar. This contains multiple Stimulus controllers. +
    +
  • A tablist controller for the tabs.
  • +
  • A dropdown controller for the account dropdown menu.
  • +
  • A hamburger controller for the mobile menu.
  • +
+