218 lines
6.5 KiB
HTML
218 lines
6.5 KiB
HTML
|
|
<html>
|
|
<head>
|
|
<title>Pattern</title>
|
|
</head>
|
|
<body data-prismjs-copy-timeout="1500">
|
|
<h2>What is it</h2>
|
|
<p>A tabs component that provides different sections of content that are displayed one at a time when the user selects that information. </p>
|
|
<h2>When to use it</h2>
|
|
<p>The tabbed user interface enables users to jump to their target section quickly. Tabs present like logically group information on the same page. Information should </p>
|
|
<ul>
|
|
<li>be logically chunked and ordered</li>
|
|
<li>be arallel in nature</li>
|
|
<li>show user's context</li>
|
|
<li>obvious where they begin and end </li>
|
|
</ul>
|
|
<p>Users should not need to see content of multiple tabs simultaneously and the user should be able to easily recognise where they are within the content. </p>
|
|
<h2>How to use it</h2>
|
|
<p>The structure of the tab set is defined in html. There are two forms supported. Adding a class of <code class="inline">.tab-group</code> to the container element will work in place of the <code class="inline">tabset</code> tag, and the tab panels can be defined using either <code class="inline">tab=""</code> or <code class="inline">data-tab=""</code>. Passing an optional element to the init function will initialise tabs within that element. </p>
|
|
<tabset id="tabs">
|
|
<pre class="language-html" tab="html">
|
|
<tabset id="uniqueID">
|
|
<div tab="[tab title]"></div>
|
|
<div tab="[tab title]"></div>
|
|
</tabset></pre>
|
|
<pre class="language-pug" tab="pug">tabset#uniqueID
|
|
div(tab="[tab title]")
|
|
div(tab="[tab title]")
|
|
</pre>
|
|
<pre class="language-css" tab="css">tabset, .tab-group {
|
|
margin: 2rem 0 1rem 0;
|
|
}
|
|
tabset > ul, .tab-group > ul {
|
|
display: -webkit-box;
|
|
display: -ms-flexbox;
|
|
display: flex;
|
|
margin: 0;
|
|
padding: 0;
|
|
}
|
|
tabset > ul li.separator, .tab-group > ul li.separator {
|
|
border-bottom: 1px solid #7f7f7f;
|
|
border-left: 1px solid #7f7f7f;
|
|
display: inline-block;
|
|
margin: 0.45rem 0 0 0;
|
|
width: 100%;
|
|
}
|
|
tabset .tab-hidden, .tab-group .tab-hidden {
|
|
display: none;
|
|
}
|
|
tabset [role=tab], .tab-group [role=tab] {
|
|
background-color: #FFF;
|
|
border-left: 1px solid #7f7f7f;
|
|
border-top: 1px solid #7f7f7f;
|
|
border-radius: 0.5rem 0.5rem 0 0;
|
|
cursor: pointer;
|
|
margin: 0;
|
|
display: inline;
|
|
padding: 1rem 1.5rem 0.14rem 1.5rem;
|
|
z-index: 2;
|
|
}
|
|
tabset [role=tab]:last-of-type, .tab-group [role=tab]:last-of-type {
|
|
border-right: 1px solid #7f7f7f;
|
|
}
|
|
tabset [role=tab]:not(.selected), .tab-group [role=tab]:not(.selected) {
|
|
background-color: #f0f0f0;
|
|
border-bottom: 1px solid #7f7f7f;
|
|
}
|
|
tabset [role=tab] span, .tab-group [role=tab] span {
|
|
display: block;
|
|
margin: 0 0 0.5rem 0;
|
|
}
|
|
tabset [role=tabpanel], .tab-group [role=tabpanel] {
|
|
background-color: #FFF;
|
|
border: 1px solid #7f7f7f;
|
|
border-top: none;
|
|
padding: 1rem;
|
|
z-index: 1;
|
|
}
|
|
tabset [role=tabpanel]:not(.open), .tab-group [role=tabpanel]:not(.open) {
|
|
display: none;
|
|
}</pre>
|
|
<div tab="scss">
|
|
<pre class="language-sass">@import "[path to]/_tabs";
|
|
@include tabs{
|
|
// optional content block
|
|
};
|
|
</pre>
|
|
<pre class="language-sass">// DS2 core (c) 2024 Alexander McIlwraith
|
|
// Licensed under CC BY-SA 4.0
|
|
|
|
$tab-border: #7f7f7f !default;
|
|
$tab-selected: #FFF !default;
|
|
$tab-notselected: #f0f0f0 !default;
|
|
|
|
@mixin tabs {
|
|
tabset, .tab-group {
|
|
margin: 2rem 0 1rem 0;
|
|
> ul {
|
|
display: flex;
|
|
margin: 0;
|
|
padding: 0;
|
|
|
|
li.separator {
|
|
border-bottom: 1px solid $tab-border;
|
|
border-left: 1px solid $tab-border;
|
|
display: inline-block;
|
|
margin: .45rem 0 0 0;
|
|
width: 100%;
|
|
}
|
|
}
|
|
|
|
.tab-hidden {
|
|
display: none;
|
|
}
|
|
|
|
[role="tab"] {
|
|
background-color: $tab-selected;
|
|
border-left: 1px solid $tab-border;
|
|
border-top: 1px solid $tab-border;
|
|
border-radius: .5rem .5rem 0 0;
|
|
cursor:pointer;
|
|
margin: 0;
|
|
display: inline;
|
|
padding: 1rem 1.5rem .14rem 1.5rem;
|
|
z-index: 2;
|
|
|
|
&:last-of-type {
|
|
border-right: 1px solid $tab-border;
|
|
}
|
|
|
|
&:not(.selected) {
|
|
background-color: $tab-notselected;
|
|
border-bottom: 1px solid $tab-border;
|
|
}
|
|
|
|
span {
|
|
display: block;
|
|
margin: 0 0 .5rem 0;
|
|
}
|
|
|
|
}
|
|
[role="tabpanel"] {
|
|
background-color: $tab-selected;
|
|
border: 1px solid $tab-border;
|
|
border-top: none;
|
|
padding: 1rem;
|
|
z-index: 1;
|
|
|
|
&:not(.open) {
|
|
display: none;
|
|
}
|
|
@content;
|
|
|
|
}
|
|
}
|
|
}</pre>
|
|
</div>
|
|
<div tab="js">
|
|
<pre class="language-js">import * as tabs from "[path to]/_tabs.js";
|
|
tabs.init();</pre>
|
|
<pre class="language-js">/* DS2 core (c) 2024 Alexander McIlwraith
|
|
import * as tabs from "../pg/patterns/layouts/tabs/_tabs.js";
|
|
tabs.init();
|
|
*/
|
|
|
|
export function init(p = document) {
|
|
p.querySelectorAll(".tab-group, tabset").forEach(tabGroup => {
|
|
|
|
if (tabGroup.querySelector("[role=tablist]") === null) {
|
|
const tabgroup = tabGroup.getAttribute("id");
|
|
let tablist = "";
|
|
|
|
Array.from(tabGroup.children).forEach(child => {
|
|
const tab = child.getAttribute("tab") || child.getAttribute("data-tab");
|
|
if (tab !== null) {
|
|
const tabID = tab.replace(/\W+/g, "-").toLowerCase();
|
|
const tabPanel = document.createElement('div');
|
|
tabPanel.id = `tab-panel-${tabgroup}-${tabID}`;
|
|
tabPanel.className = tablist === "" ? "open" : "";
|
|
tabPanel.setAttribute("role", "tabpanel");
|
|
tabPanel.setAttribute("tabindex", "0");
|
|
tabPanel.setAttribute("aria-labelledby", `tab-${tabgroup}-${tabID}`);
|
|
tabPanel.appendChild(child.cloneNode(true));
|
|
child.parentNode.replaceChild(tabPanel, child);
|
|
tablist += `<li tabindex="0" role="tab" ${tablist === "" ? "class='selected'" : ""} id="tab-${tabgroup}-${tabID}"><span>${tab}</span></li>`;
|
|
} else {
|
|
child.classList.add("tab-hidden");
|
|
}
|
|
});
|
|
|
|
const ul = document.createElement('ul');
|
|
ul.setAttribute("role", "tablist");
|
|
ul.innerHTML = `${tablist}<li role="separator" class="separator"></li>`;
|
|
tabGroup.insertBefore(ul, tabGroup.firstChild);
|
|
|
|
tabGroup.querySelectorAll('[role="tab"]').forEach(tab => {
|
|
tab.addEventListener("click", () => {
|
|
const siblings = Array.from(tab.parentNode.children);
|
|
siblings.forEach(sibling => sibling.classList.remove("selected"));
|
|
tab.classList.add("selected");
|
|
|
|
const tabPanels = Array.from(tab.parentNode.parentNode.children)
|
|
.filter(child => child.getAttribute("role") === "tabpanel");
|
|
tabPanels.forEach(panel => panel.classList.remove("open"));
|
|
|
|
const tabPanelId = tab.getAttribute("id").replace("tab", "tab-panel");
|
|
document.getElementById(tabPanelId).classList.add("open");
|
|
});
|
|
});
|
|
|
|
}
|
|
});
|
|
}
|
|
</pre>
|
|
</div>
|
|
</tabset>
|
|
</body>
|
|
</html> |