# ZeenButton

Компонент кнопки

# Примеры:

Размеры:

buttons

button-font-size

По умолчанию наследуется от main-size

button-padding-horizontal

button-padding-vertical

button-border-radius

По умолчанию наследуется от main-input-radius

button-border-width

По умолчанию наследуется от main-input-border-width

Цвета:

button-main-color

По умолчанию наследуется от main-color

button-background-color

По умолчанию наследуется от button-main-color

button-border-color

button-additional-color

button-hover-color-base

По умолчанию наследуется от main-hover-color

button-click-color-base

По умолчанию наследуется от main-active-color

button-disabled-background-color

По умолчанию наследуется от main-disable-color

button-disabled-color

По умолчанию наследуется от main-disable-text-color

button-text-color-base

По умолчанию наследуется от button-additional-color

button-text-alter-color

По умолчанию наследуется от button-main-color

  • Кнопка-ссылка

    Связаться с нами
    Связаться с нами
    Связаться с нами
  • Кнопка обычная

  • Disabled

  • Кнопка c кастомными цветами

  • Кнопка с шириной по контенту и по родителю

  • Лоадер в кнопке (нажми). На время работы лоадера кнопка становится неактивной, однако сохраняет изначальные цвета своей темы.

  • Кнопки c иконками

# props

Название Тип Обязательный По умолчанию Описание
href string - - ссылка
to string или object - - путь для router-link
theme string - fill-main fill-main - фон имеет главный цвет, а текст - дополнительный; fill-additional - фон имеет дополнительный цвет, а текст - главный; outline - фон прозрачный, текст и бордер имеют главный цвет
size string - contentWidth contentWidth - ширина кнопки определяется содержимым, parentWidth - шириной родителя
isLoading boolean - - состояние загрузки
disabled boolean - - если true кнопка становится disabled
color object - {} объект с кастомными цветами (подробнее см.ниже)

# Кастомные цвета в объекте color

Название Тип Обязательный По умолчанию
buttonMainColor главный цвет - берет значение из темы ($button-main-color)
buttonAditionalColor дополнительный цвет - берет значение из темы ($button-additional-color)
buttonHoverColor цвет для состояния ховера - берет значение из темы ($button-hover-color)
buttonClickColor цвет для состояний focus и active - берет значение из темы ($button-click-color)

# Иконки

Компонент имеет 2 именованных слота для иконок - rightIcon и leftIcon.

# Source Code - исходный код компонента

<template>
  <component
    :is="getElement"
    :id="`zeen-button-${componentId}`"
    class="zeen-button"
    :class="{
      'zeen-button_fill-main': theme === 'fill-main',
      'zeen-button_fill-additional': theme === 'fill-additional',
      'zeen-button_outline': theme === 'outline',
      'zeen-button_parent-width': size === 'parentWidth',
      'zeen-button_no-padding': theme === 'no-padding',
      'zeen-button_is-loading': isLoading,
      'zeen-button_no-radius': noRadius,
    }"
    :href="href"
    :to="to"
    :disabled="disabled || isLoading"
    v-on="$listeners"
    v-bind="$attrs"
  >
    <div class="zeen-button__content">
      <slot name="leftIcon"></slot>
      <slot></slot>
      <slot name="rightIcon"></slot>
    </div>

    <div class="zeen-button__loader" v-if="isLoading">
      <slot name="loading">
        {{ loadingText }}
      </slot>
    </div>
  </component>
</template>

<script>
export default {
  name: 'ZeenButton',
  props: {
    loadingText: {
      type: String,
      default: 'Загрузка...',
    },
    href: {
      type: String,
      default: null,
    },
    to: {
      validator: (prop) => typeof prop === 'object' || typeof prop === 'string',
      default: null,
    },
    theme: {
      type: String,
      default: 'fill-main',
      validator: (theme) => ['fill-main', 'fill-additional', 'outline', 'clean', 'no-padding'].includes(theme),
    },
    size: {
      type: String,
      default: 'contentWidth',
      validator: (size) => ['contentWidth', 'parentWidth'].includes(size),
    },
    isLoading: {
      type: Boolean,
      required: false,
    },
    disabled: {
      type: Boolean,
      required: false,
    },
    noRadius: {
      type: Boolean,
      default: false,
    },
  },
  methods: {},
  computed: {
    componentId() {
      return this._uid
    },
    getElement() {
      if (this.href) {
        return 'a'
      } else if (this.to) {
        return 'router-link'
      }

      return 'button'
    },
  },
}
</script>

<style>
:root {
  /* Размеры */
  --button-font-size: var(--main-size);
  --button-padding-horizontal: 29px; /*// мекет - 1px бордер*/
  --button-padding-vertical: 15px; /*// мекет - 1px бордер*/
  --button-border-radius: var(--main-input-radius);
  --button-border-width: 1px;
  --button-line-height: calc(var(--button-font-size) * 1.375);

  /* Цвета */
  --button-main-color: var(--main-color);
  --button-border-color: transparent;
  --button-additional-color: var(--main-light);
  --button-disabled-background-color: var(--gray-1);
  --button-disabled-color: var(--gray-2);
  --button-text-color: var(--button-additional-color);
}
</style>

<style lang="scss" scoped>
@import '/src/styles/mixins.scss';

.zeen-button {
  --button-main: var(--button-background-color-base, var(--button-main-color));
  --button-real-background-color: var(--button-background-color-base, var(--button-main-color));
  --button-hover-color: var(--button-hover-color-base, var(--main-hover-color));
  --button-click-color: var(--button-click-color-base, var(--main-active-color));
  --button-text-color: var(--button-text-color-base, var(--button-additional-color));

  position: relative;
  display: inline-flex;
  justify-content: center;
  align-items: center;
  padding: var(--button-padding-vertical) var(--button-padding-horizontal);
  border: var(--button-border-width) solid var(--button-border-color);
  box-sizing: border-box;
  border-radius: var(--button-border-radius);
  font-weight: 600;
  font-size: var(--button-font-size);
  line-height: var(--button-line-height);
  text-align: center;
  cursor: pointer;
  box-shadow: none;
  transition: background-color 0.25s ease, color 0.25s ease, opacity 0.25s ease;
  white-space: nowrap;
  text-decoration: none;
  font-family: inherit;
  color: var(--button-text-color);
  background: var(--button-real-background-color);

  &:focus,
  &:active,
  &:visited,
  &:hover {
    outline: none;
    text-decoration: none !important;
  }

  &:disabled {
    cursor: auto;
  }

  &_fill-main {
    &:hover {
      background-color: var(--button-hover-color);
    }

    &:active {
      background-color: var(--button-click-color);
    }
  }

  &_fill-additional {
    background: transparent;
    color: var(--button-main);

    &:hover {
      color: var(--button-hover-color);
    }

    &:active {
      color: var(--button-click-color);
    }
  }

  &_outline {
    background: transparent;
    color: var(--button-main);
    border-color: var(--button-main);

    &:hover {
      color: var(--button-hover-color);
      border-color: var(--button-hover-color);
    }

    &:active {
      color: var(--button-click-color);
      border-color: var(--button-click-color);
    }
  }

  &:disabled,
  &:disabled:hover,
  &:disabled:focus {
    color: var(--button-disabled-color);
    background-color: var(--button-disabled-background-color);
  }

  &_is-loading:disabled,
  &_is-loading:disabled:hover,
  &_is-loading:disabled:focus {
    color: var(--button-text-color);
    background-color: var(--button-real-background-color);
  }

  //&_parent-width  -> .zeen-button_parent-width
  //.zeen-button_parent-width  -> .zeen-button .zeen-button_parent-width
  //& &_parent-width  -> .zeen-button .zeen-button_parent-width
  //&_mod  -> .zeen-button_mod
  //&#{&}_mod  -> .zeen-button.zeen-button_mod
  &_parent-width {
    width: 100%;
  }

  &_is-loading {
    .zeen-button__content {
      opacity: 0;
    }
  }

  &_no-radius {
    border-radius: 0;
  }

  &__content {
    display: flex;
    align-items: center;
    justify-content: center;

    svg > * {
      fill: var(--button-text-color);
    }
  }

  &__loader {
    display: flex;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
  }

  &_no-padding {
    padding: 0;
    background: none;
    border: none;
  }
}
</style>