raneomik / tracy-dark-mode
Dark theme for the Tracy bar, its panels and the bluescreen, with a toggle
Requires
- php: >=8.3
- tracy/tracy: ^2.11.4
Requires (Dev)
- nette/di: ^3.2
- phpstan/phpstan-nette: ^2.0@stable
Suggests
- nette/di: To enable it with one line of NEON, through DarkTracyExtension
Provides
None
Conflicts
- nette/di: <3.2
Replaces
None
README
🌗 Dark theme for the Tracy bar,
its panels (third-party ones too) and the bluescreen.
It follows the system (prefers-color-scheme); the half-moon tab of the bar switches the theme and remembers the choice.
Requirements
- PHP 8.3 or newer
Tracy 2.11.4 and above (the bar and the bluescreen in shadow roots: supported)
- Optional:
nette/di 3.2 or newer, to enable it with one line of NEON
Getting started
Install the package:
composer require --dev raneomik/tracy-dark-mode
With Nette, register the extension:
extensions: tracyDarkMode: Raneomik\TracyDarkMode\DarkTracyExtension
Reload a page in debug mode: the bar is dark if your system is, and a 🌗 half-moon tab sits at its right end. Click it to switch between dark and light.
⚠️ Installed with
--dev, the class is missing aftercomposer install --no-dev: registered in your common config, the extension breaks the production container. See Keep it out of production.
How-to guides
Keep it out of production
Register the extensions of your require-dev packages in a config file of their own:
# config/dev.neon extensions: tracyDarkMode: Raneomik\TracyDarkMode\DarkTracyExtension
Load it only when Composer installed the dev packages:
// app/Bootstrap.php if (Composer\InstalledVersions::getRootPackage()['dev']) { // false after composer install --no-dev. "%rootDir" may need definition $configurator->addConfig('%rootDir%/config/dev.neon'); }
The $customCssFiles line of the next guide goes in the same condition.
Theme the early bluescreens and the panels opened in a window
The extension themes the bar, its panels and the bluescreens raised once the container has started.
Tracy serves its own assets as soon as it is enabled, before any DI extension runs: to also cover a bluescreen
raised earlier and a panel opened in its own window, add the stylesheet before enableTracy().
// app/Bootstrap.php Tracy\Debugger::$customCssFiles['darkMode'] = __DIR__ . '/../vendor/raneomik/tracy-dark-mode/assets/dark-mode.css'; $configurator->enableTracy(__DIR__ . '/../log');
Use an absolute path: a relative one is resolved from the working directory, which is the document root in a web request.
Use it without Nette
The stylesheet line above and the toggle are all it takes:
Tracy\Debugger::$customCssFiles['darkMode'] = __DIR__ . '/vendor/raneomik/tracy-dark-mode/assets/dark-mode.css'; Tracy\Debugger::getBar()->addPanel(new Raneomik\TracyDarkMode\DarkModePanel, 'darkMode');
Go back to the system theme
A click on the toggle is remembered, and wins over the system from then on. To follow the system again, remove the stored choice in the browser console, then reload the page:
localStorage.removeItem('tracy-dark-mode');
Reference
| Item | Description |
|---|---|
Raneomik\TracyDarkMode\DarkTracyExtension |
DI extension, no option. Registers the stylesheet at container startup and adds the toggle to the bar when Tracy's extension is registered. |
Raneomik\TracyDarkMode\DarkModePanel |
Bar panel: the toggle tab, with the stylesheet and the script inlined. It has no panel content, and no tab in AJAX requests. |
assets/dark-mode.css |
The theme. To pass to Tracy\Debugger::$customCssFiles for what the panel cannot reach. |
assets/dark-mode.js |
The toggle, mouse and keyboard (Enter, Space). Inlined by the panel, nothing to load yourself. |
localStorage['tracy-dark-mode'] |
dark or light once the toggle was clicked; absent, the system decides. When the storage is blocked, the choice lasts for the page only. |
--tracy-dark-filter, --tracy-dark-undo, --tracy-dark-bg |
Custom properties set on <html> by the toggle. |
How it works
Tracy's colours are hard-coded, in third-party panels too. Instead of recolouring them one by one, the bar, each
panel and the bluescreen are inverted as a whole, hues kept (filter: invert() hue-rotate()): no panel needs to know about it.
What must keep its own colours is inverted back: pictures and the dumps that are already dark (tracy: dumpTheme: dark).
The red error header of the bluescreen is left untouched.
The choice made with the toggle is written as custom properties on <html>: they inherit into the shadow roots
of Tracy 2.13, where no selector of the page reaches.
Development
composer install && composer ci # PHPStan + tests/smoke.php
Resources
Tracy and its extensions
Nette