mitmproxy/web/package.json
Sleeyax 9362b05c29
feat(web): add dark theme (#8317)
* feat(web): add dark theme and web_theme option

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 #7789.

* fix(web): theme native form controls for dark mode

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.

* fix(web): make search and close icons legible in dark mode

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.

* [autofix.ci] apply automated fixes

* fix(web): theme header and tab separators for dark mode

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.

* feat(web): add a theme selector to the Options menu

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.

* refactor(web): drop the dark flow table rule override

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.

* fix(web): give row hover a dark highlight color

--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.

* fix(web): darken the first-line banner in dark mode

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.

* fix(web): make status codes legible in dark mode

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.

* fix(web): stop footers casting a light halo in dark mode

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.

* fix(web): dim OS-supplied app icons in dark mode

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.

* fix(web): stop idle scrollbars showing as stray lines in dark mode

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.

* fix(web): blend the process-filter input into its dark header

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.

* fix(web): make the filter-docs row hover visible in dark mode

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.

* test(web): cover theme selector and status column colors

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-07-29 07:45:53 +02:00

59 lines
2 KiB
JSON

{
"name": "mitmproxy",
"private": true,
"scripts": {
"test": "eslint . && tsc --noEmit && jest --coverage",
"start": "vite",
"prettier": "prettier --write .",
"eslint": "eslint --fix .",
"ci-build-release": "rm -rf ../mitmproxy/tools/web/static && vite build"
},
"dependencies": {
"@codemirror/lang-css": "^6.3.1",
"@codemirror/lang-html": "^6.4.9",
"@codemirror/lang-javascript": "^6.2.3",
"@codemirror/lang-yaml": "^6.1.2",
"@codemirror/theme-one-dark": "^6.1.2",
"@floating-ui/react-dom": "^2.1.2",
"@popperjs/core": "^2.11.8",
"@reduxjs/toolkit": "^2.8.1",
"@types/react": "^19.2.6",
"@uiw/react-codemirror": "^4.23.12",
"classnames": "^2.3.1",
"codemirror": "^6.0.1",
"lodash": "^4.17.21",
"lucide-react": "^1.16.0",
"qrcode": "^1.5.4",
"react": "^19.1.0",
"react-dom": "^19.1.0",
"react-redux": "^9.2.0"
},
"devDependencies": {
"@eslint/js": "^9.26.0",
"@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.3.0",
"@testing-library/user-event": "^14.6.1",
"@types/jest": "^29.5.14",
"@types/lodash": "^4.17.24",
"@types/qrcode": "^1.5.6",
"@types/react-dom": "^19.2.3",
"@types/redux-mock-store": "^1.5.0",
"@vitejs/plugin-react": "^5.1.0",
"babel-plugin-react-compiler": "^1.0.0",
"esbuild-jest": "^0.5.0",
"eslint": "^9.26.0",
"eslint-plugin-react": "^7.37.5",
"globals": "^16.1.0",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"jest-fetch-mock": "^3.0.3",
"less": "^4.4.2",
"prettier": "^3.5.3",
"redux-mock-store": "^1.5.5",
"through2": "^4.0.2",
"typescript": "^5.8.3",
"typescript-eslint": "^8.32.1",
"vite": "^7.2.2"
}
}