From 9df2d3fcb84d20ff407ad224c423c1205fb99a04 Mon Sep 17 00:00:00 2001
From: Felix Eckhofer <felix@eckhofer.com>
Date: Fri, 20 Dec 2024 21:18:06 +0100
Subject: [PATCH] Hide using display:none instead of hidden

This is more consistent and actually removes the elements from the layout.

The commit also hides the conditional elements by default, which should
be a more natural loading experience.
---
 .../controllers/session_controller.js         | 18 ++++++++++-----
 app/views/sessions/_session.html.erb          | 23 +++++++++++--------
 2 files changed, 26 insertions(+), 15 deletions(-)

diff --git a/app/javascript/controllers/session_controller.js b/app/javascript/controllers/session_controller.js
index 8cef9dc..e58fcfd 100644
--- a/app/javascript/controllers/session_controller.js
+++ b/app/javascript/controllers/session_controller.js
@@ -1,5 +1,13 @@
 import { Controller } from "@hotwired/stimulus"
 
+function hide(elem, hide) {
+  if (hide) {
+    elem.classList.add("hidden");
+  } else {
+    elem.classList.remove("hidden");
+  }
+}
+
 export default class extends Controller {
   static targets = ["candidates"];
 
@@ -8,19 +16,17 @@ export default class extends Controller {
     const isCandidate = this.candidatesTarget.querySelector(`a.candidate[data-candidate-uid="${uid}"]`);
 
     this.element.querySelectorAll('.only-loggedin').forEach(el => {
-      el.hidden = !uid;
+      hide(el, !uid);
     });
     this.element.querySelectorAll('.only-loggedout').forEach(el => {
-      el.hidden = uid;
+      hide(el, uid);
     });
     this.element.querySelectorAll('.only-candidate').forEach(el => {
-      el.hidden = !isCandidate;
+      hide(el, !isCandidate);
     });
     this.element.querySelectorAll('.only-no-candidate').forEach(el => {
-      el.hidden = isCandidate;
+      hide(el, isCandidate);
     });
-
-
   }
 
   submitWithPrompt(event) {
diff --git a/app/views/sessions/_session.html.erb b/app/views/sessions/_session.html.erb
index 9a2b4fc..59e8592 100644
--- a/app/views/sessions/_session.html.erb
+++ b/app/views/sessions/_session.html.erb
@@ -20,15 +20,15 @@
         </svg>
         <%= session.stage.name %>
       </span>
-      <span class="absolute top-0 right-0 text-3xl only-loggedin">
-        <%= link_to conference_session_candidates_path(session.conference, session), class: "pr-1 only-candidate", title: "Withdraw", aria_label: "Withdraw", data: { turbo_method: :delete, turbo_frame: dom_id(session) }, method: :delete do %>
+      <span class="absolute top-0 right-0 text-3xl only-loggedin hidden">
+        <%= link_to conference_session_candidates_path(session.conference, session), class: "pr-1 only-candidate hidden", title: "Withdraw", aria_label: "Withdraw", data: { turbo_method: :delete, turbo_frame: dom_id(session) }, method: :delete do %>
           🙅
         <% end %>
-        <%= link_to conference_session_candidates_path(session.conference, session), class: "pr-1 only-no-candidate", title: "Volunteer Myself", aria_label: "Volunteer Myself", data: { turbo_method: :post, turbo_frame: dom_id(session) } do %>
+        <%= link_to conference_session_candidates_path(session.conference, session), class: "pr-1 only-no-candidate hidden", title: "Volunteer Myself", aria_label: "Volunteer Myself", data: { turbo_method: :post, turbo_frame: dom_id(session) } do %>
           🙋
         <% end %>
         <%= form_with url: conference_session_candidates_path(session.conference, session), method: :post, class: "inline", data: { turbo_frame: dom_id(session) } do |form| %>
-          <%= link_to conference_session_candidates_path(session.conference, session), class: "pr-1 only-no-candidate", title: "Volunteer (with special skills)", aria_label: "Volunteer (with special skills)", data: { action: "session#submitWithPrompt", prompt: "Why are you especially qualified? (Please keep it short, thanks)", turbo_prefetch:"false" } do %>
+          <%= link_to conference_session_candidates_path(session.conference, session), class: "pr-1 only-no-candidate hidden", title: "Volunteer (with special skills)", aria_label: "Volunteer (with special skills)", data: { action: "session#submitWithPrompt", prompt: "Why are you especially qualified? (Please keep it short, thanks)", turbo_prefetch:"false" } do %>
               🙌
           <% end %>
         <% end %>
@@ -58,8 +58,8 @@
         </li>
       <% end %>
     </ul>
-    <hr>
     <% if @assignment&.errors&.any? %>
+      <hr>
       <div class="alert alert-danger bg-red-600 border-red-800 text-white border p-2 shadow z-30 rounded-md" onclick="this.parentNode.removeChild(this)">
         <div class="float-right"><span class="sr-only">Close</span>
           <svg viewBox="0 0 14 14" class="size-3.5 stroke-white">
@@ -70,16 +70,21 @@
         <%= @assignment.errors.full_messages.join(", ") %>
       </div>
     <% end %>
+    <div data-session-target="candidates">
+    <% if session.candidates.length > 0 %>
+    <hr>
     <small>candidates (<%= session.candidates.length %>)</small>
-    <ul class="inline-flex flex-wrap gap-1 my-1" data-session-target="candidates">
+    <ul class="inline-flex flex-wrap gap-1 my-1">
       <% session.candidates.sort_by { |cand| cand.note.nil? ? 1:0 }.each do |candidate| %>
         <li class="inline-flex items-end">
           <span class="assigned-user"><%= render partial: 'candidates/user_avatar', locals: { candidate: } %></span>
         </li>
       <% end %>
     </ul>
-    <hr>
-    <small>unassigned (<%= unassigned_users.length %>)</small>
-    <%= render partial: 'assignments/filteredlist', locals: { session: session, users: unassigned_users } %>
+    <% end %>
+    </div>
+    <small class="hidden">unassigned (<%= unassigned_users.length %>)</small>
+    <hr class="hidden">
+    <%# render partial: 'assignments/filteredlist', locals: { session: session, users: unassigned_users } %>
   </div>
 <% end %>
-- 
GitLab