Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

  • Long press on up/down buttons - will enable faster continuous increment or decrement.

States

State

Image

Comment

Regular

Image Modified

Hover

Image ModifiedImage ModifiedImage Modified

Active

Image ModifiedImage ModifiedImage Modified

Disabled

Image Modified

Read-Only

Numeric Stepper.pngImage Added

Error

Image Modified

Warning

Image Modified

Focused

Image Modified

Focused, Hover

Image ModifiedImage ModifiedImage Modified

Focused, Active

Image ModifiedImage ModifiedImage Modified

Focused, Disabled

Image Modified

Interaction

  • Clicking the up/down buttons will increase or decrease the value by the defined interval:

Image ModifiedImage Modified
  • When the number field is empty:

    • clicking the up button will populate the field with a value one interval above the minimum.

    • clicking the down button will populate the field with the minimum value.

  • Focusing on the number field using the mouse pointer, a text cursor will appear in the position the user clicks:

Image Modified
  • Focusing on the number field using Tab, the whole number will be selected to allow quick entry of a new value:

Image Modified
  • While focused on the number field, the up/down keys on the keyboard will increase/decrease the value. The number field will remain focused and the text cursor will remain in place.

  • The user may enter a numeric value using the keyboard.

  • When the numeric stepper is selected, the user can use the mouse wheel to increase/decrease the value.

  • Long press on up/down buttons will enable faster continuous increment or decrement.

  • Pressing the Tab key or clicking outside of the control will move the focus away from the stepper and set the defined value (or the last valid value).

...

  • In the focus state, typing will enter a value

Keyboard

Description

Tab

Navigates to the next component.

Shift + tab

Navigates to the previous component.

Space

N/A

Enter

N/A

Esc

N/A

Arrows

  • Up/ Down - Increases or decreases the value accordingly.

  • Holding down the key will scroll continuously.

Home

Sets slider to its minimum value.

End

Sets slider to its maximum value.

Mouse

Date picker menu

Right click on numeric field

Set Focus on component

Design

Zeplin link

https://zpl.io/2p9kWgl

Image Modified

Code

Html macro
sanitizefalse
<link rel="stylesheet" href="https://ux.verint.com/bootstrap-4.0.0/dist/fonts/css/verint_lux.css">
<link rel="stylesheet" href="https://ux.verint.com/bootstrap-4.0.0/dist/css/bootstrap.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://ux.verint.com/bootstrap-4.0.0/dist/js/bootstrap.bundle.js"></script>
<script src="https://ux.verint.com/bootstrap-4.0.0/dist/other/accessibility.js"></script>
<script src="https://ux.verint.com/bootstrap-4.0.0/dist/other/prism.min.js"></script>
<link rel="stylesheet" href="https://ux.verint.com/bootstrap-4.0.0/dist/other/prism-coy.min.css">
			

<div class="card">
			<div class="card-header">Numeric Stepper <button id="toggleMarkup" type="button" class="btn btn-sm btn-outline-primary btn btn-fixed-width float-right m-0" onclick="$('pre' ).toggle()">Toggle Markup</button></div>
			<div class="card-body">
				<form>
					<div class="form-group row">
						<label for="inputKey" class="col-lg-2 col-form-label col-form-label-sm">Regular</label>
						<div class="col-lg-4">
							<div class="form-control-container">
								<input type="number" class="form-control form-control-sm" placeholder="Enter a number" min="0" max="100" value="0">
								<div class="btn-group btn-group-sm spinner-group">
								  <button type="button" class="btn btn-outline-light btn-sm increment" tabindex="-1">
								    <i class="icon-up"></i>
								  </button>
								  <button type="button" class="btn btn-outline-light btn-sm decrement" tabindex="-1">
								    <i class="icon-down"></i>
								  </button>
								</div>
							</div>
						</div>
						<div class="col-lg-6">
							<pre class="language-html"><code><script type="prism-html-markup"><div class="form-control-container">
	<input type="number" class="form-control form-control-sm" placeholder="Enter a number" min="0" max="100" value="0">
	<div class="btn-group btn-group-sm spinner-group">
		<button type="button" class="btn btn-outline-light btn-sm increment" tabindex="-1">
			<i class="icon-up"></i>
		</button>
		<button type="button" class="btn btn-outline-light btn-sm decrement" tabindex="-1">
			<i class="icon-down"></i>
		</button>
	</div>
</div></script></code></pre>
						</div>
					</div>
					<div class="form-group row">
						<label for="inputKey" class="col-lg-2 col-form-label col-form-label-sm">Disabled</label>
						<div class="col-lg-4">
							<div class="form-control-container">
								<input type="number" class="form-control form-control-sm" placeholder="Enter a number" min="0" max="100" value="0" disabled>
								<div class="btn-group btn-group-sm spinner-group">
								  <button type="button" class="btn btn-outline-light btn-sm increment" tabindex="-1" disabled>
								    <i class="icon-up"></i>
								  </button>
								  <button type="button" class="btn btn-outline-light btn-sm decrement" tabindex="-1" disabled>
								    <i class="icon-down"></i>
								  </button>
								</div>
							</div>
						</div>
						<div class="col-lg-6">
							<pre class="language-html"><code><script type="prism-html-markup"><div class="form-control-container">
	<input type="number" class="form-control form-control-sm" placeholder="Enter a number" min="0" max="100" value="0" disabled>
	<div class="btn-group btn-group-sm spinner-group">
		<button type="button" class="btn btn-outline-light btn-sm increment" tabindex="-1" disabled>
			<i class="icon-up"></i>
		</button>
		<button type="button" class="btn btn-outline-light btn-sm decrement" tabindex="-1" disabled>
			<i class="icon-down"></i>
		</button>
	</div>
</div></script></code></pre>
						</div>
					</div>
					<div class="form-group row">
						<label for="inputKey" class="col-lg-2 col-form-label col-form-label-sm">Read-Only</label>
						<div class="col-lg-4">
							<div class="form-control-container">
								<input type="number" class="form-control form-control-sm" placeholder="Enter a number" min="0" max="100" value="0" readonly>
								<div class="btn-group btn-group-sm spinner-group">
								  <button type="button" class="btn btn-outline-light btn-sm increment" tabindex="-1" disabled>
								    <i class="icon-up"></i>
								  </button>
								  <button type="button" class="btn btn-outline-light btn-sm decrement" tabindex="-1" disabled>
								    <i class="icon-down"></i>
								  </button>
								</div>
							</div>
						</div>
						<div class="col-lg-6">
							<pre class="language-html"><code><script type="prism-html-markup"><div class="form-control-container">
	<input type="number" class="form-control form-control-sm" placeholder="Enter a number" min="0" max="100" value="0" readonly>
	<div class="btn-group btn-group-sm spinner-group">
		<button type="button" class="btn btn-outline-light btn-sm increment" tabindex="-1" disabled>
			<i class="icon-up"></i>
		</button>
		<button type="button" class="btn btn-outline-light btn-sm decrement" tabindex="-1" disabled>
			<i class="icon-down"></i>
		</button>
	</div>
</div></script></code></pre>
						</div>
					</div>
					<div class="form-group row">
						<label for="inputKey" class="col-lg-2 col-form-label col-form-label-sm">Warning</label>
						<div class="col-lg-4">
							<div class="form-control-container">
								<input type="number" class="form-control form-control-sm is-warning" placeholder="Enter a number" min="0" max="100" value="0">
								<div class="btn-group btn-group-sm spinner-group">
								  <button type="button" class="btn btn-outline-light btn-sm is-warning increment" tabindex="-1">
								    <i class="icon-up"></i>
								  </button>
								  <button type="button" class="btn btn-outline-light btn-sm is-warning decrement" tabindex="-1">
								    <i class="icon-down"></i>
								  </button>
								</div>
							</div>
						</div>
						<div class="col-lg-6">
							<pre class="language-html"><code><script type="prism-html-markup"><div class="form-control-container">
	<input type="number" class="form-control form-control-sm is-warning" placeholder="Enter a number" min="0" max="100" value="0">
	<div class="btn-group btn-group-sm spinner-group">
		<button type="button" class="btn btn-outline-light btn-sm is-warning increment" tabindex="-1">
			<i class="icon-up"></i>
		</button>
		<button type="button" class="btn btn-outline-light btn-sm is-warning decrement" tabindex="-1">
			<i class="icon-down"></i>
		</button>
	</div>
</div></script></code></pre>
						</div>
					</div>
					<div class="form-group row">
						<label for="inputKey" class="col-lg-2 col-form-label col-form-label-sm">Error</label>
						<div class="col-lg-4">
							<div class="form-control-container">
								<input type="number" class="form-control form-control-sm is-invalid" placeholder="Enter a number" min="0" max="100" value="101">
								<div class="btn-group btn-group-sm spinner-group">
								  <button type="button" class="btn btn-outline-light btn-sm is-invalid increment" tabindex="-1">
								    <i class="icon-up"></i>
								  </button>
								  <button type="button" class="btn btn-outline-light btn-sm is-invalid decrement" tabindex="-1">
								    <i class="icon-down"></i>
								  </button>
								</div>
							</div>
						</div>
						<div class="col-lg-6">
							<pre class="language-html"><code><script type="prism-html-markup"><div class="form-control-container">
	<input type="number" class="form-control form-control-sm is-invalid" placeholder="Enter a number" min="0" max="100" value="101">
	<div class="btn-group btn-group-sm spinner-group">
		<button type="button" class="btn btn-outline-light btn-sm is-invalid increment" tabindex="-1">
			<i class="icon-up"></i>
		</button>
		<button type="button" class="btn btn-outline-light btn-sm is-invalid decrement" tabindex="-1">
			<i class="icon-down"></i>
		</button>
	</div>
</div></script></code></pre>
						</div>
					</div>
				</form>
			</div>
		</div>



<script>
// Spinner
		jQuery.propHooks.disabled = {
		  set: function (el, value) {
		    if (el.disabled !== value) {
		      el.disabled = value;
		      value && $(el).trigger('disabledSet');
		      !value && $(el).trigger('enabledSet');
		    }
		  }
		};
		
		$('.form-control[type="number"]').on('keypress', function(e){
		  return e.metaKey || // cmd/ctrl
		    e.which <= 0 || // arrow keys
		    e.which == 8 || // delete key
		    /[0-9]/.test(String.fromCharCode(e.which)); // numbers
		});
		
		$('.form-control[type="number"]').on('input', function(e){
		  	if(!($(this).is(':disabled') || $(this).is('[readonly]'))) {
		        let disableMinButton = (Number(this.value)) <= Math.abs(this.getAttribute('min'));
		      	$(this).siblings('.spinner-group').find('.decrement').prop("disabled", disableMinButton);
		      	
		      	let disableMaxButton = (Number(this.value)) >= Math.abs(this.getAttribute('max'));
		      	$(this).siblings('.spinner-group').find('.increment').prop("disabled", disableMaxButton);
	        }

		  	$(this).toggleClass('is-invalid', $(this).is(':invalid'));
		  	$(this).siblings('.spinner-group').find('button').toggleClass('is-invalid', $(this).is(':invalid'));
		});
		
		$('.form-control[type="number"]').trigger("input"); // update bars at startup
			
		function incr(elem) {
			stepper = $(elem).closest('.form-control-container').find('.form-control[type="number"]');
			stepper.get(0).stepUp(1);
			stepper.trigger("input");
		}
		
		function decr(elem) {
			stepper = $(elem).closest('.form-control-container').find('.form-control[type="number"]');
			stepper.get(0).stepDown(1);
			stepper.trigger("input");
		}
		
		var increment = $(".spinner-group .increment");
		
		increment.on( "click", function() {
			incr(this);
		});
		
		var decrement = $(".spinner-group .decrement");
		
		decrement.on( "click", function() {
			decr(this);
		});
		
		var incrTimeoutId = 0;
		
		$(increment).on('mousedown', function() {
			incrTimeoutId = setTimeout(() => {incrTimeoutId = setInterval(() => {incr(this);}, 40);}, 250);
		}).on('mouseup mouseleave disabledSet', function() {
		    clearTimeout(incrTimeoutId);
		});
		
		var decrTimeoutId = 0;
		
		$(decrement).on('mousedown', function() {
			decrTimeoutId = setTimeout(() => {decrTimeoutId = setInterval(() => {decr(this);}, 40);}, 250);
		}).on('mouseup mouseleave disabledSet', function() {
		    clearTimeout(decrTimeoutId);
		});
</script>

...