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:
+ Debug Toolbar {total_time:.2f}ms
@@ -568,6 +571,7 @@ def _render_toolbar(self, data: dict[str, Any]) -> str: History
+
""" 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:
- Debug Toolbar From 08875d80c51c173adff63f60824dbacb8ad163b8 Mon Sep 17 00:00:00 2001 From: Jacob Coffee Date: Sat, 3 Jan 2026 11:36:00 -0600 Subject: [PATCH 06/10] Update src/debug_toolbar/litestar/routes/handlers.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/debug_toolbar/litestar/routes/handlers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/debug_toolbar/litestar/routes/handlers.py b/src/debug_toolbar/litestar/routes/handlers.py index 3db2aaa..c72e9fc 100644 --- a/src/debug_toolbar/litestar/routes/handlers.py +++ b/src/debug_toolbar/litestar/routes/handlers.py @@ -2979,7 +2979,7 @@ class DebugToolbar { toggle() { this.isCollapsed = !this.isCollapsed; this.element.classList.toggle('collapsed', this.isCollapsed); - localStorage.setItem('debug-toolbar-collapsed', this.isCollapsed); + localStorage.setItem('debug-toolbar-collapsed', String(this.isCollapsed)); } showPanel(panelId) { From b5e7a678628a3c03799157808b273d592f8d5c09 Mon Sep 17 00:00:00 2001 From: Jacob Coffee Date: Sat, 3 Jan 2026 11:40:54 -0600 Subject: [PATCH 07/10] fix: wrap long line in collapse button HTML for linter compliance MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- src/debug_toolbar/litestar/middleware.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/debug_toolbar/litestar/middleware.py b/src/debug_toolbar/litestar/middleware.py index 0860d68..625f8ef 100644 --- a/src/debug_toolbar/litestar/middleware.py +++ b/src/debug_toolbar/litestar/middleware.py @@ -576,7 +576,8 @@ def _render_toolbar(self, data: dict[str, Any]) -> str:
- Debug Toolbar From 6c7cb095d32f1a930d24c11f47c297be4a98374f Mon Sep 17 00:00:00 2001 From: Jacob Coffee Date: Sat, 3 Jan 2026 11:45:22 -0600 Subject: [PATCH 08/10] fix: run examples as modules for proper import resolution MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add examples/__init__.py to make examples a proper package - Update Makefile to use `python -m` instead of direct script execution - Fixes relative imports and uvicorn module paths in examples 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- Makefile | 14 +++++++------- examples/__init__.py | 1 + 2 files changed, 8 insertions(+), 7 deletions(-) create mode 100644 examples/__init__.py diff --git a/Makefile b/Makefile index bff7212..56b5905 100644 --- a/Makefile +++ b/Makefile @@ -129,25 +129,25 @@ upgrade: ## Upgrade all dependencies example: example-litestar ## Alias for example-litestar example-asgi: ## Run ASGI example app (http://localhost:8000) - @uv run python examples/asgi_basic/app.py + @uv run python -m examples.asgi_basic.app example-litestar: ## Run Litestar example app (http://localhost:8001) - @uv run python examples/litestar_basic/app.py + @uv run python -m examples.litestar_basic.app example-aa: ## Run Litestar + Advanced-Alchemy example (http://localhost:8002) - @uv run python examples/litestar_advanced_alchemy/app.py + @uv run python -m examples.litestar_advanced_alchemy.app example-graphql: ## Run GraphQL + Strawberry example (http://localhost:8003) - @uv run python examples/graphql_panel_example.py + @uv run python -m examples.graphql_panel_example example-websocket: ## Run WebSocket example app (http://localhost:8002) - @uv run python examples/websocket_panel_example.py + @uv run python -m examples.websocket_panel_example example-mcp: ## Run MCP server example (http://localhost:8004) - @uv run python examples/mcp_server_example.py + @uv run python -m examples.mcp_server_example example-mcp-server: ## Run MCP server (stdio transport) - @uv run python examples/mcp_server_example.py --mcp + @uv run python -m examples.mcp_server_example --mcp ##@ Git Worktrees diff --git a/examples/__init__.py b/examples/__init__.py new file mode 100644 index 0000000..c938aac --- /dev/null +++ b/examples/__init__.py @@ -0,0 +1 @@ +"""Example applications for the debug-toolbar library.""" From 35e06e3528f6642bdf68c65bb5d941f57cd6497e Mon Sep 17 00:00:00 2001 From: Jacob Coffee Date: Sat, 3 Jan 2026 11:46:40 -0600 Subject: [PATCH 09/10] fix: properly minimize toolbar when collapsed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When collapsed, now only the expand button is visible - all other elements (brand, time, panels, controls) are hidden. The toolbar shrinks to a small button in the corner instead of a dropdown-style partial collapse. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- src/debug_toolbar/litestar/routes/handlers.py | 42 +++++++++++++------ uv.lock | 2 +- 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/src/debug_toolbar/litestar/routes/handlers.py b/src/debug_toolbar/litestar/routes/handlers.py index c72e9fc..e259e2c 100644 --- a/src/debug_toolbar/litestar/routes/handlers.py +++ b/src/debug_toolbar/litestar/routes/handlers.py @@ -1304,19 +1304,29 @@ def get_toolbar_css() -> str: flex-direction: column; } +/* Collapsed state - hide everything except collapse button */ #debug-toolbar.collapsed .toolbar-panels, #debug-toolbar.collapsed .toolbar-details, -#debug-toolbar.collapsed .toolbar-content { - display: none; -} - -/* Collapsed state for side positions */ +#debug-toolbar.collapsed .toolbar-content, +#debug-toolbar.collapsed .toolbar-brand, +#debug-toolbar.collapsed .toolbar-time, +#debug-toolbar.collapsed .toolbar-request-id, +#debug-toolbar.collapsed .toolbar-history-link, +#debug-toolbar.collapsed .toolbar-theme-btn, +#debug-toolbar.collapsed .toolbar-position-btn, +#debug-toolbar.collapsed .toolbar-position-controls, +#debug-toolbar.collapsed .toolbar-resize-handle { + display: none !important; +} + +/* Collapsed state for side positions - shrink to just the button */ #debug-toolbar.collapsed[data-position="right"], #debug-toolbar[data-position="right"].collapsed, #debug-toolbar.collapsed[data-position="left"], #debug-toolbar[data-position="left"].collapsed { width: auto; min-width: 0; + max-width: 50px; } #debug-toolbar.collapsed[data-position="top"], @@ -1325,6 +1335,13 @@ def get_toolbar_css() -> str: #debug-toolbar[data-position="bottom"].collapsed { height: auto; min-height: 0; + max-height: 50px; +} + +/* Collapsed toolbar bar should be minimal */ +#debug-toolbar.collapsed .toolbar-bar { + padding: 6px; + justify-content: center; } /* Resize handle */ @@ -2700,15 +2717,16 @@ def get_toolbar_css() -> str: font-size: 11px; } - /* Collapsed state on mobile - just show collapse button area */ + /* Collapsed state on mobile - just show collapse button */ #debug-toolbar.collapsed { - max-height: 40px; + max-height: 50px; min-height: 40px; - } - - #debug-toolbar.collapsed .toolbar-time, - #debug-toolbar.collapsed .toolbar-history-link { - display: none; + max-width: 60px; + width: auto; + left: auto !important; + right: 10px !important; + bottom: 10px !important; + border-radius: 8px; } /* Ensure resize handle is hidden on mobile */ diff --git a/uv.lock b/uv.lock index 0c8152f..bc3133d 100644 --- a/uv.lock +++ b/uv.lock @@ -420,7 +420,7 @@ wheels = [ [[package]] name = "debug-toolbar" -version = "0.3.0" +version = "0.3.1" source = { editable = "." } dependencies = [ { name = "jinja2" }, From f6c32caf135c06a2e4b15f030a2a1788dc1a8f78 Mon Sep 17 00:00:00 2001 From: Jacob Coffee Date: Sat, 3 Jan 2026 11:48:42 -0600 Subject: [PATCH 10/10] fix: correct collapse arrow directions for left/right positions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Right position: » when expanded (collapse), « when collapsed (expand) - Left position: « when expanded (collapse), » when collapsed (expand) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- src/debug_toolbar/litestar/routes/handlers.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/debug_toolbar/litestar/routes/handlers.py b/src/debug_toolbar/litestar/routes/handlers.py index e259e2c..cd9bf47 100644 --- a/src/debug_toolbar/litestar/routes/handlers.py +++ b/src/debug_toolbar/litestar/routes/handlers.py @@ -1500,16 +1500,24 @@ def get_toolbar_css() -> str: color: white; } -#debug-toolbar.collapsed .toolbar-collapse-btn .collapse-icon { +/* Right position (default): expanded » (points right to collapse), collapsed « (points left to expand) */ +#debug-toolbar[data-position="right"] .toolbar-collapse-btn .collapse-icon, +#debug-toolbar:not([data-position]) .toolbar-collapse-btn .collapse-icon { transform: rotate(180deg); } +#debug-toolbar[data-position="right"].collapsed .toolbar-collapse-btn .collapse-icon, +#debug-toolbar:not([data-position]).collapsed .toolbar-collapse-btn .collapse-icon { + transform: rotate(0deg); +} + +/* Left position: expanded « (points left to collapse), collapsed » (points right to expand) */ #debug-toolbar[data-position="left"] .toolbar-collapse-btn .collapse-icon { - transform: rotate(180deg); + transform: rotate(0deg); } #debug-toolbar[data-position="left"].collapsed .toolbar-collapse-btn .collapse-icon { - transform: rotate(0deg); + transform: rotate(180deg); } #debug-toolbar[data-position="top"] .toolbar-collapse-btn .collapse-icon {