feat(ui): Add thousands separator formatting to item amount input#1927
Conversation
… adjacent to thousands separator
|
Thank you for the feedback! I've pushed a fix that addresses this. Previously, pressing Backspace or Delete adjacent to a comma only moved the cursor without modifying the value, causing it to reset to the end. The updated behavior now deletes the comma together with the adjacent digit: Backspace after a comma (e.g. "12,|345") → removes 2, → "1,345" |
|
@Maximus7474 |
unitysync
left a comment
There was a problem hiding this comment.
this can be done with significantly less code. something like this would be good. (ive truncated the unchanged code, however it should be a simply copy and paste into the file)
const formatAmount = (n: number) => (n ? n.toLocaleString('en-US') : '')
const digitsOnly = (s: string) => s.replace(/\D/g, '')
const countDigitsBefore = (s: string, index: number) => digitsOnly(s.substring(0, index)).length
const itemAmount = useAppSelector(selectItemAmount)
const dispatch = useAppDispatch()
const [infoVisible, setInfoVisible] = useState(false)
const [value, setValue] = useState(formatAmount(itemAmount))
const inputRef = useRef<HTMLInputElement>(null)
const cursorRef = useRef<number | null>(null)
const commitValue = (raw: string, cursorIndex: number) => {
const digitsBefore = countDigitsBefore(raw, cursorIndex)
const num = parseInt(digitsOnly(raw), 10) || 0
setValue(formatAmount(num))
dispatch(setItemAmount(num))
cursorRef.current = digitsBefore
}
// use `handleChange` instead of `inputHandler` for naming consistency
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) =>
commitValue(event.target.value, event.target.selectionStart ?? 0)
const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
const el = event.currentTarget
const pos = el.selectionStart ?? 0
if (pos !== el.selectionEnd) return
if (event.key === 'Backspace' && el.value[pos - 1] === ',') {
event.preventDefault()
commitValue(el.value.slice(0, pos - 2) + el.value.slice(pos), pos - 2)
} else if (event.key === 'Delete' && el.value[pos] === ',') {
event.preventDefault()
commitValue(el.value.slice(0, pos) + el.value.slice(pos + 2), pos)
}
}
useEffect(() => {
if (!inputRef.current || cursorRef.current === null) return
let newPos = 0
let count = 0
for (let i = 0; i < value.length && count < cursorRef.current; i++) {
if (/\d/.test(value[i])) count++
newPos++
}
inputRef.current.setSelectionRange(newPos, newPos)
cursorRef.current = null
}, [value])```|
Thanks for the clean refactor suggestion! Applied it — much simpler now with commitValue centralizing the logic. Pushed! |

Summary
Replace the
type="number"input with atype="text"input for the itemamount field in
InventoryControl, and apply comma-separated thousandsformatting (e.g.
1,000,10,000) usingtoLocaleString('en-us').Changes
numbertotextuseRefanduseEffectMotivation
The default
numberinput does not display thousand separators, making itdifficult to read large quantities at a glance. This change improves
readability without affecting the underlying numeric value stored in state.
Testing
1000000) and verify it displays as1,000,0000Demo