@chakra-ui/react#NumberInput TypeScript Examples
The following examples show how to use
@chakra-ui/react#NumberInput.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: NumberInputPreview.tsx From openchakra with MIT License | 6 votes |
NumberInputPreview = ({ component }: IProps) => {
const { props } = useInteractive(component)
return (
<NumberInput {...props}>
<NumberInputField />
<NumberInputStepper>
<NumberIncrementStepper />
<NumberDecrementStepper />
</NumberInputStepper>
</NumberInput>
)
}
Example #2
Source File: NumberControl.tsx From openchakra with MIT License | 6 votes |
NumberControl: React.FC<NumberControlPropsType> = ({
name,
label,
...props
}) => {
const { setValue } = useForm()
const value = usePropsSelector(name)
const onChange = useCallback(
(val: React.ReactText) => {
setValue(name, val)
},
[name, setValue],
)
return (
<FormControl htmlFor={name} label={label}>
<NumberInput size="sm" value={value} onChange={onChange} {...props} />
</FormControl>
)
}
Example #3
Source File: Position.tsx From dope-monorepo with GNU General Public License v3.0 | 5 votes |
Position = (props: {object: any}) => { const [x, setX] = useState(props.object.x); const [y, setY] = useState(props.object.y); useEffect(() => { if (x) props.object.x = x; if (y) props.object.y = y; }, [x, y]); return ( // <VStack> <div> Position XY <Flex> <NumberInput maxW='100px' mr='2rem' value={x} onChange={(s, n) => setX(n)}> <NumberInputField /> <NumberInputStepper> <NumberIncrementStepper /> <NumberDecrementStepper /> </NumberInputStepper> </NumberInput> <Slider flex='1' focusThumbOnChange={false} value={x} onChange={(n) => setX(n)} > <SliderTrack> <SliderFilledTrack /> </SliderTrack> <SliderThumb fontSize='sm' boxSize='32px' children={Math.round(x)} /> </Slider> </Flex> <Flex> <NumberInput maxW='100px' mr='2rem' value={y} onChange={(s, n) => setY(n)}> <NumberInputField /> <NumberInputStepper> <NumberIncrementStepper /> <NumberDecrementStepper /> </NumberInputStepper> </NumberInput> <Slider flex='1' focusThumbOnChange={false} value={y} onChange={(n) => setY(n)} > <SliderTrack> <SliderFilledTrack /> </SliderTrack> <SliderThumb fontSize='sm' boxSize='32px' children={Math.round(y)} /> </Slider> </Flex> </div> // </VStack> ) }
Example #4
Source File: index.tsx From formik-chakra-ui with MIT License | 5 votes |
NumberInputControl: FC<NumberInputControlProps> = React.forwardRef(
(
props: NumberInputControlProps,
ref: React.ForwardedRef<HTMLInputElement>
) => {
const {
name,
label,
showStepper = true,
children,
numberInputProps,
...rest
} = props;
const [field, { error, touched }] = useField(name);
const { setFieldValue } = useFormikContext();
const $setFieldValue = (name: string) => (value: any) =>
setFieldValue(name, value);
return (
<FormControl name={name} label={label} {...rest}>
<NumberInput
{...field}
id={name}
onChange={$setFieldValue(name)}
isInvalid={!!error && touched}
{...numberInputProps}
>
<NumberInputField name={name} ref={ref} />
{showStepper && (
<NumberInputStepper>
<NumberIncrementStepper />
<NumberDecrementStepper />
</NumberInputStepper>
)}
{children}
</NumberInput>
</FormControl>
);
}
)
Example #5
Source File: AvatarGroupPanel.tsx From openchakra with MIT License | 5 votes |
AvatarGroupPanel = () => {
const { setValue, setValueFromEvent } = useForm()
const size = usePropsSelector('size')
const spacing = usePropsSelector('spacing')
const max = usePropsSelector('max')
return (
<>
<FormControl label="Size" htmlFor="size">
<Select
name="size"
id="size"
size="sm"
value={size || ''}
onChange={setValueFromEvent}
>
<option>2xs</option>
<option>xs</option>
<option>sm</option>
<option>md</option>
<option>lg</option>
<option>xl</option>
<option>2xl</option>
</Select>
</FormControl>
<FormControl label="Spacing">
<Slider
onChange={value => setValue('spacing', value)}
min={-3}
max={6}
step={1}
defaultValue={spacing}
>
<SliderTrack>
<SliderFilledTrack />
</SliderTrack>
<SliderThumb />
</Slider>
</FormControl>
<FormControl label="max">
<NumberInput
size="sm"
onChange={value => setValue('max', value)}
value={max}
min={1}
>
<NumberInputField />
<NumberInputStepper>
<NumberIncrementStepper />
<NumberDecrementStepper />
</NumberInputStepper>
</NumberInput>
</FormControl>
</>
)
}
Example #6
Source File: index.tsx From jsonschema-editor-react with Apache License 2.0 | 4 votes |
AdvancedNumber: React.FunctionComponent<AdvancedItemStateProps> = (
props: React.PropsWithChildren<AdvancedItemStateProps>
) => {
const { itemStateProp } = props;
const changeEnumOtherValue = (value: string): string[] | null => {
const array = value.split("\n");
if (array.length === 0 || (array.length === 1 && !array[0])) {
return null;
}
return array;
};
const itemState = useState(itemStateProp);
const isEnumChecked = (itemState.value as JSONSchema7).enum !== undefined;
const enumData = (itemState.value as JSONSchema7).enum
? (itemState.enum.value as string[])
: [];
const enumValue = enumData?.join("\n");
return (
<Flex direction="column" wrap="nowrap">
<Stack
isInline
alignItems="center"
justifyContent="center"
alignContent="center"
m={1}
>
<FormLabel mr={2}>Default: </FormLabel>
<NumberInput
size="sm"
defaultValue={Number(itemState.default.value)}
placeholder="Default value"
onChange={(value: number | string) => {
itemState.default.set(Number(value));
}}
>
<NumberInputField value={Number(itemState.default.value)} />
<NumberInputStepper>
<NumberIncrementStepper />
<NumberDecrementStepper />
</NumberInputStepper>
</NumberInput>
</Stack>
<Stack
isInline
alignItems="center"
justifyContent="center"
alignContent="center"
m={1}
>
<FormLabel mr={2}>Min Value: </FormLabel>
<NumberInput
size="sm"
defaultValue={Number(itemState.minimum.value)}
onChange={(value: number | string) => {
itemState.minimum.set(Number(value));
}}
>
<NumberInputField value={Number(itemState.minimum.value)} />
<NumberInputStepper>
<NumberIncrementStepper />
<NumberDecrementStepper />
</NumberInputStepper>
</NumberInput>
<FormLabel mr={2}>Max Value: </FormLabel>
<NumberInput
size="sm"
defaultValue={Number(itemState.maximum.value)}
onChange={(value: number | string) => {
itemState.maximum.set(Number(value));
}}
>
<NumberInputField value={Number(itemState.maximum.value)} />
<NumberInputStepper>
<NumberIncrementStepper />
<NumberDecrementStepper />
</NumberInputStepper>
</NumberInput>
</Stack>
<Stack
isInline
alignItems="center"
justifyContent="center"
alignContent="center"
m={1}
>
<FormLabel mr={2}>Enum: </FormLabel>
<Checkbox
isChecked={isEnumChecked}
onChange={(evt: React.ChangeEvent<HTMLInputElement>) => {
if (!evt.target.checked) {
itemState.enum.set(none);
} else {
itemState.enum.set(Array<string>());
}
}}
/>
<Textarea
value={enumValue}
isDisabled={!isEnumChecked}
placeholder="ENUM Values - One Entry Per Line"
type={"number"}
onChange={(evt: React.ChangeEvent<HTMLTextAreaElement>) => {
const re = /^[0-9\n]+$/;
if (evt.target.value === "" || re.test(evt.target.value)) {
const update = changeEnumOtherValue(evt.target.value);
if (update === null) {
itemState.enum.set(none);
} else {
itemState.enum.set(update as string[]);
}
}
}}
/>
</Stack>
</Flex>
);
}
Example #7
Source File: index.tsx From jsonschema-editor-react with Apache License 2.0 | 4 votes |
AdvancedString: React.FunctionComponent<AdvancedItemStateProps> = (
props: React.PropsWithChildren<AdvancedItemStateProps>
) => {
const { itemStateProp } = props;
const changeEnumOtherValue = (value: string): string[] | null => {
const array = value.split("\n");
if (array.length === 0 || (array.length === 1 && !array[0])) {
return null;
}
return array;
};
const itemState = useState(itemStateProp);
const isEnumChecked = (itemState.value as JSONSchema7).enum !== undefined;
const enumData = (itemState.value as JSONSchema7).enum
? (itemState.enum.value as string[])
: [];
const enumValue = enumData?.join("\n");
return (
<Flex direction="column" wrap="nowrap">
<Stack
isInline
alignItems="center"
justifyContent="center"
alignContent="center"
m={1}
>
<FormLabel mr={2}>Default: </FormLabel>
<Input
id="default"
placeholder="Default value"
value={(itemState.default.value as string) ?? ""}
onChange={(evt: React.ChangeEvent<HTMLInputElement>) => {
itemState.default.set(evt.target.value);
}}
/>
</Stack>
<Stack
isInline
alignItems="center"
justifyContent="center"
alignContent="center"
m={1}
>
<FormLabel mr={2}>Min Length: </FormLabel>
<NumberInput
size="sm"
defaultValue={Number(itemState.minLength.value)}
onChange={(value: number | string) => {
itemState.minLength.set(Number(value));
}}
>
<NumberInputField value={Number(itemState.minLength.value)} />
<NumberInputStepper>
<NumberIncrementStepper />
<NumberDecrementStepper />
</NumberInputStepper>
</NumberInput>
<FormLabel mr={2}>Max Length: </FormLabel>
<NumberInput
size="sm"
defaultValue={Number(itemState.maxLength.value)}
onChange={(value: number | string) => {
itemState.maxLength.set(Number(value));
}}
>
<NumberInputField value={Number(itemState.maxLength.value)} />
<NumberInputStepper>
<NumberIncrementStepper />
<NumberDecrementStepper />
</NumberInputStepper>
</NumberInput>
</Stack>
<Stack
isInline
alignItems="center"
justifyContent="center"
alignContent="center"
m={1}
>
<FormLabel mr={2} htmlFor="pattern">
Pattern:{" "}
</FormLabel>
<Input
id="pattern"
placeholder="MUST be a valid regular expression."
value={itemState.pattern.value ?? ""}
onChange={(evt: React.ChangeEvent<HTMLInputElement>) => {
itemState.pattern.set(evt.target.value);
}}
/>
</Stack>
<Stack
isInline
alignItems="center"
justifyContent="center"
alignContent="center"
m={1}
>
<FormLabel mr={2}>Enum: </FormLabel>
<Checkbox
isChecked={isEnumChecked}
onChange={(evt: React.ChangeEvent<HTMLInputElement>) => {
if (!evt.target.checked) {
itemState.enum.set(none);
} else {
itemState.enum.set(Array<string>());
}
}}
/>
<Textarea
value={enumValue || ""}
isDisabled={!isEnumChecked}
placeholder="ENUM Values - One Entry Per Line"
onChange={(evt: React.ChangeEvent<HTMLTextAreaElement>) => {
const update = changeEnumOtherValue(evt.target.value);
if (update === null) {
itemState.enum.set(none);
} else {
itemState.enum.set(update as string[]);
}
}}
/>
</Stack>
<Stack
isInline
alignItems="center"
justifyContent="center"
alignContent="center"
m={1}
>
<FormLabel mr={2} htmlFor="format">
Format:{" "}
</FormLabel>
<Select
variant="outline"
value={itemState.format.value ?? ""}
size="sm"
margin={2}
placeholder="Choose data type"
onChange={(evt: React.ChangeEvent<HTMLSelectElement>) => {
if (evt.target.value === "") {
itemState.format.set(none);
} else {
itemState.format.set(evt.target.value);
}
}}
>
{StringFormat.map((item, index) => {
return (
<option key={String(index)} value={item.name}>
{item.name}
</option>
);
})}
</Select>
</Stack>
</Flex>
);
}
Example #8
Source File: EditRewardsDistributorModal.tsx From rari-dApp with GNU Affero General Public License v3.0 | 4 votes |
EditRewardsDistributorModal = ({
rewardsDistributor,
pool,
isOpen,
onClose,
}: {
rewardsDistributor: RewardsDistributor;
pool: FusePoolData;
isOpen: boolean;
onClose: () => any;
}) => {
const { t } = useTranslation();
const { address, fuse } = useRari();
const rewardsDistributorInstance = useRewardsDistributorInstance(
rewardsDistributor.address
);
const tokenData = useTokenData(rewardsDistributor.rewardToken);
const isAdmin = address === rewardsDistributor.admin;
// Balances
const { data: balanceERC20 } = useTokenBalance(
rewardsDistributor.rewardToken,
rewardsDistributor.address
);
const { data: myBalance } = useTokenBalance(rewardsDistributor.rewardToken);
const toast = useToast();
// Inputs
const [sendAmt, setSendAmt] = useState<number>(0);
const [supplySpeed, setSupplySpeed] = useState<number>(0.001);
const [borrowSpeed, setBorrowSpeed] = useState<number>(0.001);
// Loading states
const [fundingDistributor, setFundingDistributor] = useState(false);
const [seizing, setSeizing] = useState(false);
const [changingSpeed, setChangingSpeed] = useState(false);
const [changingBorrowSpeed, setChangingBorrowSpeed] = useState(false);
const [selectedAsset, setSelectedAsset] = useState<
USDPricedFuseAsset | undefined
>(pool?.assets[0] ?? undefined);
// RewardsSpeeds
const [supplySpeedForCToken, borrowSpeedForCToken] = useRewardSpeedsOfCToken(
rewardsDistributor.address,
selectedAsset?.cToken
);
const { hasCopied, onCopy } = useClipboard(rewardsDistributor?.address ?? "");
// Sends tokens to distributor
const fundDistributor = async () => {
// Create ERC20 instance of rewardToken
const token = new fuse.web3.eth.Contract(
JSON.parse(
fuse.compoundContracts["contracts/EIP20Interface.sol:EIP20Interface"]
.abi
),
rewardsDistributor.rewardToken
);
setFundingDistributor(true);
try {
await token.methods
.transfer(
rewardsDistributor.address,
Fuse.Web3.utils
.toBN(sendAmt)
.mul(
Fuse.Web3.utils
.toBN(10)
.pow(Fuse.Web3.utils.toBN(tokenData?.decimals ?? 18))
)
)
.send({
from: address,
});
setFundingDistributor(false);
} catch (err) {
handleGenericError(err, toast);
setFundingDistributor(false);
}
};
// Adds LM to supply side of a CToken in this fuse pool
const changeSupplySpeed = async () => {
try {
if (!isAdmin) throw new Error("User is not admin of this Distributor!");
setChangingSpeed(true);
await rewardsDistributorInstance.methods
._setCompSupplySpeed(
selectedAsset?.cToken,
Fuse.Web3.utils.toBN(supplySpeed * 10 ** (tokenData?.decimals ?? 18)) // set supplySpeed to 0.001e18 for now
)
.send({ from: address });
setChangingSpeed(false);
} catch (err) {
handleGenericError(err, toast);
setChangingSpeed(false);
}
};
// Adds LM to supply side of a CToken in this fuse pool
const changeBorrowSpeed = async () => {
try {
if (!isAdmin) throw new Error("User is not admin of this Distributor!");
setChangingBorrowSpeed(true);
await rewardsDistributorInstance.methods
._setCompBorrowSpeed(
selectedAsset?.cToken,
Fuse.Web3.utils.toBN(borrowSpeed * 10 ** (tokenData?.decimals ?? 18)) // set supplySpeed to 0.001e18 for now
)
.send({ from: address });
setChangingBorrowSpeed(false);
} catch (err) {
handleGenericError(err, toast);
setChangingBorrowSpeed(false);
}
};
const handleSeizeTokens = async () => {
setSeizing(true);
if (isAdmin) {
await rewardsDistributorInstance.methods._grantComp(
address,
balanceERC20
);
} else {
toast({
title: "Admin Only!",
description: "Only admin can seize tokens!",
status: "error",
duration: 9000,
isClosable: true,
position: "top-right",
});
}
setSeizing(false);
};
return (
<Modal
motionPreset="slideInBottom"
isOpen={isOpen}
onClose={onClose}
isCentered
>
<ModalOverlay />
<ModalContent {...MODAL_PROPS}>
<Heading fontSize="27px" my={4} textAlign="center">
{t("Edit Rewards Distributor")}
</Heading>
<ModalDivider />
{/* RewardToken data */}
<Column
mainAxisAlignment="flex-start"
crossAxisAlignment="center"
p={4}
>
<>
{tokenData?.logoURL ? (
<Image
mt={4}
src={tokenData.logoURL}
boxSize="50px"
borderRadius="50%"
backgroundImage={`url(${SmallWhiteCircle})`}
backgroundSize="100% auto"
/>
) : null}
<Heading
my={tokenData?.symbol ? 3 : 6}
fontSize="22px"
color={tokenData?.color ?? "#FFF"}
>
{tokenData ? tokenData.name ?? "Invalid Address!" : "Loading..."}
</Heading>
<Text>
{balanceERC20 && tokenData && tokenData.decimals
? (
parseFloat(balanceERC20?.toString()) /
10 ** tokenData.decimals
).toFixed(3)
: 0}{" "}
{tokenData?.symbol}
</Text>
<Text onClick={onCopy}>
Contract: {shortAddress(rewardsDistributor.address)}{" "}
{hasCopied && "Copied!"}
</Text>
</>
</Column>
<AdminAlert
isAdmin={isAdmin}
mt={2}
isNotAdminText="You are not the admin of this RewardsDistributor. Only the admin can configure rewards."
/>
{/* Basic Info */}
<Column
mainAxisAlignment="flex-start"
crossAxisAlignment="flex-start"
py={4}
>
{/* <Row mainAxisAlignment="flex-start" crossAxisAlignment="center">
<Text>Address: {rewardsDistributor.address}</Text>
</Row>
<Row mainAxisAlignment="flex-start" crossAxisAlignment="center">
<Text>Admin: {rewardsDistributor.admin}</Text>
</Row>
<Row mainAxisAlignment="flex-start" crossAxisAlignment="center">
<Text>
Balance:{" "}
{balanceERC20 ? parseFloat(balanceERC20?.toString()) / 1e18 : 0}{" "}
{tokenData?.symbol}
</Text>
</Row> */}
<ModalDivider />
{/* Fund distributor */}
<Column
mainAxisAlignment="flex-start"
crossAxisAlignment="flex-start"
p={4}
>
<Heading fontSize={"lg"}> Fund Distributor </Heading>
<Row
mainAxisAlignment="flex-start"
crossAxisAlignment="center"
mt={1}
>
<NumberInput
step={0.1}
min={0}
onChange={(valueString) => {
console.log({ valueString });
setSendAmt(parseFloat(valueString));
}}
>
<NumberInputField
width="100%"
textAlign="center"
placeholder={"0 " + tokenData?.symbol}
/>
<NumberInputStepper>
<NumberIncrementStepper />
<NumberDecrementStepper />
</NumberInputStepper>
</NumberInput>
<Button
onClick={fundDistributor}
bg="black"
disabled={fundingDistributor}
>
{fundingDistributor ? <Spinner /> : "Send"}
</Button>
{isAdmin && (!balanceERC20?.isZero() ?? false) && (
<Button onClick={handleSeizeTokens} bg="red" disabled={seizing}>
{seizing ? <Spinner /> : "Withdraw Tokens"}
</Button>
)}
</Row>
<Text mt={1}>
Your balance:{" "}
{myBalance
? (
parseFloat(myBalance?.toString()) /
10 ** (tokenData?.decimals ?? 18)
).toFixed(2)
: 0}{" "}
{tokenData?.symbol}
</Text>
</Column>
{/* Add or Edit a CToken to the Distributor */}
{pool.assets.length ? (
<Column
mainAxisAlignment="flex-start"
crossAxisAlignment="flex-start"
p={4}
>
<Heading fontSize={"lg"}> Manage CToken Rewards </Heading>
{/* Select Asset */}
<Row
mainAxisAlignment="flex-start"
crossAxisAlignment="center"
mt={1}
>
{pool.assets.map(
(asset: USDPricedFuseAsset, index: number, array: any[]) => {
return (
<Box
pr={index === array.length - 1 ? 4 : 2}
key={asset.cToken}
flexShrink={0}
>
<DashboardBox
as="button"
onClick={() => setSelectedAsset(asset)}
{...(asset.cToken === selectedAsset?.cToken
? activeStyle
: noop)}
>
<Center expand px={4} py={1} fontWeight="bold">
{asset.underlyingSymbol}
</Center>
</DashboardBox>
</Box>
);
}
)}
</Row>
{/* Change Supply Speed */}
<Column
mainAxisAlignment="flex-start"
crossAxisAlignment="flex-start"
py={3}
>
<Row
mainAxisAlignment="flex-start"
crossAxisAlignment="flex-start"
>
<NumberInput
step={0.1}
min={0}
onChange={(supplySpeed) => {
console.log({ supplySpeed });
setSupplySpeed(parseFloat(supplySpeed));
}}
>
<NumberInputField
width="100%"
textAlign="center"
placeholder={"0 " + tokenData?.symbol}
/>
<NumberInputStepper>
<NumberIncrementStepper />
<NumberDecrementStepper />
</NumberInputStepper>
</NumberInput>
<Button
onClick={changeSupplySpeed}
bg="black"
disabled={changingSpeed || !isAdmin}
>
{changingSpeed ? <Spinner /> : "Set"}
</Button>
</Row>
<Row
mainAxisAlignment="flex-start"
crossAxisAlignment="flex-start"
>
<Text>
Supply Speed:{" "}
{(parseFloat(supplySpeedForCToken) / 1e18).toFixed(4)}
</Text>
</Row>
</Column>
{/* Change Borrow Speed */}
<Column
mainAxisAlignment="flex-start"
crossAxisAlignment="flex-start"
py={3}
>
<Row
mainAxisAlignment="flex-start"
crossAxisAlignment="flex-start"
>
<NumberInput
step={0.1}
min={0}
onChange={(borrowSpeed) => {
console.log({ borrowSpeed });
setBorrowSpeed(parseFloat(borrowSpeed));
}}
>
<NumberInputField
width="100%"
textAlign="center"
placeholder={"0 " + tokenData?.symbol}
/>
<NumberInputStepper>
<NumberIncrementStepper />
<NumberDecrementStepper />
</NumberInputStepper>
</NumberInput>
<Button
onClick={changeBorrowSpeed}
bg="black"
disabled={changingBorrowSpeed || !isAdmin}
>
{changingBorrowSpeed ? <Spinner /> : "Set"}
</Button>
</Row>
<Row
mainAxisAlignment="flex-start"
crossAxisAlignment="flex-start"
>
<Text>
Borrow Speed:{" "}
{(parseFloat(borrowSpeedForCToken) / 1e18).toFixed(2)}
</Text>
</Row>
</Column>
</Column>
) : (
<Center p={4}>
<Text fontWeight="bold">
Add CTokens to this pool to configure their rewards.
</Text>
</Center>
)}
</Column>
</ModalContent>
</Modal>
);
}
Example #9
Source File: HairSelector.tsx From dope-monorepo with GNU General Public License v3.0 | 4 votes |
HairSelector = ({ config, setHustlerConfig }: ConfigureHustlerProps) => {
const isMale = config.sex == 'male';
return (
<div>
<Flex gridGap={4}>
<Box width="100px" borderBottom="1px solid #EFEFEF" paddingBottom="16px">
<FormLabel htmlFor="hair" color="blackAlpha.900" fontSize="14px">
Hair
</FormLabel>
<NumberInput
backgroundColor="#CCC"
height="60px"
maxWidth="90px"
boxShadow="0 0 0 2px black"
border="none"
borderRadius="8px"
name="hair"
defaultValue={0}
min={0}
max={MAX_HAIR}
onChange={value => setHustlerConfig({ ...config, hair: parseInt(value) })}
value={config.hair}
color="blackAlpha.900"
>
<ImageWrapper>
<Image height="100%" width="100%" alt="hair" src="/images/config/hair.png" />
</ImageWrapper>
<NumberInputStepper borderLeft="2px solid black">
<NumberIncrementStepper
backgroundColor="#EFEFEF"
boxShadow={`inset -1px -1px 0px rgba(0, 0, 0, 0.25), inset 1px 1px 0px rgba(255, 255, 255, 0.25);`}
borderRight="1px solid #b3b3b3"
borderBottom="2px solid #b3b3b3"
height="30px"
/>
<NumberDecrementStepper
backgroundColor="#EFEFEF"
boxShadow={`inset -1px -1px 0px rgba(0, 0, 0, 0.25), inset 1px 1px 0px rgba(255, 255, 255, 0.25);`}
borderTop="2px solid black"
borderRight="1px solid #b3b3b3"
borderBottom="1px solid #b3b3b3"
height="30px"
/>
</NumberInputStepper>
</NumberInput>
</Box>
{/* Only render Facial Hair for Males */}
{isMale && (
<Box width="100px" borderBottom="1px solid #EFEFEF" paddingBottom="16px">
<FormLabel htmlFor="facial_hair" color="blackAlpha.900" fontSize="14px">
Facial Hair
</FormLabel>
<NumberInput
backgroundColor="#CCC"
height="60px"
maxWidth="90px"
boxShadow="0 0 0 2px black"
border="none"
borderRadius="8px"
name="facial_hair"
defaultValue={0}
min={0}
max={MAX_FACIAL_HAIR}
onChange={value => setHustlerConfig({ ...config, facialHair: parseInt(value) })}
value={config.facialHair}
color="blackAlpha.900"
>
<ImageWrapper>
<Image
height="100%"
width="100%"
alt="facial-hair"
src="/images/config/facial-hair.png"
/>
</ImageWrapper>
<NumberInputStepper>
<NumberIncrementStepper
backgroundColor="#EFEFEF"
boxShadow={`inset -1px -1px 0px rgba(0, 0, 0, 0.25), inset 1px 1px 0px rgba(255, 255, 255, 0.25);`}
borderRight="1px solid #b3b3b3"
borderBottom="2px solid #b3b3b3"
height="30px"
/>
<NumberDecrementStepper
backgroundColor="#EFEFEF"
boxShadow={`inset -1px -1px 0px rgba(0, 0, 0, 0.25), inset 1px 1px 0px rgba(255, 255, 255, 0.25);`}
borderTop="2px solid black"
borderRight="1px solid #b3b3b3"
borderBottom="1px solid #b3b3b3"
height="30px"
/>
</NumberInputStepper>
</NumberInput>
</Box>
)}
</Flex>
</div>
);
}