Let’s not start with nav menus. Let’s start somewhere else…
What do Github, Laravel Forge, MacOS, VS Code, Sublime Text, JetBrains IDEs like PHPStorm, Google Chrome’s dev tools, Windows Terminal, the Warp terminal application, and Netlify all have in common?
They all have “command palettes” – as do an increasing number of both native and web-based applications.
For those not familiar, command palettes are pop-up user interfaces that provide keyboard-driven, searchable menus of actions for your application. They take all the things you can do in the application and make them available with a few keystrokes. And some include more advanced features like searching content or files too.
For those who love to use their keyboard to navigate their computer, they are valuable tools, allowing keyboard access to application features that goes way beyond keyboard shortcuts, and removing the need to memorise a large number of keyboard shortcuts to be efficient.
And command palettes seem to be a growing trend. All the applications I mentioned above have command palettes, but there’s Alfred App for MacOS, Raycast, MacOS’s own Spotlight. Plus TailwindUI added some command palette designs so that other people can add them to their web apps, and kbar is a JS library to help you add them too.
This trend is one that I claim I was ahead of the curve on as I made my own command palette tool for WordPress, and then played with making that same tool work on other web applications, such as Laravel Forge and Github months before they added their own command palettes.
But there’s a problem – especially with web applications such as Forge, GitHub and Netlify: Each command palette is different! The keyboard shortcut to trigger the palette may be different. The presentation of the commands may be different. The way that search and sub-menus work may be different.
There must be a better way! And I think that there could be.
Config-driven Turbo Admin
Let’s go back a bit to the inception of my “Turbo Admin” command palette for WordPress.
I had seen “Laravel Spotlight“, and the moment I saw it my first thought was “That’s genius – why don’t all web apps have command palettes?”
My second thought was “WordPress should have a command palette!”
I set to it, and the easiest way I could come up with to gather up the menu items and commands was, surprisingly, not to hook into the back-end somehow, but to use JavaScript to scrape the menu items and their URLs from the WordPress dashboard.
This worked fine as a basic first implementation. But it quickly hit limitations.
Initially I just wanted to add some of my own hard-coded extra commands for things like “Logout”, but then I realised that the Logout link was in the admin bar at the top of the WordPress dashboard. So I added the ability to grab that too.
And as I wanted to grab more and more links from throughout the Dashboard I realised I needed some kind of array of things to grab. And this idea eventually evolved into a configuration-based system for injecting items into the Turbo Admin palette.
This configuration lets you specify:
- The “type” of link to discover – it can be a hard-coded title and URL, or dynamically discovered links using a DOM/CSS selector
- The selector to use (for selector-based links)
- Either the title to use, or a function for generating a title from a discovered element
- Either the URL to use, or a function for generating a URL from a discovered element
This probably makes sense with a simple example. This config entry discovers all of the “New <post type>” links in the WordPress admin bar, such as “New Post”, “New Page” and so on:
{
'detectType': 'dom',
'detectSelector': '#wp-admin-bar-new-content .ab-submenu a',
'itemTitleFunction': (item) => 'New ' + item.textContent,
'itemUrlFunction': (item) => item.href
},
With this config-driven approach I can specify DOM selectors for non-WordPress applications too – and this is exactly how my simple palettes for GitHub and Forge came about. (I note that these were just demos, and never made it into public in any way other than teaser videos).
An API for command palettes
With this config driven approach in place, I can seemingly inject a command palette into any* web-based application!
* – Not quite any, some use dynamically generated items or randomly generated IDs. What can you do?
What I’ve made here is an API or protocol for defining command palette items.
The next obvious step is something like: “What if an application can provide these configurations itself?”
Or if not “What if standard-format configurations could be user/community-generated, like user scripts and user styles?” (Note: use these at your own risk!)
Then there could be any number of command palette browser extensions that sucked in these configs and made the menus for you. Or maybe the browsers could have them built in themselves?
You’d have the same interface and the same keyboard shortcut for all your web applications. It would be amazing!
An API for menu items in general?
A note to designers and people who love fancy websites with intricate designs: you’re gonna hate me! I make no apology for that. UI conventions are a thing that can be useful, and I’m just exploring ideas. Bear with me.
So if we have a system for a website or web application to specify command palette items… well… aren’t these just the menu items? So… umm… can’t we also use this API/protocol for defining the menu items for a website rather than scraping them from the DOM. Use the configuration to ADD them to the DOM? Or just let the browser handle all this for you.
Items wouldn’t have to be links. They could be callbacks/functions that “do stuff”. This doesn’t have to be a restriction.
Yes, I know it would be really boring if every website had the same menus. We’d have to figure that out. Perhaps there is some compromise with design?
But look at how applications on your desktop/laptop work… the menus are in the same place for most apps.
And those that do things their own way are SUPER annoying (I’m looking at YOU Warp terminal…)
And look at how the MS Office suite and Apple’s work applications have consistently placed user interface components. Once you have learned one tool, you can easily learn others.
User interface conventions can be helpful.
AND… as the developer… building nav menus is flippin hard, and we so often don’t get interactions and accessibility right. What if this was all handled for us? We just provide the data, and the browser takes care of it, and we get the possibility of command palettes – and maybe other kinds of interface – for free?
And why stop at menus? You could define keyboard shortcuts too, thus removing a zillion
How would this work?
If this was a thing then we would need a way to get the configuration to the browser or browser extension. It would probably be JSON. I guess. But how would it be delivered/discovered?
I’ve not thought about this a lot, but there seem to be a few obvious ways to me:
- A file in the root of a site, like robots.txt, or the old standardised favicon location, with a standard name. Maybe “commands.json” or something.
- Like the above, but with a meta tag in the HTML to specify the file’s location.
- A standardised – or meta-tag specified – API route. This would work like the above but could allow options to be passed and deliver dynamic configurations.
So, Ross, this sounds great. Why do you say you “know nothing”?
(This probably is not the question you were asking, but if you were…)
Simply because it seems so obvious that many people MUST have thought of it before and dismissed it for a hundred and one good reasons that I’m too stupid to have thought of.
Perhaps they just want to maintain the ability to design menus. In which case, let’s find that compromise because a standardised, easy-to-develop, accessible-by-default, machine-readable website navigation seems to have a lot of benefits!
I’ve really tried to think of some downsides. I don’t think it’s insecure or open to abuse (though I’m sure people will tell me I’m wrong). I’m sure it can handle translations, sub-menus, mega-menus and some elements of design. You wouldn’t have to worry about responsive design or RTL languages – it would all be taken care of for you!
It could even help Google discover site links and improve search results!
I’ve had the thought that “We don’t have other APIs like this that send config to the browser?”, but we clearly do! Especially in modern browsers.
We have all manner of meta headers we can add to control languages and browser features and icons that get displayed and color schemes.
We have web app manifests that specify all sorts of options.
We have all sorts of APIs for interacting with things like the clipboard, bluetooth devices, browser history, scroll behaviour and standard sharing options.
The browser is doing so much for us these days… why do we continue to handle navigation manually?
Why would we not do this? Am I really the first to have thought of it?
I’m not a browser engineer, or involved in any way at all with the committees that define browser APIs. This just seems like a good idea to me. Perhaps there’s already an RFC? I really don’t know.
As I said… I know nothing. So tell me what you know. Why shouldn’t this happen?