# Stepper
Ô tăng/giảm số lượng gồm nút −, ô nhập số và nút +, dùng khi lên kế hoạch số phần mỗi món.
## Khi nào dùng
- Chỉnh một số nguyên trong khoảng [min, max], ví dụ số phần Trà sữa cần chuẩn bị.
- Cho phép cả bấm nút lẫn gõ trực tiếp số.
## Biến thể
| Biến thể | Lớp | Dùng khi |
|---|---|---|
| Mặc định | `tt-stepper` | Nút 30×32, ô số rộng 46px |
## Cấu trúc
```html
```
Nút − là `.tt-stepper__btn` đầu tiên, nút + là cái cuối.
## Trạng thái
| Trạng thái | Hiệu ứng |
|---|---|
| Chạm biên | Nút tương ứng `disabled` (opacity .4) |
| Focus | Vòng `focus-ring` 3px trên nút hoặc ô số |
## Hành vi JS
```js
var s = TTMU.stepper(el, { min: 0, max: 99, step: 5, onChange: function (v) {} });
s.value; // số hiện tại
s.set(12); // đặt, kẹp trong [min, max]
```
- Mặc định `min = 0`, `max = ∞`, `step = 1`. Gõ số lạ khi rời ô thì quay về giá trị cũ.
- Gắn một lần (`data-tt-bound`); trả về `{ value, set(n), destroy() }`.
- **Quy ước `onChange`:** chỉ thao tác của người dùng mới gọi `onChange`, và chỉ khi giá trị thật sự đổi; `set()` từ code thì im lặng.
## Token sử dụng
`line`, `bg`, `ink`, `radius-8`, cùng token của Button `--small`.
## Khả năng tiếp cận
- Nút có `aria-label` "Bớt"/"Thêm" (nên kèm tên món ở ô số: "Số phần Trà sữa").
- `inputmode="numeric"` mở bàn phím số trên điện thoại; nút spin mặc định bị ẩn.
## Nên / Không nên
| Nên | Không nên |
|---|---|
| Đặt `min`/`max` rõ ràng | Để người chơi nhập số âm |
| Dùng `aria-label` có tên món cho ô số | Dùng "+"/"−" không có nhãn |
## Nguồn
`.step5`, `.step5 .sbtn`, `.step5 input` (+ ẩn spin button) — css/style.css; markup trong js/game.js (`data-d`, `data-v`).
- Nút gốc là `.sbtn` nên Stepper dùng `tt-button tt-button--small` cộng `tt-stepper__btn`.
- Game cộng/trừ 5 mỗi lần bấm; ở đây là tuỳ chọn `step`.