zachleat / seven-minute-tabs

A minimal no-theme Tabs web component.
https://zachleat.github.io/seven-minute-tabs/demo.html
87 stars 7 forks source link

Maintaining unique tab state #4

Open bradleyburgess opened 2 years ago

bradleyburgess commented 2 years ago

This is great. Thank you.

But here's a feature I would love: maintained tab state.

Let's say we have a site for a Bed & Breakfast (fakebnb.com), and on one page (fakebnb.com/rooms) we have the different rooms — each room on a different tab panel. I, a potential guest, go to the site, and really like room no. 2. While on room 2's tab, I send my wife the link in the url bar (fakebnb.com/rooms) — except when she opens it, it obviously shows room no. 1, because it's the first tab.

Because you're doing event.preventDefault() when the tab buttons are clicked (or similarly via keyboard), the tab id isn't being pushed to history. It would be great if we could have the active tab reflected in the history. That way, when you click a tab, it gets pushed to the history (fakebnb.com/rooms#room-2), and when that link is shared, it opens to the "right" tab.

I would propose something like this (obviously tidied up):

// at the end of `_init()` method:
const hash = location.hash;
const tabPanelIds = Array.from(this.panels).map(panel => panel.id);
if (hash && tabPanelIds.includes(hash?.substr(1)) {
  this.activateTab(Array.prototype.find.call(this.buttons, button => button.href.endsWith(hash), false);
}

// at the end of `activateTab()` method:
if (location.hash?.substr(1) !== controls) {
  history.replaceState({}, "", "#" + controls);
}

Granted, I haven't tested this yet. But would you be open to a PR that implements this?

bradleyburgess commented 2 years ago

Here is a working Codepen, with it tidied up a little. (Note, because it's a Codepen, I've manually set the second tab being in location.hash with a script tag, so this simulates sending a link like example.com/index.html#second-tab)

bradleyburgess commented 2 years ago

In my testing, I can see some potential accessibility issues with navigating to the tab on page load. I don't know what you think. It could perhaps be better achieved by using URL query parameters instead. There's also the added complication of having more than one <seven-minute-tabs> component on the page, but that again could be probably accomplished using query parameters, like index.html?tabgroup1=first-tab&tabgroup2=second-tab, but that could get real ugly.

zachleat commented 9 months ago

I shipped a persist attribute that has the idea of a global persistent group (think maintaining Nunjucks across a bunch of different template syntax chooser tab instances on the 11ty docs https://www.11ty.dev/docs/collections/) but that isn’t quite what you’re asking for here