I want to have this design
This is what I have now
export default function Minter({
...
}) {
const uploadButton = (
<div>
Choose file
</div>
);
const uploadView = (
<div style={{ padding: 50 }}>
<p className="uppercase text-gray-400 mb-6 text-center">
PNG, GIF, WEBP, MP4 or MP3. Max 100mb.
</p>
<Upload
name="avatar"
accept=".jpeg,.jpg,.png,.gif"
listType="picture-card"
className="avatar-uploader"
showUploadList={false}
action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
beforeUpload={beforeUpload}
>
{uploadButton}
</Upload>
</div>
);
const preview = previewURL ? <img src={previewURL} style={{ maxWidth: "800px" }} /> : <div />
const nameField = (
<Input
style={{
border: 0,
}}
placeholder="Enter a name" onChange={e => {
setName(e.target.value);
}} />
);
const descriptionField = (
<Input.TextArea
placeholder="Enter a description" onChange={e => {
setDescription(e.target.value);
}} />
);
const priceField = (
<Input.TextArea placeholder="Enter a price" onChange={e => {
setPrice(e.target.value);
}} />
);
const mintButton = (
<Button type="primary" disabled={!mintEnabled} onClick={startMinting}>
{minting ? <LoadingOutlined /> : "Mint!"}
</Button>
)
const minterForm = (
<body>
<div style={{
alignItems: 'center',
display: "flex", flexDirection: "column",
}}>
<div style={{justifyContent:'space-between',display: "flex", flexDirection: "row" }}>
<div style={{
borderStyle: 'dotted',
borderRadius: 1,
}}>
{file == null && uploadView}
{preview}
</div>
<div>
<div> Name</div>
{nameField}
<p>Description</p>
{descriptionField}
<p>Price</p>
{priceField}
{mintButton}
{status}
</div>
</div>
</div>
</body>
);
return minterForm;
}
How to add space in middle?
How to align name,description,price to left?
I would like to shorten the height of the "Choose file", make it look exactly like the above image.
Any suggestion would be much appreciated.
It's difficult to answer some of these questions as there's no reproducible code link (CodeSandbox, etc).
The outer flexbox is likely causing some issues as it's probably not letting the children breathe - for these two components you should only need one parent flex with both justify-content: center and align-items: center
gap css property for flex/grid should be your friend here. If adding a gap on the second flex does nothing, see above or add a minWidth.
This is likely due to other styles interfering. Either add an explicit text-align: left, or use the Inspect feature of your browser to see what's happening.
Add a maxHeight to the div, or look into what styles are being applied by the avatar-uploader class.
I'd look into the Material UI library, as the TextField component has similar styling to the reference image.
Related
I have a button to show details of each card in my react project like this. the amount of cards are unknown and it is based on what I get from API.
just like this, I get the data and I'm mapping it:
<div className={styles.contentCardContainer}>
{factorList !== undefined && factorList.length > 0 ? (
factorList.map((list, i) => (
<div key={uuidv4()} className={styles.contentCard}>
<IconButton
color={showListService ? "error" : "success"}
onClick={() => {
setShowlistService((prev) => !prev);
HandleFetchDetails(list.ID);
}}
sx={{
display: "flex",
alignItems: "center",
alignSelf: "flex-start",
}}
>
{showListService ? <RemoveCircle /> : <AddCircle />}
</IconButton>
<section className={styles.eachSection}>
<img src={doctorImage} alt="doctor" />
<p>{list.Doctor}</p>
</section>
<section className={styles.eachSection}>
<img src={calendarImage} alt="doctor" />
<p>
{list.Date}
{list.Time}
</p>
</section>
<section className={styles.eachSection}>
<img src={RialImage} alt="doctor" />
<p>{list.Payable} ریال</p>
</section>
<section className={styles.eachSection}>
<img src={discountImage} alt="doctor" />
<p>{list.discount}</p>
</section>
{showListService && (
<DetailsListService listDetails={listDetails} styles={styles} />
)}
</div>
))
) : (
<Alert
variant="filled"
severity="warning"
sx={{ justifyContent: "space-between" }}
>
<p>There's no data</p>
</Alert>
)}
</div>
</div>
as you can see, I have IconButton element that I mapped it so each element have this button. but there's a problem.
I just have one state.
just like this :
const [showListService, setShowlistService] = React.useState(false);
since the amount cards I will receive is unknown. I can't define multiple states, because I don't know how many I should define. this is a bad practice too.
so whenever I click on IconButton, state changes for ALL buttons. how can I make it work individually.
change state for just a button in that specific element
Create a component for the cards and each card can keep the state:
factorList.map((factor, index) => {
return <Card key={index} factor={factor} />;
});
const Card = ({ factor }) => {
const [state, setState] = useState(false);
return <div>Your card stuff here</div>;
};
I've custom multiselect dropdown which is implemented as given below:
const RequestExpertSupport = function Basic({
data,
onSelectedItemsChanged,
selectedItemsIndices,
}) {
const props = {
data: [
"My account and profile",
"Understanding my footprint",
"Target setting",
"Specific actions",
"Creating a plan",
"Finance, funding and grants ",
"Using the Carbon Planner platform",
"Other",
],
selectedItemsIndices: [],
};
//
const handleSelectedItemsChanged = useCallback(
selectedItemsIndices => {
onSelectedItemsChanged(selectedItemsIndices);
},
[onSelectedItemsChanged]
);
function onSelectedItemsChanged(selectedItemsIndices) {
console.log(selectedItemsIndices);
}
function renderItem(datum, index) {
return <span>{datum}</span>;
}
return (
<RequestExpertSupportDiv>
<div className="container">
<div className="formContainer">
<form>
<label className="helpLabel">What would you like help with?</label>
<DropdownListTrigger
dropdownList={
<MultiSelectDropdownList
id="multiSelectDrop"
data={props.data}
onSelectedItemsChanged={handleSelectedItemsChanged}
renderItem={renderItem}
selectedItemsIndices={selectedItemsIndices}
/>
}
position="right"
className="ddlFilter"
>
<button className="zb-button zb-button-secondary zb-button-with-icon-after">
<span>Choose topic(s)</span>
<Icon
name="chev-down-xsmall"
style={{
verticalAlign: "text-bottom",
}}
title={null}
/>
</button>
</DropdownListTrigger>
<div className="selectedTopics">Selected topics are:</div>
<label className="tellUsLabel">What would you like help with?</label>
<textarea
name="helpReview"
rows="4"
cols="43"
className="textArea"
style={{ width: "410px", height: "290px", marginTop: "2%" }}
placeholder="Type your message here ..."
></textarea>
<button className="sendBtn" name="sendBtn">
Send
</button>
</form>
</div>
</div>
</RequestExpertSupportDiv>
);
};
export default RequestExpertSupport;
This code fetches the indices of selected options in Multiselect dropdown.
function onSelectedItemsChanged(selectedItemsIndices) {
console.log(selectedItemsIndices);
}
Console is given below:
Now I want to display those selected options as tags like this:
This is the code for tags:
<Div
flex="flex"
display="inline-flex"
height="36px"
borderWidth="1px solid #009FAC"
borderRadius="3px"
backgroundColor="#def8fa"
justifyContent="space-around"
alignItems="center"
marginRight="10px"
marginBottom="10px"
style={{ minWidth: "92px", maxWidth: "175px" }}
>
<span
padding="0px"
fontSize="14px"
lineHeight="20px"
fontWeight="400"
marginLeft="5px"
marginRight="5px"
style={{ maxWidth: "142px" }}
>
// need to put selected options here
</span>
<img name="close-inverted-small" onClick={event => removeSelectedTopic(event, topicId)} />
</Div>
I'm not getting how to link function SelectedItemsChanged(selectedItemsIndices) with that tags frontend code to dosplay selected options as tags...
You need to put all the codes in the last part in a loop for rendering data. for example you should write last part as below by using selectedItemIncedies and data:
{ selectedItemIncedies.map ((selectedItemIndex) => { return (<Div
flex="flex"
display="inline-flex"
height="36px"
borderWidth="1px solid #009FAC"
borderRadius="3px"
backgroundColor="#def8fa"
justifyContent="space-around"
alignItems="center"
marginRight="10px"
marginBottom="10px"
style={{ minWidth: "92px", maxWidth: "175px" }}
<span
padding="0px"
fontSize="14px"
lineHeight="20px"
fontWeight="400"
marginLeft="5px"
marginRight="5px"
style={{ maxWidth: "142px" }}
>
{data.find((item, index)=> index===selectedItemIndex)}
</span>
<img name="close-inverted-small" onClick={event => removeSelectedTopic(event, topicId)} />
</Div>)})}
You'll want to render the tags using map based on the selectedItemsIndices array. First, pass the selectedItemsIndices array as props to a TagListComponent.
Once that's all set, render each of the selected tags in selectedItemsIndices in the TagListComponent
TagListComponent.js
const TagListComponent = function Basic({
selectedItemsIndices,
}) {
return (
<div>
{selectedItemsIndices.map((selectedItemIndex, index) => {
return (
<div>
<span>{data[selectedItemIndex]}</span>
</div>
);
})}
</div>
);
};
export default TagListComponent;
In the <span/> tag above, put whatever styling you'd like for the tag itself.
Now i have used state hook to hide the Form when the page loads. And upon the click or toggle of the radio I'm able to show the Form, But if i toggle the radio again, the form is not hiding.
This is what i have implemented:
const WelcomeTab = () => {
const [toggle, settoggle] = useState(false);
return (
<React.Fragment>
<Tab.Pane
style={{
borderRadius: '7px',
padding: '30px',
}}
attached={false}
>
<Grid>
<Grid.Row>
<Grid.Column floated="left" width={8}>
<Header
style={{
fontSize: '18px',
fontFamily: 'Nunito-Regular',
color: '#4F4F4F',
}}
>
Welcome Screen
</Header>
</Grid.Column>
<Grid.Column floated="right" width={4}>
<Header
as="h4"
style={{
display: 'flex',
justifyContent: 'space-around',
marginLeft: '30px',
}}
>
Customize
<Radio toggle onChange={() => settoggle({ toggle: !toggle })} />
</Header>
</Grid.Column>
</Grid.Row>
</Grid>
{toggle ? (
<Form style={{ paddingTop: '20px' }}>
<Form.Field>
<label style={lableStyle}>Title</label>
<input style={{ marginBottom: '20px' }} />
<label style={lableStyle}>Message</label>
<TextArea />
</Form.Field>
</Form>
) : null}
</Tab.Pane>
</React.Fragment>
);
};
const lableStyle = {
fontFamily: 'Nunito-Regular',
fontWeight: 400,
color: '#4F4F4F',
fontSize: '15px',
display: 'inline-block',
marginBottom: '10px',
};
export default WelcomeTab;
try to add useEffect hook along with change like below,
you no longer need to {} this is old syntax of setState, using hooks we directly make the changes, hope this helps
useEffect(()=>{},[toggle])
replace this wrong syntax code, i can see its not json its boolean value
<Radio toggle onChange={()=>settoggle({toggle: !toggle})}/>
as this is old syntax not work with hooks, try to implment this instead,
<Radio toggle onChange={()=>settoggle(!toggle)}/>
Hy, I'm trying to disable/hide the arrow buttons of a horizontal scroller on start and end of the scroll.
I tried to use useEffect lifecycle by by setting its dependency document.getElementById('hscroll').scrollLeft, so that i can fire a function on scrollLeft change... but on load it shows an error "Cannot read property 'scrollLeft' of null" which is obviously right.
code is here ... hscroll CodeSandBox
how can I be able to do that?
need your help!
Thank you in advance <3.
You can do that only with useState hook and conditional rendering.
Here's a fully-working solution assuming we know width of the div that wraps your slides:
const HorizontalScroll = () => {
const [slideLeft, setSlideLeft] = useState(0);
const sliderWidth = 1900;
//on arrow click
const moveRight = () => {
const el = document.getElementById(`hscroll`);
setSlideLeft(el.scrollLeft += 200);
};
const moveLeft = () => {
const el = document.getElementById(`hscroll`);
setSlideLeft(el.scrollLeft -= 200);
};
return (
<div className="homepageMargin">
<section style={{ display: "flex", justifyContent: "space-between" }}>
{slideLeft > 0 ? <IconButton onClick={moveLeft}>
<ArrowBackIcon
style={{
paddingTop: ".2rem",
cursor: "pointer"
}}
/>
</IconButton> : <div />}
{slideLeft < sliderWidth ? <IconButton onClick={moveRight}>
<ArrowForwardIcon
style={{
paddingTop: ".2rem",
cursor: "pointer"
}}
/>
</IconButton> : <div />}
</section>
<hr style={{ backgroundColor: "black" }} />
<div class="flex-container" id={`hscroll`}>
{data.map((item) => (
<div style={{ minWidth: "300px" }}>
<img src={item.imgSrc} alt="images" style={{ width: "18rem" }} />
<h6>{item.title}</h6>
</div>
))}
</div>
</div>
);
};
Above example works becouse React component re-render every time you update the state. Also, you can get width of your slider like that:
const sliderWidth = yourRefName.current.style.width;
But it has to be declared explicitly in your CSS.
I am using https://www.npmjs.com/package/react-multi-carousel in one of my react project and I have implemented it and it works fine.
I am now in the need to implement the text (legend) over the carousel exactly like https://codesandbox.io/s/lp602ljjj7 which uses another package but I need that scenario and not that package because my need is different (Using nextjs so multi-carousel supports ssr and hence using it).
My only need is need to know how to implement the legend text over the carousel image using react-multi-carousel.
My code example: https://codesandbox.io/s/react-multi-carousel-playground-bt3v7
Change the structure of the return statement to the following structure.
Then you can store the value of the legend in the image array and pass the value to the p tag
const Simple = ({ deviceType }) => {
return (
<Carousel
ssr
partialVisbile
deviceType={deviceType}
itemClass="image-item"
responsive={responsive}
>
{images.slice(0, 5).map((image, index) => {
return (
<div key={index} style={{ position: "relative" }}>
<img
draggable={false}
alt="text"
style={{ width: "100%", height: "100%" }}
src={image}
/>
<p
style={{
position: "absolute",
left: "50%",
bottom: 0,
color: "white",
transform: " translateX(-50%)"
}}
>
Legend:{index}.
</p>
</div>
);
})}
</Carousel>
);
};
export default Simple;
Live demo
You should change array structure like below.
const images = [
{
image: "https://images.unsplash.com/photo-1549989476-69a92fa57c36?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=60",
text: "First image",
}
];
Then inside loop just add text and style it our way!
const Simple = ({ deviceType }) => {
return (
<Carousel
ssr
partialVisbile
deviceType={deviceType}
itemClass="image-item"
responsive={responsive}
>
{images.map(image => {
return (
<div>
<img
draggable={false}
alt="text"
style={{ width: "100%", height: "100%" }}
src={image.image}
/>
{/* Have to style so this should see over the image */}
<span>{image.text}</span>
</div>
);
})}
</Carousel>
);
};