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.

Revisions

  1. mbtrs created this gist Dec 4, 2022.
    34 changes: 34 additions & 0 deletions index.html
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,34 @@
    <!--
    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 -->
    7 changes: 7 additions & 0 deletions nick-drake-current-link-indicator.markdown
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,7 @@
    nick drake current link indicator
    ---------------------------------
    :) thanks

    A [Pen](https://codepen.io/m--b/pen/eYYrRvX) by [mB](https://codepen.io/m--b) on [CodePen](https://codepen.io).

    [License](https://codepen.io/license/pen/eYYrRvX).
    122 changes: 122 additions & 0 deletions script.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,122 @@
    //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
    */
    103 changes: 103 additions & 0 deletions style.postcss
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,103 @@
    @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; }
    }
    */