JSFiddle - React, Tailwind, and code Playground

by Julien Etienne

HTML

<form id="form" class="upload-form-js" method="post" enctype="multipart/form-data">
        <!-- IMAGE DETAILS COMPONENT. THESE COMPONENTS ARE OUTPUTTED WITH A WHILE LOOP-->  
        <div class="upload-details-component" data-upload-details-component>                
            <div class="image-wrapper">
                <img src="image.jpg">
            </div>
            <div class="edit-zone">
                <div class="form-row">
                    <label for="image-title">Image Title</label>
                    <input data-image-title id="title-title" class="input-title" type="text" name="image-title[]">
                </div>
                <div class="form-row">
                    <label for="tags">Comma Separated Image Tags</label>
                    <textarea data-tab id="tags" class="text-area" type="text" name="image-tags[]"></textarea>
                </div>
                <div class="form-row">
                    <!-- DELETE BUTTON -->
                    <button name="upload-details-delete" value="12" class="remove-image">DELETE</button>
                    <input type="hidden" name="image-id[]" value="12">
                </div>
            </div>
        </div>
        <!-- IMAGE DETAILS COMPONENT - END -->
    <div class="form-row upload-details-submit-row">
        <button id="upload-submit" class="upload-details-submit" type="submit" name="upload-submit">COMPLETE UPLOADS</button>
    </div>
</form>

JavaScript

const empty = ''
const uploadSubmit = document.querySelector('#upload-submit')
const form = document.querySelector('#form')

let activeElement
document.addEventListener('keydown', (e) => {
  //document.body.insertAdjacentHTML('afterend', document.activeElement)
  // Avoid using e.target.classList.contains, if the class changes 
  // You also have to change the code.
  const hasImageTitle = activeElement.hasAttribute('data-image-title')
  if (hasImageTitle) {
    if (e.key === 'Enter' && hasImageTitle) {
      // Click is only for testing purposes
      uploadSubmit.click()
      e.preventDefault()
      //  Use `form.submit()` in production as it is less hacky and will be less prone to any propagation issues.
      // Submit will submit the form but does not fire the submit event
      // form.submit() 
      return
    } 
    if(e.key === 'Tab') {
    currentImageTab = e.target.closest('[data-upload-details-component]')
      .querySelector('[data-tab]')
      e.preventDefault()
      currentImageTab.focus()
    }
    
  }
})


let currentImageTab;
document.addEventListener('focus', () => {
  activeElement = document.activeElement

  if (activeElement.hasAttribute('data-image-title')) {
    currentImageTab = activeElement.closest('[data-upload-details-component]')
      .querySelector('[data-tab]')
    currentImageTab.setAttribute('tabindex', '-1')
  } else {
    if (currentImageTab) {
    currentImageTab = activeElement.closest('[data-upload-details-component]')
      .querySelector('[data-tab]')
      currentImageTab.removeAttribute('tabindex')
    }
  }
}, true)



// To test you can borrow @bravo's test example. This is not needed, only to see it in action.
form.addEventListener('submit', e => {
 document.body.insertAdjacentHTML('afterend', 'form would submit')
  console.log('form would submit', document.activeElement)
  e.preventDefault()
})