JSFiddle - React, Tailwind, and code Playground

HTML

<form id="frmMain">
    <label for="edQuantity">Quantity:</label>
    <input id="edQuantity" type="number" min="2" max="10" step="3" required
        onchange="edQuantityChange(this, event)" 
        onkeyup="edQuantityChange(this, event)"/>
    <br/><input type="submit" />
    <br/><button type="submit">Submit through button</button>
    <br><a href='javascript:DoFakeSubmit()'>Submit through javascript</a>
        
    <ul style="margin-top: 3em">
        <li>edQuantity.value = <span id="lblValue"></span>
        </li>
        <li>edQuantity.validity = <span id="lblValidity"></span>
        </li>
        <li>edQuantity.validity.valid = <span id="lblValidityValid"></span>
        </li>
        <li>edQuantity.validity.badInput = <span id="lblValidityBadInput"></span>
        </li>
        <li>edQuantity.validity.rangeUnderflow = <span id="lblValidityRangeUnderflow"></span>
        </li>
        <li>edQuantity.validity.rangeOverflow = <span id="lblValidityRangeOverflow"></span>
        </li>
        <li>edQuantity.validity.patternMismatch = <span id="lblValidityPatternMismatch"></span>
        </li>
        <li>edQuantity.validity.stepMismatch = <span id="lblValidityStepMismatch"></span>
        </li>
    </ul>
</form>

CSS

:invalid {
    background-color: #FFCCCC;
}

JavaScript

function edQuantityChange(sender, event) {
    var value = sender.value;

    document.getElementById("lblValue").innerText = value;

    document.getElementById("lblValidity").innerText = sender.validity;
    if (sender.validity !== null) {
        document.getElementById("lblValidityValid").textContent = sender.validity.valid;
        document.getElementById("lblValidityBadInput").textContent = sender.validity.badInput;
        document.getElementById("lblValidityRangeUnderflow").textContent = sender.validity.rangeUnderflow;
        document.getElementById("lblValidityRangeOverflow").textContent = sender.validity.rangeOverflow;
        document.getElementById("lblValidityPatternMismatch").textContent = sender.validity.patternMismatch;
        document.getElementById("lblValidityStepMismatch").textContent = sender.validity.stepMismatch;
    }
}

function DoFakeSubmit()
{
    var form = document.getElementById('frmMain');
    if (form === null) 
       return;
    
    form.submit();
}