From b6ffa64c64e1560cf6aa1a325830e08b0c2ea5fa Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sun, 28 Dec 2025 21:46:04 +0000
Subject: [PATCH 01/10] Initial plan
From 6bc34ee2e5e4d8f824a2aabc1bfc2bc34b478c06 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sun, 28 Dec 2025 21:53:34 +0000
Subject: [PATCH 02/10] Add collapse button and mobile responsiveness to
toolbar
- Added collapse button to toolbar with directional icons
- Implemented CSS for collapsed state across all toolbar positions
- Added localStorage persistence for collapsed state
- Added comprehensive mobile responsiveness with media queries
- Mobile optimizations:
- Automatic bottom positioning on mobile
- Touch-friendly button sizes (min 32px)
- Responsive font sizes and spacing
- Optimized panel tables and grids for small screens
- Hide non-essential elements on very small screens (<480px)
- Support for landscape orientation
- JavaScript collapse toggle function with state persistence
- All linting checks passed
Co-authored-by: JacobCoffee <45884264+JacobCoffee@users.noreply.github.com>
---
src/debug_toolbar/litestar/middleware.py | 4 +
src/debug_toolbar/litestar/routes/handlers.py | 222 +++++++++++++++++-
tests/integration/test_litestar_middleware.py | 4 +-
3 files changed, 227 insertions(+), 3 deletions(-)
diff --git a/src/debug_toolbar/litestar/middleware.py b/src/debug_toolbar/litestar/middleware.py
index 4bf6d60..bd56adc 100644
--- a/src/debug_toolbar/litestar/middleware.py
+++ b/src/debug_toolbar/litestar/middleware.py
@@ -556,6 +556,9 @@ def _render_toolbar(self, data: dict[str, Any]) -> str:
"""
diff --git a/src/debug_toolbar/litestar/routes/handlers.py b/src/debug_toolbar/litestar/routes/handlers.py
index 8be448e..ecec7f5 100644
--- a/src/debug_toolbar/litestar/routes/handlers.py
+++ b/src/debug_toolbar/litestar/routes/handlers.py
@@ -1462,6 +1462,55 @@ def get_toolbar_css() -> str:
font-size: 14px;
}
+.toolbar-collapse-btn {
+ background: var(--dt-bg-tertiary);
+ border: none;
+ width: 28px;
+ height: 28px;
+ border-radius: 4px;
+ color: var(--dt-text-secondary);
+ cursor: pointer;
+ font-size: 16px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ transition: background 0.15s, color 0.15s, transform 0.2s;
+ flex-shrink: 0;
+}
+
+.toolbar-collapse-btn:hover {
+ background: var(--dt-accent);
+ color: white;
+}
+
+#debug-toolbar.collapsed .toolbar-collapse-btn .collapse-icon {
+ transform: rotate(180deg);
+}
+
+#debug-toolbar[data-position="left"] .toolbar-collapse-btn .collapse-icon {
+ transform: rotate(180deg);
+}
+
+#debug-toolbar[data-position="left"].collapsed .toolbar-collapse-btn .collapse-icon {
+ transform: rotate(0deg);
+}
+
+#debug-toolbar[data-position="top"] .toolbar-collapse-btn .collapse-icon {
+ transform: rotate(90deg);
+}
+
+#debug-toolbar[data-position="top"].collapsed .toolbar-collapse-btn .collapse-icon {
+ transform: rotate(-90deg);
+}
+
+#debug-toolbar[data-position="bottom"] .toolbar-collapse-btn .collapse-icon {
+ transform: rotate(-90deg);
+}
+
+#debug-toolbar[data-position="bottom"].collapsed .toolbar-collapse-btn .collapse-icon {
+ transform: rotate(90deg);
+}
+
.toolbar-brand {
font-weight: bold;
color: var(--dt-accent);
@@ -2540,6 +2589,160 @@ def get_toolbar_css() -> str:
border-radius: 4px;
font-size: 11px;
}
+
+/* Mobile Responsiveness */
+@media (max-width: 768px) {
+ /* Automatically position toolbar at bottom on mobile for better UX */
+ #debug-toolbar,
+ #debug-toolbar[data-position="right"],
+ #debug-toolbar[data-position="left"],
+ #debug-toolbar[data-position="top"] {
+ top: auto !important;
+ bottom: 0 !important;
+ left: 0 !important;
+ right: 0 !important;
+ width: 100vw !important;
+ height: auto;
+ max-width: 100vw !important;
+ min-height: 40px;
+ max-height: 70vh;
+ border-left: none !important;
+ border-right: none !important;
+ border-bottom: none !important;
+ border-top: 2px solid var(--dt-accent);
+ flex-direction: column;
+ }
+
+ /* Adjust toolbar bar for mobile */
+ .toolbar-bar {
+ flex-wrap: wrap;
+ padding: 8px 12px;
+ gap: 8px;
+ font-size: 12px;
+ }
+
+ /* Make brand smaller on mobile */
+ .toolbar-brand {
+ font-size: 13px;
+ }
+
+ /* Adjust time display */
+ .toolbar-time {
+ font-size: 11px;
+ }
+
+ /* Stack panels vertically or wrap */
+ .toolbar-panels {
+ flex-wrap: wrap;
+ width: 100%;
+ gap: 6px;
+ }
+
+ .toolbar-panel-btn {
+ padding: 6px 10px;
+ font-size: 11px;
+ min-height: 32px;
+ flex: 1 1 auto;
+ }
+
+ /* Touch-friendly buttons - minimum 44px */
+ .toolbar-collapse-btn,
+ .toolbar-theme-btn,
+ .toolbar-position-btn {
+ min-width: 32px;
+ min-height: 32px;
+ width: 32px;
+ height: 32px;
+ }
+
+ /* Hide certain elements on very small screens to save space */
+ @media (max-width: 480px) {
+ .toolbar-request-id {
+ display: none;
+ }
+
+ .panel-subtitle {
+ display: none;
+ }
+ }
+
+ /* Adjust details panel for mobile */
+ .toolbar-details {
+ max-height: 50vh;
+ overflow-y: auto;
+ font-size: 12px;
+ }
+
+ /* Make content scrollable */
+ .toolbar-content {
+ overflow-y: auto;
+ -webkit-overflow-scrolling: touch;
+ }
+
+ /* Optimize panel tables for mobile */
+ .panel-table {
+ font-size: 11px;
+ }
+
+ .panel-table td {
+ padding: 6px 8px;
+ }
+
+ /* Adjust metadata list for mobile */
+ .metadata-list {
+ grid-template-columns: 100px 1fr;
+ gap: 6px 12px;
+ font-size: 12px;
+ }
+
+ /* Better spacing for alerts on mobile */
+ .alert-card {
+ padding: 10px;
+ margin-bottom: 8px;
+ }
+
+ /* Memory stats grid adjustment */
+ .memory-summary,
+ .async-summary,
+ .graphql-summary,
+ .ws-summary {
+ grid-template-columns: repeat(auto-fit, minmax(70px, 1fr));
+ gap: 6px;
+ font-size: 11px;
+ }
+
+ /* Collapsed state on mobile - just show collapse button area */
+ #debug-toolbar.collapsed {
+ max-height: 40px;
+ min-height: 40px;
+ }
+
+ #debug-toolbar.collapsed .toolbar-time,
+ #debug-toolbar.collapsed .toolbar-history-link {
+ display: none;
+ }
+
+ /* Ensure resize handle is hidden on mobile */
+ .toolbar-resize-handle {
+ display: none;
+ }
+
+ /* Position controls - make them more touch-friendly */
+ .toolbar-position-controls {
+ gap: 6px;
+ }
+}
+
+/* Landscape mobile / small tablets */
+@media (max-width: 1024px) and (max-height: 600px) {
+ #debug-toolbar {
+ max-height: 50vh;
+ }
+
+ .toolbar-details {
+ max-height: 35vh;
+ }
+}
"""
@@ -2590,7 +2793,7 @@ def get_toolbar_js() -> str:
class DebugToolbar {
constructor(element) {
this.element = element;
- this.isCollapsed = false;
+ this.isCollapsed = localStorage.getItem('debug-toolbar-collapsed') === 'true';
this.activePanel = null;
this.position = localStorage.getItem('debug-toolbar-position') || 'right';
this.theme = localStorage.getItem('debug-toolbar-theme') || 'dark';
@@ -2607,6 +2810,12 @@ class DebugToolbar {
this.addThemeToggle();
this.addPositionControls();
this.addResizeHandle();
+ this.addCollapseButton();
+
+ // Apply saved collapsed state
+ if (this.isCollapsed) {
+ this.element.classList.add('collapsed');
+ }
const brand = this.element.querySelector('.toolbar-brand');
if (brand) {
@@ -2620,6 +2829,16 @@ class DebugToolbar {
});
}
+ addCollapseButton() {
+ const collapseBtn = this.element.querySelector('.toolbar-collapse-btn');
+ if (collapseBtn) {
+ collapseBtn.addEventListener('click', (e) => {
+ e.stopPropagation();
+ this.toggle();
+ });
+ }
+ }
+
addThemeToggle() {
this.themeBtn = document.createElement('button');
this.themeBtn.className = 'toolbar-theme-btn';
@@ -2760,6 +2979,7 @@ class DebugToolbar {
toggle() {
this.isCollapsed = !this.isCollapsed;
this.element.classList.toggle('collapsed', this.isCollapsed);
+ localStorage.setItem('debug-toolbar-collapsed', this.isCollapsed);
}
showPanel(panelId) {
diff --git a/tests/integration/test_litestar_middleware.py b/tests/integration/test_litestar_middleware.py
index 8a92396..fb3c6e8 100644
--- a/tests/integration/test_litestar_middleware.py
+++ b/tests/integration/test_litestar_middleware.py
@@ -5,11 +5,11 @@
import gzip
import pytest
+from litestar.status_codes import HTTP_200_OK
from litestar.testing import TestClient
from debug_toolbar.litestar import DebugToolbarPlugin, LitestarDebugToolbarConfig
from litestar import Litestar, MediaType, Response, get
-from litestar.status_codes import HTTP_200_OK
@get("/", media_type=MediaType.HTML)
@@ -277,7 +277,7 @@ def test_works_with_before_after_request(self) -> None:
Note: We only verify before_request hook is called. The after_request
hook timing varies in CI environments due to async execution order.
"""
- from litestar import Request, Response
+ from litestar import Request
hook_state: dict[str, bool] = {"before": False, "after": False}
From 1f0d9d1a304cb6f7850f68070f51c7d06275bf7d Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 3 Jan 2026 17:31:17 +0000
Subject: [PATCH 03/10] refactor: Extract nested media query to separate block
Extracted @media (max-width: 480px) from inside @media (max-width: 768px)
to a separate top-level media query for better CSS organization.
No functional changes - same styles apply at same breakpoints.
Co-authored-by: JacobCoffee <45884264+JacobCoffee@users.noreply.github.com>
---
src/debug_toolbar/litestar/routes/handlers.py | 22 +++++++++----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/src/debug_toolbar/litestar/routes/handlers.py b/src/debug_toolbar/litestar/routes/handlers.py
index ecec7f5..3db2aaa 100644
--- a/src/debug_toolbar/litestar/routes/handlers.py
+++ b/src/debug_toolbar/litestar/routes/handlers.py
@@ -2655,17 +2655,6 @@ def get_toolbar_css() -> str:
height: 32px;
}
- /* Hide certain elements on very small screens to save space */
- @media (max-width: 480px) {
- .toolbar-request-id {
- display: none;
- }
-
- .panel-subtitle {
- display: none;
- }
- }
-
/* Adjust details panel for mobile */
.toolbar-details {
max-height: 50vh;
@@ -2733,6 +2722,17 @@ def get_toolbar_css() -> str:
}
}
+/* Extra small screens - hide non-essential elements */
+@media (max-width: 480px) {
+ .toolbar-request-id {
+ display: none;
+ }
+
+ .panel-subtitle {
+ display: none;
+ }
+}
+
/* Landscape mobile / small tablets */
@media (max-width: 1024px) and (max-height: 600px) {
#debug-toolbar {
From d00e949161e95c7237af305ec2ff668cfe3331ba Mon Sep 17 00:00:00 2001
From: Jacob Coffee
Date: Sat, 3 Jan 2026 11:35:45 -0600
Subject: [PATCH 04/10] Update src/debug_toolbar/litestar/middleware.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---
src/debug_toolbar/litestar/middleware.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/debug_toolbar/litestar/middleware.py b/src/debug_toolbar/litestar/middleware.py
index bd56adc..8426d49 100644
--- a/src/debug_toolbar/litestar/middleware.py
+++ b/src/debug_toolbar/litestar/middleware.py
@@ -571,6 +571,7 @@ def _render_toolbar(self, data: dict[str, Any]) -> str:
History
+
From 61ab3c7ce2c8e1db409ef86ee57adcf59b319d6f Mon Sep 17 00:00:00 2001
From: Jacob Coffee
Date: Sat, 3 Jan 2026 11:35:53 -0600
Subject: [PATCH 05/10] Update src/debug_toolbar/litestar/middleware.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---
src/debug_toolbar/litestar/middleware.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/debug_toolbar/litestar/middleware.py b/src/debug_toolbar/litestar/middleware.py
index 8426d49..7cb2356 100644
--- a/src/debug_toolbar/litestar/middleware.py
+++ b/src/debug_toolbar/litestar/middleware.py
@@ -556,7 +556,7 @@ def _render_toolbar(self, data: dict[str, Any]) -> str: