From a6ae5c08a12b51f4c5a6d86f28fc10711112276a Mon Sep 17 00:00:00 2001
From: nod_ <nod_@598310.no-reply.drupal.org>
Date: Tue, 30 Apr 2024 02:57:34 +0900
Subject: [PATCH] Issue #3441124 by mherchel, nod_, smustgrave, xjm: Views UI
 action buttons create janky layout shift on page load

(cherry picked from commit 299f4c8e87f0716ca460dcb07c61e76f6d9703b5)
---
 core/modules/views_ui/css/views_ui.admin.css  | 27 ++++++++++++++++++
 core/themes/claro/css/components/views-ui.css | 28 +++++++++++++++++++
 .../claro/css/components/views-ui.pcss.css    | 28 +++++++++++++++++++
 3 files changed, 83 insertions(+)

diff --git a/core/modules/views_ui/css/views_ui.admin.css b/core/modules/views_ui/css/views_ui.admin.css
index 2507d306578a..aca14d88bf69 100644
--- a/core/modules/views_ui/css/views_ui.admin.css
+++ b/core/modules/views_ui/css/views_ui.admin.css
@@ -206,3 +206,30 @@ html.js span.js-only {
 .js .views-edit-view .dropbutton-wrapper {
   width: auto;
 }
+
+/* JS moves Views action buttons under a secondary tabs container, which causes
+a large layout shift. We mitigate this by using animations to temporarily hide
+the buttons, but they will appear after a set amount of time just in case the JS
+is loaded but does not properly run. */
+@media (scripting: enabled) {
+  .views-tabs__action-list-button:not(.views-tabs--secondary *) {
+    animation-name: appear;
+    animation-duration: 0.1s;
+    /* Buttons will be hidden for the amount of time in the animation-delay if
+    not moved. Note this is the approximate time to download the views
+    aggregate CSS with slow 3G. */
+    animation-delay: 5s;
+    animation-iteration-count: 1;
+    animation-fill-mode: backwards;
+  }
+}
+
+@keyframes appear {
+  from {
+    display: none;
+  }
+
+  to {
+    display: unset;
+  }
+}
diff --git a/core/themes/claro/css/components/views-ui.css b/core/themes/claro/css/components/views-ui.css
index ae0bb5a0afee..3b4a505af00f 100644
--- a/core/themes/claro/css/components/views-ui.css
+++ b/core/themes/claro/css/components/views-ui.css
@@ -406,6 +406,34 @@ details.fieldset-no-legend {
   font-weight: normal;
 }
 
+/* JS moves Views action buttons under a secondary tabs container, which causes
+a large layout shift. We mitigate this by using animations to temporarily hide
+the buttons, but they will appear after a set amount of time just in case the JS
+is loaded but does not properly run. */
+
+@media (scripting: enabled) {
+  .views-tabs__action-list-button:not(.views-tabs--secondary *) {
+    animation-name: appear;
+    animation-duration: 0.1s;
+    /* Buttons will be hidden for the amount of time in the animation-delay if
+    not moved. Note this is the approximate time to download the views
+    aggregate CSS with slow 3G. */
+    animation-delay: 5s;
+    animation-iteration-count: 1;
+    animation-fill-mode: backwards;
+  }
+}
+
+@keyframes appear {
+  from {
+    display: none;
+  }
+
+  to {
+    display: unset;
+  }
+}
+
 /* RTL required for precedence over core's styles. */
 
 [dir="rtl"] .views-tabs__action-list-button {
diff --git a/core/themes/claro/css/components/views-ui.pcss.css b/core/themes/claro/css/components/views-ui.pcss.css
index eec7ad688ac2..1537a1f93f30 100644
--- a/core/themes/claro/css/components/views-ui.pcss.css
+++ b/core/themes/claro/css/components/views-ui.pcss.css
@@ -350,6 +350,34 @@ details.fieldset-no-legend {
   background: none repeat scroll 0 0 transparent;
   font-weight: normal;
 }
+
+/* JS moves Views action buttons under a secondary tabs container, which causes
+a large layout shift. We mitigate this by using animations to temporarily hide
+the buttons, but they will appear after a set amount of time just in case the JS
+is loaded but does not properly run. */
+@media (scripting: enabled) {
+  .views-tabs__action-list-button:not(.views-tabs--secondary *) {
+    animation-name: appear;
+    animation-duration: 0.1s;
+    /* Buttons will be hidden for the amount of time in the animation-delay if
+    not moved. Note this is the approximate time to download the views
+    aggregate CSS with slow 3G. */
+    animation-delay: 5s;
+    animation-iteration-count: 1;
+    animation-fill-mode: backwards;
+  }
+}
+
+@keyframes appear {
+  from {
+    display: none;
+  }
+
+  to {
+    display: unset;
+  }
+}
+
 /* RTL required for precedence over core's styles. */
 [dir="rtl"] .views-tabs__action-list-button {
   margin: 0;
-- 
GitLab