<div style="position: relative">
    <button class="OverflowContainer-button OverflowContainer-button--previous js-overflow-container-previous">
            <span class="screenreader">
                Click to go back
            </span>

            <span class="icon _arrow-left _before"></span>
        </button>

    <div id="" class="OverflowContainer js-overflow-container " style="">
        <a class="u-display-block u-space-margin-around-400" href="http://lorempixel.com/600/400/abstract?14799">

            <div class="Media _square" style="">

                <img id="" class="image  " alt="" style="" src="http://fillmurray.com/g/400/400" />

            </div>

        </a>

        <a class="u-display-block u-space-margin-around-400" href="http://lorempixel.com/600/400/fashion?91309">

            <div class="Media _square" style="">

                <img id="" class="image  " alt="" style="" src="http://fillmurray.com/g/400/400" />

            </div>

        </a>

        <a class="u-display-block u-space-margin-around-400" href="http://lorempixel.com/600/400/nature?99975">

            <div class="Media _square" style="">

                <img id="" class="image  " alt="" style="" src="http://fillmurray.com/g/400/400" />

            </div>

        </a>

        <a class="u-display-block u-space-margin-around-400" href="http://lorempixel.com/600/400/sports?7404">

            <div class="Media _square" style="">

                <img id="" class="image  " alt="" style="" src="http://fillmurray.com/g/400/400" />

            </div>

        </a>

        <a class="u-display-block u-space-margin-around-400" href="http://lorempixel.com/600/400/business?63565">

            <div class="Media _square" style="">

                <img id="" class="image  " alt="" style="" src="http://fillmurray.com/g/400/400" />

            </div>

        </a>

        <a class="u-display-block u-space-margin-around-400" href="http://lorempixel.com/600/400/food?98293">

            <div class="Media _square" style="">

                <img id="" class="image  " alt="" style="" src="http://fillmurray.com/g/400/400" />

            </div>

        </a>

    </div>

    <button class="OverflowContainer-button OverflowContainer-button--next js-overflow-container-advance">
            <span class="screenreader">
                Click to advance
            </span>

            <span class="icon _arrow _before"></span>
        </button>
</div>
{{#if shownavigation}}
    <div style="position: relative">
        <button class="OverflowContainer-button OverflowContainer-button--previous js-overflow-container-previous">
            <span class="screenreader">
                Click to go back
            </span>

            <span class="icon _arrow-left _before"></span>
        </button>
{{/if}}

        <div id="{{id}}"
             class="OverflowContainer js-overflow-container {{modifier}}"
             style="{{style}}"
        >
            {{> @children}}
        </div>

{{#if shownavigation}}
        <button class="OverflowContainer-button OverflowContainer-button--next js-overflow-container-advance">
            <span class="screenreader">
                Click to advance
            </span>

            <span class="icon _arrow _before"></span>
        </button>
    </div>
{{/if}}
{
  "id": null,
  "modifier": null,
  "style": null,
  "children": [
    {
      "component": "link",
      "context": {
        "href": "http://lorempixel.com/600/400/abstract?14799",
        "modifier": "u-display-block u-space-margin-around-400",
        "children": [
          {
            "component": "media",
            "context": {
              "modifier": "_square",
              "children": [
                {
                  "component": "image",
                  "context": {
                    "src": "http://fillmurray.com/g/400/400"
                  }
                }
              ]
            }
          }
        ]
      }
    },
    {
      "component": "link",
      "context": {
        "href": "http://lorempixel.com/600/400/fashion?91309",
        "modifier": "u-display-block u-space-margin-around-400",
        "children": [
          {
            "component": "media",
            "context": {
              "modifier": "_square",
              "children": [
                {
                  "component": "image",
                  "context": {
                    "src": "http://fillmurray.com/g/400/400"
                  }
                }
              ]
            }
          }
        ]
      }
    },
    {
      "component": "link",
      "context": {
        "href": "http://lorempixel.com/600/400/nature?99975",
        "modifier": "u-display-block u-space-margin-around-400",
        "children": [
          {
            "component": "media",
            "context": {
              "modifier": "_square",
              "children": [
                {
                  "component": "image",
                  "context": {
                    "src": "http://fillmurray.com/g/400/400"
                  }
                }
              ]
            }
          }
        ]
      }
    },
    {
      "component": "link",
      "context": {
        "href": "http://lorempixel.com/600/400/sports?7404",
        "modifier": "u-display-block u-space-margin-around-400",
        "children": [
          {
            "component": "media",
            "context": {
              "modifier": "_square",
              "children": [
                {
                  "component": "image",
                  "context": {
                    "src": "http://fillmurray.com/g/400/400"
                  }
                }
              ]
            }
          }
        ]
      }
    },
    {
      "component": "link",
      "context": {
        "href": "http://lorempixel.com/600/400/business?63565",
        "modifier": "u-display-block u-space-margin-around-400",
        "children": [
          {
            "component": "media",
            "context": {
              "modifier": "_square",
              "children": [
                {
                  "component": "image",
                  "context": {
                    "src": "http://fillmurray.com/g/400/400"
                  }
                }
              ]
            }
          }
        ]
      }
    },
    {
      "component": "link",
      "context": {
        "href": "http://lorempixel.com/600/400/food?98293",
        "modifier": "u-display-block u-space-margin-around-400",
        "children": [
          {
            "component": "media",
            "context": {
              "modifier": "_square",
              "children": [
                {
                  "component": "image",
                  "context": {
                    "src": "http://fillmurray.com/g/400/400"
                  }
                }
              ]
            }
          }
        ]
      }
    }
  ],
  "shownavigation": true
}
  • Content:
    class OverflowContainer {
        static defaultProps = {
            container: document.querySelector('.js-overflow-container') // Required
        };
    
        constructor(props = {}) {
            this.props = Object.assign({}, this.constructor.defaultProps, props);
    
            const advancedButton = this.props.container.parentNode.querySelector('.js-overflow-container-advance');
    
            if (advancedButton) {
                advancedButton.addEventListener('click', this.moveCarousel);
            }
    
            const previousButton = this.props.container.parentNode.querySelector('.js-overflow-container-previous');
    
            if (previousButton) {
                previousButton.addEventListener('click', this.moveCarousel);
            }
    
            // Gets the width of the first child to determine how much it should scroll
    
            this.scrollWidth = this.props.container.querySelector('*:first-child').clientWidth;
        }
    
        moveCarousel = event => {
            this.props.container.scrollLeft += event.currentTarget.classList.contains('js-overflow-container-previous')
                ? -this.scrollWidth
                : this.scrollWidth;
        };
    }
    
    export default OverflowContainer;
    
  • URL: /components/raw/overflowcontainer/OverflowContainer.js
  • Filesystem Path: components/molecules/OverflowContainer/OverflowContainer.js
  • Size: 1.1 KB
  • Content:
    .OverflowContainer {
        display: flex;
        width: 100%;
        -webkit-overflow-scrolling: touch;
        -ms-overflow-style: -ms-autohiding-scrollbar;
        overflow-y: auto;
        justify-content: flex-start;
        white-space: nowrap;
        scroll-behavior: smooth;
        * {
            white-space: normal;
        }
        > * {
            flex: 1 0 100%;
            @media #{$mobile-media} {
                flex-basis: 75%;
            }
            @media #{$desktop-media} {
                flex-basis: 30%;
            }
        }
        &-button {
            @include Elevation($level: "Button", $hasShadow: false, $withZindex: true);
            @include clear-default-button-styling;
            position: absolute;
            top: 0;
            bottom: 0;
            display: none;
            width: 5%;
            &:focus {
                .icon {
                    display: inline-flex;
                    width: Space(500);
                    height: Space(500);
                    justify-content: center;
                    align-items: center;
                    background: get-color(neutral, 0);
                    opacity: .5;
                    border-radius: 50%;
                    &::before {
                        display: block;
                    }
                }
            }
            &--next {
                right: 0;
                cursor: e-resize;
            }
            &--previous {
                left: 0;
                cursor: w-resize;
            }
            .icon {
                display: none;
            }
            @media #{$desktop-media} {
                display: block;
            }
        }
        &::-webkit-scrollbar {
            display: none;
        }
    }
    
  • URL: /components/raw/overflowcontainer/OverflowContainer.scss
  • Filesystem Path: components/molecules/OverflowContainer/OverflowContainer.scss
  • Size: 1.5 KB

OverflowContainer

The OverflowContainer is a component that allows a bunch of atoms inside of it and creates a horizontal scrolling behavior for those components. By default it should behave with the ability to scroll horizontally on mobile, then progressively enhance click control of the container.

Best Practices

  • It should be agnostic to what is inside of it and allow for any sort of content type, be it images or cards or whatever you want (maybe George will put a slider in there 😱). That said the actual click mechanism will assume everything is equal width (as the flex container is creating equal width children).
  • It should just work on mobile.

Accessibility

  • If a user chooses to allow for click scrolling it should still function without Javascript (function meaning the ability to use arrow keys and controlling the scrollbar)