<script src="tabs.js" type="module"></script>
<style>
tab-window {
display: none;
&[open] {
display: block;
}
}
</style>
<tab-control group="some-group">
<label><input type="radio" name="whatever" value="tab-1"> Tab 1</label>
<label><input type="radio" name="whatever" value="tab-2"> Tab 2</label>
</tab-control>
<tab-window group="some-group" value="tab-1">
Tab 1 Content
</tab-window>
<tab-window group="some-group" value="tab-2">
Tab 2 Content
</tab-window>
<tab-window group="some-group" value="tab-1">
A second Tab 1 Window
</tab-window>
<tab-control group="some-group">
A select control
<select name="whatever">
<option value="tab-1">Tab 1</option>
<option value="tab-2">Tab 2</option>
</select>
</tab-control>
<tab-control group="some-group" on="click">
A button control
<button type="button" value="tab-1">Tab 1</button>
<button type="button" value="tab-2">Tab 2</button>
</tab-control>
Last active
October 14, 2025 03:59
-
-
Save tobz-nz/2447216683e6733b4a6fc91b0e2b0ceb to your computer and use it in GitHub Desktop.
A super simple pair of tab custom elements
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| customElements.define('tab-control', class extends HTMLElement { | |
| #tabWindows = [] | |
| connectedCallback() { | |
| this.addEventListener(this.on, this) | |
| // Set the initial active tab window | |
| Array.from(this.#tabWindows) | |
| .find(tabWindow => tabWindow.value === this.activeTab) | |
| ?.toggle(true) | |
| } | |
| disconnectedCallback() { | |
| this.removeEventListener(this.on, this) | |
| } | |
| handleEvent(event) { | |
| if (event.type === this.on) { | |
| // Toggle the open attribute on the tab window | |
| this.#tabWindows.forEach(tabWindow => { | |
| tabWindow.toggle(tabWindow.value === event.target.value) | |
| }) | |
| } | |
| } | |
| get on() { | |
| return this.getAttribute('on') || 'input' | |
| } | |
| set on(value) { | |
| this.setAttribute('on', value) | |
| } | |
| get targets() { | |
| return this.getAttribute('targets') | |
| } | |
| get activeTab() { | |
| return this.getAttribute('active-tab') | |
| } | |
| add(tabWindow) { | |
| this.#tabWindows.push(tabWindow) | |
| } | |
| }) | |
| customElements.define('tab-window', class extends HTMLElement { | |
| connectedCallback() { | |
| // push this window into the control's list of tab-windows | |
| document.querySelectorAll(`tab-control[group="${this.group}"]`).forEach(control => control.add(this)) | |
| } | |
| toggle(value) { | |
| this.open = value | |
| } | |
| get group() { | |
| return this.getAttribute('group') | |
| } | |
| set group(value) { | |
| this.setAttribute('group', value) | |
| } | |
| get value() { | |
| return this.getAttribute('value') | |
| } | |
| set value(value) { | |
| this.setAttribute('value', value) | |
| } | |
| get open() { | |
| return this.getAttribute('open') | |
| } | |
| set open(value) { | |
| this.toggleAttribute('open', !!value) | |
| } | |
| }) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment