A macOS stepper (NSStepper): two stacked segments that increment and decrement a number. Press-and-hold auto-repeats with acceleration. The whole control is a single tab stop with role="spinbutton"; the segments themselves stay out of the tab order — keyboard users step with the arrow keys: Up/Down move by step, Home/End jump to min/max.
The classic AppKit pairing — a text field and a stepper over one value. A dedicated number-field composite is planned; until then the pairing is a pattern.
vue
<script setup lang="ts">import { MacStepper, MacTextField } from '@macvue/core'import { computed, ref } from 'vue'const copies = ref(1)// The classic AppKit pairing: a text field and a stepper share one value.const text = computed({ get: () => String(copies.value), set: (value) => { const parsed = Number.parseInt(value, 10) if (!Number.isNaN(parsed)) copies.value = Math.min(99, Math.max(1, parsed)) },})</script><template> <div style="display: flex; align-items: center; gap: 4px"> <MacTextField v-model="text" aria-label="Copies" style="width: 60px" /> <MacStepper v-model="copies" :min="1" :max="99" aria-label="Adjust copies" /> </div></template>
wraps mirrors NSStepper.valueWraps: stepping past a bound continues from the opposite one. With name set, the stepper renders a hidden input inside a <form> and participates in native form submission.