# ZeenRadio

Компонент radio input для форм

# Примеры:

  • Radio:

  • Radio disabled:

  • Правильный или с ошибкой:

  • С кастомными цветами: Первый вариант

# props

Название Тип Обязательный По умолчанию Описание
value any + - то, значение, которое хотим сохранять в data родителя
modelValue any + - сюда передается значение из v-model
label string - - label рядом с чекбоксом
disabled boolean - - если true, то инпут становится disabled и добавляется класс zeen-input_disabled (для стилизации лейбла)
name string - -
hasError boolean - - если true, то добавляется класс zeen-radio_error
hasCorrect boolean - - если true, то добавляется класс zeen-radio_correct
color object - {} объект с кастомными цветами (подробнее см.ниже)

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

Название Тип Обязательный По умолчанию
radioBackgroundColor цвет фона радиокнопки - берет значение из темы ($radio-background-color)
radioCheckedBackgroundColor цвет фона отмеченной радиокнопки - берет значение из темы ($radio-checked-background-color)
radioCheckedColor цвет точки в отмеченной радиокнопке - берет значение из темы ($radio-checked-color)
radioDisabledBackgroundColor цвет фона радиокнопки в состоянии disabled - берет значение из темы ($radio-disabled-background-color)
radioDisabledLabelColor цвет лейбла радиокнопки в состоянии disabled - берет значение из темы ($radio-disabled-label-color)
radioLabelColor цвет фона лейбла - берет значение из темы ($radio-label-color)
errorColor цвет лейбла и точки внутри отмеченной радиокнопки при hasError = true - берет значение из темы ($input-error-color)
correctColor цвет лейбла и точки внутри отмеченной радиокнопки при hasCorrect = true - берет значение из темы ($input-correct-color)

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

<template>
  <div
    :id="`zeen-radio-${componentId}`"
    class="zeen-radio"
    :class="{
      'zeen-radio_error': hasError,
      'zeen-radio_correct': hasCorrect,
      'zeen-radio_disabled': disabled,
    }"
  >
    <div class="zeen-radio__radio">
      <input
        class="zeen-radio__real"
        :value="value"
        :name="name"
        type="radio"
        v-model="model"
        :disabled="disabled"
        :id="componentId"
      />
      <span class="zeen-radio__pseudo"></span>
    </div>
    <label class="zeen-radio__label" :for="componentId" v-html="label"></label>
  </div>
</template>

<script>
export default {
  name: 'ZeenRadio',
  model: {
    prop: 'modelValue',
    event: 'change',
  },
  props: {
    value: {
      required: true,
    },
    modelValue: {
      required: true,
    },
    label: {
      type: String,
      required: false,
    },
    disabled: {
      type: Boolean,
      required: false,
    },
    name: {
      type: String,
      required: false,
    },
    hasError: {
      type: Boolean,
      required: false,
    },
    hasCorrect: {
      type: Boolean,
      required: false,
    },
  },
  computed: {
    componentId() {
      return this._uid
    },
    model: {
      get() {
        return this.modelValue
      },
      set(val) {
        this.$emit('change', val)
      },
    },
  },
}
</script>

<style lang="scss">
:root {
  /* Размеры */
  --radio-size: var(--checkbox-size);
  --radio-size-small: 11px;
  --radio-border-radius: 50%;
  --radio-font-size: var(--main-small-text);
  --radio-label-offset-left: var(--checkbox-label-offset-left);

  /* Цвета */
  --radio-background-color: var(--main-light);
  --radio-label-color: var(--main-text-color);
  --radio-checked-background-color: var(--main-light);
  --radio-checked-color: var(--main-color);
  --radio-border-color: var(--gray-2);

  --radio-error-label-color: var(--input-error-color);
  --radio-error-checked-background-color: var(--radio-checked-background-color);

  --radio-correct-label-color: var(--input-correct-color);
  --radio-correct-background-color: var(--radio-checked-background-color);

  --radio-disabled-label-color: var(--input-disable-color);
  --radio-disabled-background-color: var(--input-disable-color);
}
</style>

<style lang="scss" scoped>
.zeen-radio {
  display: flex;
  align-items: center;

  &_error {
    --radio-label-color: var(--radio-error-label-color);
    --radio-checked-color: var(--radio-error-label-color);
    --radio-checked-background-color: var(--radio-error-checked-background-color);
  }

  &_correct {
    --radio-label-color: var(--radio-correct-label-color);
    --radio-checked-color: var(--radio-correct-label-color);
    --radio-checked-background-color: var(--radio-correct-background-color);
  }

  &_disabled {
    --radio-label-color: var(--radio-disabled-label-color);
    --radio-checked-color: var(--radio-disabled-label-color);
  }

  &__label {
    font-size: var(--radio-font-size);
    line-height: 1.4;
    color: var(--radio-label-color);
    padding: 0 0 0 var(--radio-label-offset-left);
    cursor: pointer;
  }

  &__real {
    position: absolute;
    cursor: pointer;
    opacity: 0;
    margin: 0;
    z-index: 1;

    &:disabled {
      cursor: auto;

      &,
      &:checked {
        --radio-checked-background-color: var(--radio-disabled-background-color);
      }
    }

    &:checked + .zeen-radio__pseudo {
      background-color: var(--radio-checked-background-color);

      &:before {
        background-color: var(--radio-checked-color);
      }
    }
  }

  &__pseudo {
    display: flex;
    position: relative;
    border-radius: var(--radio-border-radius);
    background: var(--radio-background-color);
    border: 1px solid var(--radio-border-color);

    &:before {
      content: '';
      display: block;
      margin: auto;
      width: var(--radio-size-small);
      height: var(--radio-size-small);
      border-radius: var(--radio-border-radius);
    }
  }
}

.zeen-radio__real,
.zeen-radio__real:checked + .zeen-radio__pseudo,
.zeen-radio__pseudo {
  width: var(--radio-size);
  height: var(--radio-size);
}

.zeen-radio__real {
  & + .zeen-radio__pseudo {
    transition: background-color 0.25s ease;
  }
}
</style>