投稿画面のモーダル化

This commit is contained in:
Rikuoh Tsujitani 2025-02-25 09:23:00 +09:00
parent e7bee77eea
commit 6dd33e849b
Signed by: riq0h
GPG key ID: 010F09DEA298C717
13 changed files with 122 additions and 83 deletions

View file

@ -14,3 +14,30 @@
transform: translateY(0);
}
}
.modal {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
z-index: 1000;
cursor: pointer;
}
.modal-dialog {
position: relative;
margin: 1.75rem auto;
max-width: 500px;
cursor: default;
}
.modal-content {
position: relative;
background-color: #fff;
border-radius: 0.5rem;
padding: 1rem;
margin: 2rem;
}

View file

@ -1,8 +1,11 @@
import { application } from "./application";
import SearchController from "./search_controller";
import MemoCardController from "./memo_card_controller";
import MemoFormController from "./memo_form_controller";
// This file is auto-generated by ./bin/rails stimulus:manifest:update
// Run that command whenever you add a new controller or create them with
// ./bin/rails generate stimulus controllerName
import { application } from "./application";
import ModalController from "./modal_controller";
application.register("modal", ModalController);
import SearchController from "./search_controller";
application.register("search", SearchController);
application.register("memo_card", MemoCardController);
application.register("memo_form", MemoFormController);

View file

@ -1,15 +0,0 @@
import { Controller } from "@hotwired/stimulus";
export default class extends Controller {
connect() {
this.element.classList.add("opacity-0");
this.element.classList.add("translate-y-4");
requestAnimationFrame(() => {
this.element.classList.remove("opacity-0");
this.element.classList.remove("translate-y-4");
this.element.classList.add("transition-all");
this.element.classList.add("duration-300");
});
}
}

View file

@ -1,11 +0,0 @@
import { Controller } from "@hotwired/stimulus";
export default class extends Controller {
static targets = ["textarea"];
connect() {
if (this.hasTextareaTarget) {
this.textareaTarget.focus();
}
}
}

View file

@ -0,0 +1,24 @@
import { Controller } from "@hotwired/stimulus";
export default class extends Controller {
connect() {
this.element.style.display = "none";
}
open() {
this.element.style.display = "block";
}
close() {
this.element.style.display = "none";
const frame = document.getElementById("modal");
frame.removeAttribute("src");
frame.innerHTML = "";
}
clickOutside(event) {
if (event.target === this.element) {
this.close();
}
}
}

View file

@ -3,33 +3,42 @@
<head>
<title>rails8-memoapp</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="turbo-cache-control" content="no-cache">
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
<%= stylesheet_link_tag "tailwind", "data-turbo-track": "reload" %>
<%= javascript_include_tag "application", "data-turbo-track": "reload", type: "module", as: "script" %>
</head>
<% if current_user %>
<div class="fixed top-4 left-4 text-sm text-gray-600 bg-gray-100 px-3 py-1 rounded-full">
<%= current_user.email %>
</div>
<% end %>
<body class="bg-gray-50">
<% if user_signed_in? %>
<div class="fixed top-4 right-4">
<%= button_to destroy_user_session_path,
method: :delete,
class: "bg-gray-500 hover:bg-gray-600 text-white font-bold py-2 px-4 rounded-lg transition-colors duration-200" do %>
退出
<% end %>
<% if current_user %>
<div class="fixed top-4 left-4 text-sm text-gray-600 bg-gray-100 px-3 py-1 rounded-full">
<%= current_user.email %>
</div>
<% end %>
<% if user_signed_in? %>
<div class="fixed top-4 right-4">
<%= button_to destroy_user_session_path,
method: :delete,
class: "bg-gray-500 hover:bg-gray-600 text-white font-bold py-2 px-4 rounded-lg transition-colors duration-200" do %>
退出
<% end %>
</div>
<% end %>
<div class="max-w-2xl mx-auto px-4">
<%= yield %>
</div>
<div class="modal"
tabindex="-1"
data-controller="modal"
data-action="click->modal#clickOutside turbo:frame-load->modal#open turbo:submit-end->modal#close">
<div class="modal-dialog">
<div class="modal-content">
<%= turbo_frame_tag "modal" %>
</div>
</div>
<% end %>
<div class="max-w-2xl mx-auto px-4">
<%= yield %>
</div>
</body>
</body>
</html>

View file

@ -1,7 +1,8 @@
<div class="space-y-6">
<%= turbo_frame_tag "modal" do %>
<div class="space-y-6">
<%= form_with(model: memo,
class: "space-y-6",
data: { turbo: false }) do |f| %>
data: { turbo: true }) do |f| %>
<% if memo.errors.any? %>
<div class="bg-red-50 p-4 rounded-md">
<div class="text-red-700">
@ -14,7 +15,6 @@
</div>
</div>
<% end %>
<div>
<%= f.text_area :content,
class: "w-full h-64 p-4 border rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500",
@ -27,12 +27,16 @@
<p class="mt-2 text-sm text-gray-500">現在の画像: <%= memo.image.filename %></p>
<% end %>
</div>
<div class="flex gap-4 items-center">
<%= f.submit memo.new_record? ? "出力" : "修正",
class: "bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded" %>
<%= link_to "終了", memos_path,
class: "bg-gray-500 hover:bg-gray-700 text-white font-bold py-2 px-4 rounded" %>
class: "bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded" %>
<%= link_to "終了", "#",
class: "bg-gray-500 hover:bg-gray-700 text-white font-bold py-2 px-4 rounded",
data: {
action: "modal#close",
turbo_frame: "modal"
} %>
</div>
<% end %>
</div>
<% end %>
</div>
<% end %>

View file

@ -1,7 +1,6 @@
<%= turbo_frame_tag dom_id(memo) do %>
<div data-controller="memo-card"
class="relative bg-white p-6 rounded-lg shadow-md hover:shadow-lg transition-all duration-200 transform hover:-translate-y-1">
<%= link_to edit_memo_path(memo), class: "h-full flex flex-col", data: { turbo_frame: "_top" } do %>
<div class="relative bg-white p-6 rounded-lg shadow-md hover:shadow-lg transition-all duration-200 transform hover:-translate-y-1">
<%= link_to edit_memo_path(memo), class: "h-full flex flex-col", data: { turbo_frame: "modal" } do %>
<h2 class="text-xl font-semibold text-gray-800 mb-2 line-clamp-2">
<%= memo.content.lines.first.try(:strip) || "無題" %>
</h2>
@ -19,7 +18,6 @@
</span>
</div>
<% end %>
<div class="absolute top-4 right-4">
<%= button_to memo_path(memo),
method: :delete,

View file

@ -1 +0,0 @@
<turbo-stream action="redirect" url="<%= memos_path %>"></turbo-stream>

View file

@ -1,4 +1,5 @@
<div class="max-w-2xl mx-auto">
<h1 class="text-2xl font-bold text-gray-900 mb-6">修正</h1>
<%= render 'form', memo: @memo %>
</div>
<%= turbo_frame_tag "modal" do %>
<div class="modal-body">
<%= render "form", memo: @memo %>
</div>
<% end %>

View file

@ -8,20 +8,20 @@
data: { action: "input->search#search" } %>
</div>
<% end %>
<%= link_to new_memo_path, class: "bg-blue-500 hover:bg-blue-600 text-white font-bold py-2 px-4 rounded-lg transition-colors duration-200" do %>
<span class="flex items-center">
出力開始
</span>
<% end %>
<%= link_to new_memo_path,
class: "bg-blue-500 hover:bg-blue-600 text-white font-bold py-2 px-4 rounded-lg transition-colors duration-200",
data: { turbo_frame: "modal" } do %>
<span class="flex items-center">
出力開始
</span>
<% end %>
</div>
</div>
<%= turbo_frame_tag "memos" do %>
<%= turbo_frame_tag "memos", data: { turbo_action: :advance } do %>
<div id="memos-container" class="flex flex-col gap-4">
<%= render @memos %>
<%= render "empty_results", query: @q&.content_cont if @memos.empty? %>
</div>
<div class="text-center mt-8">
<%= link_to_next_page @memos, "気力十分😤",
class: "inline-flex items-center px-4 py-2 bg-blue-500 hover:bg-blue-600 text-white font-medium rounded-lg transition-colors duration-200",

View file

@ -1,4 +1,5 @@
<div class="max-w-2xl mx-auto">
<h1 class="text-2xl font-bold text-gray-900 mb-6">出力</h1>
<%= render 'form', memo: @memo %>
</div>
<%= turbo_frame_tag "modal" do %>
<div class="modal-body">
<%= render "form", memo: @memo %>
</div>
<% end %>

View file

@ -1 +0,0 @@
<turbo-stream action="redirect" url="<%= memos_path %>"></turbo-stream>