Newer
Older
vmk-ui-kit / src / scss / components / _forms.scss
/* =========================
   Forms / Input
   Figma: Inputs / Text Field.
========================= */

@use "sass:color";
@use "../kit-deps" as *;

.form-group {
  display: flex;
  flex-direction: column;
  gap: $space-1;
  width: 100%;
  max-width: 600px;

  .label {
    display: flex;
    flex-direction: column;
    gap: $space-1;
    font-size: 14px;
    font-weight: $font-weight-semibold;
    color: $neutral-900;
    position: relative;

    .vmk-icon {
      position: absolute;
      left: $space-3;
      bottom: $space-3;
      color: $neutral-700;
      font-size: $icon-size-md;
      pointer-events: none;
      transition: color $motion-base $motion-ease;
    }

    &.is-required::after {
      content: "*";
      color: $danger-text;
      margin-left: $space-1;
    }
  }

  .input {
    min-height: 48px;
    padding: $space-3 $space-4;
    font-family: $font-family-base;
    font-size: 15px;
    font-weight: $font-weight-medium;
    line-height: 1.25;
    color: $neutral-900;
    background-color: $neutral-0;
    border: $border-width-base $border-style-base $neutral-300;
    border-radius: $radius-lg;
    transition:
      border-color $motion-base $motion-ease,
      box-shadow $motion-base $motion-ease,
      background-color $motion-base $motion-ease;

    &:hover:not(:disabled):not([readonly]),
    &.is-hover:not(:disabled):not([readonly]) {
      border-color: $mint-600;
    }

    &:focus {
      outline: none;
      border-color: $mint-600;
      box-shadow: 0 0 0 3px #{rgba($mint-600, 0.24)};
      background-color: $neutral-0;
    }

    &::placeholder {
      color: $neutral-600;
      font-weight: $font-weight-regular;
    }

    &:disabled {
      color: $neutral-500;
      background-color: $neutral-50;
      border-color: $neutral-300;
      cursor: not-allowed;
      opacity: 0.72;
    }

    &[readonly] {
      color: $neutral-700;
      background-color: $neutral-50;
      border-color: $neutral-300;
    }

    &.input-sm {
      min-height: 40px;
      padding: $space-2 $space-3;
      font-size: 14px;
      border-radius: $radius-sm;
    }

    &.input-lg {
      min-height: 56px;
      padding: $space-3 $space-5;
      font-size: 16px;
      border-radius: $radius-lg;
    }

    &.input-icon-left {
      padding-left: $space-8;
    }

    &.input-icon-right {
      padding-right: $space-8;
    }

    &.input-date {
      min-height: 48px;
      padding: $space-3 $space-4;
      background-color: $neutral-0;
      background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='none' stroke='%236B7280' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2' ry='2'%3E%3C/rect%3E%3Cline x1='16' y1='2' x2='16' y2='6'%3E%3C/line%3E%3Cline x1='8' y1='2' x2='8' y2='6'%3E%3C/line%3E%3Cline x1='3' y1='10' x2='21' y2='10'%3E%3C/line%3E%3C/svg%3E");
      background-repeat: no-repeat;
      background-position: right $space-3 center;
      background-size: 20px 20px;
      border: $border-width-base $border-style-base $neutral-300;
      border-radius: $radius-lg;
      font-family: $font-family-base;
      font-size: 15px;
      font-weight: $font-weight-medium;
      color: $neutral-900;
      cursor: pointer;

      &::-webkit-calendar-picker-indicator {
        opacity: 0;
        position: absolute;
        inset: 0;
        width: 100%;
        height: 100%;
        cursor: pointer;
      }

      &:hover:not(:disabled):not([readonly]) {
        border-color: $mint-600;
      }

      &:focus {
        outline: none;
        border-color: $mint-600;
        box-shadow: 0 0 0 3px #{rgba($mint-600, 0.24)};
      }

      &::placeholder {
        color: $neutral-500;
      }
    }
  }

  .input-help {
    font-size: 13px;
    color: $neutral-700;
    margin: 0;

    &.is-error   { color: $danger-text; }
    &.is-success { color: $success-text; }
    &.is-warning { color: $warning-text; }
  }

  &.is-error .input:not(:focus) {
    border-color: $danger-text;
    background-color: $danger-bg;

    &:hover {
      border-color: color.adjust($danger-text, $lightness: -8%);
    }
  }

  &.is-success .input:not(:focus) {
    border-color: $success-text;
    background-color: $success-bg;
  }

  &.is-warning .input:not(:focus) {
    border-color: $warning-text;
    background-color: $warning-bg;
  }
}

.form-group {
  textarea.input {
    min-height: 120px;
    resize: vertical;
    line-height: 1.4;
  }
}

.form-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: $space-4;
  width: 100%;
  max-width: 760px;

  @media (max-width: 768px) {
    grid-template-columns: 1fr;
  }
}

.range {
  display: flex;
  flex-direction: column;
  gap: $space-2;
  width: 100%;
  max-width: 400px;

  .range-input {
    width: 100%;
    height: 6px;
    margin: $space-2 0;
    appearance: none;
    background: $neutral-200;
    border-radius: $radius-full;
    cursor: pointer;

    &::-webkit-slider-thumb {
      appearance: none;
      width: 18px;
      height: 18px;
      border-radius: 50%;
      background: $neutral-900;
      border: 2px solid $neutral-0;
      box-shadow: 0 1px 4px rgba($neutral-900, 0.16);
      transition: transform $motion-base $motion-ease;
    }

    &::-moz-range-thumb {
      width: 18px;
      height: 18px;
      border-radius: 50%;
      background: $neutral-900;
      border: 2px solid $neutral-0;
      box-shadow: 0 1px 4px rgba($neutral-900, 0.16);
      transition: transform $motion-base $motion-ease;
    }

    &:hover::-webkit-slider-thumb { transform: scale(1.1); }
    &:hover::-moz-range-thumb { transform: scale(1.1); }

    &:focus {
      outline: none;
      &::-webkit-slider-thumb { box-shadow: 0 0 0 3px rgba($mint-600, 0.32); }
      &::-moz-range-thumb { box-shadow: 0 0 0 3px rgba($mint-600, 0.32); }
    }

    &:disabled {
      opacity: 0.5;
      cursor: not-allowed;
    }
  }
}