Not something I would use, since I use portrait mode tabs in Vivaldi (one of the many things missing since Opera converted to blink, telling their handful of fans to golf foxtrot yankee)... But some comments:
As Jos Fabre mentioned there are keys for doing this, have you considered intercepting the standard keystrokes for tab navigation?
You've got perfectly good LI, what's with all the 'span for nothing' inside it?
Not every element needs a class on it, leverage your semantics via selectors!
There is no such thing as a FOR attribute on INPUT... did you mean to add a LABEL so it's accessible?
The use of PX metrics particularly on the font-size flips the bird at usability and accessibility, failing to scale to user preferences.
Rather than the slow memory and battery wasting innerHTML for your style, why aren't you using insertRule? At least use textContent on a DOM created STYLE element so the parser doesn't have to get involved.
If you have multiple let/const/var don't waste time saying it on each and every one, you can comma delimit those bad boys.
Array.from.foreach and the arrow function is slow and memory hogging, with the ternary without assignment hard to follow and could be greatly simplified. A conventional "for" would likely be faster, especially on an object.
Check this out:
for (let data of event.currentTarget.Attributes) {
if (data.name !== 'class') {
selectedTab[selectedTab.tabId ? 'windowId' : 'tabId'] = data.value;
}
}
Smaller/simpler and removes the stack overhead of the pointless function call. Because foreach uses callbacks, even as arrow functions it can trigger large amounts of memory thrashing and slowdowns. I avoid using it where practical to do so. Same for conversion to array when you've got a perfectly good object.
Also doing innerHTML for the title risks the possibility of a malformed title creating a script injection. That's appendChild of a createTextNode's job. Also did you know that appendChild returns the appended child, meaning you could simplify your logic a LOT during DOM creation.
For example:
for (let tab of tabs) {
let listItem = document.createElement('li');
listItem.appendChild(
document.createElement('img')
).src = tab.favIconUrl ? tab.favIconUrl : CONFIG.DEFAULT_FAVICON;
listItem.appendChild(document.createTextNode(tab.title));
listItem.setAttribute('data-tab-id', tab.id);
listItem.setAttribute('data-window-id', tab.windowId);
listItem.addEventListener('click', chromeTabModule.switchTab);
// always make it live LAST
tabList.appendChild(listItem);
}
Swings an axe at the multiple "variables for nothing", "span for nothing", "classes for nothing", and fixes the possibility of script injection via the title.
Basically, avoid using innerHTML, it's a crutch that just creates more problems than it solves.
Also you can further reduce the code size and provide a bit of a speedup by passing document as "d" to your SIF/IIFE.
(function(d) {
// rest of your code here
})(document);
Google does this in a lot of their scripts as it shrinks down the code nice, and does run faster since it moves a reference to document into the local scope instead of having to wait for the parser to go through the whole stack of globals to find it. Since you already have it all in a SIF / IIFE (same thing, latter term is just newer) leverage that to make your life easier.
Just some suggestions.