Fix mobile layout issues

This commit is contained in:
2025-06-21 06:44:35 +02:00
parent 4a5874d4f8
commit 5985a726e3
15 changed files with 229 additions and 45 deletions

View File

@ -16,7 +16,7 @@
<!-- Sidebar -->
<aside class="hidden md:flex md:w-64 flex-col h-full min-h-screen bg-white border-r border-gray-300 dark:bg-gray-800 dark:border-gray-700" id="sidebar" aria-label="sidebar">
<aside class="hidden lg:flex lg:w-64 flex-col h-full min-h-screen bg-white border-r border-gray-300 dark:bg-gray-800 dark:border-gray-700" id="sidebar" aria-label="sidebar">
{% include "base/partials/sidebar.html.j2" %}
</aside>
<!-- Main Panel -->

View File

@ -2,25 +2,58 @@
{% block page_content %}
<!-- Master-Detail Split View -->
<div class="flex h-[calc(100vh-3.5rem)] overflow-hidden">
<!-- Master-Detail Split View -->
<div class="flex h-[calc(100vh-5.5rem)] lg:h-[calc(100vh-3.5rem)] overflow-hidden">
<!-- Master Pane -->
<aside id="master-pane"
class="md:w-80 w-full shrink-0 border-r overflow-y-auto bg-white md:block border-gray-200 p-4 dark:bg-gray-800 dark:border-gray-700">
{% block master %}
<p class="p-4 text-gray-500">Master view (e.g. list/tree)</p>
{% endblock %}
</aside>
<!-- Master Pane -->
<aside id="master-pane"
class="lg:w-80 w-full shrink-0 border-r overflow-y-auto bg-white lg:block border-gray-200 p-4 dark:bg-gray-800 dark:border-gray-700 {% if mobile_show_details|default(false) -%} hidden{% endif -%}">
{% block master %}
<p class="p-4 text-gray-500">Master view (e.g. list/tree)</p>
{% endblock %}
</aside>
<!-- Detail Pane -->
<section id="detail-pane"
class="flex-1 flex overflow-y-auto bg-white p-4 hidden md:block dark:bg-gray-800">
{% block detail %}
<p class="p-4 text-gray-500 dark:text-gray-200">Select an item to view details</p>
<!-- Detail Pane -->
<section id="detail-pane"
class="flex-1 flex overflow-y-auto bg-white p-4 {%- if not mobile_show_details|default(false) -%} hidden{%- endif -%} lg:block dark:bg-gray-800">
{% block detail %}
<p class="p-4 text-gray-500 dark:text-gray-200">Select an item to view details</p>
{% endblock %}
<div class="lg:hidden h-16 block">
&nbsp;
</div>
</section>
{% block master_detail_nav %}
{# mobile navigation for master-detail views #}
<div class="lg:hidden fixed bottom-0 left-0 z-10 w-full h-16 bg-white border-t border-gray-200 dark:bg-gray-700 dark:border-gray-600">
<section id="bottom-toolbar"
class="flex-1 flex grid grid-cols-2 blace-content-between">
<div class="flex w-full justify-start">
<sl-tooltip content="Back to list">
<sl-icon-button name="caret-left" label="back" id="showMasterBtn" style="font-size: 2.5rem;"></sl-icon-button>
</sl-tooltip>
</div>
<div class="flex w-full justify-end">
<sl-tooltip content="Show Details">
<sl-icon-button name="caret-right" label="back" id="showDetailsBtn" style="font-size: 2.5rem;"></sl-icon-button>
</sl-tooltip>
</div>
</section>
</div>
{% endblock %}
</section>
</div>
</div>
<script>
{% include '/base/partials/master-detail-nav.js' %}
</script>
{% endblock %}

View File

@ -0,0 +1,51 @@
function toggleDetails() {
const masterPane = document.getElementById("master-pane");
const detailPane = document.getElementById("detail-pane");
masterPane.classList.toggle("hidden");
detailPane.classList.toggle("hidden");
}
function showDetails() {
const masterPane = document.getElementById("master-pane");
const detailPane = document.getElementById("detail-pane");
masterPane.classList.add("hidden");
detailPane.classList.remove("hidden");
}
function showMaster() {
const masterPane = document.getElementById("master-pane");
const detailPane = document.getElementById("detail-pane");
masterPane.classList.remove("hidden");
detailPane.classList.add("hidden");
}
function addBtnEvent() {
const showDetailsBtn = document.getElementById("showDetailsBtn");
const showMasterBtn = document.getElementById("showMasterBtn");
const masterPane = document.getElementById("master-pane");
const detailPane = document.getElementById("detail-pane");
if (!showDetailsBtn) {
console.log("Can't find the button!");
return;
}
showMasterBtn.addEventListener("click", () => {
showMaster();
});
showDetailsBtn.addEventListener("click", () => {
showDetails();
});
}
document.addEventListener("DOMContentLoaded", () => {
addBtnEvent();
});
document.addEventListener("htmx:afterSettle", () => {
addBtnEvent();
});

View File

@ -8,7 +8,7 @@
id="sidebar-toggle"
aria-expanded="true"
aria-controls="mobile-sidebar"
class="md:hidden text-gray-600 hover:text-gray-900 focus:outline-none"
class="lg:hidden text-gray-600 hover:text-gray-900 focus:outline-none"
aria-label="Toggle sidebar"
>
<sl-icon name="list" class="text-xl"></sl-icon>

View File

@ -5,6 +5,7 @@
<div id="client-tree">
{% include '/clients/partials/tree.html.j2' %}
</div>
{% include '/clients/partials/drawer_create.html.j2' %}
{% endblock %}
@ -13,9 +14,9 @@
<div id="clientdetails" class="w-full">
{% include '/clients/partials/client_details.html.j2' %}
</div>
<!-- after clientdetails -->
{% endblock %}
{% include '/clients/partials/drawer_create.html.j2' %}
{% block local_scripts %}
<script>
{% include '/clients/partials/tree_event.js' %}

View File

@ -1,6 +1,9 @@
<!-- menu -->
<div class="flowbite-init-target">
<!-- start of client details inner -->
<div class="flex justify-end px-4">
<button id="client-menu-button" data-dropdown-toggle="client-edit-menu" class="inline-block text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 focus:ring-4 focus:outline-none focus:ring-gray-200 dark:focus:ring-gray-700 rounded-lg text-sm p-1.5" type="button">
<span class="sr-only">Open dropdown</span>
@ -38,6 +41,8 @@
</ul>
</div>
</div>
<sl-tab-group >
<sl-tab slot="nav" panel="client_data">Client Data</sl-tab>
<sl-tab slot="nav" panel="events">Events</sl-tab>
@ -84,12 +89,14 @@
</div>
</div>
</sl-tab-panel>
<sl-tab-panel name="events">
<div id="client-audit-events">
{% include '/clients/partials/client_events.html.j2' %}
</div>
</sl-tab-panel>
</sl-tab-group>
</div>
{% include '/clients/partials/drawer_edit.html.j2' %}
</div>
<!-- end of client details -->
{% include '/clients/partials/drawer_edit.html.j2' %}

View File

@ -91,6 +91,7 @@
<div
class="sticky bottom-0 right-0 items-center w-full p-4 bg-white border-t border-gray-200 sm:flex sm:justify-between dark:bg-gray-800 dark:border-gray-700"
>
<div class="flex items-center mb-4 sm:mb-0">
<span class="text-sm font-normal text-gray-500 dark:text-gray-400"
@ -100,11 +101,10 @@
{% else %}
<span class="font-semibold text-gray-900 dark:text-white">{{events_paging.first }}-{{ events_paging.last}}</span> of
{% endif %}
<span class="font-semibold text-gray-900 dark:text-white"
>{{ events_paging.total }}</span
></span
>
<span class="font-semibold text-gray-900 dark:text-white">{{ events_paging.total }}</span>
</span>
</div>
<div class="flex items-center space-x-3">
<div class="flex space-x-1">
@ -139,19 +139,20 @@
</button>
{% endif %}
{% endfor %}
<button
{% if events_paging.page < events_paging.total_pages %}
class="px-3 py-1 min-w-9 min-h-9 text-sm font-normal text-white bg-primary-700 hover:bg-primary-800 focus:ring-4 focus:ring-primary-300 dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800 transition duration-200 ease"
hx-get="/clients/client/{{ client.id }}/events/{{ events_paging.page + 1 }}"
hx-target="#client-audit-events"
<button
class="px-3 py-1 min-w-9 min-h-9 text-sm font-normal text-white bg-primary-700 hover:bg-primary-800 focus:ring-4 focus:ring-primary-300 dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800 transition duration-200 ease"
hx-get="/clients/client/{{ client.id }}/events/{{ events_paging.page + 1 }}"
hx-target="#client-audit-events">
Next
</button>
{% else %}
class="px-3 py-1 min-w-9 min-h-9 text-sm font-normal text-gray-900 bg-white border border-gray-300 rounded hover:bg-gray-100 focus:ring-4 focus:ring-primary-300 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700 transition duration-200 ease"
disabled=""
<button
class="px-3 py-1 min-w-9 min-h-9 text-sm font-normal text-gray-900 bg-white border border-gray-300 rounded hover:bg-gray-100 focus:ring-4 focus:ring-primary-300 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700 transition duration-200 ease"
disabled="">
Next
</button>
{% endif %}
>
Next
</button>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,21 @@
function addBtnEvent() {
const swapButton = document.getElementById("swapPanes");
const masterPane = document.getElementById("master-pane");
const detailPane = document.getElementById("detail-pane");
if (!swapButton) {
console.log("Can't find the button!");
return;
}
swapButton.addEventListener("click", () => {
console.log("Swap!");
masterPane.classList.remove("hidden");
detailPane.classList.add("hidden");
});
}
document.addEventListener("htmx:afterSettle", () => {
addBtnEvent();
});
document.addEventListener("DOMContentLoaded", () => {
addBtnEvent();
});

View File

@ -1,6 +1,6 @@
<div
id="drawer-update-client-{{ client.id }}"
class="fixed top-0 right-0 z-40 w-full h-screen max-w-xs p-4 overflow-y-auto transition-transform translate-x-full bg-white dark:bg-gray-800"
class="fixed top-0 right-0 z-50 w-full h-screen max-w-xs p-4 overflow-y-auto transition-transform translate-x-full bg-white dark:bg-gray-800"
tabindex="-1"
aria-labelledby="drawer-label-{{ client.id }}"
aria-hidden="true"

View File

@ -109,5 +109,3 @@
{% include '/secrets/partials/tree_event.js' %}
</script>
{% endblock %}

View File

@ -0,0 +1,27 @@
function addBtnEvent() {
const swapButton = document.getElementById("swapPanes");
const masterPane = document.getElementById("master-pane");
const detailPane = document.getElementById("detail-pane");
if (!swapButton) {
console.log("Can't find the button!");
return;
}
swapButton.addEventListener("click", () => {
console.log("Swap!");
masterPane.classList.remove("hidden");
detailPane.classList.add("hidden");
});
}
document.addEventListener("DOMContentLoaded", () => {
const masterPane = document.getElementById("master-pane");
const detailPane = document.getElementById("detail-pane");
masterPane.classList.add("hidden");
detailPane.classList.remove("hidden");
addBtnEvent();
});
document.addEventListener("htmx:afterSettle", () => {
addBtnEvent();
});

View File

@ -1,4 +1,5 @@
<div class="w-full dark:text-white">
<sl-details summary="Create secret">
<form
hx-post="/secrets/create/root"
@ -49,5 +50,4 @@
</button>
</form>
</sl-details>
</div>

View File

@ -55,6 +55,14 @@ function setGroupBreadcrumbs(name, path, secret = null) {
}
}
function toggleDetails() {
const masterPane = document.getElementById("master-pane");
const detailPane = document.getElementById("detail-pane");
masterPane.classList.toggle("hidden");
detailPane.classList.toggle("hidden");
}
function addTreeListener() {
const tree = document.querySelector("sl-tree");
@ -83,11 +91,18 @@ function addTreeListener() {
}
if (url) {
htmx.ajax("GET", url, {
target: "#secretdetails",
swap: "OuterHTML",
indicator: ".secret-spinner",
});
htmx
.ajax("GET", url, {
target: "#secretdetails",
swap: "OuterHTML",
indicator: ".secret-spinner",
})
.then(() => {
toggleDetails();
selectedEl.addEventListener("click", () => {
toggleDetails();
});
});
}
});
}

View File

@ -96,6 +96,7 @@ def create_router(dependencies: FrontendDependencies) -> APIRouter:
"clients": clients,
"breadcrumbs": breadcrumbs,
"root_group_page": True,
"mobile_show_details": True,
}
headers: dict[str, str] = {}
if request.headers.get("HX-Request"):
@ -144,6 +145,7 @@ def create_router(dependencies: FrontendDependencies) -> APIRouter:
"group": group,
"clients": clients,
"breadcrumbs": breadcrumbs,
"mobile_show_details": True,
}
if request.headers.get("HX-Request"):
# This is a HTMX request.
@ -187,6 +189,7 @@ def create_router(dependencies: FrontendDependencies) -> APIRouter:
"flat_groups": flat_groups,
"events": events,
"secret_page": True,
"mobile_show_details": True,
}
headers: dict[str, str] = {}

View File

@ -403,6 +403,9 @@
.col-span-full {
grid-column: 1 / -1;
}
.clear-both {
clear: both;
}
.container {
width: 100%;
@media (width >= 40rem) {
@ -694,6 +697,9 @@
.h-\[36rem\] {
height: 36rem;
}
.h-\[calc\(100vh-2\.5rem\)\] {
height: calc(100vh - 2.5rem);
}
.h-\[calc\(100vh-2rem\)\] {
height: calc(100vh - 2rem);
}
@ -703,9 +709,15 @@
.h-\[calc\(100vh-3rem\)\] {
height: calc(100vh - 3rem);
}
.h-\[calc\(100vh-4\.5rem\)\] {
height: calc(100vh - 4.5rem);
}
.h-\[calc\(100vh-4rem\)\] {
height: calc(100vh - 4rem);
}
.h-\[calc\(100vh-5\.5rem\)\] {
height: calc(100vh - 5.5rem);
}
.h-\[calc\(100vh-6rem\)\] {
height: calc(100vh - 6rem);
}
@ -2876,6 +2888,11 @@
display: none;
}
}
.md\:h-\[calc\(100vh-3\.5rem\)\] {
@media (width >= 48rem) {
height: calc(100vh - 3.5rem);
}
}
.md\:h-auto {
@media (width >= 48rem) {
height: auto;
@ -3131,6 +3148,11 @@
height: 24rem;
}
}
.lg\:h-\[calc\(100vh-3\.5rem\)\] {
@media (width >= 64rem) {
height: calc(100vh - 3.5rem);
}
}
.lg\:max-h-\[60rem\] {
@media (width >= 64rem) {
max-height: 60rem;
@ -3146,6 +3168,11 @@
width: calc(var(--spacing) * 64);
}
}
.lg\:w-80 {
@media (width >= 64rem) {
width: calc(var(--spacing) * 80);
}
}
.lg\:w-96 {
@media (width >= 64rem) {
width: calc(var(--spacing) * 96);