-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #367 from texastribune/new-tabs
Add new tabs design
- Loading branch information
Showing
2 changed files
with
189 additions
and
88 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,51 +1,39 @@ | ||
// Tabs (c-tabs) | ||
// | ||
// Tab class {{isWide}} https://gist.github.com/jonathantneal/435478e415bfe4f54d06 | ||
// The tabs HTML is based on a [w3 example](https://www.w3.org/TR/wai-aria-practices-1.1/examples/tabs/tabs-1/tabs.html). The JS in the example uses [w3's script](https://www.w3.org/TR/wai-aria-practices-1.1/examples/tabs/tabs-1/js/tabs.js), but state change implementation will vary by environment. | ||
// | ||
// Markup: 6-components/tabs/tabs.html | ||
// | ||
// Styleguide 6.1.3 | ||
.c-tabs { | ||
align-items: flex-end; | ||
display: flex; | ||
flex-wrap: wrap; | ||
list-style: none; | ||
border-bottom: 5px solid $color-yellow-tribune; | ||
&__list { | ||
border-bottom: 1px solid $color-gray-light; | ||
display: flex; | ||
} | ||
|
||
&__tab { | ||
&--wide { | ||
flex: 0 1 10rem; | ||
color: currentColor; | ||
padding-bottom: $size-xs; | ||
&--active { | ||
&:after { | ||
background-color: currentColor; | ||
bottom: -2px; | ||
content: ''; | ||
height: 3px; | ||
left: 0; | ||
position: absolute; | ||
width: 100%; | ||
} | ||
} | ||
} | ||
|
||
&__link { | ||
background-color: $color-black-off; | ||
color: $color-white-pure; | ||
display: block; | ||
border-right: 2px solid #fff; | ||
padding: $size-s; | ||
text-align: center; | ||
|
||
&--s { | ||
padding: $size-xxxs; | ||
// prevent outline on mouse click | ||
&:focus { | ||
outline: 2px solid inherit; | ||
} | ||
|
||
&--active { | ||
background-color: $color-yellow-tribune; | ||
color: $color-black-off; | ||
font-weight: 700; | ||
&:not(:focus-visible) { | ||
outline: none; | ||
} | ||
} | ||
|
||
} | ||
|
||
// display helpers | ||
.c-tab-panes { | ||
&__pane { | ||
display: none; | ||
|
||
&--active { | ||
display: block; | ||
&:focus-visible { | ||
outline: 2px solid inherit; | ||
} | ||
} | ||
} | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,57 +1,170 @@ | ||
<ul class="c-tabs"> | ||
<li class="c-tabs__tab"><a href="#tab1" class="c-tabs__link c-tabs__link--active">Tab 1</a></li> | ||
<li class="c-tabs__tab c-tabs__tab--wide"><a href="#tab2" class="c-tabs__link">Wide Tab</a></li> | ||
<li class="c-tabs__tab"><a href="#tab3" class="c-tabs__link c-tabs__link--s">Small Link</a></li> | ||
<li class="c-tabs__tab"><a href="#tab4" class="c-tabs__link">Tab 4</a></li> | ||
</ul> | ||
<div class="c-tab-panes"> | ||
<div id="tab1" class="c-tab-panes__pane c-tab-panes__pane--active"> | ||
<p>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Atque, quas eum sequi quasi neque magni aperiam laborum incidunt modi repellendus minima eligendi vel illum soluta rem. Odio officiis dicta quam?</p> | ||
</div> | ||
<div id="tab2" class="c-tab-panes__pane"> | ||
<p>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Atque, quas eum sequi quasi neque magni aperiam laborum | ||
incidunt modi repellendus minima eligendi vel illum soluta rem. Odio officiis dicta quam?</p> | ||
<p>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Atque, quas eum sequi quasi neque magni aperiam laborum | ||
incidunt modi repellendus minima eligendi vel illum soluta rem. Odio officiis dicta quam?</p> | ||
</div> | ||
<div id="tab3" class="c-tab-panes__pane"> | ||
<p>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Atque, quas eum sequi quasi neque magni aperiam laborum | ||
incidunt modi repellendus minima eligendi vel illum soluta rem. Odio officiis dicta quam?</p> | ||
</div> | ||
<div id="tab4" class="c-tab-panes__pane"> | ||
<p>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Atque, quas eum sequi quasi neque magni aperiam laborum | ||
incidunt modi repellendus minima eligendi vel illum soluta rem. Odio officiis dicta quam?</p> | ||
</div> | ||
<div class="c-tabs"> | ||
<div | ||
class="c-tabs__list has-text-gray-dark" | ||
role="tablist" | ||
aria-label="Seinfeld taglines" | ||
> | ||
<button | ||
class="c-tabs__tab c-tabs__tab--active has-text-teal t-uppercase t-weight-bold t-size-xs t-lsp-m l-pos-rel has-xs-padding" | ||
role="tab" | ||
aria-selected="true" | ||
aria-controls="jerry-tab" | ||
id="jerry" | ||
> | ||
Jerry Seinfeld | ||
</button> | ||
<button | ||
class="c-tabs__tab t-uppercase t-weight-bold t-size-xs t-lsp-m l-pos-rel has-xs-padding" | ||
role="tab" | ||
aria-selected="false" | ||
aria-controls="elaine-tab" | ||
id="elaine" | ||
tabindex="-1" | ||
> | ||
Elaine Benes | ||
</button> | ||
<button | ||
class="c-tabs__tab t-uppercase t-weight-bold t-size-xs t-lsp-m l-pos-rel has-xs-padding" | ||
role="tab" | ||
aria-selected="false" | ||
aria-controls="cosmo-tab" | ||
id="cosmo" | ||
tabindex="-1" | ||
> | ||
Cosmo Kramer | ||
</button> | ||
<button | ||
class="c-tabs__tab t-uppercase t-weight-bold t-size-xs t-lsp-m l-pos-rel has-xs-padding" | ||
role="tab" | ||
aria-selected="false" | ||
aria-controls="george-tab" | ||
id="george" | ||
tabindex="-1" | ||
> | ||
George Costanza | ||
</button> | ||
</div> | ||
<div | ||
class="has-xs-padding" | ||
tabindex="0" | ||
role="tabpanel" | ||
id="jerry-tab" | ||
aria-labelledby="jerry" | ||
> | ||
<p>Hello, Newman.</p> | ||
<p>– Jerry</p> | ||
</div> | ||
<div | ||
class="has-xs-padding" | ||
tabindex="0" | ||
role="tabpanel" | ||
id="elaine-tab" | ||
aria-labelledby="elaine" | ||
hidden | ||
> | ||
<p>Get out!</p> | ||
<p>– Elaine</p> | ||
</div> | ||
<div | ||
class="has-xs-padding" | ||
tabindex="0" | ||
role="tabpanel" | ||
id="cosmo-tab" | ||
aria-labelledby="cosmo" | ||
hidden | ||
> | ||
<p>Giddyup!</p> | ||
<p>– Kramer</p> | ||
</div> | ||
<div | ||
class="has-xs-padding" | ||
tabindex="0" | ||
role="tabpanel" | ||
id="george-tab" | ||
aria-labelledby="george" | ||
hidden | ||
> | ||
<p>Serenity now.</p> | ||
<p>– George</p> | ||
</div> | ||
</div> | ||
|
||
<!-- sample JS based on example in w3 --> | ||
<!-- link: https://www.w3.org/TR/wai-aria-practices-1.1/examples/tabs/tabs-1/js/tabs.js --> | ||
<script> | ||
(function () { | ||
// implementation approaches may vary, but tabs should always be keyboard accessible | ||
// and will likely require listeners for left/right keys | ||
var tabs = document.querySelectorAll('[role="tab"]'); | ||
var panels = document.querySelectorAll('[role="tabpanel"]'); | ||
var activeState = 'c-tabs__tab--active'; | ||
var activeColor = 'has-text-teal'; | ||
var currentIndex = 0; | ||
|
||
function activateTab(tab) { | ||
// visual style changes | ||
tab.classList.add(activeState, activeColor); | ||
|
||
<script> | ||
// Remove tabindex attribute | ||
tab.removeAttribute('tabindex'); | ||
|
||
// Set the tab as selected | ||
tab.setAttribute('aria-selected', 'true'); | ||
|
||
// Get the value of aria-controls (which is an ID) | ||
var controls = tab.getAttribute('aria-controls'); | ||
|
||
// Remove hidden attribute from tab panel to make it visible | ||
document.getElementById(controls).removeAttribute('hidden'); | ||
|
||
// update current index | ||
currentIndex = parseInt(tab.dataset.order); | ||
|
||
// update focus | ||
tab.focus(); | ||
} | ||
function deactivateTabs() { | ||
for (var i = 0; i < tabs.length; ++i) { | ||
tabs[i].classList.remove(activeState, activeColor); | ||
tabs[i].setAttribute('tabindex', '-1'); | ||
tabs[i].setAttribute('aria-selected', 'false'); | ||
} | ||
for (var p = 0; p < panels.length; p++) { | ||
panels[p].setAttribute('hidden', 'hidden'); | ||
} | ||
} | ||
function onClick(event) { | ||
// deactivate all tabs | ||
deactivateTabs(); | ||
// activate current | ||
activateTab(event.target); | ||
} | ||
function onKeyUp(event) { | ||
var isOnFirst = currentIndex === 0; | ||
var isOnLast = currentIndex === tabs.length - 1; | ||
var noTabActive = currentIndex === -1; | ||
var isLeftArrow = event.keyCode === 37; | ||
var isRightArrow = event.keyCode === 39; | ||
|
||
window.addEventListener("load", function() { | ||
// store tabs variable | ||
var myTabs = document.querySelectorAll(".c-tabs__link"); | ||
function myTabClicks(tabClickEvent) { | ||
var activeTabClass = 'c-tabs__link--active'; | ||
var activePaneClass = 'c-tab-panes__pane--active'; | ||
for (var i = 0; i < myTabs.length; i++) { | ||
myTabs[i].classList.remove(activeTabClass); | ||
} | ||
var clickedTab = tabClickEvent.currentTarget; | ||
clickedTab.classList.add(activeTabClass); | ||
tabClickEvent.preventDefault(); | ||
var myContentPanes = document.querySelectorAll(".c-tab-panes__pane"); | ||
for (i = 0; i < myContentPanes.length; i++) { | ||
myContentPanes[i].classList.remove(activePaneClass); | ||
} | ||
var anchorReference = tabClickEvent.target; | ||
var activePaneId = anchorReference.getAttribute("href"); | ||
var activePane = document.querySelector(activePaneId); | ||
activePane.classList.add(activePaneClass); | ||
} | ||
|
||
for (i = 0; i < myTabs.length; i++) { | ||
myTabs[i].addEventListener("click", myTabClicks) | ||
} | ||
}); | ||
if ((isLeftArrow || isRightArrow) && noTabActive) { | ||
tabs[0].click(); | ||
} else if (isLeftArrow && isOnFirst) { | ||
tabs[tabs.length - 1].click(); | ||
} else if (isLeftArrow) { | ||
tabs[currentIndex - 1].click(); | ||
} else if (isRightArrow && isOnLast) { | ||
tabs[0].click(); | ||
} else if (isRightArrow) { | ||
tabs[currentIndex + 1].click(); | ||
} | ||
} | ||
for (var i = 0; i < tabs.length; ++i) { | ||
// assign an index to the tab | ||
tabs[i].dataset.order = i; | ||
// click display/hide behavior | ||
tabs[i].addEventListener('click', onClick); | ||
// navigate through tabs with left/right keys | ||
tabs[i].addEventListener('keyup', onKeyUp); | ||
} | ||
})(); | ||
</script> |