Skip to content

Commit a64cbee

Browse files
authored
A better Device tab UI experience when there is latency (#2382)
When a tab is clicked, select it straight away, reduce the opacity of the current tab content by 50%, and when the tab has finished loading, fade the new content in. https://github.com/user-attachments/assets/482fc102-ee25-478b-97ba-c343c41b2146 This is using the latency simulator set to 300ms
1 parent 21d7c60 commit a64cbee

File tree

11 files changed

+72
-37
lines changed

11 files changed

+72
-37
lines changed

assets/ui-rework/app.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,26 @@ topbar.config({
5858
shadowColor: "rgba(0, 0, 0, .3)"
5959
})
6060

61-
window.addEventListener("phx:page-loading-start", () => {
61+
window.addEventListener("phx:page-loading-start", info => {
62+
if (info.detail.kind == "initial") {
63+
document.querySelectorAll(".tab-content").forEach(el => {
64+
el.classList.remove("opacity-0")
65+
})
66+
}
67+
68+
if (info.detail.kind == "patch") {
69+
document.querySelectorAll(".tab-content").forEach(el => {
70+
el.classList.add("phx-click-loading")
71+
})
72+
}
73+
6274
topbar.show(300)
6375
})
6476
window.addEventListener("phx:page-loading-stop", () => {
77+
document.querySelectorAll(".tab-content").forEach(el => {
78+
el.classList.remove("phx-click-loading")
79+
})
80+
6581
topbar.hide()
6682
})
6783

lib/nerves_hub_web.ex

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,7 @@ defmodule NervesHubWeb do
272272
quote do
273273
use Phoenix.Component
274274
alias Phoenix.Socket.Broadcast
275+
alias Phoenix.LiveView.JS
275276
end
276277
end
277278

lib/nerves_hub_web/components/device_page/activity_tab.ex

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,11 @@ defmodule NervesHubWeb.Components.DevicePage.ActivityTab do
3434

3535
def render(assigns) do
3636
~H"""
37-
<div class="h-full flex flex-col items-start justify-between gap-4">
37+
<div
38+
id="activity-tab"
39+
phx-mounted={JS.remove_class("opacity-0")}
40+
class="transition-all duration-500 opacity-0 tab-content phx-click-loading:opacity-50 h-full flex flex-col items-start justify-between gap-4"
41+
>
3842
<div class="p-6 w-full">
3943
<div class="w-full flex flex-col bg-zinc-900 border border-zinc-700 rounded">
4044
<div class="flex justify-between items-center h-14 px-4 border-b border-zinc-700">

lib/nerves_hub_web/components/device_page/console_tab.ex

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,11 @@ defmodule NervesHubWeb.Components.DevicePage.ConsoleTab do
8181
assigns = Map.put(assigns, :user_token, token)
8282

8383
~H"""
84-
<div class="size-full">
84+
<div
85+
id="console-tab"
86+
phx-mounted={JS.remove_class("opacity-0")}
87+
class="transition-all duration-500 opacity-0 tab-content phx-click-loading:opacity-50 size-full"
88+
>
8589
<div class="flex flex-col size-full items-start justify-between">
8690
<.async_result :let={online?} assign={@console_active?}>
8791
<:loading>

lib/nerves_hub_web/components/device_page/details_tab.ex

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,11 @@ defmodule NervesHubWeb.Components.DevicePage.DetailsTab do
7474
assigns = Map.put(assigns, :auto_refresh_health, !!assigns.health_check_timer)
7575

7676
~H"""
77-
<div class="flex items-start justify-between gap-4 p-6">
77+
<div
78+
id="details-tab"
79+
phx-mounted={JS.remove_class("opacity-0")}
80+
class="transition-all duration-500 opacity-0 tab-content phx-click-loading:opacity-50 flex items-start justify-between gap-4 p-6"
81+
>
7882
<div class="w-1/2 flex flex-col gap-4">
7983
<div :if={!@product.extensions.health || !@device.extensions.health} class="flex flex-col rounded border border-zinc-700 bg-zinc-900 shadow-device-details-content">
8084
<div class="h-14 pl-4 pr-3 flex items-center justify-between">

lib/nerves_hub_web/components/device_page/health_tab.ex

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,11 @@ defmodule NervesHubWeb.Components.DevicePage.HealthTab do
9090
assigns = Map.put(assigns, :health_enabled?, health_enabled)
9191

9292
~H"""
93-
<div class="w-full p-6">
93+
<div
94+
id="health-tab"
95+
phx-mounted={JS.remove_class("opacity-0")}
96+
class="transition-all duration-500 opacity-0 tab-content phx-click-loading:opacity-50 w-full p-6"
97+
>
9498
<div :if={Enum.any?(@latest_metrics) && @health_enabled?} class="mb-6 w-full flex flex-col bg-zinc-900 border border-zinc-700 rounded">
9599
<div class="flex flex-col shadow-device-details-content">
96100
<div class="flex pt-2 px-4 pb-4 gap-2 items-center justify-items-stretch flex-wrap">

lib/nerves_hub_web/components/device_page/local_shell_tab.ex

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,11 @@ defmodule NervesHubWeb.Components.DevicePage.LocalShellTab do
6464
assigns = Map.put(assigns, :user_token, token)
6565

6666
~H"""
67-
<div class="size-full">
67+
<div
68+
id="local-shell-tab"
69+
phx-mounted={JS.remove_class("opacity-0")}
70+
class="transition-all duration-500 opacity-0 tab-content phx-click-loading:opacity-50 size-full"
71+
>
6872
<div class="flex flex-col size-full items-start justify-between">
6973
<.async_result :let={online?} assign={@local_shell_active?}>
7074
<:loading>

lib/nerves_hub_web/components/device_page/logs_tab.ex

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,11 @@ defmodule NervesHubWeb.Components.DevicePage.LogsTab do
121121

122122
def render(assigns) do
123123
~H"""
124-
<div class="size-full bg-[#0e1019] pb-10">
124+
<div
125+
id="logs-tab"
126+
phx-mounted={JS.remove_class("opacity-0")}
127+
class="transition-all duration-500 opacity-0 tab-content phx-click-loading:opacity-50 size-full bg-[#0e1019] pb-10"
128+
>
125129
<div :if={!@has_logs} class="size-full flex justify-center items-center p-6 gap-6 text-medium font-mono">
126130
<div>No logs have been received yet.</div>
127131
</div>

lib/nerves_hub_web/components/device_page/settings_tab.ex

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,11 @@ defmodule NervesHubWeb.Components.DevicePage.SettingsTab do
3131
assigns = Map.put(assigns, :device, device)
3232

3333
~H"""
34-
<div class="flex flex-col items-start justify-between gap-4 p-6">
34+
<div
35+
id="settings-tab"
36+
phx-mounted={JS.remove_class("opacity-0")}
37+
class="transition-all duration-500 opacity-0 tab-content phx-click-loading:opacity-50 flex flex-col items-start justify-between gap-4 p-6"
38+
>
3539
<.form id="settings-form" for={@settings_form} class="w-full" phx-change="validate-device-settings" phx-submit="update-device-settings">
3640
<div class="flex flex-col w-full bg-zinc-900 border border-zinc-700 rounded">
3741
<div class="flex justify-between items-center h-14 px-4 border-b border-zinc-700">

lib/nerves_hub_web/live/devices/show.ex

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -392,13 +392,17 @@ defmodule NervesHubWeb.Live.Devices.Show do
392392
assign(socket, :tab, socket.assigns.live_action || :details)
393393
end
394394

395-
# TODO: refactor to use tailwind attributes
396-
def tab_classes(tab_selected, tab) do
397-
if tab_selected == tab do
398-
"px-6 py-2 h-11 font-normal text-sm text-neutral-50 border-b border-indigo-500 bg-tab-selected relative -bottom-px"
399-
else
400-
"px-6 py-2 h-11 font-normal text-sm text-zinc-300 hover:border-b hover:border-indigo-500 relative -bottom-px"
401-
end
395+
defp tab(assigns) do
396+
~H"""
397+
<.link
398+
data-selected={"#{@selected}"}
399+
class="px-6 py-2 h-11 font-normal text-sm text-zinc-300 hover:border-b hover:border-indigo-500 data-[selected=true]:text-neutral-50 data-[selected=true]:border-b data-[selected=true]:border-indigo-500 relative -bottom-px"
400+
phx-click={JS.set_attribute({"data-selected", "false"}, to: "#tabs a") |> JS.set_attribute({"data-selected", "true"})}
401+
patch={@path}
402+
>
403+
{@display}
404+
</.link>
405+
"""
402406
end
403407

404408
defp health_polling_seconds() do

0 commit comments

Comments
 (0)