Setting "max" on an Input with type "number" in Chakra-UI - reactjs

While building a user interface with a few inputs, I decided to migrate the base input components to form a single component I can use, while that's not really the problem. Here's the code for it. For easy and memorable use for Inputs.
import {
FormControl,
FormErrorMessage,
FormHelperText,
FormLabel,
Input,
} from "#chakra-ui/react";
const DefaultInput = ({
isInvalid,
label,
helperText,
errorMessage,
...otherProps
}) => {
return (
<FormControl isInvalid={isInvalid}>
{label && <FormLabel>{label}</FormLabel>}
<Input
variant="outline"
padding="25px 10px"
margin="10px 0px"
border={"0px"}
{...(isInvalid && { border: "0px" })}
{...otherProps}
/>
{!isInvalid ? (
<FormHelperText>{helperText}</FormHelperText>
) : (
<FormErrorMessage>{errorMessage}</FormErrorMessage>
)}
</FormControl>
);
};
export default DefaultInput;
Used it like this but it doesn't seem to take notice of the "max" property.
<DefaultInput
value={custom.credits}
isInvalid={creditsError}
helperText={"Minimum of 50 Credits."}
errorMessage={"Please enter a valid number above 50."}
maxW={isNotSmallerScreen ? "50%" : "70%"}
fontSize={!isNotSmallerScreen ? "12px" : "16px"}
onChange={handleCustomCredit}
type="number"
placeholder="Enter Credits"
name="credits"
max="5000"
/>
I've also tried manually declaring the "max" and "type" within the component I created but still nothing.
.....
<Input
variant="outline"
padding="25px 10px"
margin="10px 0px"
border={"0px"}
max="5000"
type="number"
{...(isInvalid && { border: "0px" })}
{...otherProps}
/>
.....

This is actually a browser quirk and not related to Chakra. max HTML5 attribute won't actually restrict you from typing larger numbers until you submit the containing form. If you want to limit it on the fly you have to build out your own function.
Unless you aren't seeing anything on submit either? See this example of what you should see https://www.w3schools.com/tags/tryit.asp?filename=tryhtml5_input_max_min.

Related

Chakra UI icon not positioned inside Input

I'm trying to position an icon correctly in the middle of an input, where that input has size="xs". However, all my attempts have failed, and the icon keeps being positioned too low/down. I've also tried using IconButton instead of a regular icon but that didn't work either.
import { Input, InputGroup, InputLeftElement } from "#chakra-ui/react"
import { SearchIcon } from "#chakra-ui/icons"
// ...
<InputGroup>
<InputLeftElement
pointerEvents="none"
children={<SearchIcon color="gray.300"/>}
size="xs"
/>
<Input
variant="outline"
size="xs"
placeholder={``}
/>
</InputGroup>
What am I doing wrong?
Here's the codesandbox. Note that in this codesandbox, the icon is actually above the middle of Input (which is still wrong), instead of below as on my local machine.
https://codesandbox.io/s/optimistic-bartik-5ifsd?file=/src/App.tsx
You can solve the problem by adding className to chakra components and editing styles:
export default function App() {
return (
<InputGroup>
<InputLeftElement
className="InputLeft"
pointerEvents="none"
children={<SearchIcon className="SearchIcon" color="gray.300" />}
size="xs"
/>
<Input className="Input" variant="outline" size="xs" placeholder={``} />
</InputGroup>
);
}
And Here's the styles:
.InputLeft {
top: 3px !important;
left: 3px !important;
}
.Input {
padding-left: 24px !important;
}
If in your local, the icon is below the input. You can change the top to bottom in InputLeft class.
Here's the updated codesandbox :
This issue is solvable without CSS. You just have to add the size attribute to the InputGroup as well.
See the updated code sandbox.
<InputGroup size="xs">
<InputLeftElement
pointerEvents="none"
children={<SearchIcon color="gray.300" />}
size="xs"
/>
<Input variant="outline" size="xs" placeholder={``} />
</InputGroup>

CSSTransition not working with stripe elements React

I have a CSSTransition that works until I add the CardElement from "#stripe/react-stripe-js";
<CSSTransition
classNames="method"
in={radio === 'add-card'}
exit={!(radio === 'add-card')}
timeout={500}
unmountOnExit>
<form id="payment-form" onSubmit={handleSubmit} className="stripe-ad">
<input
type="text"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Enter Email Address (Optional)"
/>
<CardElement id="card-element" options={cardStyle} onChange={handleChange} />
{error && (
<div className="card-error" role="alert">
{error}
</div>
)}
<p className={succeeded ? "result-message" : "result-message hidden"}>
Payment succeeded, see the result in your
<a
href={`https://dashboard.stripe.com/test/payments`}
>
{" "}
Stripe dashboard.
</a> Refresh the page to pay again.
</p>
</form>
</CSSTransition>
When I comment out the , the transition will work properly over the 500ms time interval. When I leave the Card element in, it will refuse to adhere to the transition rules.
I'm using the base cardstyle
const cardStyle = {
style: {
base: {
color: "#32325d",
fontFamily: 'Arial, sans-serif',
fontSmoothing: "antialiased",
fontSize: "16px",
"::placeholder": {
color: "#32325d"
}
},
invalid: {
color: "#fa755a",
iconColor: "#fa755a"
}
}
};
The problem is that the CardElement either has its own transition on mount, or the style needs to be changed. Has anyone ever had this issue with the stripe element on transition?
I suspect that this will not work as the Elements exist within a Stripe-hosted iframe. Only certain styles are supported on Elements:
https://stripe.com/docs/js/appendix/style
I suggest opening an issue on github with a minimal example of this, for example forked from the codesandbox demo.
https://github.com/stripe/react-stripe-js/issues

React-select options shows default blue background

I have created a select component using react-select. I need to append a badge to the option who's available value is false. I have achieved it using -
const formatOptionLabel = ({ code, name, available }) => (
<div className="ds-select-distibutor-step-container format-option" style={{ display: "flex", cursor:"none" }}>
<div>{name}</div>
{!available ?
<div className="format-label" style={{ borderRadius: "12px" ,marginLeft: "auto", color: "#fff" , backgroundColor: "#aaa", padding: "2px 10px", fontSize:"12px"}}>
<span>Coming Soon</span>
</div>
: ''}
</div>
);
Following json comes at run time, which I map and use as options-
const options= [
{code:"abc",name:"abc",rank:0,available:true},
{code:"xyz",name:"xyz",rank:0,available:false},
{code:"pqr",name:"pqr",rank:0,available:true}]
And following is my custom select component
<Field
id="selectedDistributor"
name="selectedDistributor"
component={customSelect}
options={sortBy(options, 'name').map(({ code, name, available}) => ({ code, name, available }))}
formatOptionLabel={formatOptionLabel}
className="select-step"
placeholder="abc"
touched={false}
defaultValue="abc"
requiredField
>
</Field>
<FieldWrapper
label={label}
requiredField={requiredField}
touched={touched}
forId={inputId}
>
<Select
{...input}
id={inputId}
disabled={isEditMode || disabled}
onChange={value => input.onChange(value.code)}
formatOptionLabel={formatOptionLabel}
options={options}
placeholder={placeholder}
value={input.code}
className={`input-components-select ${className}`}
>
</Select>
</FieldWrapper>
enter code here
Everything is almost working but when I select the option, the background of all the options turns into blue, I tried making changes and found that if I pass the 'value' as a key of JSON instead of 'name' in the option this error goes away. But I can't use it since the json is coming from the backend and its dynamic.
Could anybody please suggest what should be done so that the background doesn't change? I have attached images for reference
first time
after selecting
I faced the same problem and I found that you need to declare a function getOptionValue as the Select's props. In your example, it should be like this
<Select
{...input}
id={inputId}
disabled={isEditMode || disabled}
onChange={value => input.onChange(value.code)}
formatOptionLabel={formatOptionLabel}
options={options}
placeholder={placeholder}
value={input.code}
getOptionValue={(option) => option.code} // changes here!!!
className={`input-components-select ${className}`}
>
</Select>
This function is used for comparison to highlight the currently selected option in the list. You can check more details in the discussion here
https://github.com/JedWatson/react-select/issues/3388

Is the z-index incorrect for these radio toggles behind the Semantic-UI-React Loading component?

I'm working on a form that has Semantic-UI Radio toggles, and the loader and the toggle's appear to be loading in the wrong z-index.
I checked the css and the toggle contains the following
.ui.toggle.checkbox label:after {
z-index: 2;
}
while the loader is
.ui.dimmer {
z-index: 1000;
}
which seems like the appropriate behaviour. I want the toggles to be behind the loader to present the best user experience. Can anyone tell me if the current behaviour is by design or not? Trying to determine if this is a bug to be reported or a feature to be requested or if there's a problem with my implementation.
My code (edited for brevity)
import { Form, Dropdown, DropdownItemProps, Dimmer, Loader, Button, Icon, Segment } from "semantic-ui-react";
return (
<Fragment>
<div style={{ display: "flex", flexDirection: "column" }}>
<div className="ui segments">
<PageHeader
text="Some text"
subText="Some subtext"
pageIcon="cogs icon"
/>
</div>
<Dimmer.Dimmable dimmed={loading}>
<Dimmer simple active={loading}>
<Loader>Loading</Loader>{" "}
</Dimmer>
<Form onSubmit={() => save()}>
<Form.Checkbox
label="Label 1"
checked={display}
onChange={(e, { checked }) => setDisplay(!!checked)}
toggle
/>
<Form.Input
label="Label 2"
placeholder="Placeholder"
value={data}
onChange={(e, { value }) => setData(value)}
/>
</Form.Group>
</Form>
</Dimmer.Dimmable>
</div>
</Fragment>
);
The comment helped me out. The problem was resolved using https://coder-coder.com/z-index-isnt-working/#alternative-solution-remove-positioning-from-the-content-so-it-wont-limit-the-modals-z-index from the suggestion.
I used a sticky position for the form element. Not necessarily the best solution but it sufficed for this purpose.

How to style Formik fields based on error and touched state

I have a question about rendering errors when using Formik#1.5.7 to create forms in React.
I am trying to figure out how to properly render different styles for my input based on whether or not the input has been touched and has errors.
{({ values, error, touched }) => (
<Form>
<Field name="Lawn" type="text">
{({ field, form }) => (
<Input
style={form.touched.Lawn && form.errors.Lawn ?
{ style } : { styleError }}
{...field}
type="text"
placeholder="Lawn Details"
/>
)}
</Field>
const style = {
margin: '1em 0em',
fontSize: '1.5em',
backgroundColor: 'white',
};
const styleError = {
margin: '1em 10em',
fontSize: '1.5em',
};
I believe my error has to do with not properly accessing the touched and error states in the form.
Any help would be very appreciated.
You're close, you just incorrectly passed style and styleError. They should not be surrounded with braces (and they're also backwards because the error formatting will show when there is no error and vice versa).
<Input
style={form.touched.Lawn && form.errors.Lawn ? styleError : style}
{...field}
type="text"
placeholder="Lawn Details"
/>
Here's a full example.

Resources