Stacks Dev Journal - Custom Toolbar Buttons

Toolbars and dark mode

I had hoped to get away without modifying the Stacks 3 custom toolbars and toolbar buttons too much. Their look is simple enough not to need too much modification, or so I thought. Stacks 4 will add a smaller variant of the toolbar for text editing features – that bit seemed to work great in dark mode too.

But dark mode changed other things. And not everything works perfectly. In Stacks 3 the info pane at the bottom of the Library is “vibrant” – it shows colors from underneath the pane in an etched glass sort of way. In Stacks 3.5 dark mode is supported, but when switching between modes this little pane stays stubbornly the same.

It’s due to a compatibility shim I added to allow me to support OS versions before vibrancy was introduced. Stacks 4 won’t need this shim, so I removed it and that fixed the problem. But the shim was also being used in all the toolbars.

Oh no.

The info pane was connected to the toolbars

I then spent a couple days fixing the affected toolbars and getting their vibrancy materials right in dark mode too. But this, of course, affected the all the custom toolbar buttons as well.

Oh no.

Customizing NSButtons is not as trivial as you’d hope. It’s certainly nothing like iOS, that’s for sure. In an old-school Cocoa sort of way, each NSButton is paired with a corresponding NSButtonCell. The cell does the drawing for each of the oh-em-gee-there-are-so-many-states in the NSButton. And now, with dark mode, there are double the number of states. Worse, dark mode toolbar buttons have quite a few differences to their light mode counterpart.

  • Light mode buttons get darker when pushed.
  • Dark mode buttons get lighter.
  • On-state and off-state work slightly differently.
  • Light mode toolbar buttons have a flat white background, a noticeable border-shadow (only ½ pixel wide on retina) and black foreground color.
  • Dark mode toolbar buttons have a gradient gray background, no visible border-shadow and off-white foreground color.

Oh no.

I nearly punted. It’s a lot of little detailed quirky things. A whole bunch of custom gradients – that are of course slightly different in dark mode. If I deleted my custom buttons and went with a vanilla NSButton I could get rid of a lot of code and be days closer to final release. But having a few colored buttons has been a staple part of the look of Stacks since version 1.0 – I really like those colors. They help identify Stacks amidst a complex and ever changing RapidWeaver UI.

Oh yes.

So I did the work. It took about four days if I include the vibrancy bit and the toolbars. I built new gradients for dark mode that are darker and more saturated. I added the thin light gray border-shadow in light mode. And a dark-mode-only interior bevel. I was already using NSColor.labelColor for the foreground drawing. So that’s one tiny little bit I got for free. The end result isn’t a direct copy of any specific NSButton UI and that’s just fine. I wanted them to be a tiny bit unique.

And here’s the result. The gif is showing the three new colored buttons that also happen to be one of the large feature additions in Stacks 4. The posterized colors in the gif don’t do the gradients justice, but you get the idea. I imagine I’ll keep tweaking these right up to the release. So if I missed any little details let me know.

Toolbar Buttons

#dotblog #devjournal #custom-ui

*What is this: these are random snippets from my dev journal working various projects. Some of these projects are for work, some are just for fun.

isaiah @isaiah