feat(web): add dark theme by sleeyax · Pull Request #8317 · mitmproxy/mitmproxy · GitHub
Skip to content

feat(web): add dark theme - #8317

Merged
emanuele-em merged 16 commits into
mitmproxy:mainfrom
sleeyax:feat/web-dark-mode
Jul 29, 2026
Merged

emanuele-em merged 16 commits into
mitmproxy:mainfrom
sleeyax:feat/web-dark-mode

Conversation

@sleeyax

@sleeyax sleeyax commented Jul 8, 2026 •

Copy link
Copy Markdown
Contributor

Requires #8316 to be merged first.

Adds a web_theme option (system/dark/light, default system) and a dark palette that overrides the color tokens under [data-theme="dark"]. system follows the OS prefers-color-scheme and reacts to live changes. The CodeMirror content editor uses the one-dark theme in dark mode.

Historically, dark mode was declined on maintenance-cost grounds (#3886), but this implementation keeps the cost to a single token-override block plus only a handful of targeted overrides. Hopefully that's simple enough of an implementation to convince you to merge this :)

Closes #7828.

Part of #7789.

Screenshots

image

@lups2000 lups2000 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, really nice work! I just noticed a few things:

(dropdown)
Image
(search icon)
Image
(close icon when hovering)
Image

Maybe addressing what I suggested in #8316 could also fix these issues. Let me know :)

Comment thread mitmproxy/tools/web/webaddons.py
@lups2000
lups2000 requested a review from emanuele-em July 12, 2026 07:10
@sleeyax
sleeyax force-pushed the feat/web-dark-mode branch 2 times, most recently from 24461df to 2b12e71 Compare July 12, 2026 10:52
@sleeyax

sleeyax commented Jul 12, 2026 •

Copy link
Copy Markdown
Contributor Author

@sleeyax
sleeyax force-pushed the feat/web-dark-mode branch from 2b12e71 to 204d91c Compare July 12, 2026 11:00
@sleeyax
sleeyax requested a review from lups2000 July 12, 2026 11:01
@sleeyax
sleeyax force-pushed the feat/web-dark-mode branch 2 times, most recently from 2544bf8 to d6b3dbb Compare July 18, 2026 12:15
sleeyax and others added 8 commits July 18, 2026 14:38
Add a `web_theme` mitmweb option (system/dark/light; default system) and apply it in the frontend by setting `data-theme` on the document root.
`system` follows the OS `prefers-color-scheme` and tracks live changes.
The dark palette overrides the semantic color tokens under `[data-theme="dark"]`, with targeted overrides for surfaces whose colors are consumed by LESS functions.
The CodeMirror content editor switches to the one-dark theme in dark mode.

Part of mitmproxy#7789.
Native selects, inputs, checkboxes and scrollbars ignored the semantic tokens and rendered with the browser's light defaults.
Set color-scheme per theme so they follow it, and replace the remaining literal black text colors on the local-applications input and the close-button hover states with tokens.
The search filter icon and the eventlog/flow-detail close icons were hardcoded to black/grey, which is hard to read on dark surfaces.
Route them through the foreground tokens instead.
The header, nav-tab, and menu-group separator borders were computed with lighten(grey, ...), leaving them as bright literals that stayed light-grey on dark surfaces.
Route them through the border tokens instead so they follow the theme.
The web_theme option was only reachable by scrolling to the bottom of the raw options list in the Edit Options modal.
Surface it as an Appearance dropdown (system/dark/light) in the header Options menu so the theme is discoverable and switchable in one click.
The base branch tokenized every flow table row color, so the nested .flow-table tr block in the dark theme now duplicates rules that var() already resolves.
Override the --mitmweb-row-* tokens instead.
Base rows fall through to --mitmweb-bg / --mitmweb-bg-alt like they do in the light theme, rather than carrying their own near-identical literals.
--mitmweb-highlight kept its light value in dark mode, compositing a pale blue over the dark surface and leaving hovered header rows and command suggestions hard to read.
@sleeyax
sleeyax force-pushed the feat/web-dark-mode branch from 2b41d46 to ece7ca5 Compare July 18, 2026 12:44
The request/response first line reused --mitmweb-accent, which is brightened for dark surfaces and left white monospace text at roughly 2.5:1 contrast.
Give the banner its own token pair so dark mode can use a deep blue with pale text without dragging the accent color along.

@emanuele-em emanuele-em left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see these problems in the dark theme:

  1. low contrast for the colored statuses (200 is almost invisible)
image
  1. There is a thick white border above the footer, the problem is caused by the hardcoded shadow 0 -1px 3px lightgray
image
  1. There is a problem with the alignement/padding/spacing of the elements in the "flow" tab
image
  1. In "capture" tab, under local applications, if I click on the dropdown menu, the "default" icon is a white square, i think it should be "dark"
image

Moreover, imho, it's not clear that the theme selection is located in the "options" tab, I would expect to see it as an icon that is always visible

sleeyax added 3 commits July 20, 2026 11:59
The status column painted itself with hardcoded CSS color names.
`darkgreen` and `darkred` are near-invisible against the dark surface, so route the colors through per-class tokens instead.
Light values are byte-equal to the literals they replace.

The shadow token added alongside them is consumed in the next commit.
Both footer shadows were hardcoded to a light gray, which on a dark surface reads as a thick white border rather than a shadow.
Route them through the shadow token so the dark theme casts black instead.
The executable icons in the local-applications dropdown come from the OS as bitmaps, so we cannot recolor them.
macOS hands back a plain white square for the generic executable, which glares against the dark popover.
Dim them via a token so the white square reads as grey while colored app icons stay recognizable.
@sleeyax

sleeyax commented Jul 20, 2026

Copy link
Copy Markdown
Contributor Author
  1. Addressed by extracting the status code colors to CSS variables as well and adding a dark mode variant:
image
  1. Fixed by replacing the hardcoded value with the correct variable (--mitmweb-shadow)
  2. Can you clarify what you mean by this @emanuele-em ? Not sure what you're referring to exactly. A screenshot with some arrow / square pointer would help or a comparison with the main branch mitmweb.
  3. See reply below

@sleeyax

sleeyax commented Jul 20, 2026

Copy link
Copy Markdown
Contributor Author

Regarding your point 4:

I dug into where those icons come from: /executable-icon serves whatever mitmproxy_rs.process_info.executable_icon() returns, and on macOS that's NSRunningApplication.icon() -> TIFF -> resized to 32×32 -> PNG. If the lookup fails it raises an exception and it falls back to a transparent PNG.

So the white squares are macOS's own generic Unix-executable icon (a white sheet) coming through. Tools like akd, ctkd and bash are daemons/CLI tools with no bundle icon. It isn't something we can recolor server-side, and as far as I understand it won't follow the OS appearance either: they are static .icns assets with no dark variant.

Given that, I've handled it in CSS: a --mitmweb-bitmap-icon-filter token that's none in light mode and brightness(0.7) in dark, applied to .process-icon. That knocks the white square back to grey while leaving colored app icons recognizable. It's a mitigation rather than a real fix though. Let me know if you prefer to handle it differently.

One thing I can't explain from your screenshot: Mail also shows as a white square, and it should have a real colorful icon. Could you open devtools on that dropdown and check what /executable-icon?path=... actually returns for Mail (real PNG bytes or the 1×1 transparent fallback)? If it's the fallback, there may be a lookup bug underneath that's worth a separate issue.

I'm on Arch Linux, where executable_icon raises NotImplementedError, so I can't reproduce any of this locally.

@sleeyax

sleeyax commented Jul 20, 2026 •

Copy link
Copy Markdown
Contributor Author

Moreover, imho, it's not clear that the theme selection is located in the "options" tab, I would expect to see it as an icon that is always visible

Where would you place it? To me it feels native in the options tab.

I tried placing it at the far right but it's still not so clear imo, since the default is the "system" theme and a PC icon isn't obvious.

image

EDIT: as discussed on discord, we are thinking not to add this toggle in this iteration yet.

@emanuele-em

Copy link
Copy Markdown
Member
  1. Can you clarify what you mean by this @emanuele-em ? Not sure what you're referring to exactly. A screenshot with some arrow / square pointer would help or a comparison with the main branch mitmweb.

please see the screenshot below

Screenshot 2026-07-20 at 12 39 51

This is the light mode:

image

Panes such as the flow table reserve a scrollbar gutter permanently via `overflow-y: scroll`.
Under `color-scheme: dark` the UA paints that gutter light, so an idle scrollbar reads as a stray vertical line beside the pane divider rather than as a scrollbar.
Color the track to match the surface so it stays as invisible as it already is on light backgrounds.
@sleeyax

sleeyax commented Jul 20, 2026

Copy link
Copy Markdown
Contributor Author
  1. should be fixed in 39c3616

@lups2000 lups2000 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall it looks good I think 🙌

Just some nits:

  1. This looks a bit weird
Image
  1. Maybe this could be more visible
Image
  1. I agree with @emanuele-em that the theme selector should be more visible. What if we create a toggle and put it in the top.right corner? what do you think?

sleeyax added 2 commits July 22, 2026 12:05
Under color-scheme: dark the browser paints the native text field a lighter grey than the transparent dropdown header around it, so the input read lighter than the chevron beside it.
Making the field background transparent lets it blend with the header.
The dark highlight token was barely distinguishable from the popover surface, so a hovered suggestion row read as unhighlighted.
Brightening it makes the hovered row stand out.
The command-bar suggestion highlight shares this token and gains the same visibility.
@sleeyax

sleeyax commented Jul 22, 2026

Copy link
Copy Markdown
Contributor Author

@sleeyax
sleeyax requested review from emanuele-em and lups2000 July 22, 2026 10:19

@lups2000 lups2000 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 🚀

@emanuele-em emanuele-em left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm :)

@emanuele-em
emanuele-em merged commit 9362b05 into mitmproxy:main Jul 29, 2026
28 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Dark Theme Mode

3 participants