formulaires · upload

Upload de fichier

Zone de dépôt de fichier (glisser-déposer ou clic pour parcourir), qui affiche le nom et le poids du fichier une fois choisi. Nécessite du JavaScript.

Voir le code source
<style>
.bn-upload {
  max-width: 420px;
  padding: 2rem;
  font-family: 'Inter', sans-serif;
  background: #0B0F10;
}

.bn-upload__zone {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.4rem;

  padding: 2.5rem 1.5rem;
  border: 1px dashed rgba(230, 228, 221, 0.3);
  border-radius: 8px;

  cursor: pointer;
  transition: border-color 0.2s ease, background 0.2s ease;
}

.bn-upload__zone:hover,
.bn-upload__zone.is-dragover {
  border-color: #E6E4DD;
  background: rgba(255, 255, 255, 0.03);
}

.bn-upload__icon {
  font-size: 1.4rem;
  color: #979793;
  margin-bottom: 0.4rem;
}

.bn-upload__text {
  color: #E6E4DD;
  font-size: 0.85rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.bn-upload__sub {
  color: #5C6160;
  font-size: 0.8rem;
}

.bn-upload__input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
}

.bn-upload__file {
  display: flex;
  align-items: center;
  gap: 0.75rem;

  margin-top: 1rem;
  padding: 0.9rem 1rem;
  border: 1px solid rgba(230, 228, 221, 0.15);
  border-radius: 8px;
}

.bn-upload__file-icon {
  font-size: 1.2rem;
}

.bn-upload__file-info {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.bn-upload__file-name {
  color: #E6E4DD;
  font-size: 0.85rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.bn-upload__file-size {
  color: #979793;
  font-size: 0.75rem;
}

.bn-upload__file-remove {
  flex-shrink: 0;
  width: 24px;
  height: 24px;
  border: none;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.06);
  color: #E6E4DD;
  cursor: pointer;
}

.bn-upload__hint {
  margin: 1rem 0 0;
  font-size: 0.75rem;
  color: #5C6160;
}

</style>

<div class="bn-upload" data-fx-root>
  <label class="bn-upload__zone" for="bn-upload-input">
    <span class="bn-upload__icon">⇧</span>
    <span class="bn-upload__text">Glissez votre fichier ici</span>
    <span class="bn-upload__sub">ou cliquez pour parcourir</span>
    <input type="file" id="bn-upload-input" class="bn-upload__input" />
  </label>

  <div class="bn-upload__file" hidden>
    <span class="bn-upload__file-icon">📄</span>
    <div class="bn-upload__file-info">
      <span class="bn-upload__file-name"></span>
      <span class="bn-upload__file-size"></span>
    </div>
    <button type="button" class="bn-upload__file-remove" aria-label="Retirer le fichier">✕</button>
  </div>

  <p class="bn-upload__hint">Formats acceptés : PDF, JPG, PNG, DOC, DOCX · Taille max : 10 Mo</p>
</div>


<script>
/* ==========================================================
   UPLOAD DE FICHIER
   Gère 3 choses : le glisser-déposer (surbrillance + dépôt réel),
   l'affichage du fichier une fois choisi (nom + poids lisible),
   et le bouton pour le retirer.
   ========================================================== */

(function () {
  const root = document.querySelector('.bn-upload[data-fx-root]');
  if (!root) return;

  const zone = root.querySelector('.bn-upload__zone');
  const input = root.querySelector('.bn-upload__input');
  const filePanel = root.querySelector('.bn-upload__file');
  const fileName = root.querySelector('.bn-upload__file-name');
  const fileSize = root.querySelector('.bn-upload__file-size');
  const removeBtn = root.querySelector('.bn-upload__file-remove');

  // Convertit un nombre d'octets en texte lisible (Ko / Mo)
  function formatSize(bytes) {
    if (bytes < 1024) return `${bytes} o`;
    if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} Ko`;
    return `${(bytes / (1024 * 1024)).toFixed(1)} Mo`;
  }

  function showFile(file) {
    fileName.textContent = file.name;
    fileSize.textContent = formatSize(file.size);
    filePanel.hidden = false;
    zone.hidden = true;
  }

  function clearFile() {
    input.value = '';
    filePanel.hidden = true;
    zone.hidden = false;
  }

  input.addEventListener('change', () => {
    if (input.files[0]) showFile(input.files[0]);
  });

  removeBtn.addEventListener('click', clearFile);

  // Glisser-déposer : surbrillance de la zone au survol du fichier
  ['dragenter', 'dragover'].forEach((eventName) => {
    zone.addEventListener(eventName, (event) => {
      event.preventDefault();
      zone.classList.add('is-dragover');
    });
  });

  ['dragleave', 'drop'].forEach((eventName) => {
    zone.addEventListener(eventName, () => {
      zone.classList.remove('is-dragover');
    });
  });

  zone.addEventListener('drop', (event) => {
    event.preventDefault();
    const file = event.dataTransfer.files[0];
    if (file) {
      input.files = event.dataTransfer.files;
      showFile(file);
    }
  });
})();

</script>