Copy environment

Button

<button type="button" class="button">
    <span class="button__inner">
        <span class="button__text">Button text</span>
    </span>
</button>
{% set element = data.link ? 'a' : 'button' %}
{% set icon = icon|default(data.icon|default(false)) %}
{% set iconPosition = iconPosition|default(data.iconPosition|default(false)) %}

{% set BEM -%}
    button
    {%- if modifier %} {{ modifier }}{% endif %}
    {%- if class %} {{ class }}{% endif %}
    {%- if icon %} button--icon{% if iconPosition %}{{ '-' ~ iconPosition }}{% endif %}{% endif %}
{% endset %}

<{{ element }}
    {% if data.link %} href="{{ data.link }}"{% else %} type="{{ type|default('button') }}" {% endif %}
    class="{{ BEM }}"
    {%- if data.attributes %} {{ data.attributes }}{% endif %}
>
    {% if 'button--magnetic' in modifier or 'button--magnetic' in class %}
        <span class="button__filler"></span>
    {% endif %}
    <span class="button__inner">
        {% if data.icon %}<span class="button__icon-wrapper">{% include '@icon' with { name: data.icon, modifier: '', class: 'button__icon' } %}</span>{% endif %}
        <span class="button__text">{{ data.text }}</span>
    </span>
</{{ element }}>
{
  "language": "en-US",
  "data": {
    "text": "Button text"
  }
}
  • Content:
    $button-primary-background: $color-brand-01;
    $button-primary-hover: $color-text-03;
    $button-primary-active: $color-brand-01;
    
    .button {
        position: relative;
        border-radius: $border-radius-base;
        border: none;
        -webkit-appearance: none;
        text-align: center;
        cursor: pointer;
        min-width: 156px;
        display: inline-block;
        padding: 14px 32px;
        margin: 0;
        font-size: $font-size-small;
        font-weight: $font-weight-medium;
        line-height: 1.15;
        background-color: transparent;
        color: $button-primary-hover;
        text-decoration: none;
        text-transform: uppercase;
        transition-property: color;
        transition-duration: $transition-duration;
        transition-timing-function: $transition-easing-in;
        z-index: map-get($zindex, 'default');
        outline-offset: 2px;
        overflow: hidden;
    
        .text > * + & {
            margin-top: 1.5em;
        }
    
        &:before {
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            bottom: 0;
            right: 0;
            background-color: $button-primary-background;
            transition-property: background-color, transform;
            transition-duration: $transition-duration;
            transition-timing-function: $transition-easing-in;
            box-shadow: inset 0 0 0 2px $button-primary-background;
            transform: scale(1);
            border-radius: $border-radius-base;
            z-index: 4;
        }
    
        &.is-hover,
        &:hover {
            transition-timing-function: $transition-easing-out;
            color: $button-primary-background;
    
            &:before {
                transition-timing-function: $transition-easing-out;
                background-color: transparent;
            }
        }
    
        &:active {
            color: $button-primary-background;
    
            &:before {
                background-color: transparent;
                transform: scale(.96);
                transition: none;
            }
        }
    }
    
    .button--icon {
        min-width: 0;
        padding: 12px;
        border-radius: $border-radius-round;
    
        &:before {
            border-radius: $border-radius-round;
        }
    }
    
    .button--icon-left {
        padding-left: 56px;
    }
    
    .button--icon-right {
        padding-right: 56px;
    }
    
    .button--arrow-animate {
        padding-right: 48px;
    }
    
    .button--reverted {
        color: $button-primary-background;
    
        &:before {
            background-color: $button-primary-hover;
            box-shadow: inset 0 0 0 2px $button-primary-hover;
        }
    
        &.is-hover,
        &:hover {
            color: $button-primary-hover;
    
            &:before {
                background-color: $button-primary-background;
            }
        }
    
        &:active {
            color: $button-primary-hover;
        }
    }
    
    .button--magnetic {
        html[data-whatintent='mouse'] & {
            background-color: $button-primary-background;
        }
    
        &:before {
            html[data-whatintent='mouse'] & {
                background-color: transparent;
            }
        }
    
        &.is-hover,
        &:active,
        &:hover {
            &:before {
                html[data-whatintent='mouse'] & {
                    background-color: transparent;
                }
            }
        }
    
        &.button--reverted {
            html[data-whatintent='mouse'] & {
                background-color: $button-primary-hover;
            }
        }
    }
    
    .button--block {
        display: block;
        width: 100%;
    }
    
    .button--block-xs {
        @media only screen and (max-width: $bp-sm-min - 1) {
            display: block;
            width: 100%;
        }
    }
    
    .button__icon-wrapper {
        position: relative;
        z-index: 5;
    
        .button--icon & {
            display: block;
        }
    
        .button--icon-left &,
        .button--icon-right & {
            position: absolute;
            top: auto;
            bottom: auto;
            margin: auto;
            display: inline-block;
            flex: 0 0 24px;
        }
    
        .button--icon-left & {
            left: 32px;
        }
    
        .button--icon-right & {
            right: 32px;
        }
    
        .button--arrow-animate & {
            width: 16px;
            height: 24px;
            overflow: hidden;
            right: 32px;
            transition-property: width, right;
            transition-timing-function: $transition-easing-in;
            transition-duration: $transition-duration;
        }
    
        .button--arrow-animate.is-hover &,
        .button--arrow-animate:hover & {
            width: 24px;
            right: 24px;
            transition-timing-function: $transition-easing-out;
        }
    
        .button--arrow-rotate & {
            transition-property: transform;
            transition-duration: $transition-duration;
            transition-timing-function: $transition-easing-in;
            transform: rotate(0);
        }
    
        .button--arrow-rotate.is-hover &,
        .button--arrow-rotate:hover & {
            transition-timing-function: $transition-easing-out;
            transform: rotate(45deg);
        }
    }
    
    .button__icon {
        font-size: 24px;
        display: block;
    
        .button--arrow-animate & {
            float: right;
        }
    }
    
    .button__text {
        position: relative;
        z-index: 5;
    
        .button--icon & {
            @include visually-hidden();
        }
    
        .button--icon-left & {
            margin-left: 8px;
        }
    
        .button--icon-right & {
            margin-right: 8px;
        }
    }
    
    .button__inner {
        display: flex;
        align-items: center;
        justify-content: center;
    }
    
    .button--text {
        color: $button-primary-hover;
        position: relative;
        transition: $transition-duration $transition-easing;
        min-width: auto;
        padding: 0;
        text-transform: none;
    
        &:hover {
            color: $button-primary-hover;
        }
    
        &:before {
            content: '';
            position: absolute;
            top: auto;
            left: auto;
            right: 0;
            bottom: -1px;
            width: 100%;
            border-bottom: 2px solid $button-primary-hover;
            transition: width $transition-duration $transition-easing-out $transition-duration, border-bottom $transition-duration $transition-easing-out;
        }
    
        &:hover:before {
            width: 0;
            transition: width $transition-duration $transition-easing-in, border-bottom $transition-duration $transition-easing-in;
        }
    
        &:after {
            content: '';
            position: absolute;
            left: 0;
            bottom: 0;
            width: 0;
            border-bottom: 2px solid $button-primary-hover;
            transition: width $transition-duration $transition-easing-in, border-bottom $transition-duration $transition-easing-in;
        }
    
        &:hover:after {
            width: 100%;
            transition: width $transition-duration $transition-easing-out $transition-duration, border-bottom $transition-duration $transition-easing-out;
        }
    }
    
    .button__filler {
        display: none;
        position: absolute;
        z-index: 2;
        width: 150%;
        height: 200%;
        border-radius: $border-radius-round;
        background-color: $color-ui-01;
        color: $color-text-01;
        top: -50%;
        left: -25%;
        transform: translate3d(0, 75%, 0);
        transition-property: transform;
        transition-duration: $transition-duration;
        transition-timing-function: $transition-easing-in;
        will-change: transform; /* stylelint-disable-line plugin/no-unsupported-browser-features */
    
        .button--magnetic & {
            html[data-whatintent='mouse'] & {
                display: block;
            }
        }
    
        .button--reverted & {
            background-color: $button-primary-background;
            color: $color-text-03;
        }
    }
    
  • URL: /components/raw/button/button.scss
  • Filesystem Path: src/patterns/components/button/button.scss
  • Size: 7.2 KB
  • Content:
    import Component from '../component/component';
    import Helpers from '../helpers/helpers';
    import Icon from '../icon/icon';
    
    import './button.scss';
    
    export interface IButton {
        text: string;
        icon?: string;
        link?: string;
        iconPosition?: string;
    }
    
    export interface ITransform {
        amt: number;
        current: number;
        previous: number;
    }
    
    export interface IStyles {
        tx: ITransform;
        ty: ITransform;
    }
    
    export default class Button extends Component {
        static initSelector: string = '.button--magnetic';
    
        public filler: JQuery;
        public renderedStyles: IStyles;
        public buttonRect: DOMRect;
        public distanceToTrigger: number;
    
        constructor(element: HTMLElement) {
            super(element);
    
            this.filler = this.element.find('.button__filler');
    
            this.buttonRect = this.element[0].getBoundingClientRect();
            this.distanceToTrigger = this.buttonRect.width * 0.7;
    
            this.renderedStyles = {
                tx: {amt: 0.1, current: 0, previous: 0},
                ty: {amt: 0.1, current: 0, previous: 0},
            };
    
            this.init();
        }
    
        static render(data: IButton, className?: string): JQuery {
            const element: string = data.link ? 'a' : 'button';
            const icon: string = data.icon ? Icon.render(data.icon, 'button__icon') : '';
            const classArray: string[] = ['button'];
    
            if (className) {
                classArray.push(className);
            }
    
            if (data.icon && !data.iconPosition) {
                classArray.push('button--icon');
            }
    
            if (data.icon && data.iconPosition === 'right') {
                classArray.push('button--icon-right');
            }
    
            if (data.icon && data.iconPosition === 'left') {
                classArray.push('button--icon-left');
            }
    
            return $(`<${element} class="${classArray.join(' ')}" ${data.link ? `href="${data.link}"` : 'type="button"'}><span class="button__filler"></span><span class="button__inner"><span class="button__icon-wrapper">${icon}</span><span class="button__text">${data.text}</span></span></${element}>`);
        }
    
        init(): void {
            if (!Helpers.isMobileDevice) {
                this.element.on('mouseenter', this.enter.bind(this));
                this.element.on('mouseleave', this.leave.bind(this));
    
                $(window).on('resize scroll', this.resizeHandler.bind(this));
    
                this.run();
            }
    
        }
    
        resizeHandler(): void {
            this.buttonRect = this.element[0].getBoundingClientRect();
            this.distanceToTrigger = this.buttonRect.width * 0.7;
        }
    
        distance(x1: number, y1: number, x2: number, y2: number): number {
            const a: number = x1 - x2;
            const b: number = y1 - y2;
    
            return Math.hypot(a,b);
        }
    
        lerp(a: number, b: number, n: number): number {
            return (1 - n) * a + n * b;
        }
    
        run(): void {
            // Linear interpolation
            const distanceMouseButton: number = this.distance(window.gotoAndPlay.mousePos.x, window.gotoAndPlay.mousePos.y, this.buttonRect.left + this.buttonRect.width / 2, window.scrollY + this.buttonRect.top + this.buttonRect.height / 2);
    
            // new values for the translations
            let x: number = 0;
            let y: number = 0;
    
            if (distanceMouseButton < this.distanceToTrigger) {
                x = (window.gotoAndPlay.mousePos.x - (this.buttonRect.left + this.buttonRect.width / 2)) * .3;
                y = (window.gotoAndPlay.mousePos.y - (window.scrollY + this.buttonRect.top + this.buttonRect.height / 2)) * .3;
            }
    
            this.renderedStyles.tx.current = parseFloat(x.toFixed(3));
            this.renderedStyles.ty.current = parseFloat(y.toFixed(3));
    
            for (const key in this.renderedStyles) {
                if (key) {
                    this.renderedStyles[key].previous = parseFloat(this.lerp(this.renderedStyles[key].previous, this.renderedStyles[key].current, this.renderedStyles[key].amt).toFixed(3));
                }
            }
    
            this.element[0].style.transform = `translate3d(${this.renderedStyles.tx.previous}px, ${this.renderedStyles.ty.previous}px, 0)`;
    
            requestAnimationFrame(() => this.run());
        }
    
        enter(): void {
            this.element.addClass('is-hover');
            this.filler[0].style.transitionDuration = `250ms`;
            this.filler[0].style.transform = `translate3d(0, 0, 0)`;
        }
    
        leave(): void {
            this.element.removeClass('is-hover');
            this.filler[0].style.transform = `translate3d(0, -75%, 0)`;
    
            setTimeout(() => {
                if (!this.element.hasClass('is-hover')) {
                    this.filler[0].style.transitionDuration = `0ms`;
                    this.filler[0].style.transform = `translate3d(0, 75%, 0)`;
                }
            }, 250);
        }
    }
    
  • URL: /components/raw/button/button.ts
  • Filesystem Path: src/patterns/components/button/button.ts
  • Size: 4.7 KB

Anchor

<a href="https://play.ee/" class="button">
    <span class="button__inner">
        <span class="button__text">Button text</span>
    </span>
</a>
{% set element = data.link ? 'a' : 'button' %}
{% set icon = icon|default(data.icon|default(false)) %}
{% set iconPosition = iconPosition|default(data.iconPosition|default(false)) %}

{% set BEM -%}
    button
    {%- if modifier %} {{ modifier }}{% endif %}
    {%- if class %} {{ class }}{% endif %}
    {%- if icon %} button--icon{% if iconPosition %}{{ '-' ~ iconPosition }}{% endif %}{% endif %}
{% endset %}

<{{ element }}
    {% if data.link %} href="{{ data.link }}"{% else %} type="{{ type|default('button') }}" {% endif %}
    class="{{ BEM }}"
    {%- if data.attributes %} {{ data.attributes }}{% endif %}
>
    {% if 'button--magnetic' in modifier or 'button--magnetic' in class %}
        <span class="button__filler"></span>
    {% endif %}
    <span class="button__inner">
        {% if data.icon %}<span class="button__icon-wrapper">{% include '@icon' with { name: data.icon, modifier: '', class: 'button__icon' } %}</span>{% endif %}
        <span class="button__text">{{ data.text }}</span>
    </span>
</{{ element }}>
{
  "language": "en-US",
  "data": {
    "text": "Button text",
    "link": "https://play.ee/"
  }
}
  • Content:
    $button-primary-background: $color-brand-01;
    $button-primary-hover: $color-text-03;
    $button-primary-active: $color-brand-01;
    
    .button {
        position: relative;
        border-radius: $border-radius-base;
        border: none;
        -webkit-appearance: none;
        text-align: center;
        cursor: pointer;
        min-width: 156px;
        display: inline-block;
        padding: 14px 32px;
        margin: 0;
        font-size: $font-size-small;
        font-weight: $font-weight-medium;
        line-height: 1.15;
        background-color: transparent;
        color: $button-primary-hover;
        text-decoration: none;
        text-transform: uppercase;
        transition-property: color;
        transition-duration: $transition-duration;
        transition-timing-function: $transition-easing-in;
        z-index: map-get($zindex, 'default');
        outline-offset: 2px;
        overflow: hidden;
    
        .text > * + & {
            margin-top: 1.5em;
        }
    
        &:before {
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            bottom: 0;
            right: 0;
            background-color: $button-primary-background;
            transition-property: background-color, transform;
            transition-duration: $transition-duration;
            transition-timing-function: $transition-easing-in;
            box-shadow: inset 0 0 0 2px $button-primary-background;
            transform: scale(1);
            border-radius: $border-radius-base;
            z-index: 4;
        }
    
        &.is-hover,
        &:hover {
            transition-timing-function: $transition-easing-out;
            color: $button-primary-background;
    
            &:before {
                transition-timing-function: $transition-easing-out;
                background-color: transparent;
            }
        }
    
        &:active {
            color: $button-primary-background;
    
            &:before {
                background-color: transparent;
                transform: scale(.96);
                transition: none;
            }
        }
    }
    
    .button--icon {
        min-width: 0;
        padding: 12px;
        border-radius: $border-radius-round;
    
        &:before {
            border-radius: $border-radius-round;
        }
    }
    
    .button--icon-left {
        padding-left: 56px;
    }
    
    .button--icon-right {
        padding-right: 56px;
    }
    
    .button--arrow-animate {
        padding-right: 48px;
    }
    
    .button--reverted {
        color: $button-primary-background;
    
        &:before {
            background-color: $button-primary-hover;
            box-shadow: inset 0 0 0 2px $button-primary-hover;
        }
    
        &.is-hover,
        &:hover {
            color: $button-primary-hover;
    
            &:before {
                background-color: $button-primary-background;
            }
        }
    
        &:active {
            color: $button-primary-hover;
        }
    }
    
    .button--magnetic {
        html[data-whatintent='mouse'] & {
            background-color: $button-primary-background;
        }
    
        &:before {
            html[data-whatintent='mouse'] & {
                background-color: transparent;
            }
        }
    
        &.is-hover,
        &:active,
        &:hover {
            &:before {
                html[data-whatintent='mouse'] & {
                    background-color: transparent;
                }
            }
        }
    
        &.button--reverted {
            html[data-whatintent='mouse'] & {
                background-color: $button-primary-hover;
            }
        }
    }
    
    .button--block {
        display: block;
        width: 100%;
    }
    
    .button--block-xs {
        @media only screen and (max-width: $bp-sm-min - 1) {
            display: block;
            width: 100%;
        }
    }
    
    .button__icon-wrapper {
        position: relative;
        z-index: 5;
    
        .button--icon & {
            display: block;
        }
    
        .button--icon-left &,
        .button--icon-right & {
            position: absolute;
            top: auto;
            bottom: auto;
            margin: auto;
            display: inline-block;
            flex: 0 0 24px;
        }
    
        .button--icon-left & {
            left: 32px;
        }
    
        .button--icon-right & {
            right: 32px;
        }
    
        .button--arrow-animate & {
            width: 16px;
            height: 24px;
            overflow: hidden;
            right: 32px;
            transition-property: width, right;
            transition-timing-function: $transition-easing-in;
            transition-duration: $transition-duration;
        }
    
        .button--arrow-animate.is-hover &,
        .button--arrow-animate:hover & {
            width: 24px;
            right: 24px;
            transition-timing-function: $transition-easing-out;
        }
    
        .button--arrow-rotate & {
            transition-property: transform;
            transition-duration: $transition-duration;
            transition-timing-function: $transition-easing-in;
            transform: rotate(0);
        }
    
        .button--arrow-rotate.is-hover &,
        .button--arrow-rotate:hover & {
            transition-timing-function: $transition-easing-out;
            transform: rotate(45deg);
        }
    }
    
    .button__icon {
        font-size: 24px;
        display: block;
    
        .button--arrow-animate & {
            float: right;
        }
    }
    
    .button__text {
        position: relative;
        z-index: 5;
    
        .button--icon & {
            @include visually-hidden();
        }
    
        .button--icon-left & {
            margin-left: 8px;
        }
    
        .button--icon-right & {
            margin-right: 8px;
        }
    }
    
    .button__inner {
        display: flex;
        align-items: center;
        justify-content: center;
    }
    
    .button--text {
        color: $button-primary-hover;
        position: relative;
        transition: $transition-duration $transition-easing;
        min-width: auto;
        padding: 0;
        text-transform: none;
    
        &:hover {
            color: $button-primary-hover;
        }
    
        &:before {
            content: '';
            position: absolute;
            top: auto;
            left: auto;
            right: 0;
            bottom: -1px;
            width: 100%;
            border-bottom: 2px solid $button-primary-hover;
            transition: width $transition-duration $transition-easing-out $transition-duration, border-bottom $transition-duration $transition-easing-out;
        }
    
        &:hover:before {
            width: 0;
            transition: width $transition-duration $transition-easing-in, border-bottom $transition-duration $transition-easing-in;
        }
    
        &:after {
            content: '';
            position: absolute;
            left: 0;
            bottom: 0;
            width: 0;
            border-bottom: 2px solid $button-primary-hover;
            transition: width $transition-duration $transition-easing-in, border-bottom $transition-duration $transition-easing-in;
        }
    
        &:hover:after {
            width: 100%;
            transition: width $transition-duration $transition-easing-out $transition-duration, border-bottom $transition-duration $transition-easing-out;
        }
    }
    
    .button__filler {
        display: none;
        position: absolute;
        z-index: 2;
        width: 150%;
        height: 200%;
        border-radius: $border-radius-round;
        background-color: $color-ui-01;
        color: $color-text-01;
        top: -50%;
        left: -25%;
        transform: translate3d(0, 75%, 0);
        transition-property: transform;
        transition-duration: $transition-duration;
        transition-timing-function: $transition-easing-in;
        will-change: transform; /* stylelint-disable-line plugin/no-unsupported-browser-features */
    
        .button--magnetic & {
            html[data-whatintent='mouse'] & {
                display: block;
            }
        }
    
        .button--reverted & {
            background-color: $button-primary-background;
            color: $color-text-03;
        }
    }
    
  • URL: /components/raw/button/button.scss
  • Filesystem Path: src/patterns/components/button/button.scss
  • Size: 7.2 KB
  • Content:
    import Component from '../component/component';
    import Helpers from '../helpers/helpers';
    import Icon from '../icon/icon';
    
    import './button.scss';
    
    export interface IButton {
        text: string;
        icon?: string;
        link?: string;
        iconPosition?: string;
    }
    
    export interface ITransform {
        amt: number;
        current: number;
        previous: number;
    }
    
    export interface IStyles {
        tx: ITransform;
        ty: ITransform;
    }
    
    export default class Button extends Component {
        static initSelector: string = '.button--magnetic';
    
        public filler: JQuery;
        public renderedStyles: IStyles;
        public buttonRect: DOMRect;
        public distanceToTrigger: number;
    
        constructor(element: HTMLElement) {
            super(element);
    
            this.filler = this.element.find('.button__filler');
    
            this.buttonRect = this.element[0].getBoundingClientRect();
            this.distanceToTrigger = this.buttonRect.width * 0.7;
    
            this.renderedStyles = {
                tx: {amt: 0.1, current: 0, previous: 0},
                ty: {amt: 0.1, current: 0, previous: 0},
            };
    
            this.init();
        }
    
        static render(data: IButton, className?: string): JQuery {
            const element: string = data.link ? 'a' : 'button';
            const icon: string = data.icon ? Icon.render(data.icon, 'button__icon') : '';
            const classArray: string[] = ['button'];
    
            if (className) {
                classArray.push(className);
            }
    
            if (data.icon && !data.iconPosition) {
                classArray.push('button--icon');
            }
    
            if (data.icon && data.iconPosition === 'right') {
                classArray.push('button--icon-right');
            }
    
            if (data.icon && data.iconPosition === 'left') {
                classArray.push('button--icon-left');
            }
    
            return $(`<${element} class="${classArray.join(' ')}" ${data.link ? `href="${data.link}"` : 'type="button"'}><span class="button__filler"></span><span class="button__inner"><span class="button__icon-wrapper">${icon}</span><span class="button__text">${data.text}</span></span></${element}>`);
        }
    
        init(): void {
            if (!Helpers.isMobileDevice) {
                this.element.on('mouseenter', this.enter.bind(this));
                this.element.on('mouseleave', this.leave.bind(this));
    
                $(window).on('resize scroll', this.resizeHandler.bind(this));
    
                this.run();
            }
    
        }
    
        resizeHandler(): void {
            this.buttonRect = this.element[0].getBoundingClientRect();
            this.distanceToTrigger = this.buttonRect.width * 0.7;
        }
    
        distance(x1: number, y1: number, x2: number, y2: number): number {
            const a: number = x1 - x2;
            const b: number = y1 - y2;
    
            return Math.hypot(a,b);
        }
    
        lerp(a: number, b: number, n: number): number {
            return (1 - n) * a + n * b;
        }
    
        run(): void {
            // Linear interpolation
            const distanceMouseButton: number = this.distance(window.gotoAndPlay.mousePos.x, window.gotoAndPlay.mousePos.y, this.buttonRect.left + this.buttonRect.width / 2, window.scrollY + this.buttonRect.top + this.buttonRect.height / 2);
    
            // new values for the translations
            let x: number = 0;
            let y: number = 0;
    
            if (distanceMouseButton < this.distanceToTrigger) {
                x = (window.gotoAndPlay.mousePos.x - (this.buttonRect.left + this.buttonRect.width / 2)) * .3;
                y = (window.gotoAndPlay.mousePos.y - (window.scrollY + this.buttonRect.top + this.buttonRect.height / 2)) * .3;
            }
    
            this.renderedStyles.tx.current = parseFloat(x.toFixed(3));
            this.renderedStyles.ty.current = parseFloat(y.toFixed(3));
    
            for (const key in this.renderedStyles) {
                if (key) {
                    this.renderedStyles[key].previous = parseFloat(this.lerp(this.renderedStyles[key].previous, this.renderedStyles[key].current, this.renderedStyles[key].amt).toFixed(3));
                }
            }
    
            this.element[0].style.transform = `translate3d(${this.renderedStyles.tx.previous}px, ${this.renderedStyles.ty.previous}px, 0)`;
    
            requestAnimationFrame(() => this.run());
        }
    
        enter(): void {
            this.element.addClass('is-hover');
            this.filler[0].style.transitionDuration = `250ms`;
            this.filler[0].style.transform = `translate3d(0, 0, 0)`;
        }
    
        leave(): void {
            this.element.removeClass('is-hover');
            this.filler[0].style.transform = `translate3d(0, -75%, 0)`;
    
            setTimeout(() => {
                if (!this.element.hasClass('is-hover')) {
                    this.filler[0].style.transitionDuration = `0ms`;
                    this.filler[0].style.transform = `translate3d(0, 75%, 0)`;
                }
            }, 250);
        }
    }
    
  • URL: /components/raw/button/button.ts
  • Filesystem Path: src/patterns/components/button/button.ts
  • Size: 4.7 KB
  • Handle: @button--anchor
  • Filesystem Path: src/patterns/components/button/button.twig
  • References (1): @icon

Icon

<button type="button" class="button button--icon">
    <span class="button__inner">
        <span class="button__icon-wrapper"><svg class="icon  button__icon">
                <use xlink:href="../../inc/svg/global.bc9cdd731ad718497c5d8f03d08908d4.svg#search-24"></use>
            </svg>
        </span> <span class="button__text">Search</span>
    </span>
</button>
{% set element = data.link ? 'a' : 'button' %}
{% set icon = icon|default(data.icon|default(false)) %}
{% set iconPosition = iconPosition|default(data.iconPosition|default(false)) %}

{% set BEM -%}
    button
    {%- if modifier %} {{ modifier }}{% endif %}
    {%- if class %} {{ class }}{% endif %}
    {%- if icon %} button--icon{% if iconPosition %}{{ '-' ~ iconPosition }}{% endif %}{% endif %}
{% endset %}

<{{ element }}
    {% if data.link %} href="{{ data.link }}"{% else %} type="{{ type|default('button') }}" {% endif %}
    class="{{ BEM }}"
    {%- if data.attributes %} {{ data.attributes }}{% endif %}
>
    {% if 'button--magnetic' in modifier or 'button--magnetic' in class %}
        <span class="button__filler"></span>
    {% endif %}
    <span class="button__inner">
        {% if data.icon %}<span class="button__icon-wrapper">{% include '@icon' with { name: data.icon, modifier: '', class: 'button__icon' } %}</span>{% endif %}
        <span class="button__text">{{ data.text }}</span>
    </span>
</{{ element }}>
{
  "language": "en-US",
  "data": {
    "text": "Search",
    "icon": "search-24"
  }
}
  • Content:
    $button-primary-background: $color-brand-01;
    $button-primary-hover: $color-text-03;
    $button-primary-active: $color-brand-01;
    
    .button {
        position: relative;
        border-radius: $border-radius-base;
        border: none;
        -webkit-appearance: none;
        text-align: center;
        cursor: pointer;
        min-width: 156px;
        display: inline-block;
        padding: 14px 32px;
        margin: 0;
        font-size: $font-size-small;
        font-weight: $font-weight-medium;
        line-height: 1.15;
        background-color: transparent;
        color: $button-primary-hover;
        text-decoration: none;
        text-transform: uppercase;
        transition-property: color;
        transition-duration: $transition-duration;
        transition-timing-function: $transition-easing-in;
        z-index: map-get($zindex, 'default');
        outline-offset: 2px;
        overflow: hidden;
    
        .text > * + & {
            margin-top: 1.5em;
        }
    
        &:before {
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            bottom: 0;
            right: 0;
            background-color: $button-primary-background;
            transition-property: background-color, transform;
            transition-duration: $transition-duration;
            transition-timing-function: $transition-easing-in;
            box-shadow: inset 0 0 0 2px $button-primary-background;
            transform: scale(1);
            border-radius: $border-radius-base;
            z-index: 4;
        }
    
        &.is-hover,
        &:hover {
            transition-timing-function: $transition-easing-out;
            color: $button-primary-background;
    
            &:before {
                transition-timing-function: $transition-easing-out;
                background-color: transparent;
            }
        }
    
        &:active {
            color: $button-primary-background;
    
            &:before {
                background-color: transparent;
                transform: scale(.96);
                transition: none;
            }
        }
    }
    
    .button--icon {
        min-width: 0;
        padding: 12px;
        border-radius: $border-radius-round;
    
        &:before {
            border-radius: $border-radius-round;
        }
    }
    
    .button--icon-left {
        padding-left: 56px;
    }
    
    .button--icon-right {
        padding-right: 56px;
    }
    
    .button--arrow-animate {
        padding-right: 48px;
    }
    
    .button--reverted {
        color: $button-primary-background;
    
        &:before {
            background-color: $button-primary-hover;
            box-shadow: inset 0 0 0 2px $button-primary-hover;
        }
    
        &.is-hover,
        &:hover {
            color: $button-primary-hover;
    
            &:before {
                background-color: $button-primary-background;
            }
        }
    
        &:active {
            color: $button-primary-hover;
        }
    }
    
    .button--magnetic {
        html[data-whatintent='mouse'] & {
            background-color: $button-primary-background;
        }
    
        &:before {
            html[data-whatintent='mouse'] & {
                background-color: transparent;
            }
        }
    
        &.is-hover,
        &:active,
        &:hover {
            &:before {
                html[data-whatintent='mouse'] & {
                    background-color: transparent;
                }
            }
        }
    
        &.button--reverted {
            html[data-whatintent='mouse'] & {
                background-color: $button-primary-hover;
            }
        }
    }
    
    .button--block {
        display: block;
        width: 100%;
    }
    
    .button--block-xs {
        @media only screen and (max-width: $bp-sm-min - 1) {
            display: block;
            width: 100%;
        }
    }
    
    .button__icon-wrapper {
        position: relative;
        z-index: 5;
    
        .button--icon & {
            display: block;
        }
    
        .button--icon-left &,
        .button--icon-right & {
            position: absolute;
            top: auto;
            bottom: auto;
            margin: auto;
            display: inline-block;
            flex: 0 0 24px;
        }
    
        .button--icon-left & {
            left: 32px;
        }
    
        .button--icon-right & {
            right: 32px;
        }
    
        .button--arrow-animate & {
            width: 16px;
            height: 24px;
            overflow: hidden;
            right: 32px;
            transition-property: width, right;
            transition-timing-function: $transition-easing-in;
            transition-duration: $transition-duration;
        }
    
        .button--arrow-animate.is-hover &,
        .button--arrow-animate:hover & {
            width: 24px;
            right: 24px;
            transition-timing-function: $transition-easing-out;
        }
    
        .button--arrow-rotate & {
            transition-property: transform;
            transition-duration: $transition-duration;
            transition-timing-function: $transition-easing-in;
            transform: rotate(0);
        }
    
        .button--arrow-rotate.is-hover &,
        .button--arrow-rotate:hover & {
            transition-timing-function: $transition-easing-out;
            transform: rotate(45deg);
        }
    }
    
    .button__icon {
        font-size: 24px;
        display: block;
    
        .button--arrow-animate & {
            float: right;
        }
    }
    
    .button__text {
        position: relative;
        z-index: 5;
    
        .button--icon & {
            @include visually-hidden();
        }
    
        .button--icon-left & {
            margin-left: 8px;
        }
    
        .button--icon-right & {
            margin-right: 8px;
        }
    }
    
    .button__inner {
        display: flex;
        align-items: center;
        justify-content: center;
    }
    
    .button--text {
        color: $button-primary-hover;
        position: relative;
        transition: $transition-duration $transition-easing;
        min-width: auto;
        padding: 0;
        text-transform: none;
    
        &:hover {
            color: $button-primary-hover;
        }
    
        &:before {
            content: '';
            position: absolute;
            top: auto;
            left: auto;
            right: 0;
            bottom: -1px;
            width: 100%;
            border-bottom: 2px solid $button-primary-hover;
            transition: width $transition-duration $transition-easing-out $transition-duration, border-bottom $transition-duration $transition-easing-out;
        }
    
        &:hover:before {
            width: 0;
            transition: width $transition-duration $transition-easing-in, border-bottom $transition-duration $transition-easing-in;
        }
    
        &:after {
            content: '';
            position: absolute;
            left: 0;
            bottom: 0;
            width: 0;
            border-bottom: 2px solid $button-primary-hover;
            transition: width $transition-duration $transition-easing-in, border-bottom $transition-duration $transition-easing-in;
        }
    
        &:hover:after {
            width: 100%;
            transition: width $transition-duration $transition-easing-out $transition-duration, border-bottom $transition-duration $transition-easing-out;
        }
    }
    
    .button__filler {
        display: none;
        position: absolute;
        z-index: 2;
        width: 150%;
        height: 200%;
        border-radius: $border-radius-round;
        background-color: $color-ui-01;
        color: $color-text-01;
        top: -50%;
        left: -25%;
        transform: translate3d(0, 75%, 0);
        transition-property: transform;
        transition-duration: $transition-duration;
        transition-timing-function: $transition-easing-in;
        will-change: transform; /* stylelint-disable-line plugin/no-unsupported-browser-features */
    
        .button--magnetic & {
            html[data-whatintent='mouse'] & {
                display: block;
            }
        }
    
        .button--reverted & {
            background-color: $button-primary-background;
            color: $color-text-03;
        }
    }
    
  • URL: /components/raw/button/button.scss
  • Filesystem Path: src/patterns/components/button/button.scss
  • Size: 7.2 KB
  • Content:
    import Component from '../component/component';
    import Helpers from '../helpers/helpers';
    import Icon from '../icon/icon';
    
    import './button.scss';
    
    export interface IButton {
        text: string;
        icon?: string;
        link?: string;
        iconPosition?: string;
    }
    
    export interface ITransform {
        amt: number;
        current: number;
        previous: number;
    }
    
    export interface IStyles {
        tx: ITransform;
        ty: ITransform;
    }
    
    export default class Button extends Component {
        static initSelector: string = '.button--magnetic';
    
        public filler: JQuery;
        public renderedStyles: IStyles;
        public buttonRect: DOMRect;
        public distanceToTrigger: number;
    
        constructor(element: HTMLElement) {
            super(element);
    
            this.filler = this.element.find('.button__filler');
    
            this.buttonRect = this.element[0].getBoundingClientRect();
            this.distanceToTrigger = this.buttonRect.width * 0.7;
    
            this.renderedStyles = {
                tx: {amt: 0.1, current: 0, previous: 0},
                ty: {amt: 0.1, current: 0, previous: 0},
            };
    
            this.init();
        }
    
        static render(data: IButton, className?: string): JQuery {
            const element: string = data.link ? 'a' : 'button';
            const icon: string = data.icon ? Icon.render(data.icon, 'button__icon') : '';
            const classArray: string[] = ['button'];
    
            if (className) {
                classArray.push(className);
            }
    
            if (data.icon && !data.iconPosition) {
                classArray.push('button--icon');
            }
    
            if (data.icon && data.iconPosition === 'right') {
                classArray.push('button--icon-right');
            }
    
            if (data.icon && data.iconPosition === 'left') {
                classArray.push('button--icon-left');
            }
    
            return $(`<${element} class="${classArray.join(' ')}" ${data.link ? `href="${data.link}"` : 'type="button"'}><span class="button__filler"></span><span class="button__inner"><span class="button__icon-wrapper">${icon}</span><span class="button__text">${data.text}</span></span></${element}>`);
        }
    
        init(): void {
            if (!Helpers.isMobileDevice) {
                this.element.on('mouseenter', this.enter.bind(this));
                this.element.on('mouseleave', this.leave.bind(this));
    
                $(window).on('resize scroll', this.resizeHandler.bind(this));
    
                this.run();
            }
    
        }
    
        resizeHandler(): void {
            this.buttonRect = this.element[0].getBoundingClientRect();
            this.distanceToTrigger = this.buttonRect.width * 0.7;
        }
    
        distance(x1: number, y1: number, x2: number, y2: number): number {
            const a: number = x1 - x2;
            const b: number = y1 - y2;
    
            return Math.hypot(a,b);
        }
    
        lerp(a: number, b: number, n: number): number {
            return (1 - n) * a + n * b;
        }
    
        run(): void {
            // Linear interpolation
            const distanceMouseButton: number = this.distance(window.gotoAndPlay.mousePos.x, window.gotoAndPlay.mousePos.y, this.buttonRect.left + this.buttonRect.width / 2, window.scrollY + this.buttonRect.top + this.buttonRect.height / 2);
    
            // new values for the translations
            let x: number = 0;
            let y: number = 0;
    
            if (distanceMouseButton < this.distanceToTrigger) {
                x = (window.gotoAndPlay.mousePos.x - (this.buttonRect.left + this.buttonRect.width / 2)) * .3;
                y = (window.gotoAndPlay.mousePos.y - (window.scrollY + this.buttonRect.top + this.buttonRect.height / 2)) * .3;
            }
    
            this.renderedStyles.tx.current = parseFloat(x.toFixed(3));
            this.renderedStyles.ty.current = parseFloat(y.toFixed(3));
    
            for (const key in this.renderedStyles) {
                if (key) {
                    this.renderedStyles[key].previous = parseFloat(this.lerp(this.renderedStyles[key].previous, this.renderedStyles[key].current, this.renderedStyles[key].amt).toFixed(3));
                }
            }
    
            this.element[0].style.transform = `translate3d(${this.renderedStyles.tx.previous}px, ${this.renderedStyles.ty.previous}px, 0)`;
    
            requestAnimationFrame(() => this.run());
        }
    
        enter(): void {
            this.element.addClass('is-hover');
            this.filler[0].style.transitionDuration = `250ms`;
            this.filler[0].style.transform = `translate3d(0, 0, 0)`;
        }
    
        leave(): void {
            this.element.removeClass('is-hover');
            this.filler[0].style.transform = `translate3d(0, -75%, 0)`;
    
            setTimeout(() => {
                if (!this.element.hasClass('is-hover')) {
                    this.filler[0].style.transitionDuration = `0ms`;
                    this.filler[0].style.transform = `translate3d(0, 75%, 0)`;
                }
            }, 250);
        }
    }
    
  • URL: /components/raw/button/button.ts
  • Filesystem Path: src/patterns/components/button/button.ts
  • Size: 4.7 KB
  • Handle: @button--icon
  • Filesystem Path: src/patterns/components/button/button.twig
  • References (1): @icon

Icon Left

<button type="button" class="button button--icon-left">
    <span class="button__inner">
        <span class="button__icon-wrapper"><svg class="icon  button__icon">
                <use xlink:href="../../inc/svg/global.bc9cdd731ad718497c5d8f03d08908d4.svg#plus-24"></use>
            </svg>
        </span> <span class="button__text">Button text</span>
    </span>
</button>
{% set element = data.link ? 'a' : 'button' %}
{% set icon = icon|default(data.icon|default(false)) %}
{% set iconPosition = iconPosition|default(data.iconPosition|default(false)) %}

{% set BEM -%}
    button
    {%- if modifier %} {{ modifier }}{% endif %}
    {%- if class %} {{ class }}{% endif %}
    {%- if icon %} button--icon{% if iconPosition %}{{ '-' ~ iconPosition }}{% endif %}{% endif %}
{% endset %}

<{{ element }}
    {% if data.link %} href="{{ data.link }}"{% else %} type="{{ type|default('button') }}" {% endif %}
    class="{{ BEM }}"
    {%- if data.attributes %} {{ data.attributes }}{% endif %}
>
    {% if 'button--magnetic' in modifier or 'button--magnetic' in class %}
        <span class="button__filler"></span>
    {% endif %}
    <span class="button__inner">
        {% if data.icon %}<span class="button__icon-wrapper">{% include '@icon' with { name: data.icon, modifier: '', class: 'button__icon' } %}</span>{% endif %}
        <span class="button__text">{{ data.text }}</span>
    </span>
</{{ element }}>
{
  "language": "en-US",
  "data": {
    "text": "Button text",
    "icon": "plus-24",
    "iconPosition": "left"
  }
}
  • Content:
    $button-primary-background: $color-brand-01;
    $button-primary-hover: $color-text-03;
    $button-primary-active: $color-brand-01;
    
    .button {
        position: relative;
        border-radius: $border-radius-base;
        border: none;
        -webkit-appearance: none;
        text-align: center;
        cursor: pointer;
        min-width: 156px;
        display: inline-block;
        padding: 14px 32px;
        margin: 0;
        font-size: $font-size-small;
        font-weight: $font-weight-medium;
        line-height: 1.15;
        background-color: transparent;
        color: $button-primary-hover;
        text-decoration: none;
        text-transform: uppercase;
        transition-property: color;
        transition-duration: $transition-duration;
        transition-timing-function: $transition-easing-in;
        z-index: map-get($zindex, 'default');
        outline-offset: 2px;
        overflow: hidden;
    
        .text > * + & {
            margin-top: 1.5em;
        }
    
        &:before {
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            bottom: 0;
            right: 0;
            background-color: $button-primary-background;
            transition-property: background-color, transform;
            transition-duration: $transition-duration;
            transition-timing-function: $transition-easing-in;
            box-shadow: inset 0 0 0 2px $button-primary-background;
            transform: scale(1);
            border-radius: $border-radius-base;
            z-index: 4;
        }
    
        &.is-hover,
        &:hover {
            transition-timing-function: $transition-easing-out;
            color: $button-primary-background;
    
            &:before {
                transition-timing-function: $transition-easing-out;
                background-color: transparent;
            }
        }
    
        &:active {
            color: $button-primary-background;
    
            &:before {
                background-color: transparent;
                transform: scale(.96);
                transition: none;
            }
        }
    }
    
    .button--icon {
        min-width: 0;
        padding: 12px;
        border-radius: $border-radius-round;
    
        &:before {
            border-radius: $border-radius-round;
        }
    }
    
    .button--icon-left {
        padding-left: 56px;
    }
    
    .button--icon-right {
        padding-right: 56px;
    }
    
    .button--arrow-animate {
        padding-right: 48px;
    }
    
    .button--reverted {
        color: $button-primary-background;
    
        &:before {
            background-color: $button-primary-hover;
            box-shadow: inset 0 0 0 2px $button-primary-hover;
        }
    
        &.is-hover,
        &:hover {
            color: $button-primary-hover;
    
            &:before {
                background-color: $button-primary-background;
            }
        }
    
        &:active {
            color: $button-primary-hover;
        }
    }
    
    .button--magnetic {
        html[data-whatintent='mouse'] & {
            background-color: $button-primary-background;
        }
    
        &:before {
            html[data-whatintent='mouse'] & {
                background-color: transparent;
            }
        }
    
        &.is-hover,
        &:active,
        &:hover {
            &:before {
                html[data-whatintent='mouse'] & {
                    background-color: transparent;
                }
            }
        }
    
        &.button--reverted {
            html[data-whatintent='mouse'] & {
                background-color: $button-primary-hover;
            }
        }
    }
    
    .button--block {
        display: block;
        width: 100%;
    }
    
    .button--block-xs {
        @media only screen and (max-width: $bp-sm-min - 1) {
            display: block;
            width: 100%;
        }
    }
    
    .button__icon-wrapper {
        position: relative;
        z-index: 5;
    
        .button--icon & {
            display: block;
        }
    
        .button--icon-left &,
        .button--icon-right & {
            position: absolute;
            top: auto;
            bottom: auto;
            margin: auto;
            display: inline-block;
            flex: 0 0 24px;
        }
    
        .button--icon-left & {
            left: 32px;
        }
    
        .button--icon-right & {
            right: 32px;
        }
    
        .button--arrow-animate & {
            width: 16px;
            height: 24px;
            overflow: hidden;
            right: 32px;
            transition-property: width, right;
            transition-timing-function: $transition-easing-in;
            transition-duration: $transition-duration;
        }
    
        .button--arrow-animate.is-hover &,
        .button--arrow-animate:hover & {
            width: 24px;
            right: 24px;
            transition-timing-function: $transition-easing-out;
        }
    
        .button--arrow-rotate & {
            transition-property: transform;
            transition-duration: $transition-duration;
            transition-timing-function: $transition-easing-in;
            transform: rotate(0);
        }
    
        .button--arrow-rotate.is-hover &,
        .button--arrow-rotate:hover & {
            transition-timing-function: $transition-easing-out;
            transform: rotate(45deg);
        }
    }
    
    .button__icon {
        font-size: 24px;
        display: block;
    
        .button--arrow-animate & {
            float: right;
        }
    }
    
    .button__text {
        position: relative;
        z-index: 5;
    
        .button--icon & {
            @include visually-hidden();
        }
    
        .button--icon-left & {
            margin-left: 8px;
        }
    
        .button--icon-right & {
            margin-right: 8px;
        }
    }
    
    .button__inner {
        display: flex;
        align-items: center;
        justify-content: center;
    }
    
    .button--text {
        color: $button-primary-hover;
        position: relative;
        transition: $transition-duration $transition-easing;
        min-width: auto;
        padding: 0;
        text-transform: none;
    
        &:hover {
            color: $button-primary-hover;
        }
    
        &:before {
            content: '';
            position: absolute;
            top: auto;
            left: auto;
            right: 0;
            bottom: -1px;
            width: 100%;
            border-bottom: 2px solid $button-primary-hover;
            transition: width $transition-duration $transition-easing-out $transition-duration, border-bottom $transition-duration $transition-easing-out;
        }
    
        &:hover:before {
            width: 0;
            transition: width $transition-duration $transition-easing-in, border-bottom $transition-duration $transition-easing-in;
        }
    
        &:after {
            content: '';
            position: absolute;
            left: 0;
            bottom: 0;
            width: 0;
            border-bottom: 2px solid $button-primary-hover;
            transition: width $transition-duration $transition-easing-in, border-bottom $transition-duration $transition-easing-in;
        }
    
        &:hover:after {
            width: 100%;
            transition: width $transition-duration $transition-easing-out $transition-duration, border-bottom $transition-duration $transition-easing-out;
        }
    }
    
    .button__filler {
        display: none;
        position: absolute;
        z-index: 2;
        width: 150%;
        height: 200%;
        border-radius: $border-radius-round;
        background-color: $color-ui-01;
        color: $color-text-01;
        top: -50%;
        left: -25%;
        transform: translate3d(0, 75%, 0);
        transition-property: transform;
        transition-duration: $transition-duration;
        transition-timing-function: $transition-easing-in;
        will-change: transform; /* stylelint-disable-line plugin/no-unsupported-browser-features */
    
        .button--magnetic & {
            html[data-whatintent='mouse'] & {
                display: block;
            }
        }
    
        .button--reverted & {
            background-color: $button-primary-background;
            color: $color-text-03;
        }
    }
    
  • URL: /components/raw/button/button.scss
  • Filesystem Path: src/patterns/components/button/button.scss
  • Size: 7.2 KB
  • Content:
    import Component from '../component/component';
    import Helpers from '../helpers/helpers';
    import Icon from '../icon/icon';
    
    import './button.scss';
    
    export interface IButton {
        text: string;
        icon?: string;
        link?: string;
        iconPosition?: string;
    }
    
    export interface ITransform {
        amt: number;
        current: number;
        previous: number;
    }
    
    export interface IStyles {
        tx: ITransform;
        ty: ITransform;
    }
    
    export default class Button extends Component {
        static initSelector: string = '.button--magnetic';
    
        public filler: JQuery;
        public renderedStyles: IStyles;
        public buttonRect: DOMRect;
        public distanceToTrigger: number;
    
        constructor(element: HTMLElement) {
            super(element);
    
            this.filler = this.element.find('.button__filler');
    
            this.buttonRect = this.element[0].getBoundingClientRect();
            this.distanceToTrigger = this.buttonRect.width * 0.7;
    
            this.renderedStyles = {
                tx: {amt: 0.1, current: 0, previous: 0},
                ty: {amt: 0.1, current: 0, previous: 0},
            };
    
            this.init();
        }
    
        static render(data: IButton, className?: string): JQuery {
            const element: string = data.link ? 'a' : 'button';
            const icon: string = data.icon ? Icon.render(data.icon, 'button__icon') : '';
            const classArray: string[] = ['button'];
    
            if (className) {
                classArray.push(className);
            }
    
            if (data.icon && !data.iconPosition) {
                classArray.push('button--icon');
            }
    
            if (data.icon && data.iconPosition === 'right') {
                classArray.push('button--icon-right');
            }
    
            if (data.icon && data.iconPosition === 'left') {
                classArray.push('button--icon-left');
            }
    
            return $(`<${element} class="${classArray.join(' ')}" ${data.link ? `href="${data.link}"` : 'type="button"'}><span class="button__filler"></span><span class="button__inner"><span class="button__icon-wrapper">${icon}</span><span class="button__text">${data.text}</span></span></${element}>`);
        }
    
        init(): void {
            if (!Helpers.isMobileDevice) {
                this.element.on('mouseenter', this.enter.bind(this));
                this.element.on('mouseleave', this.leave.bind(this));
    
                $(window).on('resize scroll', this.resizeHandler.bind(this));
    
                this.run();
            }
    
        }
    
        resizeHandler(): void {
            this.buttonRect = this.element[0].getBoundingClientRect();
            this.distanceToTrigger = this.buttonRect.width * 0.7;
        }
    
        distance(x1: number, y1: number, x2: number, y2: number): number {
            const a: number = x1 - x2;
            const b: number = y1 - y2;
    
            return Math.hypot(a,b);
        }
    
        lerp(a: number, b: number, n: number): number {
            return (1 - n) * a + n * b;
        }
    
        run(): void {
            // Linear interpolation
            const distanceMouseButton: number = this.distance(window.gotoAndPlay.mousePos.x, window.gotoAndPlay.mousePos.y, this.buttonRect.left + this.buttonRect.width / 2, window.scrollY + this.buttonRect.top + this.buttonRect.height / 2);
    
            // new values for the translations
            let x: number = 0;
            let y: number = 0;
    
            if (distanceMouseButton < this.distanceToTrigger) {
                x = (window.gotoAndPlay.mousePos.x - (this.buttonRect.left + this.buttonRect.width / 2)) * .3;
                y = (window.gotoAndPlay.mousePos.y - (window.scrollY + this.buttonRect.top + this.buttonRect.height / 2)) * .3;
            }
    
            this.renderedStyles.tx.current = parseFloat(x.toFixed(3));
            this.renderedStyles.ty.current = parseFloat(y.toFixed(3));
    
            for (const key in this.renderedStyles) {
                if (key) {
                    this.renderedStyles[key].previous = parseFloat(this.lerp(this.renderedStyles[key].previous, this.renderedStyles[key].current, this.renderedStyles[key].amt).toFixed(3));
                }
            }
    
            this.element[0].style.transform = `translate3d(${this.renderedStyles.tx.previous}px, ${this.renderedStyles.ty.previous}px, 0)`;
    
            requestAnimationFrame(() => this.run());
        }
    
        enter(): void {
            this.element.addClass('is-hover');
            this.filler[0].style.transitionDuration = `250ms`;
            this.filler[0].style.transform = `translate3d(0, 0, 0)`;
        }
    
        leave(): void {
            this.element.removeClass('is-hover');
            this.filler[0].style.transform = `translate3d(0, -75%, 0)`;
    
            setTimeout(() => {
                if (!this.element.hasClass('is-hover')) {
                    this.filler[0].style.transitionDuration = `0ms`;
                    this.filler[0].style.transform = `translate3d(0, 75%, 0)`;
                }
            }, 250);
        }
    }
    
  • URL: /components/raw/button/button.ts
  • Filesystem Path: src/patterns/components/button/button.ts
  • Size: 4.7 KB
  • Handle: @button--icon-left
  • Filesystem Path: src/patterns/components/button/button.twig
  • References (1): @icon

Icon Right

<button type="button" class="button button--icon-right">
    <span class="button__inner">
        <span class="button__icon-wrapper"><svg class="icon  button__icon">
                <use xlink:href="../../inc/svg/global.bc9cdd731ad718497c5d8f03d08908d4.svg#plus-24"></use>
            </svg>
        </span> <span class="button__text">Button text</span>
    </span>
</button>
{% set element = data.link ? 'a' : 'button' %}
{% set icon = icon|default(data.icon|default(false)) %}
{% set iconPosition = iconPosition|default(data.iconPosition|default(false)) %}

{% set BEM -%}
    button
    {%- if modifier %} {{ modifier }}{% endif %}
    {%- if class %} {{ class }}{% endif %}
    {%- if icon %} button--icon{% if iconPosition %}{{ '-' ~ iconPosition }}{% endif %}{% endif %}
{% endset %}

<{{ element }}
    {% if data.link %} href="{{ data.link }}"{% else %} type="{{ type|default('button') }}" {% endif %}
    class="{{ BEM }}"
    {%- if data.attributes %} {{ data.attributes }}{% endif %}
>
    {% if 'button--magnetic' in modifier or 'button--magnetic' in class %}
        <span class="button__filler"></span>
    {% endif %}
    <span class="button__inner">
        {% if data.icon %}<span class="button__icon-wrapper">{% include '@icon' with { name: data.icon, modifier: '', class: 'button__icon' } %}</span>{% endif %}
        <span class="button__text">{{ data.text }}</span>
    </span>
</{{ element }}>
{
  "language": "en-US",
  "data": {
    "text": "Button text",
    "icon": "plus-24",
    "iconPosition": "right"
  }
}
  • Content:
    $button-primary-background: $color-brand-01;
    $button-primary-hover: $color-text-03;
    $button-primary-active: $color-brand-01;
    
    .button {
        position: relative;
        border-radius: $border-radius-base;
        border: none;
        -webkit-appearance: none;
        text-align: center;
        cursor: pointer;
        min-width: 156px;
        display: inline-block;
        padding: 14px 32px;
        margin: 0;
        font-size: $font-size-small;
        font-weight: $font-weight-medium;
        line-height: 1.15;
        background-color: transparent;
        color: $button-primary-hover;
        text-decoration: none;
        text-transform: uppercase;
        transition-property: color;
        transition-duration: $transition-duration;
        transition-timing-function: $transition-easing-in;
        z-index: map-get($zindex, 'default');
        outline-offset: 2px;
        overflow: hidden;
    
        .text > * + & {
            margin-top: 1.5em;
        }
    
        &:before {
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            bottom: 0;
            right: 0;
            background-color: $button-primary-background;
            transition-property: background-color, transform;
            transition-duration: $transition-duration;
            transition-timing-function: $transition-easing-in;
            box-shadow: inset 0 0 0 2px $button-primary-background;
            transform: scale(1);
            border-radius: $border-radius-base;
            z-index: 4;
        }
    
        &.is-hover,
        &:hover {
            transition-timing-function: $transition-easing-out;
            color: $button-primary-background;
    
            &:before {
                transition-timing-function: $transition-easing-out;
                background-color: transparent;
            }
        }
    
        &:active {
            color: $button-primary-background;
    
            &:before {
                background-color: transparent;
                transform: scale(.96);
                transition: none;
            }
        }
    }
    
    .button--icon {
        min-width: 0;
        padding: 12px;
        border-radius: $border-radius-round;
    
        &:before {
            border-radius: $border-radius-round;
        }
    }
    
    .button--icon-left {
        padding-left: 56px;
    }
    
    .button--icon-right {
        padding-right: 56px;
    }
    
    .button--arrow-animate {
        padding-right: 48px;
    }
    
    .button--reverted {
        color: $button-primary-background;
    
        &:before {
            background-color: $button-primary-hover;
            box-shadow: inset 0 0 0 2px $button-primary-hover;
        }
    
        &.is-hover,
        &:hover {
            color: $button-primary-hover;
    
            &:before {
                background-color: $button-primary-background;
            }
        }
    
        &:active {
            color: $button-primary-hover;
        }
    }
    
    .button--magnetic {
        html[data-whatintent='mouse'] & {
            background-color: $button-primary-background;
        }
    
        &:before {
            html[data-whatintent='mouse'] & {
                background-color: transparent;
            }
        }
    
        &.is-hover,
        &:active,
        &:hover {
            &:before {
                html[data-whatintent='mouse'] & {
                    background-color: transparent;
                }
            }
        }
    
        &.button--reverted {
            html[data-whatintent='mouse'] & {
                background-color: $button-primary-hover;
            }
        }
    }
    
    .button--block {
        display: block;
        width: 100%;
    }
    
    .button--block-xs {
        @media only screen and (max-width: $bp-sm-min - 1) {
            display: block;
            width: 100%;
        }
    }
    
    .button__icon-wrapper {
        position: relative;
        z-index: 5;
    
        .button--icon & {
            display: block;
        }
    
        .button--icon-left &,
        .button--icon-right & {
            position: absolute;
            top: auto;
            bottom: auto;
            margin: auto;
            display: inline-block;
            flex: 0 0 24px;
        }
    
        .button--icon-left & {
            left: 32px;
        }
    
        .button--icon-right & {
            right: 32px;
        }
    
        .button--arrow-animate & {
            width: 16px;
            height: 24px;
            overflow: hidden;
            right: 32px;
            transition-property: width, right;
            transition-timing-function: $transition-easing-in;
            transition-duration: $transition-duration;
        }
    
        .button--arrow-animate.is-hover &,
        .button--arrow-animate:hover & {
            width: 24px;
            right: 24px;
            transition-timing-function: $transition-easing-out;
        }
    
        .button--arrow-rotate & {
            transition-property: transform;
            transition-duration: $transition-duration;
            transition-timing-function: $transition-easing-in;
            transform: rotate(0);
        }
    
        .button--arrow-rotate.is-hover &,
        .button--arrow-rotate:hover & {
            transition-timing-function: $transition-easing-out;
            transform: rotate(45deg);
        }
    }
    
    .button__icon {
        font-size: 24px;
        display: block;
    
        .button--arrow-animate & {
            float: right;
        }
    }
    
    .button__text {
        position: relative;
        z-index: 5;
    
        .button--icon & {
            @include visually-hidden();
        }
    
        .button--icon-left & {
            margin-left: 8px;
        }
    
        .button--icon-right & {
            margin-right: 8px;
        }
    }
    
    .button__inner {
        display: flex;
        align-items: center;
        justify-content: center;
    }
    
    .button--text {
        color: $button-primary-hover;
        position: relative;
        transition: $transition-duration $transition-easing;
        min-width: auto;
        padding: 0;
        text-transform: none;
    
        &:hover {
            color: $button-primary-hover;
        }
    
        &:before {
            content: '';
            position: absolute;
            top: auto;
            left: auto;
            right: 0;
            bottom: -1px;
            width: 100%;
            border-bottom: 2px solid $button-primary-hover;
            transition: width $transition-duration $transition-easing-out $transition-duration, border-bottom $transition-duration $transition-easing-out;
        }
    
        &:hover:before {
            width: 0;
            transition: width $transition-duration $transition-easing-in, border-bottom $transition-duration $transition-easing-in;
        }
    
        &:after {
            content: '';
            position: absolute;
            left: 0;
            bottom: 0;
            width: 0;
            border-bottom: 2px solid $button-primary-hover;
            transition: width $transition-duration $transition-easing-in, border-bottom $transition-duration $transition-easing-in;
        }
    
        &:hover:after {
            width: 100%;
            transition: width $transition-duration $transition-easing-out $transition-duration, border-bottom $transition-duration $transition-easing-out;
        }
    }
    
    .button__filler {
        display: none;
        position: absolute;
        z-index: 2;
        width: 150%;
        height: 200%;
        border-radius: $border-radius-round;
        background-color: $color-ui-01;
        color: $color-text-01;
        top: -50%;
        left: -25%;
        transform: translate3d(0, 75%, 0);
        transition-property: transform;
        transition-duration: $transition-duration;
        transition-timing-function: $transition-easing-in;
        will-change: transform; /* stylelint-disable-line plugin/no-unsupported-browser-features */
    
        .button--magnetic & {
            html[data-whatintent='mouse'] & {
                display: block;
            }
        }
    
        .button--reverted & {
            background-color: $button-primary-background;
            color: $color-text-03;
        }
    }
    
  • URL: /components/raw/button/button.scss
  • Filesystem Path: src/patterns/components/button/button.scss
  • Size: 7.2 KB
  • Content:
    import Component from '../component/component';
    import Helpers from '../helpers/helpers';
    import Icon from '../icon/icon';
    
    import './button.scss';
    
    export interface IButton {
        text: string;
        icon?: string;
        link?: string;
        iconPosition?: string;
    }
    
    export interface ITransform {
        amt: number;
        current: number;
        previous: number;
    }
    
    export interface IStyles {
        tx: ITransform;
        ty: ITransform;
    }
    
    export default class Button extends Component {
        static initSelector: string = '.button--magnetic';
    
        public filler: JQuery;
        public renderedStyles: IStyles;
        public buttonRect: DOMRect;
        public distanceToTrigger: number;
    
        constructor(element: HTMLElement) {
            super(element);
    
            this.filler = this.element.find('.button__filler');
    
            this.buttonRect = this.element[0].getBoundingClientRect();
            this.distanceToTrigger = this.buttonRect.width * 0.7;
    
            this.renderedStyles = {
                tx: {amt: 0.1, current: 0, previous: 0},
                ty: {amt: 0.1, current: 0, previous: 0},
            };
    
            this.init();
        }
    
        static render(data: IButton, className?: string): JQuery {
            const element: string = data.link ? 'a' : 'button';
            const icon: string = data.icon ? Icon.render(data.icon, 'button__icon') : '';
            const classArray: string[] = ['button'];
    
            if (className) {
                classArray.push(className);
            }
    
            if (data.icon && !data.iconPosition) {
                classArray.push('button--icon');
            }
    
            if (data.icon && data.iconPosition === 'right') {
                classArray.push('button--icon-right');
            }
    
            if (data.icon && data.iconPosition === 'left') {
                classArray.push('button--icon-left');
            }
    
            return $(`<${element} class="${classArray.join(' ')}" ${data.link ? `href="${data.link}"` : 'type="button"'}><span class="button__filler"></span><span class="button__inner"><span class="button__icon-wrapper">${icon}</span><span class="button__text">${data.text}</span></span></${element}>`);
        }
    
        init(): void {
            if (!Helpers.isMobileDevice) {
                this.element.on('mouseenter', this.enter.bind(this));
                this.element.on('mouseleave', this.leave.bind(this));
    
                $(window).on('resize scroll', this.resizeHandler.bind(this));
    
                this.run();
            }
    
        }
    
        resizeHandler(): void {
            this.buttonRect = this.element[0].getBoundingClientRect();
            this.distanceToTrigger = this.buttonRect.width * 0.7;
        }
    
        distance(x1: number, y1: number, x2: number, y2: number): number {
            const a: number = x1 - x2;
            const b: number = y1 - y2;
    
            return Math.hypot(a,b);
        }
    
        lerp(a: number, b: number, n: number): number {
            return (1 - n) * a + n * b;
        }
    
        run(): void {
            // Linear interpolation
            const distanceMouseButton: number = this.distance(window.gotoAndPlay.mousePos.x, window.gotoAndPlay.mousePos.y, this.buttonRect.left + this.buttonRect.width / 2, window.scrollY + this.buttonRect.top + this.buttonRect.height / 2);
    
            // new values for the translations
            let x: number = 0;
            let y: number = 0;
    
            if (distanceMouseButton < this.distanceToTrigger) {
                x = (window.gotoAndPlay.mousePos.x - (this.buttonRect.left + this.buttonRect.width / 2)) * .3;
                y = (window.gotoAndPlay.mousePos.y - (window.scrollY + this.buttonRect.top + this.buttonRect.height / 2)) * .3;
            }
    
            this.renderedStyles.tx.current = parseFloat(x.toFixed(3));
            this.renderedStyles.ty.current = parseFloat(y.toFixed(3));
    
            for (const key in this.renderedStyles) {
                if (key) {
                    this.renderedStyles[key].previous = parseFloat(this.lerp(this.renderedStyles[key].previous, this.renderedStyles[key].current, this.renderedStyles[key].amt).toFixed(3));
                }
            }
    
            this.element[0].style.transform = `translate3d(${this.renderedStyles.tx.previous}px, ${this.renderedStyles.ty.previous}px, 0)`;
    
            requestAnimationFrame(() => this.run());
        }
    
        enter(): void {
            this.element.addClass('is-hover');
            this.filler[0].style.transitionDuration = `250ms`;
            this.filler[0].style.transform = `translate3d(0, 0, 0)`;
        }
    
        leave(): void {
            this.element.removeClass('is-hover');
            this.filler[0].style.transform = `translate3d(0, -75%, 0)`;
    
            setTimeout(() => {
                if (!this.element.hasClass('is-hover')) {
                    this.filler[0].style.transitionDuration = `0ms`;
                    this.filler[0].style.transform = `translate3d(0, 75%, 0)`;
                }
            }, 250);
        }
    }
    
  • URL: /components/raw/button/button.ts
  • Filesystem Path: src/patterns/components/button/button.ts
  • Size: 4.7 KB
  • Handle: @button--icon-right
  • Filesystem Path: src/patterns/components/button/button.twig
  • References (1): @icon

Arrow Animate

<button type="button" class="button button--arrow-animate button--icon-right">
    <span class="button__inner">
        <span class="button__icon-wrapper"><svg class="icon  button__icon">
                <use xlink:href="../../inc/svg/global.bc9cdd731ad718497c5d8f03d08908d4.svg#tiny-arrow-right-long-24"></use>
            </svg>
        </span> <span class="button__text">Button text</span>
    </span>
</button>
{% set element = data.link ? 'a' : 'button' %}
{% set icon = icon|default(data.icon|default(false)) %}
{% set iconPosition = iconPosition|default(data.iconPosition|default(false)) %}

{% set BEM -%}
    button
    {%- if modifier %} {{ modifier }}{% endif %}
    {%- if class %} {{ class }}{% endif %}
    {%- if icon %} button--icon{% if iconPosition %}{{ '-' ~ iconPosition }}{% endif %}{% endif %}
{% endset %}

<{{ element }}
    {% if data.link %} href="{{ data.link }}"{% else %} type="{{ type|default('button') }}" {% endif %}
    class="{{ BEM }}"
    {%- if data.attributes %} {{ data.attributes }}{% endif %}
>
    {% if 'button--magnetic' in modifier or 'button--magnetic' in class %}
        <span class="button__filler"></span>
    {% endif %}
    <span class="button__inner">
        {% if data.icon %}<span class="button__icon-wrapper">{% include '@icon' with { name: data.icon, modifier: '', class: 'button__icon' } %}</span>{% endif %}
        <span class="button__text">{{ data.text }}</span>
    </span>
</{{ element }}>
{
  "language": "en-US",
  "data": {
    "text": "Button text",
    "icon": "tiny-arrow-right-long-24",
    "iconPosition": "right"
  },
  "modifier": "button--arrow-animate"
}
  • Content:
    $button-primary-background: $color-brand-01;
    $button-primary-hover: $color-text-03;
    $button-primary-active: $color-brand-01;
    
    .button {
        position: relative;
        border-radius: $border-radius-base;
        border: none;
        -webkit-appearance: none;
        text-align: center;
        cursor: pointer;
        min-width: 156px;
        display: inline-block;
        padding: 14px 32px;
        margin: 0;
        font-size: $font-size-small;
        font-weight: $font-weight-medium;
        line-height: 1.15;
        background-color: transparent;
        color: $button-primary-hover;
        text-decoration: none;
        text-transform: uppercase;
        transition-property: color;
        transition-duration: $transition-duration;
        transition-timing-function: $transition-easing-in;
        z-index: map-get($zindex, 'default');
        outline-offset: 2px;
        overflow: hidden;
    
        .text > * + & {
            margin-top: 1.5em;
        }
    
        &:before {
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            bottom: 0;
            right: 0;
            background-color: $button-primary-background;
            transition-property: background-color, transform;
            transition-duration: $transition-duration;
            transition-timing-function: $transition-easing-in;
            box-shadow: inset 0 0 0 2px $button-primary-background;
            transform: scale(1);
            border-radius: $border-radius-base;
            z-index: 4;
        }
    
        &.is-hover,
        &:hover {
            transition-timing-function: $transition-easing-out;
            color: $button-primary-background;
    
            &:before {
                transition-timing-function: $transition-easing-out;
                background-color: transparent;
            }
        }
    
        &:active {
            color: $button-primary-background;
    
            &:before {
                background-color: transparent;
                transform: scale(.96);
                transition: none;
            }
        }
    }
    
    .button--icon {
        min-width: 0;
        padding: 12px;
        border-radius: $border-radius-round;
    
        &:before {
            border-radius: $border-radius-round;
        }
    }
    
    .button--icon-left {
        padding-left: 56px;
    }
    
    .button--icon-right {
        padding-right: 56px;
    }
    
    .button--arrow-animate {
        padding-right: 48px;
    }
    
    .button--reverted {
        color: $button-primary-background;
    
        &:before {
            background-color: $button-primary-hover;
            box-shadow: inset 0 0 0 2px $button-primary-hover;
        }
    
        &.is-hover,
        &:hover {
            color: $button-primary-hover;
    
            &:before {
                background-color: $button-primary-background;
            }
        }
    
        &:active {
            color: $button-primary-hover;
        }
    }
    
    .button--magnetic {
        html[data-whatintent='mouse'] & {
            background-color: $button-primary-background;
        }
    
        &:before {
            html[data-whatintent='mouse'] & {
                background-color: transparent;
            }
        }
    
        &.is-hover,
        &:active,
        &:hover {
            &:before {
                html[data-whatintent='mouse'] & {
                    background-color: transparent;
                }
            }
        }
    
        &.button--reverted {
            html[data-whatintent='mouse'] & {
                background-color: $button-primary-hover;
            }
        }
    }
    
    .button--block {
        display: block;
        width: 100%;
    }
    
    .button--block-xs {
        @media only screen and (max-width: $bp-sm-min - 1) {
            display: block;
            width: 100%;
        }
    }
    
    .button__icon-wrapper {
        position: relative;
        z-index: 5;
    
        .button--icon & {
            display: block;
        }
    
        .button--icon-left &,
        .button--icon-right & {
            position: absolute;
            top: auto;
            bottom: auto;
            margin: auto;
            display: inline-block;
            flex: 0 0 24px;
        }
    
        .button--icon-left & {
            left: 32px;
        }
    
        .button--icon-right & {
            right: 32px;
        }
    
        .button--arrow-animate & {
            width: 16px;
            height: 24px;
            overflow: hidden;
            right: 32px;
            transition-property: width, right;
            transition-timing-function: $transition-easing-in;
            transition-duration: $transition-duration;
        }
    
        .button--arrow-animate.is-hover &,
        .button--arrow-animate:hover & {
            width: 24px;
            right: 24px;
            transition-timing-function: $transition-easing-out;
        }
    
        .button--arrow-rotate & {
            transition-property: transform;
            transition-duration: $transition-duration;
            transition-timing-function: $transition-easing-in;
            transform: rotate(0);
        }
    
        .button--arrow-rotate.is-hover &,
        .button--arrow-rotate:hover & {
            transition-timing-function: $transition-easing-out;
            transform: rotate(45deg);
        }
    }
    
    .button__icon {
        font-size: 24px;
        display: block;
    
        .button--arrow-animate & {
            float: right;
        }
    }
    
    .button__text {
        position: relative;
        z-index: 5;
    
        .button--icon & {
            @include visually-hidden();
        }
    
        .button--icon-left & {
            margin-left: 8px;
        }
    
        .button--icon-right & {
            margin-right: 8px;
        }
    }
    
    .button__inner {
        display: flex;
        align-items: center;
        justify-content: center;
    }
    
    .button--text {
        color: $button-primary-hover;
        position: relative;
        transition: $transition-duration $transition-easing;
        min-width: auto;
        padding: 0;
        text-transform: none;
    
        &:hover {
            color: $button-primary-hover;
        }
    
        &:before {
            content: '';
            position: absolute;
            top: auto;
            left: auto;
            right: 0;
            bottom: -1px;
            width: 100%;
            border-bottom: 2px solid $button-primary-hover;
            transition: width $transition-duration $transition-easing-out $transition-duration, border-bottom $transition-duration $transition-easing-out;
        }
    
        &:hover:before {
            width: 0;
            transition: width $transition-duration $transition-easing-in, border-bottom $transition-duration $transition-easing-in;
        }
    
        &:after {
            content: '';
            position: absolute;
            left: 0;
            bottom: 0;
            width: 0;
            border-bottom: 2px solid $button-primary-hover;
            transition: width $transition-duration $transition-easing-in, border-bottom $transition-duration $transition-easing-in;
        }
    
        &:hover:after {
            width: 100%;
            transition: width $transition-duration $transition-easing-out $transition-duration, border-bottom $transition-duration $transition-easing-out;
        }
    }
    
    .button__filler {
        display: none;
        position: absolute;
        z-index: 2;
        width: 150%;
        height: 200%;
        border-radius: $border-radius-round;
        background-color: $color-ui-01;
        color: $color-text-01;
        top: -50%;
        left: -25%;
        transform: translate3d(0, 75%, 0);
        transition-property: transform;
        transition-duration: $transition-duration;
        transition-timing-function: $transition-easing-in;
        will-change: transform; /* stylelint-disable-line plugin/no-unsupported-browser-features */
    
        .button--magnetic & {
            html[data-whatintent='mouse'] & {
                display: block;
            }
        }
    
        .button--reverted & {
            background-color: $button-primary-background;
            color: $color-text-03;
        }
    }
    
  • URL: /components/raw/button/button.scss
  • Filesystem Path: src/patterns/components/button/button.scss
  • Size: 7.2 KB
  • Content:
    import Component from '../component/component';
    import Helpers from '../helpers/helpers';
    import Icon from '../icon/icon';
    
    import './button.scss';
    
    export interface IButton {
        text: string;
        icon?: string;
        link?: string;
        iconPosition?: string;
    }
    
    export interface ITransform {
        amt: number;
        current: number;
        previous: number;
    }
    
    export interface IStyles {
        tx: ITransform;
        ty: ITransform;
    }
    
    export default class Button extends Component {
        static initSelector: string = '.button--magnetic';
    
        public filler: JQuery;
        public renderedStyles: IStyles;
        public buttonRect: DOMRect;
        public distanceToTrigger: number;
    
        constructor(element: HTMLElement) {
            super(element);
    
            this.filler = this.element.find('.button__filler');
    
            this.buttonRect = this.element[0].getBoundingClientRect();
            this.distanceToTrigger = this.buttonRect.width * 0.7;
    
            this.renderedStyles = {
                tx: {amt: 0.1, current: 0, previous: 0},
                ty: {amt: 0.1, current: 0, previous: 0},
            };
    
            this.init();
        }
    
        static render(data: IButton, className?: string): JQuery {
            const element: string = data.link ? 'a' : 'button';
            const icon: string = data.icon ? Icon.render(data.icon, 'button__icon') : '';
            const classArray: string[] = ['button'];
    
            if (className) {
                classArray.push(className);
            }
    
            if (data.icon && !data.iconPosition) {
                classArray.push('button--icon');
            }
    
            if (data.icon && data.iconPosition === 'right') {
                classArray.push('button--icon-right');
            }
    
            if (data.icon && data.iconPosition === 'left') {
                classArray.push('button--icon-left');
            }
    
            return $(`<${element} class="${classArray.join(' ')}" ${data.link ? `href="${data.link}"` : 'type="button"'}><span class="button__filler"></span><span class="button__inner"><span class="button__icon-wrapper">${icon}</span><span class="button__text">${data.text}</span></span></${element}>`);
        }
    
        init(): void {
            if (!Helpers.isMobileDevice) {
                this.element.on('mouseenter', this.enter.bind(this));
                this.element.on('mouseleave', this.leave.bind(this));
    
                $(window).on('resize scroll', this.resizeHandler.bind(this));
    
                this.run();
            }
    
        }
    
        resizeHandler(): void {
            this.buttonRect = this.element[0].getBoundingClientRect();
            this.distanceToTrigger = this.buttonRect.width * 0.7;
        }
    
        distance(x1: number, y1: number, x2: number, y2: number): number {
            const a: number = x1 - x2;
            const b: number = y1 - y2;
    
            return Math.hypot(a,b);
        }
    
        lerp(a: number, b: number, n: number): number {
            return (1 - n) * a + n * b;
        }
    
        run(): void {
            // Linear interpolation
            const distanceMouseButton: number = this.distance(window.gotoAndPlay.mousePos.x, window.gotoAndPlay.mousePos.y, this.buttonRect.left + this.buttonRect.width / 2, window.scrollY + this.buttonRect.top + this.buttonRect.height / 2);
    
            // new values for the translations
            let x: number = 0;
            let y: number = 0;
    
            if (distanceMouseButton < this.distanceToTrigger) {
                x = (window.gotoAndPlay.mousePos.x - (this.buttonRect.left + this.buttonRect.width / 2)) * .3;
                y = (window.gotoAndPlay.mousePos.y - (window.scrollY + this.buttonRect.top + this.buttonRect.height / 2)) * .3;
            }
    
            this.renderedStyles.tx.current = parseFloat(x.toFixed(3));
            this.renderedStyles.ty.current = parseFloat(y.toFixed(3));
    
            for (const key in this.renderedStyles) {
                if (key) {
                    this.renderedStyles[key].previous = parseFloat(this.lerp(this.renderedStyles[key].previous, this.renderedStyles[key].current, this.renderedStyles[key].amt).toFixed(3));
                }
            }
    
            this.element[0].style.transform = `translate3d(${this.renderedStyles.tx.previous}px, ${this.renderedStyles.ty.previous}px, 0)`;
    
            requestAnimationFrame(() => this.run());
        }
    
        enter(): void {
            this.element.addClass('is-hover');
            this.filler[0].style.transitionDuration = `250ms`;
            this.filler[0].style.transform = `translate3d(0, 0, 0)`;
        }
    
        leave(): void {
            this.element.removeClass('is-hover');
            this.filler[0].style.transform = `translate3d(0, -75%, 0)`;
    
            setTimeout(() => {
                if (!this.element.hasClass('is-hover')) {
                    this.filler[0].style.transitionDuration = `0ms`;
                    this.filler[0].style.transform = `translate3d(0, 75%, 0)`;
                }
            }, 250);
        }
    }
    
  • URL: /components/raw/button/button.ts
  • Filesystem Path: src/patterns/components/button/button.ts
  • Size: 4.7 KB
  • Handle: @button--arrow-animate
  • Filesystem Path: src/patterns/components/button/button.twig
  • References (1): @icon

Block

Modifier to force button always full width.

<button type="button" class="button button--block">
    <span class="button__inner">
        <span class="button__text">Button text</span>
    </span>
</button>
{% set element = data.link ? 'a' : 'button' %}
{% set icon = icon|default(data.icon|default(false)) %}
{% set iconPosition = iconPosition|default(data.iconPosition|default(false)) %}

{% set BEM -%}
    button
    {%- if modifier %} {{ modifier }}{% endif %}
    {%- if class %} {{ class }}{% endif %}
    {%- if icon %} button--icon{% if iconPosition %}{{ '-' ~ iconPosition }}{% endif %}{% endif %}
{% endset %}

<{{ element }}
    {% if data.link %} href="{{ data.link }}"{% else %} type="{{ type|default('button') }}" {% endif %}
    class="{{ BEM }}"
    {%- if data.attributes %} {{ data.attributes }}{% endif %}
>
    {% if 'button--magnetic' in modifier or 'button--magnetic' in class %}
        <span class="button__filler"></span>
    {% endif %}
    <span class="button__inner">
        {% if data.icon %}<span class="button__icon-wrapper">{% include '@icon' with { name: data.icon, modifier: '', class: 'button__icon' } %}</span>{% endif %}
        <span class="button__text">{{ data.text }}</span>
    </span>
</{{ element }}>
{
  "language": "en-US",
  "data": {
    "text": "Button text"
  },
  "modifier": "button--block"
}
  • Content:
    $button-primary-background: $color-brand-01;
    $button-primary-hover: $color-text-03;
    $button-primary-active: $color-brand-01;
    
    .button {
        position: relative;
        border-radius: $border-radius-base;
        border: none;
        -webkit-appearance: none;
        text-align: center;
        cursor: pointer;
        min-width: 156px;
        display: inline-block;
        padding: 14px 32px;
        margin: 0;
        font-size: $font-size-small;
        font-weight: $font-weight-medium;
        line-height: 1.15;
        background-color: transparent;
        color: $button-primary-hover;
        text-decoration: none;
        text-transform: uppercase;
        transition-property: color;
        transition-duration: $transition-duration;
        transition-timing-function: $transition-easing-in;
        z-index: map-get($zindex, 'default');
        outline-offset: 2px;
        overflow: hidden;
    
        .text > * + & {
            margin-top: 1.5em;
        }
    
        &:before {
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            bottom: 0;
            right: 0;
            background-color: $button-primary-background;
            transition-property: background-color, transform;
            transition-duration: $transition-duration;
            transition-timing-function: $transition-easing-in;
            box-shadow: inset 0 0 0 2px $button-primary-background;
            transform: scale(1);
            border-radius: $border-radius-base;
            z-index: 4;
        }
    
        &.is-hover,
        &:hover {
            transition-timing-function: $transition-easing-out;
            color: $button-primary-background;
    
            &:before {
                transition-timing-function: $transition-easing-out;
                background-color: transparent;
            }
        }
    
        &:active {
            color: $button-primary-background;
    
            &:before {
                background-color: transparent;
                transform: scale(.96);
                transition: none;
            }
        }
    }
    
    .button--icon {
        min-width: 0;
        padding: 12px;
        border-radius: $border-radius-round;
    
        &:before {
            border-radius: $border-radius-round;
        }
    }
    
    .button--icon-left {
        padding-left: 56px;
    }
    
    .button--icon-right {
        padding-right: 56px;
    }
    
    .button--arrow-animate {
        padding-right: 48px;
    }
    
    .button--reverted {
        color: $button-primary-background;
    
        &:before {
            background-color: $button-primary-hover;
            box-shadow: inset 0 0 0 2px $button-primary-hover;
        }
    
        &.is-hover,
        &:hover {
            color: $button-primary-hover;
    
            &:before {
                background-color: $button-primary-background;
            }
        }
    
        &:active {
            color: $button-primary-hover;
        }
    }
    
    .button--magnetic {
        html[data-whatintent='mouse'] & {
            background-color: $button-primary-background;
        }
    
        &:before {
            html[data-whatintent='mouse'] & {
                background-color: transparent;
            }
        }
    
        &.is-hover,
        &:active,
        &:hover {
            &:before {
                html[data-whatintent='mouse'] & {
                    background-color: transparent;
                }
            }
        }
    
        &.button--reverted {
            html[data-whatintent='mouse'] & {
                background-color: $button-primary-hover;
            }
        }
    }
    
    .button--block {
        display: block;
        width: 100%;
    }
    
    .button--block-xs {
        @media only screen and (max-width: $bp-sm-min - 1) {
            display: block;
            width: 100%;
        }
    }
    
    .button__icon-wrapper {
        position: relative;
        z-index: 5;
    
        .button--icon & {
            display: block;
        }
    
        .button--icon-left &,
        .button--icon-right & {
            position: absolute;
            top: auto;
            bottom: auto;
            margin: auto;
            display: inline-block;
            flex: 0 0 24px;
        }
    
        .button--icon-left & {
            left: 32px;
        }
    
        .button--icon-right & {
            right: 32px;
        }
    
        .button--arrow-animate & {
            width: 16px;
            height: 24px;
            overflow: hidden;
            right: 32px;
            transition-property: width, right;
            transition-timing-function: $transition-easing-in;
            transition-duration: $transition-duration;
        }
    
        .button--arrow-animate.is-hover &,
        .button--arrow-animate:hover & {
            width: 24px;
            right: 24px;
            transition-timing-function: $transition-easing-out;
        }
    
        .button--arrow-rotate & {
            transition-property: transform;
            transition-duration: $transition-duration;
            transition-timing-function: $transition-easing-in;
            transform: rotate(0);
        }
    
        .button--arrow-rotate.is-hover &,
        .button--arrow-rotate:hover & {
            transition-timing-function: $transition-easing-out;
            transform: rotate(45deg);
        }
    }
    
    .button__icon {
        font-size: 24px;
        display: block;
    
        .button--arrow-animate & {
            float: right;
        }
    }
    
    .button__text {
        position: relative;
        z-index: 5;
    
        .button--icon & {
            @include visually-hidden();
        }
    
        .button--icon-left & {
            margin-left: 8px;
        }
    
        .button--icon-right & {
            margin-right: 8px;
        }
    }
    
    .button__inner {
        display: flex;
        align-items: center;
        justify-content: center;
    }
    
    .button--text {
        color: $button-primary-hover;
        position: relative;
        transition: $transition-duration $transition-easing;
        min-width: auto;
        padding: 0;
        text-transform: none;
    
        &:hover {
            color: $button-primary-hover;
        }
    
        &:before {
            content: '';
            position: absolute;
            top: auto;
            left: auto;
            right: 0;
            bottom: -1px;
            width: 100%;
            border-bottom: 2px solid $button-primary-hover;
            transition: width $transition-duration $transition-easing-out $transition-duration, border-bottom $transition-duration $transition-easing-out;
        }
    
        &:hover:before {
            width: 0;
            transition: width $transition-duration $transition-easing-in, border-bottom $transition-duration $transition-easing-in;
        }
    
        &:after {
            content: '';
            position: absolute;
            left: 0;
            bottom: 0;
            width: 0;
            border-bottom: 2px solid $button-primary-hover;
            transition: width $transition-duration $transition-easing-in, border-bottom $transition-duration $transition-easing-in;
        }
    
        &:hover:after {
            width: 100%;
            transition: width $transition-duration $transition-easing-out $transition-duration, border-bottom $transition-duration $transition-easing-out;
        }
    }
    
    .button__filler {
        display: none;
        position: absolute;
        z-index: 2;
        width: 150%;
        height: 200%;
        border-radius: $border-radius-round;
        background-color: $color-ui-01;
        color: $color-text-01;
        top: -50%;
        left: -25%;
        transform: translate3d(0, 75%, 0);
        transition-property: transform;
        transition-duration: $transition-duration;
        transition-timing-function: $transition-easing-in;
        will-change: transform; /* stylelint-disable-line plugin/no-unsupported-browser-features */
    
        .button--magnetic & {
            html[data-whatintent='mouse'] & {
                display: block;
            }
        }
    
        .button--reverted & {
            background-color: $button-primary-background;
            color: $color-text-03;
        }
    }
    
  • URL: /components/raw/button/button.scss
  • Filesystem Path: src/patterns/components/button/button.scss
  • Size: 7.2 KB
  • Content:
    import Component from '../component/component';
    import Helpers from '../helpers/helpers';
    import Icon from '../icon/icon';
    
    import './button.scss';
    
    export interface IButton {
        text: string;
        icon?: string;
        link?: string;
        iconPosition?: string;
    }
    
    export interface ITransform {
        amt: number;
        current: number;
        previous: number;
    }
    
    export interface IStyles {
        tx: ITransform;
        ty: ITransform;
    }
    
    export default class Button extends Component {
        static initSelector: string = '.button--magnetic';
    
        public filler: JQuery;
        public renderedStyles: IStyles;
        public buttonRect: DOMRect;
        public distanceToTrigger: number;
    
        constructor(element: HTMLElement) {
            super(element);
    
            this.filler = this.element.find('.button__filler');
    
            this.buttonRect = this.element[0].getBoundingClientRect();
            this.distanceToTrigger = this.buttonRect.width * 0.7;
    
            this.renderedStyles = {
                tx: {amt: 0.1, current: 0, previous: 0},
                ty: {amt: 0.1, current: 0, previous: 0},
            };
    
            this.init();
        }
    
        static render(data: IButton, className?: string): JQuery {
            const element: string = data.link ? 'a' : 'button';
            const icon: string = data.icon ? Icon.render(data.icon, 'button__icon') : '';
            const classArray: string[] = ['button'];
    
            if (className) {
                classArray.push(className);
            }
    
            if (data.icon && !data.iconPosition) {
                classArray.push('button--icon');
            }
    
            if (data.icon && data.iconPosition === 'right') {
                classArray.push('button--icon-right');
            }
    
            if (data.icon && data.iconPosition === 'left') {
                classArray.push('button--icon-left');
            }
    
            return $(`<${element} class="${classArray.join(' ')}" ${data.link ? `href="${data.link}"` : 'type="button"'}><span class="button__filler"></span><span class="button__inner"><span class="button__icon-wrapper">${icon}</span><span class="button__text">${data.text}</span></span></${element}>`);
        }
    
        init(): void {
            if (!Helpers.isMobileDevice) {
                this.element.on('mouseenter', this.enter.bind(this));
                this.element.on('mouseleave', this.leave.bind(this));
    
                $(window).on('resize scroll', this.resizeHandler.bind(this));
    
                this.run();
            }
    
        }
    
        resizeHandler(): void {
            this.buttonRect = this.element[0].getBoundingClientRect();
            this.distanceToTrigger = this.buttonRect.width * 0.7;
        }
    
        distance(x1: number, y1: number, x2: number, y2: number): number {
            const a: number = x1 - x2;
            const b: number = y1 - y2;
    
            return Math.hypot(a,b);
        }
    
        lerp(a: number, b: number, n: number): number {
            return (1 - n) * a + n * b;
        }
    
        run(): void {
            // Linear interpolation
            const distanceMouseButton: number = this.distance(window.gotoAndPlay.mousePos.x, window.gotoAndPlay.mousePos.y, this.buttonRect.left + this.buttonRect.width / 2, window.scrollY + this.buttonRect.top + this.buttonRect.height / 2);
    
            // new values for the translations
            let x: number = 0;
            let y: number = 0;
    
            if (distanceMouseButton < this.distanceToTrigger) {
                x = (window.gotoAndPlay.mousePos.x - (this.buttonRect.left + this.buttonRect.width / 2)) * .3;
                y = (window.gotoAndPlay.mousePos.y - (window.scrollY + this.buttonRect.top + this.buttonRect.height / 2)) * .3;
            }
    
            this.renderedStyles.tx.current = parseFloat(x.toFixed(3));
            this.renderedStyles.ty.current = parseFloat(y.toFixed(3));
    
            for (const key in this.renderedStyles) {
                if (key) {
                    this.renderedStyles[key].previous = parseFloat(this.lerp(this.renderedStyles[key].previous, this.renderedStyles[key].current, this.renderedStyles[key].amt).toFixed(3));
                }
            }
    
            this.element[0].style.transform = `translate3d(${this.renderedStyles.tx.previous}px, ${this.renderedStyles.ty.previous}px, 0)`;
    
            requestAnimationFrame(() => this.run());
        }
    
        enter(): void {
            this.element.addClass('is-hover');
            this.filler[0].style.transitionDuration = `250ms`;
            this.filler[0].style.transform = `translate3d(0, 0, 0)`;
        }
    
        leave(): void {
            this.element.removeClass('is-hover');
            this.filler[0].style.transform = `translate3d(0, -75%, 0)`;
    
            setTimeout(() => {
                if (!this.element.hasClass('is-hover')) {
                    this.filler[0].style.transitionDuration = `0ms`;
                    this.filler[0].style.transform = `translate3d(0, 75%, 0)`;
                }
            }, 250);
        }
    }
    
  • URL: /components/raw/button/button.ts
  • Filesystem Path: src/patterns/components/button/button.ts
  • Size: 4.7 KB
  • Handle: @button--block
  • Filesystem Path: src/patterns/components/button/button.twig
  • References (1): @icon

Block Xs

Modifier to force button full width only in mobile.

<button type="button" class="button button--block-xs">
    <span class="button__inner">
        <span class="button__text">Button text</span>
    </span>
</button>
{% set element = data.link ? 'a' : 'button' %}
{% set icon = icon|default(data.icon|default(false)) %}
{% set iconPosition = iconPosition|default(data.iconPosition|default(false)) %}

{% set BEM -%}
    button
    {%- if modifier %} {{ modifier }}{% endif %}
    {%- if class %} {{ class }}{% endif %}
    {%- if icon %} button--icon{% if iconPosition %}{{ '-' ~ iconPosition }}{% endif %}{% endif %}
{% endset %}

<{{ element }}
    {% if data.link %} href="{{ data.link }}"{% else %} type="{{ type|default('button') }}" {% endif %}
    class="{{ BEM }}"
    {%- if data.attributes %} {{ data.attributes }}{% endif %}
>
    {% if 'button--magnetic' in modifier or 'button--magnetic' in class %}
        <span class="button__filler"></span>
    {% endif %}
    <span class="button__inner">
        {% if data.icon %}<span class="button__icon-wrapper">{% include '@icon' with { name: data.icon, modifier: '', class: 'button__icon' } %}</span>{% endif %}
        <span class="button__text">{{ data.text }}</span>
    </span>
</{{ element }}>
{
  "language": "en-US",
  "data": {
    "text": "Button text"
  },
  "modifier": "button--block-xs"
}
  • Content:
    $button-primary-background: $color-brand-01;
    $button-primary-hover: $color-text-03;
    $button-primary-active: $color-brand-01;
    
    .button {
        position: relative;
        border-radius: $border-radius-base;
        border: none;
        -webkit-appearance: none;
        text-align: center;
        cursor: pointer;
        min-width: 156px;
        display: inline-block;
        padding: 14px 32px;
        margin: 0;
        font-size: $font-size-small;
        font-weight: $font-weight-medium;
        line-height: 1.15;
        background-color: transparent;
        color: $button-primary-hover;
        text-decoration: none;
        text-transform: uppercase;
        transition-property: color;
        transition-duration: $transition-duration;
        transition-timing-function: $transition-easing-in;
        z-index: map-get($zindex, 'default');
        outline-offset: 2px;
        overflow: hidden;
    
        .text > * + & {
            margin-top: 1.5em;
        }
    
        &:before {
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            bottom: 0;
            right: 0;
            background-color: $button-primary-background;
            transition-property: background-color, transform;
            transition-duration: $transition-duration;
            transition-timing-function: $transition-easing-in;
            box-shadow: inset 0 0 0 2px $button-primary-background;
            transform: scale(1);
            border-radius: $border-radius-base;
            z-index: 4;
        }
    
        &.is-hover,
        &:hover {
            transition-timing-function: $transition-easing-out;
            color: $button-primary-background;
    
            &:before {
                transition-timing-function: $transition-easing-out;
                background-color: transparent;
            }
        }
    
        &:active {
            color: $button-primary-background;
    
            &:before {
                background-color: transparent;
                transform: scale(.96);
                transition: none;
            }
        }
    }
    
    .button--icon {
        min-width: 0;
        padding: 12px;
        border-radius: $border-radius-round;
    
        &:before {
            border-radius: $border-radius-round;
        }
    }
    
    .button--icon-left {
        padding-left: 56px;
    }
    
    .button--icon-right {
        padding-right: 56px;
    }
    
    .button--arrow-animate {
        padding-right: 48px;
    }
    
    .button--reverted {
        color: $button-primary-background;
    
        &:before {
            background-color: $button-primary-hover;
            box-shadow: inset 0 0 0 2px $button-primary-hover;
        }
    
        &.is-hover,
        &:hover {
            color: $button-primary-hover;
    
            &:before {
                background-color: $button-primary-background;
            }
        }
    
        &:active {
            color: $button-primary-hover;
        }
    }
    
    .button--magnetic {
        html[data-whatintent='mouse'] & {
            background-color: $button-primary-background;
        }
    
        &:before {
            html[data-whatintent='mouse'] & {
                background-color: transparent;
            }
        }
    
        &.is-hover,
        &:active,
        &:hover {
            &:before {
                html[data-whatintent='mouse'] & {
                    background-color: transparent;
                }
            }
        }
    
        &.button--reverted {
            html[data-whatintent='mouse'] & {
                background-color: $button-primary-hover;
            }
        }
    }
    
    .button--block {
        display: block;
        width: 100%;
    }
    
    .button--block-xs {
        @media only screen and (max-width: $bp-sm-min - 1) {
            display: block;
            width: 100%;
        }
    }
    
    .button__icon-wrapper {
        position: relative;
        z-index: 5;
    
        .button--icon & {
            display: block;
        }
    
        .button--icon-left &,
        .button--icon-right & {
            position: absolute;
            top: auto;
            bottom: auto;
            margin: auto;
            display: inline-block;
            flex: 0 0 24px;
        }
    
        .button--icon-left & {
            left: 32px;
        }
    
        .button--icon-right & {
            right: 32px;
        }
    
        .button--arrow-animate & {
            width: 16px;
            height: 24px;
            overflow: hidden;
            right: 32px;
            transition-property: width, right;
            transition-timing-function: $transition-easing-in;
            transition-duration: $transition-duration;
        }
    
        .button--arrow-animate.is-hover &,
        .button--arrow-animate:hover & {
            width: 24px;
            right: 24px;
            transition-timing-function: $transition-easing-out;
        }
    
        .button--arrow-rotate & {
            transition-property: transform;
            transition-duration: $transition-duration;
            transition-timing-function: $transition-easing-in;
            transform: rotate(0);
        }
    
        .button--arrow-rotate.is-hover &,
        .button--arrow-rotate:hover & {
            transition-timing-function: $transition-easing-out;
            transform: rotate(45deg);
        }
    }
    
    .button__icon {
        font-size: 24px;
        display: block;
    
        .button--arrow-animate & {
            float: right;
        }
    }
    
    .button__text {
        position: relative;
        z-index: 5;
    
        .button--icon & {
            @include visually-hidden();
        }
    
        .button--icon-left & {
            margin-left: 8px;
        }
    
        .button--icon-right & {
            margin-right: 8px;
        }
    }
    
    .button__inner {
        display: flex;
        align-items: center;
        justify-content: center;
    }
    
    .button--text {
        color: $button-primary-hover;
        position: relative;
        transition: $transition-duration $transition-easing;
        min-width: auto;
        padding: 0;
        text-transform: none;
    
        &:hover {
            color: $button-primary-hover;
        }
    
        &:before {
            content: '';
            position: absolute;
            top: auto;
            left: auto;
            right: 0;
            bottom: -1px;
            width: 100%;
            border-bottom: 2px solid $button-primary-hover;
            transition: width $transition-duration $transition-easing-out $transition-duration, border-bottom $transition-duration $transition-easing-out;
        }
    
        &:hover:before {
            width: 0;
            transition: width $transition-duration $transition-easing-in, border-bottom $transition-duration $transition-easing-in;
        }
    
        &:after {
            content: '';
            position: absolute;
            left: 0;
            bottom: 0;
            width: 0;
            border-bottom: 2px solid $button-primary-hover;
            transition: width $transition-duration $transition-easing-in, border-bottom $transition-duration $transition-easing-in;
        }
    
        &:hover:after {
            width: 100%;
            transition: width $transition-duration $transition-easing-out $transition-duration, border-bottom $transition-duration $transition-easing-out;
        }
    }
    
    .button__filler {
        display: none;
        position: absolute;
        z-index: 2;
        width: 150%;
        height: 200%;
        border-radius: $border-radius-round;
        background-color: $color-ui-01;
        color: $color-text-01;
        top: -50%;
        left: -25%;
        transform: translate3d(0, 75%, 0);
        transition-property: transform;
        transition-duration: $transition-duration;
        transition-timing-function: $transition-easing-in;
        will-change: transform; /* stylelint-disable-line plugin/no-unsupported-browser-features */
    
        .button--magnetic & {
            html[data-whatintent='mouse'] & {
                display: block;
            }
        }
    
        .button--reverted & {
            background-color: $button-primary-background;
            color: $color-text-03;
        }
    }
    
  • URL: /components/raw/button/button.scss
  • Filesystem Path: src/patterns/components/button/button.scss
  • Size: 7.2 KB
  • Content:
    import Component from '../component/component';
    import Helpers from '../helpers/helpers';
    import Icon from '../icon/icon';
    
    import './button.scss';
    
    export interface IButton {
        text: string;
        icon?: string;
        link?: string;
        iconPosition?: string;
    }
    
    export interface ITransform {
        amt: number;
        current: number;
        previous: number;
    }
    
    export interface IStyles {
        tx: ITransform;
        ty: ITransform;
    }
    
    export default class Button extends Component {
        static initSelector: string = '.button--magnetic';
    
        public filler: JQuery;
        public renderedStyles: IStyles;
        public buttonRect: DOMRect;
        public distanceToTrigger: number;
    
        constructor(element: HTMLElement) {
            super(element);
    
            this.filler = this.element.find('.button__filler');
    
            this.buttonRect = this.element[0].getBoundingClientRect();
            this.distanceToTrigger = this.buttonRect.width * 0.7;
    
            this.renderedStyles = {
                tx: {amt: 0.1, current: 0, previous: 0},
                ty: {amt: 0.1, current: 0, previous: 0},
            };
    
            this.init();
        }
    
        static render(data: IButton, className?: string): JQuery {
            const element: string = data.link ? 'a' : 'button';
            const icon: string = data.icon ? Icon.render(data.icon, 'button__icon') : '';
            const classArray: string[] = ['button'];
    
            if (className) {
                classArray.push(className);
            }
    
            if (data.icon && !data.iconPosition) {
                classArray.push('button--icon');
            }
    
            if (data.icon && data.iconPosition === 'right') {
                classArray.push('button--icon-right');
            }
    
            if (data.icon && data.iconPosition === 'left') {
                classArray.push('button--icon-left');
            }
    
            return $(`<${element} class="${classArray.join(' ')}" ${data.link ? `href="${data.link}"` : 'type="button"'}><span class="button__filler"></span><span class="button__inner"><span class="button__icon-wrapper">${icon}</span><span class="button__text">${data.text}</span></span></${element}>`);
        }
    
        init(): void {
            if (!Helpers.isMobileDevice) {
                this.element.on('mouseenter', this.enter.bind(this));
                this.element.on('mouseleave', this.leave.bind(this));
    
                $(window).on('resize scroll', this.resizeHandler.bind(this));
    
                this.run();
            }
    
        }
    
        resizeHandler(): void {
            this.buttonRect = this.element[0].getBoundingClientRect();
            this.distanceToTrigger = this.buttonRect.width * 0.7;
        }
    
        distance(x1: number, y1: number, x2: number, y2: number): number {
            const a: number = x1 - x2;
            const b: number = y1 - y2;
    
            return Math.hypot(a,b);
        }
    
        lerp(a: number, b: number, n: number): number {
            return (1 - n) * a + n * b;
        }
    
        run(): void {
            // Linear interpolation
            const distanceMouseButton: number = this.distance(window.gotoAndPlay.mousePos.x, window.gotoAndPlay.mousePos.y, this.buttonRect.left + this.buttonRect.width / 2, window.scrollY + this.buttonRect.top + this.buttonRect.height / 2);
    
            // new values for the translations
            let x: number = 0;
            let y: number = 0;
    
            if (distanceMouseButton < this.distanceToTrigger) {
                x = (window.gotoAndPlay.mousePos.x - (this.buttonRect.left + this.buttonRect.width / 2)) * .3;
                y = (window.gotoAndPlay.mousePos.y - (window.scrollY + this.buttonRect.top + this.buttonRect.height / 2)) * .3;
            }
    
            this.renderedStyles.tx.current = parseFloat(x.toFixed(3));
            this.renderedStyles.ty.current = parseFloat(y.toFixed(3));
    
            for (const key in this.renderedStyles) {
                if (key) {
                    this.renderedStyles[key].previous = parseFloat(this.lerp(this.renderedStyles[key].previous, this.renderedStyles[key].current, this.renderedStyles[key].amt).toFixed(3));
                }
            }
    
            this.element[0].style.transform = `translate3d(${this.renderedStyles.tx.previous}px, ${this.renderedStyles.ty.previous}px, 0)`;
    
            requestAnimationFrame(() => this.run());
        }
    
        enter(): void {
            this.element.addClass('is-hover');
            this.filler[0].style.transitionDuration = `250ms`;
            this.filler[0].style.transform = `translate3d(0, 0, 0)`;
        }
    
        leave(): void {
            this.element.removeClass('is-hover');
            this.filler[0].style.transform = `translate3d(0, -75%, 0)`;
    
            setTimeout(() => {
                if (!this.element.hasClass('is-hover')) {
                    this.filler[0].style.transitionDuration = `0ms`;
                    this.filler[0].style.transform = `translate3d(0, 75%, 0)`;
                }
            }, 250);
        }
    }
    
  • URL: /components/raw/button/button.ts
  • Filesystem Path: src/patterns/components/button/button.ts
  • Size: 4.7 KB
  • Handle: @button--block-xs
  • Filesystem Path: src/patterns/components/button/button.twig
  • References (1): @icon

Button Arrow Rotate

e.g explore button with 45deg rotating arrow icon

<button type="button" class="button button--arrow-rotate button--icon-right">
    <span class="button__inner">
        <span class="button__icon-wrapper"><svg class="icon  button__icon">
                <use xlink:href="../../inc/svg/global.bc9cdd731ad718497c5d8f03d08908d4.svg#tiny-right-top-24"></use>
            </svg>
        </span> <span class="button__text">Button text</span>
    </span>
</button>
{% set element = data.link ? 'a' : 'button' %}
{% set icon = icon|default(data.icon|default(false)) %}
{% set iconPosition = iconPosition|default(data.iconPosition|default(false)) %}

{% set BEM -%}
    button
    {%- if modifier %} {{ modifier }}{% endif %}
    {%- if class %} {{ class }}{% endif %}
    {%- if icon %} button--icon{% if iconPosition %}{{ '-' ~ iconPosition }}{% endif %}{% endif %}
{% endset %}

<{{ element }}
    {% if data.link %} href="{{ data.link }}"{% else %} type="{{ type|default('button') }}" {% endif %}
    class="{{ BEM }}"
    {%- if data.attributes %} {{ data.attributes }}{% endif %}
>
    {% if 'button--magnetic' in modifier or 'button--magnetic' in class %}
        <span class="button__filler"></span>
    {% endif %}
    <span class="button__inner">
        {% if data.icon %}<span class="button__icon-wrapper">{% include '@icon' with { name: data.icon, modifier: '', class: 'button__icon' } %}</span>{% endif %}
        <span class="button__text">{{ data.text }}</span>
    </span>
</{{ element }}>
{
  "language": "en-US",
  "data": {
    "text": "Button text",
    "icon": "tiny-right-top-24",
    "iconPosition": "right"
  },
  "modifier": "button--arrow-rotate"
}
  • Content:
    $button-primary-background: $color-brand-01;
    $button-primary-hover: $color-text-03;
    $button-primary-active: $color-brand-01;
    
    .button {
        position: relative;
        border-radius: $border-radius-base;
        border: none;
        -webkit-appearance: none;
        text-align: center;
        cursor: pointer;
        min-width: 156px;
        display: inline-block;
        padding: 14px 32px;
        margin: 0;
        font-size: $font-size-small;
        font-weight: $font-weight-medium;
        line-height: 1.15;
        background-color: transparent;
        color: $button-primary-hover;
        text-decoration: none;
        text-transform: uppercase;
        transition-property: color;
        transition-duration: $transition-duration;
        transition-timing-function: $transition-easing-in;
        z-index: map-get($zindex, 'default');
        outline-offset: 2px;
        overflow: hidden;
    
        .text > * + & {
            margin-top: 1.5em;
        }
    
        &:before {
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            bottom: 0;
            right: 0;
            background-color: $button-primary-background;
            transition-property: background-color, transform;
            transition-duration: $transition-duration;
            transition-timing-function: $transition-easing-in;
            box-shadow: inset 0 0 0 2px $button-primary-background;
            transform: scale(1);
            border-radius: $border-radius-base;
            z-index: 4;
        }
    
        &.is-hover,
        &:hover {
            transition-timing-function: $transition-easing-out;
            color: $button-primary-background;
    
            &:before {
                transition-timing-function: $transition-easing-out;
                background-color: transparent;
            }
        }
    
        &:active {
            color: $button-primary-background;
    
            &:before {
                background-color: transparent;
                transform: scale(.96);
                transition: none;
            }
        }
    }
    
    .button--icon {
        min-width: 0;
        padding: 12px;
        border-radius: $border-radius-round;
    
        &:before {
            border-radius: $border-radius-round;
        }
    }
    
    .button--icon-left {
        padding-left: 56px;
    }
    
    .button--icon-right {
        padding-right: 56px;
    }
    
    .button--arrow-animate {
        padding-right: 48px;
    }
    
    .button--reverted {
        color: $button-primary-background;
    
        &:before {
            background-color: $button-primary-hover;
            box-shadow: inset 0 0 0 2px $button-primary-hover;
        }
    
        &.is-hover,
        &:hover {
            color: $button-primary-hover;
    
            &:before {
                background-color: $button-primary-background;
            }
        }
    
        &:active {
            color: $button-primary-hover;
        }
    }
    
    .button--magnetic {
        html[data-whatintent='mouse'] & {
            background-color: $button-primary-background;
        }
    
        &:before {
            html[data-whatintent='mouse'] & {
                background-color: transparent;
            }
        }
    
        &.is-hover,
        &:active,
        &:hover {
            &:before {
                html[data-whatintent='mouse'] & {
                    background-color: transparent;
                }
            }
        }
    
        &.button--reverted {
            html[data-whatintent='mouse'] & {
                background-color: $button-primary-hover;
            }
        }
    }
    
    .button--block {
        display: block;
        width: 100%;
    }
    
    .button--block-xs {
        @media only screen and (max-width: $bp-sm-min - 1) {
            display: block;
            width: 100%;
        }
    }
    
    .button__icon-wrapper {
        position: relative;
        z-index: 5;
    
        .button--icon & {
            display: block;
        }
    
        .button--icon-left &,
        .button--icon-right & {
            position: absolute;
            top: auto;
            bottom: auto;
            margin: auto;
            display: inline-block;
            flex: 0 0 24px;
        }
    
        .button--icon-left & {
            left: 32px;
        }
    
        .button--icon-right & {
            right: 32px;
        }
    
        .button--arrow-animate & {
            width: 16px;
            height: 24px;
            overflow: hidden;
            right: 32px;
            transition-property: width, right;
            transition-timing-function: $transition-easing-in;
            transition-duration: $transition-duration;
        }
    
        .button--arrow-animate.is-hover &,
        .button--arrow-animate:hover & {
            width: 24px;
            right: 24px;
            transition-timing-function: $transition-easing-out;
        }
    
        .button--arrow-rotate & {
            transition-property: transform;
            transition-duration: $transition-duration;
            transition-timing-function: $transition-easing-in;
            transform: rotate(0);
        }
    
        .button--arrow-rotate.is-hover &,
        .button--arrow-rotate:hover & {
            transition-timing-function: $transition-easing-out;
            transform: rotate(45deg);
        }
    }
    
    .button__icon {
        font-size: 24px;
        display: block;
    
        .button--arrow-animate & {
            float: right;
        }
    }
    
    .button__text {
        position: relative;
        z-index: 5;
    
        .button--icon & {
            @include visually-hidden();
        }
    
        .button--icon-left & {
            margin-left: 8px;
        }
    
        .button--icon-right & {
            margin-right: 8px;
        }
    }
    
    .button__inner {
        display: flex;
        align-items: center;
        justify-content: center;
    }
    
    .button--text {
        color: $button-primary-hover;
        position: relative;
        transition: $transition-duration $transition-easing;
        min-width: auto;
        padding: 0;
        text-transform: none;
    
        &:hover {
            color: $button-primary-hover;
        }
    
        &:before {
            content: '';
            position: absolute;
            top: auto;
            left: auto;
            right: 0;
            bottom: -1px;
            width: 100%;
            border-bottom: 2px solid $button-primary-hover;
            transition: width $transition-duration $transition-easing-out $transition-duration, border-bottom $transition-duration $transition-easing-out;
        }
    
        &:hover:before {
            width: 0;
            transition: width $transition-duration $transition-easing-in, border-bottom $transition-duration $transition-easing-in;
        }
    
        &:after {
            content: '';
            position: absolute;
            left: 0;
            bottom: 0;
            width: 0;
            border-bottom: 2px solid $button-primary-hover;
            transition: width $transition-duration $transition-easing-in, border-bottom $transition-duration $transition-easing-in;
        }
    
        &:hover:after {
            width: 100%;
            transition: width $transition-duration $transition-easing-out $transition-duration, border-bottom $transition-duration $transition-easing-out;
        }
    }
    
    .button__filler {
        display: none;
        position: absolute;
        z-index: 2;
        width: 150%;
        height: 200%;
        border-radius: $border-radius-round;
        background-color: $color-ui-01;
        color: $color-text-01;
        top: -50%;
        left: -25%;
        transform: translate3d(0, 75%, 0);
        transition-property: transform;
        transition-duration: $transition-duration;
        transition-timing-function: $transition-easing-in;
        will-change: transform; /* stylelint-disable-line plugin/no-unsupported-browser-features */
    
        .button--magnetic & {
            html[data-whatintent='mouse'] & {
                display: block;
            }
        }
    
        .button--reverted & {
            background-color: $button-primary-background;
            color: $color-text-03;
        }
    }
    
  • URL: /components/raw/button/button.scss
  • Filesystem Path: src/patterns/components/button/button.scss
  • Size: 7.2 KB
  • Content:
    import Component from '../component/component';
    import Helpers from '../helpers/helpers';
    import Icon from '../icon/icon';
    
    import './button.scss';
    
    export interface IButton {
        text: string;
        icon?: string;
        link?: string;
        iconPosition?: string;
    }
    
    export interface ITransform {
        amt: number;
        current: number;
        previous: number;
    }
    
    export interface IStyles {
        tx: ITransform;
        ty: ITransform;
    }
    
    export default class Button extends Component {
        static initSelector: string = '.button--magnetic';
    
        public filler: JQuery;
        public renderedStyles: IStyles;
        public buttonRect: DOMRect;
        public distanceToTrigger: number;
    
        constructor(element: HTMLElement) {
            super(element);
    
            this.filler = this.element.find('.button__filler');
    
            this.buttonRect = this.element[0].getBoundingClientRect();
            this.distanceToTrigger = this.buttonRect.width * 0.7;
    
            this.renderedStyles = {
                tx: {amt: 0.1, current: 0, previous: 0},
                ty: {amt: 0.1, current: 0, previous: 0},
            };
    
            this.init();
        }
    
        static render(data: IButton, className?: string): JQuery {
            const element: string = data.link ? 'a' : 'button';
            const icon: string = data.icon ? Icon.render(data.icon, 'button__icon') : '';
            const classArray: string[] = ['button'];
    
            if (className) {
                classArray.push(className);
            }
    
            if (data.icon && !data.iconPosition) {
                classArray.push('button--icon');
            }
    
            if (data.icon && data.iconPosition === 'right') {
                classArray.push('button--icon-right');
            }
    
            if (data.icon && data.iconPosition === 'left') {
                classArray.push('button--icon-left');
            }
    
            return $(`<${element} class="${classArray.join(' ')}" ${data.link ? `href="${data.link}"` : 'type="button"'}><span class="button__filler"></span><span class="button__inner"><span class="button__icon-wrapper">${icon}</span><span class="button__text">${data.text}</span></span></${element}>`);
        }
    
        init(): void {
            if (!Helpers.isMobileDevice) {
                this.element.on('mouseenter', this.enter.bind(this));
                this.element.on('mouseleave', this.leave.bind(this));
    
                $(window).on('resize scroll', this.resizeHandler.bind(this));
    
                this.run();
            }
    
        }
    
        resizeHandler(): void {
            this.buttonRect = this.element[0].getBoundingClientRect();
            this.distanceToTrigger = this.buttonRect.width * 0.7;
        }
    
        distance(x1: number, y1: number, x2: number, y2: number): number {
            const a: number = x1 - x2;
            const b: number = y1 - y2;
    
            return Math.hypot(a,b);
        }
    
        lerp(a: number, b: number, n: number): number {
            return (1 - n) * a + n * b;
        }
    
        run(): void {
            // Linear interpolation
            const distanceMouseButton: number = this.distance(window.gotoAndPlay.mousePos.x, window.gotoAndPlay.mousePos.y, this.buttonRect.left + this.buttonRect.width / 2, window.scrollY + this.buttonRect.top + this.buttonRect.height / 2);
    
            // new values for the translations
            let x: number = 0;
            let y: number = 0;
    
            if (distanceMouseButton < this.distanceToTrigger) {
                x = (window.gotoAndPlay.mousePos.x - (this.buttonRect.left + this.buttonRect.width / 2)) * .3;
                y = (window.gotoAndPlay.mousePos.y - (window.scrollY + this.buttonRect.top + this.buttonRect.height / 2)) * .3;
            }
    
            this.renderedStyles.tx.current = parseFloat(x.toFixed(3));
            this.renderedStyles.ty.current = parseFloat(y.toFixed(3));
    
            for (const key in this.renderedStyles) {
                if (key) {
                    this.renderedStyles[key].previous = parseFloat(this.lerp(this.renderedStyles[key].previous, this.renderedStyles[key].current, this.renderedStyles[key].amt).toFixed(3));
                }
            }
    
            this.element[0].style.transform = `translate3d(${this.renderedStyles.tx.previous}px, ${this.renderedStyles.ty.previous}px, 0)`;
    
            requestAnimationFrame(() => this.run());
        }
    
        enter(): void {
            this.element.addClass('is-hover');
            this.filler[0].style.transitionDuration = `250ms`;
            this.filler[0].style.transform = `translate3d(0, 0, 0)`;
        }
    
        leave(): void {
            this.element.removeClass('is-hover');
            this.filler[0].style.transform = `translate3d(0, -75%, 0)`;
    
            setTimeout(() => {
                if (!this.element.hasClass('is-hover')) {
                    this.filler[0].style.transitionDuration = `0ms`;
                    this.filler[0].style.transform = `translate3d(0, 75%, 0)`;
                }
            }, 250);
        }
    }
    
  • URL: /components/raw/button/button.ts
  • Filesystem Path: src/patterns/components/button/button.ts
  • Size: 4.7 KB
  • Handle: @button--button-arrow-rotate
  • Filesystem Path: src/patterns/components/button/button.twig
  • References (1): @icon

Text

<button type="button" class="button button--text">
    <span class="button__inner">
        <span class="button__text">Button text</span>
    </span>
</button>
{% set element = data.link ? 'a' : 'button' %}
{% set icon = icon|default(data.icon|default(false)) %}
{% set iconPosition = iconPosition|default(data.iconPosition|default(false)) %}

{% set BEM -%}
    button
    {%- if modifier %} {{ modifier }}{% endif %}
    {%- if class %} {{ class }}{% endif %}
    {%- if icon %} button--icon{% if iconPosition %}{{ '-' ~ iconPosition }}{% endif %}{% endif %}
{% endset %}

<{{ element }}
    {% if data.link %} href="{{ data.link }}"{% else %} type="{{ type|default('button') }}" {% endif %}
    class="{{ BEM }}"
    {%- if data.attributes %} {{ data.attributes }}{% endif %}
>
    {% if 'button--magnetic' in modifier or 'button--magnetic' in class %}
        <span class="button__filler"></span>
    {% endif %}
    <span class="button__inner">
        {% if data.icon %}<span class="button__icon-wrapper">{% include '@icon' with { name: data.icon, modifier: '', class: 'button__icon' } %}</span>{% endif %}
        <span class="button__text">{{ data.text }}</span>
    </span>
</{{ element }}>
{
  "language": "en-US",
  "data": {
    "text": "Button text"
  },
  "modifier": "button--text"
}
  • Content:
    $button-primary-background: $color-brand-01;
    $button-primary-hover: $color-text-03;
    $button-primary-active: $color-brand-01;
    
    .button {
        position: relative;
        border-radius: $border-radius-base;
        border: none;
        -webkit-appearance: none;
        text-align: center;
        cursor: pointer;
        min-width: 156px;
        display: inline-block;
        padding: 14px 32px;
        margin: 0;
        font-size: $font-size-small;
        font-weight: $font-weight-medium;
        line-height: 1.15;
        background-color: transparent;
        color: $button-primary-hover;
        text-decoration: none;
        text-transform: uppercase;
        transition-property: color;
        transition-duration: $transition-duration;
        transition-timing-function: $transition-easing-in;
        z-index: map-get($zindex, 'default');
        outline-offset: 2px;
        overflow: hidden;
    
        .text > * + & {
            margin-top: 1.5em;
        }
    
        &:before {
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            bottom: 0;
            right: 0;
            background-color: $button-primary-background;
            transition-property: background-color, transform;
            transition-duration: $transition-duration;
            transition-timing-function: $transition-easing-in;
            box-shadow: inset 0 0 0 2px $button-primary-background;
            transform: scale(1);
            border-radius: $border-radius-base;
            z-index: 4;
        }
    
        &.is-hover,
        &:hover {
            transition-timing-function: $transition-easing-out;
            color: $button-primary-background;
    
            &:before {
                transition-timing-function: $transition-easing-out;
                background-color: transparent;
            }
        }
    
        &:active {
            color: $button-primary-background;
    
            &:before {
                background-color: transparent;
                transform: scale(.96);
                transition: none;
            }
        }
    }
    
    .button--icon {
        min-width: 0;
        padding: 12px;
        border-radius: $border-radius-round;
    
        &:before {
            border-radius: $border-radius-round;
        }
    }
    
    .button--icon-left {
        padding-left: 56px;
    }
    
    .button--icon-right {
        padding-right: 56px;
    }
    
    .button--arrow-animate {
        padding-right: 48px;
    }
    
    .button--reverted {
        color: $button-primary-background;
    
        &:before {
            background-color: $button-primary-hover;
            box-shadow: inset 0 0 0 2px $button-primary-hover;
        }
    
        &.is-hover,
        &:hover {
            color: $button-primary-hover;
    
            &:before {
                background-color: $button-primary-background;
            }
        }
    
        &:active {
            color: $button-primary-hover;
        }
    }
    
    .button--magnetic {
        html[data-whatintent='mouse'] & {
            background-color: $button-primary-background;
        }
    
        &:before {
            html[data-whatintent='mouse'] & {
                background-color: transparent;
            }
        }
    
        &.is-hover,
        &:active,
        &:hover {
            &:before {
                html[data-whatintent='mouse'] & {
                    background-color: transparent;
                }
            }
        }
    
        &.button--reverted {
            html[data-whatintent='mouse'] & {
                background-color: $button-primary-hover;
            }
        }
    }
    
    .button--block {
        display: block;
        width: 100%;
    }
    
    .button--block-xs {
        @media only screen and (max-width: $bp-sm-min - 1) {
            display: block;
            width: 100%;
        }
    }
    
    .button__icon-wrapper {
        position: relative;
        z-index: 5;
    
        .button--icon & {
            display: block;
        }
    
        .button--icon-left &,
        .button--icon-right & {
            position: absolute;
            top: auto;
            bottom: auto;
            margin: auto;
            display: inline-block;
            flex: 0 0 24px;
        }
    
        .button--icon-left & {
            left: 32px;
        }
    
        .button--icon-right & {
            right: 32px;
        }
    
        .button--arrow-animate & {
            width: 16px;
            height: 24px;
            overflow: hidden;
            right: 32px;
            transition-property: width, right;
            transition-timing-function: $transition-easing-in;
            transition-duration: $transition-duration;
        }
    
        .button--arrow-animate.is-hover &,
        .button--arrow-animate:hover & {
            width: 24px;
            right: 24px;
            transition-timing-function: $transition-easing-out;
        }
    
        .button--arrow-rotate & {
            transition-property: transform;
            transition-duration: $transition-duration;
            transition-timing-function: $transition-easing-in;
            transform: rotate(0);
        }
    
        .button--arrow-rotate.is-hover &,
        .button--arrow-rotate:hover & {
            transition-timing-function: $transition-easing-out;
            transform: rotate(45deg);
        }
    }
    
    .button__icon {
        font-size: 24px;
        display: block;
    
        .button--arrow-animate & {
            float: right;
        }
    }
    
    .button__text {
        position: relative;
        z-index: 5;
    
        .button--icon & {
            @include visually-hidden();
        }
    
        .button--icon-left & {
            margin-left: 8px;
        }
    
        .button--icon-right & {
            margin-right: 8px;
        }
    }
    
    .button__inner {
        display: flex;
        align-items: center;
        justify-content: center;
    }
    
    .button--text {
        color: $button-primary-hover;
        position: relative;
        transition: $transition-duration $transition-easing;
        min-width: auto;
        padding: 0;
        text-transform: none;
    
        &:hover {
            color: $button-primary-hover;
        }
    
        &:before {
            content: '';
            position: absolute;
            top: auto;
            left: auto;
            right: 0;
            bottom: -1px;
            width: 100%;
            border-bottom: 2px solid $button-primary-hover;
            transition: width $transition-duration $transition-easing-out $transition-duration, border-bottom $transition-duration $transition-easing-out;
        }
    
        &:hover:before {
            width: 0;
            transition: width $transition-duration $transition-easing-in, border-bottom $transition-duration $transition-easing-in;
        }
    
        &:after {
            content: '';
            position: absolute;
            left: 0;
            bottom: 0;
            width: 0;
            border-bottom: 2px solid $button-primary-hover;
            transition: width $transition-duration $transition-easing-in, border-bottom $transition-duration $transition-easing-in;
        }
    
        &:hover:after {
            width: 100%;
            transition: width $transition-duration $transition-easing-out $transition-duration, border-bottom $transition-duration $transition-easing-out;
        }
    }
    
    .button__filler {
        display: none;
        position: absolute;
        z-index: 2;
        width: 150%;
        height: 200%;
        border-radius: $border-radius-round;
        background-color: $color-ui-01;
        color: $color-text-01;
        top: -50%;
        left: -25%;
        transform: translate3d(0, 75%, 0);
        transition-property: transform;
        transition-duration: $transition-duration;
        transition-timing-function: $transition-easing-in;
        will-change: transform; /* stylelint-disable-line plugin/no-unsupported-browser-features */
    
        .button--magnetic & {
            html[data-whatintent='mouse'] & {
                display: block;
            }
        }
    
        .button--reverted & {
            background-color: $button-primary-background;
            color: $color-text-03;
        }
    }
    
  • URL: /components/raw/button/button.scss
  • Filesystem Path: src/patterns/components/button/button.scss
  • Size: 7.2 KB
  • Content:
    import Component from '../component/component';
    import Helpers from '../helpers/helpers';
    import Icon from '../icon/icon';
    
    import './button.scss';
    
    export interface IButton {
        text: string;
        icon?: string;
        link?: string;
        iconPosition?: string;
    }
    
    export interface ITransform {
        amt: number;
        current: number;
        previous: number;
    }
    
    export interface IStyles {
        tx: ITransform;
        ty: ITransform;
    }
    
    export default class Button extends Component {
        static initSelector: string = '.button--magnetic';
    
        public filler: JQuery;
        public renderedStyles: IStyles;
        public buttonRect: DOMRect;
        public distanceToTrigger: number;
    
        constructor(element: HTMLElement) {
            super(element);
    
            this.filler = this.element.find('.button__filler');
    
            this.buttonRect = this.element[0].getBoundingClientRect();
            this.distanceToTrigger = this.buttonRect.width * 0.7;
    
            this.renderedStyles = {
                tx: {amt: 0.1, current: 0, previous: 0},
                ty: {amt: 0.1, current: 0, previous: 0},
            };
    
            this.init();
        }
    
        static render(data: IButton, className?: string): JQuery {
            const element: string = data.link ? 'a' : 'button';
            const icon: string = data.icon ? Icon.render(data.icon, 'button__icon') : '';
            const classArray: string[] = ['button'];
    
            if (className) {
                classArray.push(className);
            }
    
            if (data.icon && !data.iconPosition) {
                classArray.push('button--icon');
            }
    
            if (data.icon && data.iconPosition === 'right') {
                classArray.push('button--icon-right');
            }
    
            if (data.icon && data.iconPosition === 'left') {
                classArray.push('button--icon-left');
            }
    
            return $(`<${element} class="${classArray.join(' ')}" ${data.link ? `href="${data.link}"` : 'type="button"'}><span class="button__filler"></span><span class="button__inner"><span class="button__icon-wrapper">${icon}</span><span class="button__text">${data.text}</span></span></${element}>`);
        }
    
        init(): void {
            if (!Helpers.isMobileDevice) {
                this.element.on('mouseenter', this.enter.bind(this));
                this.element.on('mouseleave', this.leave.bind(this));
    
                $(window).on('resize scroll', this.resizeHandler.bind(this));
    
                this.run();
            }
    
        }
    
        resizeHandler(): void {
            this.buttonRect = this.element[0].getBoundingClientRect();
            this.distanceToTrigger = this.buttonRect.width * 0.7;
        }
    
        distance(x1: number, y1: number, x2: number, y2: number): number {
            const a: number = x1 - x2;
            const b: number = y1 - y2;
    
            return Math.hypot(a,b);
        }
    
        lerp(a: number, b: number, n: number): number {
            return (1 - n) * a + n * b;
        }
    
        run(): void {
            // Linear interpolation
            const distanceMouseButton: number = this.distance(window.gotoAndPlay.mousePos.x, window.gotoAndPlay.mousePos.y, this.buttonRect.left + this.buttonRect.width / 2, window.scrollY + this.buttonRect.top + this.buttonRect.height / 2);
    
            // new values for the translations
            let x: number = 0;
            let y: number = 0;
    
            if (distanceMouseButton < this.distanceToTrigger) {
                x = (window.gotoAndPlay.mousePos.x - (this.buttonRect.left + this.buttonRect.width / 2)) * .3;
                y = (window.gotoAndPlay.mousePos.y - (window.scrollY + this.buttonRect.top + this.buttonRect.height / 2)) * .3;
            }
    
            this.renderedStyles.tx.current = parseFloat(x.toFixed(3));
            this.renderedStyles.ty.current = parseFloat(y.toFixed(3));
    
            for (const key in this.renderedStyles) {
                if (key) {
                    this.renderedStyles[key].previous = parseFloat(this.lerp(this.renderedStyles[key].previous, this.renderedStyles[key].current, this.renderedStyles[key].amt).toFixed(3));
                }
            }
    
            this.element[0].style.transform = `translate3d(${this.renderedStyles.tx.previous}px, ${this.renderedStyles.ty.previous}px, 0)`;
    
            requestAnimationFrame(() => this.run());
        }
    
        enter(): void {
            this.element.addClass('is-hover');
            this.filler[0].style.transitionDuration = `250ms`;
            this.filler[0].style.transform = `translate3d(0, 0, 0)`;
        }
    
        leave(): void {
            this.element.removeClass('is-hover');
            this.filler[0].style.transform = `translate3d(0, -75%, 0)`;
    
            setTimeout(() => {
                if (!this.element.hasClass('is-hover')) {
                    this.filler[0].style.transitionDuration = `0ms`;
                    this.filler[0].style.transform = `translate3d(0, 75%, 0)`;
                }
            }, 250);
        }
    }
    
  • URL: /components/raw/button/button.ts
  • Filesystem Path: src/patterns/components/button/button.ts
  • Size: 4.7 KB
  • Handle: @button--text
  • Filesystem Path: src/patterns/components/button/button.twig
  • References (1): @icon

Reverted

<button type="button" class="button button--reverted">
    <span class="button__inner">
        <span class="button__text">Button text</span>
    </span>
</button>
{% set element = data.link ? 'a' : 'button' %}
{% set icon = icon|default(data.icon|default(false)) %}
{% set iconPosition = iconPosition|default(data.iconPosition|default(false)) %}

{% set BEM -%}
    button
    {%- if modifier %} {{ modifier }}{% endif %}
    {%- if class %} {{ class }}{% endif %}
    {%- if icon %} button--icon{% if iconPosition %}{{ '-' ~ iconPosition }}{% endif %}{% endif %}
{% endset %}

<{{ element }}
    {% if data.link %} href="{{ data.link }}"{% else %} type="{{ type|default('button') }}" {% endif %}
    class="{{ BEM }}"
    {%- if data.attributes %} {{ data.attributes }}{% endif %}
>
    {% if 'button--magnetic' in modifier or 'button--magnetic' in class %}
        <span class="button__filler"></span>
    {% endif %}
    <span class="button__inner">
        {% if data.icon %}<span class="button__icon-wrapper">{% include '@icon' with { name: data.icon, modifier: '', class: 'button__icon' } %}</span>{% endif %}
        <span class="button__text">{{ data.text }}</span>
    </span>
</{{ element }}>
{
  "language": "en-US",
  "data": {
    "text": "Button text"
  },
  "modifier": "button--reverted"
}
  • Content:
    $button-primary-background: $color-brand-01;
    $button-primary-hover: $color-text-03;
    $button-primary-active: $color-brand-01;
    
    .button {
        position: relative;
        border-radius: $border-radius-base;
        border: none;
        -webkit-appearance: none;
        text-align: center;
        cursor: pointer;
        min-width: 156px;
        display: inline-block;
        padding: 14px 32px;
        margin: 0;
        font-size: $font-size-small;
        font-weight: $font-weight-medium;
        line-height: 1.15;
        background-color: transparent;
        color: $button-primary-hover;
        text-decoration: none;
        text-transform: uppercase;
        transition-property: color;
        transition-duration: $transition-duration;
        transition-timing-function: $transition-easing-in;
        z-index: map-get($zindex, 'default');
        outline-offset: 2px;
        overflow: hidden;
    
        .text > * + & {
            margin-top: 1.5em;
        }
    
        &:before {
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            bottom: 0;
            right: 0;
            background-color: $button-primary-background;
            transition-property: background-color, transform;
            transition-duration: $transition-duration;
            transition-timing-function: $transition-easing-in;
            box-shadow: inset 0 0 0 2px $button-primary-background;
            transform: scale(1);
            border-radius: $border-radius-base;
            z-index: 4;
        }
    
        &.is-hover,
        &:hover {
            transition-timing-function: $transition-easing-out;
            color: $button-primary-background;
    
            &:before {
                transition-timing-function: $transition-easing-out;
                background-color: transparent;
            }
        }
    
        &:active {
            color: $button-primary-background;
    
            &:before {
                background-color: transparent;
                transform: scale(.96);
                transition: none;
            }
        }
    }
    
    .button--icon {
        min-width: 0;
        padding: 12px;
        border-radius: $border-radius-round;
    
        &:before {
            border-radius: $border-radius-round;
        }
    }
    
    .button--icon-left {
        padding-left: 56px;
    }
    
    .button--icon-right {
        padding-right: 56px;
    }
    
    .button--arrow-animate {
        padding-right: 48px;
    }
    
    .button--reverted {
        color: $button-primary-background;
    
        &:before {
            background-color: $button-primary-hover;
            box-shadow: inset 0 0 0 2px $button-primary-hover;
        }
    
        &.is-hover,
        &:hover {
            color: $button-primary-hover;
    
            &:before {
                background-color: $button-primary-background;
            }
        }
    
        &:active {
            color: $button-primary-hover;
        }
    }
    
    .button--magnetic {
        html[data-whatintent='mouse'] & {
            background-color: $button-primary-background;
        }
    
        &:before {
            html[data-whatintent='mouse'] & {
                background-color: transparent;
            }
        }
    
        &.is-hover,
        &:active,
        &:hover {
            &:before {
                html[data-whatintent='mouse'] & {
                    background-color: transparent;
                }
            }
        }
    
        &.button--reverted {
            html[data-whatintent='mouse'] & {
                background-color: $button-primary-hover;
            }
        }
    }
    
    .button--block {
        display: block;
        width: 100%;
    }
    
    .button--block-xs {
        @media only screen and (max-width: $bp-sm-min - 1) {
            display: block;
            width: 100%;
        }
    }
    
    .button__icon-wrapper {
        position: relative;
        z-index: 5;
    
        .button--icon & {
            display: block;
        }
    
        .button--icon-left &,
        .button--icon-right & {
            position: absolute;
            top: auto;
            bottom: auto;
            margin: auto;
            display: inline-block;
            flex: 0 0 24px;
        }
    
        .button--icon-left & {
            left: 32px;
        }
    
        .button--icon-right & {
            right: 32px;
        }
    
        .button--arrow-animate & {
            width: 16px;
            height: 24px;
            overflow: hidden;
            right: 32px;
            transition-property: width, right;
            transition-timing-function: $transition-easing-in;
            transition-duration: $transition-duration;
        }
    
        .button--arrow-animate.is-hover &,
        .button--arrow-animate:hover & {
            width: 24px;
            right: 24px;
            transition-timing-function: $transition-easing-out;
        }
    
        .button--arrow-rotate & {
            transition-property: transform;
            transition-duration: $transition-duration;
            transition-timing-function: $transition-easing-in;
            transform: rotate(0);
        }
    
        .button--arrow-rotate.is-hover &,
        .button--arrow-rotate:hover & {
            transition-timing-function: $transition-easing-out;
            transform: rotate(45deg);
        }
    }
    
    .button__icon {
        font-size: 24px;
        display: block;
    
        .button--arrow-animate & {
            float: right;
        }
    }
    
    .button__text {
        position: relative;
        z-index: 5;
    
        .button--icon & {
            @include visually-hidden();
        }
    
        .button--icon-left & {
            margin-left: 8px;
        }
    
        .button--icon-right & {
            margin-right: 8px;
        }
    }
    
    .button__inner {
        display: flex;
        align-items: center;
        justify-content: center;
    }
    
    .button--text {
        color: $button-primary-hover;
        position: relative;
        transition: $transition-duration $transition-easing;
        min-width: auto;
        padding: 0;
        text-transform: none;
    
        &:hover {
            color: $button-primary-hover;
        }
    
        &:before {
            content: '';
            position: absolute;
            top: auto;
            left: auto;
            right: 0;
            bottom: -1px;
            width: 100%;
            border-bottom: 2px solid $button-primary-hover;
            transition: width $transition-duration $transition-easing-out $transition-duration, border-bottom $transition-duration $transition-easing-out;
        }
    
        &:hover:before {
            width: 0;
            transition: width $transition-duration $transition-easing-in, border-bottom $transition-duration $transition-easing-in;
        }
    
        &:after {
            content: '';
            position: absolute;
            left: 0;
            bottom: 0;
            width: 0;
            border-bottom: 2px solid $button-primary-hover;
            transition: width $transition-duration $transition-easing-in, border-bottom $transition-duration $transition-easing-in;
        }
    
        &:hover:after {
            width: 100%;
            transition: width $transition-duration $transition-easing-out $transition-duration, border-bottom $transition-duration $transition-easing-out;
        }
    }
    
    .button__filler {
        display: none;
        position: absolute;
        z-index: 2;
        width: 150%;
        height: 200%;
        border-radius: $border-radius-round;
        background-color: $color-ui-01;
        color: $color-text-01;
        top: -50%;
        left: -25%;
        transform: translate3d(0, 75%, 0);
        transition-property: transform;
        transition-duration: $transition-duration;
        transition-timing-function: $transition-easing-in;
        will-change: transform; /* stylelint-disable-line plugin/no-unsupported-browser-features */
    
        .button--magnetic & {
            html[data-whatintent='mouse'] & {
                display: block;
            }
        }
    
        .button--reverted & {
            background-color: $button-primary-background;
            color: $color-text-03;
        }
    }
    
  • URL: /components/raw/button/button.scss
  • Filesystem Path: src/patterns/components/button/button.scss
  • Size: 7.2 KB
  • Content:
    import Component from '../component/component';
    import Helpers from '../helpers/helpers';
    import Icon from '../icon/icon';
    
    import './button.scss';
    
    export interface IButton {
        text: string;
        icon?: string;
        link?: string;
        iconPosition?: string;
    }
    
    export interface ITransform {
        amt: number;
        current: number;
        previous: number;
    }
    
    export interface IStyles {
        tx: ITransform;
        ty: ITransform;
    }
    
    export default class Button extends Component {
        static initSelector: string = '.button--magnetic';
    
        public filler: JQuery;
        public renderedStyles: IStyles;
        public buttonRect: DOMRect;
        public distanceToTrigger: number;
    
        constructor(element: HTMLElement) {
            super(element);
    
            this.filler = this.element.find('.button__filler');
    
            this.buttonRect = this.element[0].getBoundingClientRect();
            this.distanceToTrigger = this.buttonRect.width * 0.7;
    
            this.renderedStyles = {
                tx: {amt: 0.1, current: 0, previous: 0},
                ty: {amt: 0.1, current: 0, previous: 0},
            };
    
            this.init();
        }
    
        static render(data: IButton, className?: string): JQuery {
            const element: string = data.link ? 'a' : 'button';
            const icon: string = data.icon ? Icon.render(data.icon, 'button__icon') : '';
            const classArray: string[] = ['button'];
    
            if (className) {
                classArray.push(className);
            }
    
            if (data.icon && !data.iconPosition) {
                classArray.push('button--icon');
            }
    
            if (data.icon && data.iconPosition === 'right') {
                classArray.push('button--icon-right');
            }
    
            if (data.icon && data.iconPosition === 'left') {
                classArray.push('button--icon-left');
            }
    
            return $(`<${element} class="${classArray.join(' ')}" ${data.link ? `href="${data.link}"` : 'type="button"'}><span class="button__filler"></span><span class="button__inner"><span class="button__icon-wrapper">${icon}</span><span class="button__text">${data.text}</span></span></${element}>`);
        }
    
        init(): void {
            if (!Helpers.isMobileDevice) {
                this.element.on('mouseenter', this.enter.bind(this));
                this.element.on('mouseleave', this.leave.bind(this));
    
                $(window).on('resize scroll', this.resizeHandler.bind(this));
    
                this.run();
            }
    
        }
    
        resizeHandler(): void {
            this.buttonRect = this.element[0].getBoundingClientRect();
            this.distanceToTrigger = this.buttonRect.width * 0.7;
        }
    
        distance(x1: number, y1: number, x2: number, y2: number): number {
            const a: number = x1 - x2;
            const b: number = y1 - y2;
    
            return Math.hypot(a,b);
        }
    
        lerp(a: number, b: number, n: number): number {
            return (1 - n) * a + n * b;
        }
    
        run(): void {
            // Linear interpolation
            const distanceMouseButton: number = this.distance(window.gotoAndPlay.mousePos.x, window.gotoAndPlay.mousePos.y, this.buttonRect.left + this.buttonRect.width / 2, window.scrollY + this.buttonRect.top + this.buttonRect.height / 2);
    
            // new values for the translations
            let x: number = 0;
            let y: number = 0;
    
            if (distanceMouseButton < this.distanceToTrigger) {
                x = (window.gotoAndPlay.mousePos.x - (this.buttonRect.left + this.buttonRect.width / 2)) * .3;
                y = (window.gotoAndPlay.mousePos.y - (window.scrollY + this.buttonRect.top + this.buttonRect.height / 2)) * .3;
            }
    
            this.renderedStyles.tx.current = parseFloat(x.toFixed(3));
            this.renderedStyles.ty.current = parseFloat(y.toFixed(3));
    
            for (const key in this.renderedStyles) {
                if (key) {
                    this.renderedStyles[key].previous = parseFloat(this.lerp(this.renderedStyles[key].previous, this.renderedStyles[key].current, this.renderedStyles[key].amt).toFixed(3));
                }
            }
    
            this.element[0].style.transform = `translate3d(${this.renderedStyles.tx.previous}px, ${this.renderedStyles.ty.previous}px, 0)`;
    
            requestAnimationFrame(() => this.run());
        }
    
        enter(): void {
            this.element.addClass('is-hover');
            this.filler[0].style.transitionDuration = `250ms`;
            this.filler[0].style.transform = `translate3d(0, 0, 0)`;
        }
    
        leave(): void {
            this.element.removeClass('is-hover');
            this.filler[0].style.transform = `translate3d(0, -75%, 0)`;
    
            setTimeout(() => {
                if (!this.element.hasClass('is-hover')) {
                    this.filler[0].style.transitionDuration = `0ms`;
                    this.filler[0].style.transform = `translate3d(0, 75%, 0)`;
                }
            }, 250);
        }
    }
    
  • URL: /components/raw/button/button.ts
  • Filesystem Path: src/patterns/components/button/button.ts
  • Size: 4.7 KB
  • Handle: @button--reverted
  • Filesystem Path: src/patterns/components/button/button.twig
  • References (1): @icon

Magnetic

<button type="button" class="button button--magnetic">
    <span class="button__filler"></span>
    <span class="button__inner">
        <span class="button__text">Button text</span>
    </span>
</button>
{% set element = data.link ? 'a' : 'button' %}
{% set icon = icon|default(data.icon|default(false)) %}
{% set iconPosition = iconPosition|default(data.iconPosition|default(false)) %}

{% set BEM -%}
    button
    {%- if modifier %} {{ modifier }}{% endif %}
    {%- if class %} {{ class }}{% endif %}
    {%- if icon %} button--icon{% if iconPosition %}{{ '-' ~ iconPosition }}{% endif %}{% endif %}
{% endset %}

<{{ element }}
    {% if data.link %} href="{{ data.link }}"{% else %} type="{{ type|default('button') }}" {% endif %}
    class="{{ BEM }}"
    {%- if data.attributes %} {{ data.attributes }}{% endif %}
>
    {% if 'button--magnetic' in modifier or 'button--magnetic' in class %}
        <span class="button__filler"></span>
    {% endif %}
    <span class="button__inner">
        {% if data.icon %}<span class="button__icon-wrapper">{% include '@icon' with { name: data.icon, modifier: '', class: 'button__icon' } %}</span>{% endif %}
        <span class="button__text">{{ data.text }}</span>
    </span>
</{{ element }}>
{
  "language": "en-US",
  "data": {
    "text": "Button text"
  },
  "modifier": "button--magnetic"
}
  • Content:
    $button-primary-background: $color-brand-01;
    $button-primary-hover: $color-text-03;
    $button-primary-active: $color-brand-01;
    
    .button {
        position: relative;
        border-radius: $border-radius-base;
        border: none;
        -webkit-appearance: none;
        text-align: center;
        cursor: pointer;
        min-width: 156px;
        display: inline-block;
        padding: 14px 32px;
        margin: 0;
        font-size: $font-size-small;
        font-weight: $font-weight-medium;
        line-height: 1.15;
        background-color: transparent;
        color: $button-primary-hover;
        text-decoration: none;
        text-transform: uppercase;
        transition-property: color;
        transition-duration: $transition-duration;
        transition-timing-function: $transition-easing-in;
        z-index: map-get($zindex, 'default');
        outline-offset: 2px;
        overflow: hidden;
    
        .text > * + & {
            margin-top: 1.5em;
        }
    
        &:before {
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            bottom: 0;
            right: 0;
            background-color: $button-primary-background;
            transition-property: background-color, transform;
            transition-duration: $transition-duration;
            transition-timing-function: $transition-easing-in;
            box-shadow: inset 0 0 0 2px $button-primary-background;
            transform: scale(1);
            border-radius: $border-radius-base;
            z-index: 4;
        }
    
        &.is-hover,
        &:hover {
            transition-timing-function: $transition-easing-out;
            color: $button-primary-background;
    
            &:before {
                transition-timing-function: $transition-easing-out;
                background-color: transparent;
            }
        }
    
        &:active {
            color: $button-primary-background;
    
            &:before {
                background-color: transparent;
                transform: scale(.96);
                transition: none;
            }
        }
    }
    
    .button--icon {
        min-width: 0;
        padding: 12px;
        border-radius: $border-radius-round;
    
        &:before {
            border-radius: $border-radius-round;
        }
    }
    
    .button--icon-left {
        padding-left: 56px;
    }
    
    .button--icon-right {
        padding-right: 56px;
    }
    
    .button--arrow-animate {
        padding-right: 48px;
    }
    
    .button--reverted {
        color: $button-primary-background;
    
        &:before {
            background-color: $button-primary-hover;
            box-shadow: inset 0 0 0 2px $button-primary-hover;
        }
    
        &.is-hover,
        &:hover {
            color: $button-primary-hover;
    
            &:before {
                background-color: $button-primary-background;
            }
        }
    
        &:active {
            color: $button-primary-hover;
        }
    }
    
    .button--magnetic {
        html[data-whatintent='mouse'] & {
            background-color: $button-primary-background;
        }
    
        &:before {
            html[data-whatintent='mouse'] & {
                background-color: transparent;
            }
        }
    
        &.is-hover,
        &:active,
        &:hover {
            &:before {
                html[data-whatintent='mouse'] & {
                    background-color: transparent;
                }
            }
        }
    
        &.button--reverted {
            html[data-whatintent='mouse'] & {
                background-color: $button-primary-hover;
            }
        }
    }
    
    .button--block {
        display: block;
        width: 100%;
    }
    
    .button--block-xs {
        @media only screen and (max-width: $bp-sm-min - 1) {
            display: block;
            width: 100%;
        }
    }
    
    .button__icon-wrapper {
        position: relative;
        z-index: 5;
    
        .button--icon & {
            display: block;
        }
    
        .button--icon-left &,
        .button--icon-right & {
            position: absolute;
            top: auto;
            bottom: auto;
            margin: auto;
            display: inline-block;
            flex: 0 0 24px;
        }
    
        .button--icon-left & {
            left: 32px;
        }
    
        .button--icon-right & {
            right: 32px;
        }
    
        .button--arrow-animate & {
            width: 16px;
            height: 24px;
            overflow: hidden;
            right: 32px;
            transition-property: width, right;
            transition-timing-function: $transition-easing-in;
            transition-duration: $transition-duration;
        }
    
        .button--arrow-animate.is-hover &,
        .button--arrow-animate:hover & {
            width: 24px;
            right: 24px;
            transition-timing-function: $transition-easing-out;
        }
    
        .button--arrow-rotate & {
            transition-property: transform;
            transition-duration: $transition-duration;
            transition-timing-function: $transition-easing-in;
            transform: rotate(0);
        }
    
        .button--arrow-rotate.is-hover &,
        .button--arrow-rotate:hover & {
            transition-timing-function: $transition-easing-out;
            transform: rotate(45deg);
        }
    }
    
    .button__icon {
        font-size: 24px;
        display: block;
    
        .button--arrow-animate & {
            float: right;
        }
    }
    
    .button__text {
        position: relative;
        z-index: 5;
    
        .button--icon & {
            @include visually-hidden();
        }
    
        .button--icon-left & {
            margin-left: 8px;
        }
    
        .button--icon-right & {
            margin-right: 8px;
        }
    }
    
    .button__inner {
        display: flex;
        align-items: center;
        justify-content: center;
    }
    
    .button--text {
        color: $button-primary-hover;
        position: relative;
        transition: $transition-duration $transition-easing;
        min-width: auto;
        padding: 0;
        text-transform: none;
    
        &:hover {
            color: $button-primary-hover;
        }
    
        &:before {
            content: '';
            position: absolute;
            top: auto;
            left: auto;
            right: 0;
            bottom: -1px;
            width: 100%;
            border-bottom: 2px solid $button-primary-hover;
            transition: width $transition-duration $transition-easing-out $transition-duration, border-bottom $transition-duration $transition-easing-out;
        }
    
        &:hover:before {
            width: 0;
            transition: width $transition-duration $transition-easing-in, border-bottom $transition-duration $transition-easing-in;
        }
    
        &:after {
            content: '';
            position: absolute;
            left: 0;
            bottom: 0;
            width: 0;
            border-bottom: 2px solid $button-primary-hover;
            transition: width $transition-duration $transition-easing-in, border-bottom $transition-duration $transition-easing-in;
        }
    
        &:hover:after {
            width: 100%;
            transition: width $transition-duration $transition-easing-out $transition-duration, border-bottom $transition-duration $transition-easing-out;
        }
    }
    
    .button__filler {
        display: none;
        position: absolute;
        z-index: 2;
        width: 150%;
        height: 200%;
        border-radius: $border-radius-round;
        background-color: $color-ui-01;
        color: $color-text-01;
        top: -50%;
        left: -25%;
        transform: translate3d(0, 75%, 0);
        transition-property: transform;
        transition-duration: $transition-duration;
        transition-timing-function: $transition-easing-in;
        will-change: transform; /* stylelint-disable-line plugin/no-unsupported-browser-features */
    
        .button--magnetic & {
            html[data-whatintent='mouse'] & {
                display: block;
            }
        }
    
        .button--reverted & {
            background-color: $button-primary-background;
            color: $color-text-03;
        }
    }
    
  • URL: /components/raw/button/button.scss
  • Filesystem Path: src/patterns/components/button/button.scss
  • Size: 7.2 KB
  • Content:
    import Component from '../component/component';
    import Helpers from '../helpers/helpers';
    import Icon from '../icon/icon';
    
    import './button.scss';
    
    export interface IButton {
        text: string;
        icon?: string;
        link?: string;
        iconPosition?: string;
    }
    
    export interface ITransform {
        amt: number;
        current: number;
        previous: number;
    }
    
    export interface IStyles {
        tx: ITransform;
        ty: ITransform;
    }
    
    export default class Button extends Component {
        static initSelector: string = '.button--magnetic';
    
        public filler: JQuery;
        public renderedStyles: IStyles;
        public buttonRect: DOMRect;
        public distanceToTrigger: number;
    
        constructor(element: HTMLElement) {
            super(element);
    
            this.filler = this.element.find('.button__filler');
    
            this.buttonRect = this.element[0].getBoundingClientRect();
            this.distanceToTrigger = this.buttonRect.width * 0.7;
    
            this.renderedStyles = {
                tx: {amt: 0.1, current: 0, previous: 0},
                ty: {amt: 0.1, current: 0, previous: 0},
            };
    
            this.init();
        }
    
        static render(data: IButton, className?: string): JQuery {
            const element: string = data.link ? 'a' : 'button';
            const icon: string = data.icon ? Icon.render(data.icon, 'button__icon') : '';
            const classArray: string[] = ['button'];
    
            if (className) {
                classArray.push(className);
            }
    
            if (data.icon && !data.iconPosition) {
                classArray.push('button--icon');
            }
    
            if (data.icon && data.iconPosition === 'right') {
                classArray.push('button--icon-right');
            }
    
            if (data.icon && data.iconPosition === 'left') {
                classArray.push('button--icon-left');
            }
    
            return $(`<${element} class="${classArray.join(' ')}" ${data.link ? `href="${data.link}"` : 'type="button"'}><span class="button__filler"></span><span class="button__inner"><span class="button__icon-wrapper">${icon}</span><span class="button__text">${data.text}</span></span></${element}>`);
        }
    
        init(): void {
            if (!Helpers.isMobileDevice) {
                this.element.on('mouseenter', this.enter.bind(this));
                this.element.on('mouseleave', this.leave.bind(this));
    
                $(window).on('resize scroll', this.resizeHandler.bind(this));
    
                this.run();
            }
    
        }
    
        resizeHandler(): void {
            this.buttonRect = this.element[0].getBoundingClientRect();
            this.distanceToTrigger = this.buttonRect.width * 0.7;
        }
    
        distance(x1: number, y1: number, x2: number, y2: number): number {
            const a: number = x1 - x2;
            const b: number = y1 - y2;
    
            return Math.hypot(a,b);
        }
    
        lerp(a: number, b: number, n: number): number {
            return (1 - n) * a + n * b;
        }
    
        run(): void {
            // Linear interpolation
            const distanceMouseButton: number = this.distance(window.gotoAndPlay.mousePos.x, window.gotoAndPlay.mousePos.y, this.buttonRect.left + this.buttonRect.width / 2, window.scrollY + this.buttonRect.top + this.buttonRect.height / 2);
    
            // new values for the translations
            let x: number = 0;
            let y: number = 0;
    
            if (distanceMouseButton < this.distanceToTrigger) {
                x = (window.gotoAndPlay.mousePos.x - (this.buttonRect.left + this.buttonRect.width / 2)) * .3;
                y = (window.gotoAndPlay.mousePos.y - (window.scrollY + this.buttonRect.top + this.buttonRect.height / 2)) * .3;
            }
    
            this.renderedStyles.tx.current = parseFloat(x.toFixed(3));
            this.renderedStyles.ty.current = parseFloat(y.toFixed(3));
    
            for (const key in this.renderedStyles) {
                if (key) {
                    this.renderedStyles[key].previous = parseFloat(this.lerp(this.renderedStyles[key].previous, this.renderedStyles[key].current, this.renderedStyles[key].amt).toFixed(3));
                }
            }
    
            this.element[0].style.transform = `translate3d(${this.renderedStyles.tx.previous}px, ${this.renderedStyles.ty.previous}px, 0)`;
    
            requestAnimationFrame(() => this.run());
        }
    
        enter(): void {
            this.element.addClass('is-hover');
            this.filler[0].style.transitionDuration = `250ms`;
            this.filler[0].style.transform = `translate3d(0, 0, 0)`;
        }
    
        leave(): void {
            this.element.removeClass('is-hover');
            this.filler[0].style.transform = `translate3d(0, -75%, 0)`;
    
            setTimeout(() => {
                if (!this.element.hasClass('is-hover')) {
                    this.filler[0].style.transitionDuration = `0ms`;
                    this.filler[0].style.transform = `translate3d(0, 75%, 0)`;
                }
            }, 250);
        }
    }
    
  • URL: /components/raw/button/button.ts
  • Filesystem Path: src/patterns/components/button/button.ts
  • Size: 4.7 KB
  • Handle: @button--magnetic
  • Filesystem Path: src/patterns/components/button/button.twig
  • References (1): @icon