Skip to content

Instantly share code, notes, and snippets.

@mbtrs
Created December 4, 2022 05:25
Show Gist options
  • Save mbtrs/bd93a08985d24593c7c7f8daa834c8e4 to your computer and use it in GitHub Desktop.
Save mbtrs/bd93a08985d24593c7c7f8daa834c8e4 to your computer and use it in GitHub Desktop.
nick drake current link indicator
<!--
ecss nearly: https://ecss.io/
-->
<!-- tab module -->
<section class="ns-TabsModule" data-active-tab="A">
<!-- horizontal scroll wrapper -->
<div class="ns-ScrollWrapper">
<!-- tab nav -->
<nav class="ns-TabNav">
<a href="#ns-TabPanelA" class="ns-TabNav_Link" data-tab="A"><span>A</span></a>
<a href="#ns-TabPanelB" class="ns-TabNav_Link" data-tab="B"><span>Black Eyed</span></a>
<a href="#ns-TabPanelC" class="ns-TabNav_Link" data-tab="C"><span>Dog</span></a>
<a href="#ns-TabPanelD" class="ns-TabNav_Link" data-tab="D"><span>He</span></a>
<a href="#ns-TabPanelE" class="ns-TabNav_Link" data-tab="E"><span>Called</span></a>
<a href="#ns-TabPanelF" class="ns-TabNav_Link" data-tab="F"><span>At</span></a>
<a href="#ns-TabPanelG" class="ns-TabNav_Link" data-tab="G"><span>My Door</span></a>
<span class="ns-TabNav_Indicator"></span>
</nav><!-- /.ns-TabNav -->
</div><!-- /.ns-ScrollWrapper -->
<!-- tab panels -->
<div class="ns-TabPanels">
<div class="ns-TabPanel" id="ns-TabPanelA" data-tab-panel="A">Panel A</div>
<div class="ns-TabPanel" id="ns-TabPanelB" data-tab-panel="B">Panel B</div>
<div class="ns-TabPanel" id="ns-TabPanelC" data-tab-panel="C">Panel C</div>
<div class="ns-TabPanel" id="ns-TabPanelD" data-tab-panel="D">Panel D</div>
<div class="ns-TabPanel" id="ns-TabPanelE" data-tab-panel="E">Panel E</div>
<div class="ns-TabPanel" id="ns-TabPanelF" data-tab-panel="F">Panel F</div>
<div class="ns-TabPanel" id="ns-TabPanelG" data-tab-panel="G">Panel G</div>
</div><!-- /.ns-TabPanels -->
</section><!-- /.ns-TabsModule -->
//tab menu w/tab panel behaviour
//still learning. be kind.
"use strict";
//get tabs module parent
var tabsModule = document.body.querySelector(".ns-TabsModule");
//get tab nav
var tabNavList = document.body.querySelector(".ns-TabNav");
//get all tab nav links
var tabNavLinks = document.querySelectorAll(".ns-TabNav_Link");
//get tab nav current nav link indicator
var tabNavCurrentLinkindicator = tabNavList.querySelector(".ns-TabNav_Indicator");
//get all tab panels
var tabPanels = document.querySelectorAll(".ns-TabPanel");
//show tab panel A first because panel A nav link has indicator on page load
document.getElementById("ns-TabPanelA").style.display = "block";
/**
* position indicator function
*/
function positionIndicator() {
//get left position of tab nav ul
var tabNavListLeftPosition = tabNavList.getBoundingClientRect().left;
//get tab module parent current data value
var tabsModuleSectionDataValue = tabsModule.getAttribute("data-active-tab") || "A";
//get nav link span with data value that matches current tab module parent data value
var tabNavCurrentLinkText = tabNavList.querySelector("[data-tab='" + tabsModuleSectionDataValue + "'] span");
//get dimensions of current nav link span
var tabNavCurrentLinkTextPosition = tabNavCurrentLinkText.getBoundingClientRect();
//set indicator left position via CSS transform
//current nav link span left position - tab nav ul left position
//prefix me for live
tabNavCurrentLinkindicator.style.transform =
"translate3d(" +
(tabNavCurrentLinkTextPosition.left - tabNavListLeftPosition) +
"px,0,0) scaleX(" +
tabNavCurrentLinkTextPosition.width * 0.01 +
")";
}
/**
* hide all tab panels function
*/
function hideAllTabPanels() {
//loop through all tab panel elements
for (i = 0; i < tabPanels.length; i++) {
//remove style attribute from all tab panels to hide them
tabPanels[i].removeAttribute("style");
}
};
/**
* tab nav link function
* tab nav link event displays matching tab panel,
* and positions current tab nav link indicator
*/
var tabNavLinkEvent = function() {
//get this link data value
var thisLink = this.getAttribute("data-tab");
//get this link href value
var thisHref = this.getAttribute("href");
//get tab panel element with ID that matches this link href value
var thisTabPanel = document.querySelector(thisHref);
//set tab module parent data to this link data value
tabsModule.setAttribute("data-active-tab", thisLink);
//fire hide all tab panels function
hideAllTabPanels();
//get tab panel element with ID that matches this link href value and set its style to show it
thisTabPanel.style.display = "block";
//fire the position indicator function
positionIndicator();
};
/**
* attach tabNavLinkEvent to all tab nav links
* loop through all nav links and add event
* need to change to parent element and use e.target maybe
*/
for (var i = 0; i < tabNavLinks.length; i++) {
//for each nav link, add click event that fires tab nav link click event function
tabNavLinks[i].addEventListener("click", tabNavLinkEvent, false);
}
/**
* should really position indicator from parent left edge rather than body,
* to keep indicator in position on resize. meh
* for now, here's a quick win because i'm tired
* https://developer.mozilla.org/en-US/docs/Web/Events/resize
*/
(function() {
//someone smarter than me "debounce" code
var resizeTimeout;
function resizeThrottler() {
if (!resizeTimeout) {
resizeTimeout = setTimeout(function() {
resizeTimeout = null;
actualResizeHandler();
}, 66);
}
}
//function to fire after resize timeout delay
function actualResizeHandler() {
//fire the position indicator function
positionIndicator();
}
//window resize event
window.addEventListener("resize", resizeThrottler, false);
})();
/**
* fire position indicator function right away
*/
positionIndicator();
//this is old code
//make your own for the fun of it :)
//p.s. i'm getting better.
/**
* listen to nick drake for peace of mind
*/
@use postcss-nested;
@use postcss-simple-vars;
$base-unit: 11px;
$indicator-speed: 0.2s;
.ns-TabsModule {
width: 100%;
text-align: center;
}
.ns-TabNav {
position: relative;
/* wipe out any unwanted whitespace around inline elements */
font-size: 0;
}
.ns-TabNav_Link {
display: inline-block;
margin: 0 $base-unit;
text-decoration: none;
font-size: 12px;
line-height: calc($base-unit * 4);
color: #bbb;
text-transform: uppercase;
span {
font-size: inherit;
line-height: inherit;
letter-spacing: 1px;
pointer-events: none;
}
}
.ns-TabNav_Indicator {
position: absolute;
bottom: 0;
left: 0;
width: 100px;
height: 2px;
background-color: indianred;
transition-property: transform, left, background-color;
transition-duration: $indicator-speed;
transform-origin: 0;
transform: translate3d(0, 0, 0) scaleX(0);
opacity: 0;
animation: fadeMeIn $indicator-speed forwards;
animation-delay: $indicator-speed;
}
.ns-TabPanel {
padding: 40px;
font-size: 11px;
color: #505050;
text-transform: uppercase;
letter-spacing: 1px;
display: none;
}
@keyframes fadeMeIn {
to {
opacity: 1;
}
}
/* prettify */
body {
box-sizing: border-box;
background: #222;
height: 100vh;
overflow: hidden;
padding-top: 100px;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.ns-ScrollWrapper {
overflow-x: scroll;
overflow-y: hidden;
-webkit-overflow-scrolling: touch;
white-space: nowrap;
box-shadow: inset 0 -2px 0 0 #404040;
&::-webkit-scrollbar {
display: none;
}
}
/**
* indicator color for each tab should you need,
* could attach data-color attribute to tab link instead, JS maybe
* performance should dictate what to do
*/
/*
.ns-TabNav_Indicator {
[data-active-tab="B"] & { background-color: black; }
[data-active-tab="C"] & { background-color: mediumaquamarine; }
[data-active-tab="D"] & { background-color: slateblue; }
[data-active-tab="E"] & { background-color: coral; }
[data-active-tab="F"] & { background-color: indianred; }
[data-active-tab="G"] & { background-color: $color-white; }
}
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment