Elements

Meta FIle Upload

27 Jul 2023

HTML
SCSS
PostCSS
JS
                            <div class="meta-upload-file" data-upload-file-animation>
  <label for="file">Upload File</label>
  <div class="meta-upload-file__input">
    <input id="file" type="file" />
    <span class="meta-upload-file__name">Upload CV</span>
  </div>
  <span class="meta-upload-file__info">PDF, DOCX, DOC, RTF, TXT up to 5MB</span>
</div>
                        
                            .meta-upload-file {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;

  label {
    font-family: var(--font-main);
    font-size: ac(16px, 14px);
    line-height: 1.2;
    font-weight: 700;
    color: var(--cl-dark-blue);
    padding-bottom: 8px;
    cursor: pointer;
    margin-right: auto;
  }

  &__input {
    width: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
    font-size: ac(16px, 14px);
    line-height: 1.2;
    font-weight: 600;
    font-family: var(--font-main);
    color: var(--cl-dark-blue);
    border: 2px dashed var(--cl-grey);
    border-radius: 6px;
    transition: all 0.3s ease;
    padding: 8px ac(16px, 12px);
    cursor: pointer;
    position: relative;
    min-height: ac(80px, 60px);

    input {
      position: absolute;
      inset: 0;
      opacity: 0;
      width: 100%;
      height: 100%;
      cursor: pointer;
    }

    input[type='file']::-webkit-file-upload-button {
      cursor: pointer;
    }

    span {
      cursor: pointer;
      @include max-line-length(1);
    }

    &:hover {
      border-color: rgba(var(--cl-dark-blue-rgb) / 0.8);
      box-shadow: inset 0px 0px 5px 0px rgba(var(--cl-dark-blue-rgb) / 0.3);
    }
  }

  &__info {
    padding-top: 6px;
    font-size: ac(14px, 12px);
    line-height: 1.2;
    font-weight: 500;
    font-family: var(--cl-font-main);
    text-align: center;
    color: var(--cl-dark-grey);
  }

  &.drag {
    .meta-upload-file__input {
      background-color: var(--cl-light-gray);
      box-shadow: inset 0px 0px 10px 0px rgba(var(--cl-dark-blue-rgb) / 0.4);
    }
  }

  &.drop {
    .meta-upload-file__input {
      border-style: solid;
    }

    &:not(.done) {
      .meta-upload-file__input {
        transform: scale(0.9);
      }
    }
  }
}
                        
                            .meta-upload-file {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;

  label {
    font-family: var(--font-main);
    font-size: ac(16px, 14px);
    line-height: 1.2;
    font-weight: 700;
    color: var(--cl-dark-blue);
    padding-bottom: 8px;
    cursor: pointer;
    margin-right: auto;
  }

  &__input {
    width: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
    font-size: ac(16px, 14px);
    line-height: 1.2;
    font-weight: 600;
    font-family: var(--font-main);
    color: var(--cl-dark-blue);
    border: 2px dashed var(--cl-dark-blue);
    border-color: var(--cl-dark-blue);
    border-radius: 4px;
    transition: all 0.3s ease;
    padding: 8px ac(16px, 12px);
    cursor: pointer;
    position: relative;
    min-height: ac(80px, 60px);

    input {
      position: absolute;
      inset: 0;
      opacity: 0;
      width: 100%;
      height: 100%;
      cursor: pointer;
    }

    input[type='file']::-webkit-file-upload-button {
      cursor: pointer;
    }

    span {
      cursor: pointer;
      @include max-line-length(1);
    }

    &:hover {
      border-color: rgba(var(--cl-dark-blue-rgb) / 0.8);
      box-shadow: inset 0px 0px 5px 0px rgba(var(--cl-dark-blue-rgb) / 0.3);
    }
  }

  &__info {
    padding-top: 6px;
    font-size: ac(14px, 12px);
    line-height: 1.2;
    font-weight: 500;
    font-family: var(--cl-font-main);
    text-align: center;
    color: var(--cl-dark-gray);
  }

  &.drag {
    .meta-upload-file__input {
      background-color: var(--cl-light-gray);
      box-shadow: inset 0px 0px 10px 0px rgba(var(--cl-dark-blue-rgb) / 0.4);
    }
  }

  &.drop {
    .meta-upload-file__input {
      border-style: solid;
    }

    &:not(.done) {
      .meta-upload-file__input {
        transform: scale(0.9);
      }
    }
  }
}
                        
                            function uploadFile() {
  if (document.getElementsByClassName('upload-file-animation')[0]) {
    const uploadFileBlocksArr = document.querySelectorAll(
      '.upload-file-animation'
    );
    uploadFileBlocksArr.forEach((fileUpload) => {
      fileUpload.addEventListener('dragover', function () {
        this.classList.add('drag');
        this.classList.remove('drop', 'done');
      });

      fileUpload.addEventListener('dragleave', function () {
        this.classList.remove('drag');
      });

      fileUpload.addEventListener('drop', start, false);
      fileUpload.addEventListener('change', start, false);

      function start() {
        this.classList.remove('drag');
        this.classList.add('drop');
        setTimeout(() => this.classList.add('done'), 500);
      }
    });
  }
};
                        

Будемо намагатися стандартизувати розмітку файлових інпутів в нових проєктах.
Цей варіант інпуту загрузки CV з оновлення розмітки попапів, яке буде з приходом
збірки на базі Parcel. Буде краще, якщо відразу стилізувати їх під
проєкт і для самих попапів. Цей варіант мінімально стилізований. Але відразу додана невелика анімація для drag&drop. Для того щоб вона працювала, треба додати для meta-upload-file атрибут data-upload-file-animation та запустити функцію.

Якщо в дизайні проєкту не потрібен label, не забувайте додавати клас sr-only, щоб його було не видно. Але він потрібен для SEO та правильної семантики DOM. Головне щоб його ключ в значенні for був завжди такий же, як id у інпута.

В функції uploadFile будуть додаватися класи, через які можна буде під проєкт застилити. Клас drag додається коли файл саме переноситься в інпут. Клас drop додається коли файл доданий, тут анімація при додаванні файлу йде, а клас done для того, щоб завершувати анімацію.

0