QuantityButton
A quantity field with a decrease and increase button on either side.
Used to display any entity quantity and let the user change it, either with the buttons or by typing
into the field. onValueChange reports the new quantity for both.
The quantity is held to min and max: the buttons disable at each end, a typed value is capped,
and an emptied field settles on min when it loses focus. Arrow keys, PageUp/PageDown and
Home/End work too, and holding a button repeats it.
The field needs an accessible name — pass aria-label, or id with a label of your own pointing at
it.
Component usage
Section titled “Component usage”import { QuantityButton } from "@caspeco/casper-ui-library";import { useState } from "react";
export default function Demo() { const [quantity, setQuantity] = useState(2);
return ( <QuantityButton value={quantity} onValueChange={setQuantity} min={1} max={20} aria-label="quantity" /> );}import { Grid, QuantityButton, Stack, Text, ThemeColor, ThemeFontSize } from "@caspeco/casper-ui-library";import { useState } from "react";
const sizes = ["sm", "lg"] as const;
export default function Demo() { const [quantities, setQuantities] = useState<Record<(typeof sizes)[number], number>>({ sm: 2, lg: 2, });
return ( <Stack gap="8px"> <Grid templateColumns="repeat(2, auto)" gap="16px" alignItems="center" justifyItems="center" border="1px solid" borderColor={ThemeColor.OnBackgroundSubdued} padding="16px" borderRadius="8px" > {sizes.map((size) => ( <Text key={`${size}-header`} fontSize={ThemeFontSize.Small} textAlign="center" color={ThemeColor.OnBackgroundHeader} > {size.toUpperCase()} </Text> ))}
{sizes.map((size) => ( <QuantityButton key={size} size={size} value={quantities[size]} onValueChange={(value) => setQuantities((prev) => ({ ...prev, [size]: value }))} min={1} max={20} aria-label={`quantity (${size})`} /> ))} </Grid> </Stack> );}