2022-07-28, updated: 2024-03-12
Tested with Nyxt 3-pre-release-1.
Theming, the Nyxt 3 approach
Color scheme customization is essential for accessibility, stylistic coherence, and aesthetics. It's not easy to customize the colors of all the applications (let alone web apps) we use. Even though Nyxt's color scheme was configurable before version 3, it was quite frustrating. There should be a better way…
We've refactored the way styles are used in Nyxt with the goal of making theming as simple as listing a set of colors. Words aside, here's how clean setting your new theme is in Nyxt 3:
;; Add to your config.lisp
(define-configuration browser
((theme (make-instance 'theme:theme
:dark-p t
:background-color "black"
:on-background-color "white"
:primary-color "rgb(170, 170, 170)"
:on-primary-color "black"
:secondary-color "rgb(100, 100, 100)"
:on-secondary-color "white"
:accent-color "#37A8E4"
:on-accent-color "black"))))
This will set the browser theme to a simple black-and-white theme resembling the Midnight theme from our previous theming blogpost.
But wait, there's more!
Configuring styles of individual interface elements
Previously, changing the color palette involved setting the style of separate interface element to the desired CSS. It was tedious, but it allowed to go beyond mere color configuration. Want to change the way things are laid out? Sure! Want to stop displaying some part of the interface? Be my guest!
While we've refactored the style configuration to ensure uniform theming, we retained the style
slots (find all of those with describe-slot
command). After all, you should call the shots, even when offending the consistency of the browser's theme!
For instance, if you want to rely less on your mouse and hide the buttons in the status buffer:
(define-configuration status-buffer
((style (str:concat %slot-value%
(theme:themed-css (theme *browser*)
;; See the `describe-class' of `status-buffer' to
;; understand what to customize
'("#controls"
:display "none"))))))
There are other ways to achieve it, but we're illustrating the potential of raw style configuration that is available underneath the pretty theming façade ;)
Enabling Nyxt themes for your extension
Why bother adding theme support, when we could just provide a set of pre-computed color palettes (including dark themes)?
Well, i) it should be up to the user to choose the theme, and ii) there should be guarantees of stylistic consistency throughout Nyxt interfaces and applications built on top of it.
The former is easy and convenient. The latter, though, is trickier. From the perspective of those authoring extensions, it makes little sense to bake complex theme logic into the extension, as that should be better handled on the Nyxt side. That's why it now takes minimal changes to enable theme support for Nyxt extensions!
Say you have written my-mode
with the style
shown below:
(define-mode my-mode ()
"A mode with its own style, that ideally should pick the user-chosen theme."
...
((style (lass:compile-and-write
'("h1"
:color "black"
:background-color "white")
...)))
...)
Hard-coded CSS is inconvenient for the users of my-mode
. While it's possible to override the style, one shouldn't need to go such great lengths to tweak something as simple as theming.
The author of my-mode
will make it fully themable by making the following trivial change:
(define-mode my-mode ()
"A dynamically themable mode."
...
;; theme:themed-css uses the current theme for colors.
((style (theme:themed-css (theme *browser*)
;; Notice that you need less parentheses here.
("h1"
;; The colors like theme:(on-)background,
;; theme:(on-)accent, theme:(on-)primary are provided by
;; theme:themed-css.
:color theme:on-background
:background-color theme:background))))
...)
Take a minute and realize that the h1 header will be black on a while background while using a default light theme, and vice versa with a dark theme. It's that easy to ensure theme consistency!
Have fun making Nyxt an eye-pleasing computer program, and writing themable extensions on top of it ;)
Did you enjoy this article? Register for our newsletter to receive the latest hacker news from the world of Lisp and browsers!
- Maximum one email per month
- Unsubscribe at any time