How can I create dropdown animation when I click to 3 dots and if I click one more time it will toggle the dropdown.
Here is my following code:
const [modalStatus, setModalStatus] = useState(false);
const openModal = () => {
setModalStatus(true);
};
<div className="member-edit" onClick={openModal}>
<Symlink />
</div>
{modalStatus && <TeamStatusModal />}
<div
className="member-avatar"
style={{
backgroundImage: `url(${member.User.picture})`,
}}
/>
<div className="member-description">
<p className="member-name">{member.User.fullname}</p>
<p className="member-date">
Joined on {moment(member.date_joined).format("MMMM Do, YYYY")}
</p>
</div>
Updated add TeamStatusModal.js:
const TeamStatusModal = () => {
return (
<div className="team-status-modal-container">
<div className="status">
<ProfileIcon /> <span>View Profile</span>
<hr />
</div>
<div className="status">
<MessageIcon /> <span>Message Me</span>
<hr />
</div>
<div className="status">
<ReviewIcon /> <span>Leave Review</span>
</div>
</div>
);
};
You should reorganize the logic a bit. Intead of: {modalStatus && <TeamStatusModal />} you can pass the state as a prop like this:
<TeamStatusModal active={modalStatus} />
and then you will use it in the TeamStatusModal component:
const TeamStatusModal = ({ active }) => {
return (
<div className={`team-status-modal-container ${active ? 'ACTIVE_CLASS' : ''}`}>
<div className="status">
<ProfileIcon /> <span>View Profile</span>
<hr />
</div>
<div className="status">
<MessageIcon /> <span>Message Me</span>
<hr />
</div>
<div className="status">
<ReviewIcon /> <span>Leave Review</span>
</div>
</div>
);
};
Another approach is using e.g. Framer Motion library, which allows animate removing elements from DOM.
https://www.framer.com/api/motion/animate-shared-layout/#syncing-layout-animations
Related
I have a state that shows which menu tab is currently active
const [activeTab, setActiveTab] = useState("home");
I use the state as class on my mark up
<div className={`${activeTab}`}>
<img src={Assets.Home} alt="Home" />
<p>Home</p>
</div>
<div className={`${activeTab}`}>
<img src={Assets.Wallet} alt="Wallet" />
<p>Wallet</p>
</div>
But that doesn't work since when the state changes it changes the class names of both divs. Now I want a way to use state as active indicator . I tried attaching an extra class for each div like this
<div className={`home ${activeTab}`}>
<img src={Assets.Home} alt="Home" />
<p>Home</p>
</div>
<div className={`wallet ${activeTab}`>
<img src={Assets.Wallet} alt="Wallet" />
<p>Wallet</p>
</div>
So that I can target in CSS. Like this
.home.home{
//some code
}
Whilst the above approach works it is messy. I would ideally like to just use the state as the class name without any extra addition. How can I do that?
Use conditional rendering to check if the specific class is active and assign it a single class active in that case:
const [activeTab, setActiveTab] = useState("home");
<div className={`${activeTab === 'home' ? 'active' : ''}`}>
<img src={Assets.Home} alt="Home" />
<p>Home</p>
</div>
<div className={`${activeTab === 'wallet' ? 'active' : ''}`}>
<img src={Assets.Wallet} alt="Wallet" />
<p>Wallet</p>
</div>
You can then target the active class in CSS by defining:
.active {
...
}
add the onClick handler at the tag to handle the activeTab state like <div onClick={() => setActiveTab("home")} className={${activeTab}}>{...}</div>
For your case you only need to do this:
<div onClick={() => setActiveTab("home")} className={`home ${activeTab}`}>
<img src={Assets.Home} alt="Home" />
<p>Home</p>
</div>
<div onClick={() => setActiveTab("wallet")} className={`wallet ${activeTab}`}>
<img src={Assets.Wallet} alt="Wallet" />
<p>Wallet</p>
</div>
This is my demo.
When we hover #image-bg, I want #bg-box-hidden will be display: block.
But I'm losing my way to figure out how to solve the problem
<div class="grid pb1rem">
<div *ngIf="avatar !== null" class="image-content">
<img
class="image-bg"
[src]="avatar"
(click)="selectImage.click()"
hover-class="test"
(mouseover)="onImgMouseover($event)"
(mouseout)="onImgMouseout($event)"
/>
<div #show class="bg-box-hidden" hover-class="show">
<button class="btn only-icon">
<i nz-icon nzType="delete" nzTheme="outline"></i>
</button>
</div>
</div>
</div>
The main problem of your code are
Wrong event name.
The element doesn't rendered so you can't targeted the element.
Here is simple solution for you, It might be other way to implement as well.
Try this one, put on your .ts file of the component.
onImgMouseover($event): void {
const box = document.getElementsByClassName('bg-box-hidden')[0];
box.style.display = 'block';
}
onImgMouseout($event): void {
const box = document.getElementsByClassName('bg-box-hidden')[0];
box.style.display = 'none';
}
and need modify some on HTML something like
<div
class="grid pb1rem"
(mouseenter)="onImgMouseover($event)"
(mouseleave)="onImgMouseout($event)"
>
<div *ngIf="avatar === null" class="image_wrapper">
<input
type="file"
accept=".png,.jpg"
(change)="updateImage($event)"
class="file-input"
#selectImage
/>
</div>
<div *ngIf="avatar !== null" class="image-content">
<img
class="image-bg"
[src]="avatar"
(click)="selectImage.click()"
hover-class="test"
/>
</div>
<div #show class="bg-box-hidden" hover-class="show">
<button class="btn only-icon">
<i nz-icon nzType="delete" nzTheme="outline"></i>
</button>
<div class="box-button-up">
<input
type="file"
accept=".png,.jpg"
(change)="updateImage($event)"
class="file-input"
#selectImage
/>
</div>
</div>
</div>
I am trying to have some text on the left side and my pure-react-carousel on the right side.
The carousel stretches to fill in the width of it's parent.
How do I adjust the flexbox to have 50% width without carousel without overflowing on the y axis?
Index.js
const index = () => {
return (
<div>
<div className="flex">
<div className="bg-red-200 w-1/2">Hello</div>
<div className="bg-gray-400 w-1/2 ">
<Carousel />
</div>
</div>
<div>
<h1>THIS IS A BLOCK ELEMENT</h1>
</div>
</div>
);
};
Carousel.js(pure-react-carousel)
const Carousel = () => {
return (
<CarouselProvider
naturalSlideWidth={100}
naturalSlideHeight={125}
totalSlides={3}
>
<Slider className="rounded">
<Slide index={0}>
<img
src="https://images.unsplash.com/photo-1502945015378-0e284ca1a5be?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1050&q=80"
alt=""
/>
</Slide>
<Slide index={1}>
<img
src="https://images.unsplash.com/photo-1502945015378-0e284ca1a5be?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1050&q=80"
alt=""
/>
</Slide>
<Slide index={2}>
<img
src="https://images.unsplash.com/photo-1502945015378-0e284ca1a5be?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1050&q=80"
alt=""
/>
</Slide>
</Slider>
</CarouselProvider>
);
};
Not sure what other info I could supply besides one of the columns that would be helpful. I'm stumped.
[edit] Added full code for this component. This looks fine on desktop but not on my phone or tablet. See the photos. I'm repeating this because I can't save my edits to this question due to having too much code and not enough information so here I am rambling about nothing.
Mobile:
Desktop:
import React, { Component } from 'react';
import API from '../utils/API';
class Attendance extends Component {
state = {
selectedOption: "",
disabled: ""
};
handleOptionChange = (changeEvent) => {
this.setState({
selectedOption: changeEvent.target.value
});
};
handleFormSubmit = (formSubmitEvent) => {
formSubmitEvent.preventDefault();
if (!this.state.selectedOption) {
return;
} else {
this.setState({
disabled: "true"
})
API.updateAttendance(this.props.student._id, { present: this.state.selectedOption });
}
};
render() {
return (
<div className="col d-flex justify-content-end" >
<form onSubmit={this.handleFormSubmit}>
<div className="row mt-3">
<div className="col-sm-3">
<label className="text-danger">
<input
type="checkbox"
value="absent"
checked={this.state.selectedOption === 'absent'}
onChange={this.handleOptionChange}
disabled={this.state.disabled}
/>
Absent
</label>
</div>
<div className="col-sm-3">
<label className="text-warning">
<input
type="checkbox"
value="excused"
checked={this.state.selectedOption === 'excused'}
onChange={this.handleOptionChange}
disabled={this.state.disabled}
/>
Excused
</label>
</div>
<div className="col-sm-3">
<label className="text-success">
<input
type="checkbox"
value="present"
checked={this.state.selectedOption === 'present'}
onChange={this.handleOptionChange}
disabled={this.state.disabled}
/>
Present
</label>
</div>
<div className="col-sm-3">
<div className="form-group">
<button type="submit" className="btn btn-sm btn-dark" onSubmit={this.handleFormSubmit} disabled={this.state.disabled}>
<i className="fas fa-user-check" />
</button>
</div>
</div>
</div>
</form>
</div>
);
}
}
export default Attendance;
I am trying to successfully express Semantic-UI code with the same functions I have used in Semantic-UI-react code. Any help would be appreciated.
This is what I have:
class Preview extends React.Component {
componentDidMount() {
const update = () => {
this.dest.textContent = this.src.innerHTML.replace(/</g,
'\n<');
};
setInterval(update, 300);
update();
}
render() {
return (
<div>
<div ref={(src) => Object.assign(this, { src })}>
<Demo />
</div>
<pre ref={(dest) => Object.assign(this, { dest })}>
</pre>
</div>
)
}
}
export class Demo extends Component { constructor(){
super();
this.localStorageClear.bind(this); }
localStorageClear = (e) => {
e.preventDefault();
window.localStorage.clear();
};
render() {
return (
<div id = "soundcloud-player">
<Container className='col'>
<div className='col-left js-playlist toggle'>
<div className='inner'>
</div>
</div>
<div className='col-right'>
<div className = 'main'>
<Input size='massive' icon='search' input = {{ className:
'input-search js-search' }} placeholder='Search for a song
or artist...'/>
<Icon className='js-submit'/>
<Button onClick={(e) => this.localStorageClear(e)}
className='clear' content='Clear Playlist'/>
<Button content='Show/Hide Playlist' id='toggle'
className='hide-toggle'/>
<Card className='js-search-results search-results'/>
</div>
</div>
</Container>
</div>
The code written in the Preview Component is specifically written to convert the code written inside of the Demo Component. The Demo Component should convert to what is shown below:
<div class="ui container col">
<div class="col-left js-playlist toggle">
<div class="inner">
</div>
</div>
<div class="col-right">
<div class="main">
<div class="ui massive icon input">
<input placeholder="Search for a song or artist..." class="js-search input-search">
<i class="search icon js-submit"></i>
</div>
<button onclick="localStorageClear();" class="clear">Clear Playlist</button>
<button class="hide-toggle" href="#" id="toggle">Show/Hide Playlist</button>
<div class="search-results js-search-results ui cards">
</div>
</div>
</div>
The actual output of the code at the top is:
<div id="soundcloud-player">
<div class="ui container col">
<div class="col-left js-playlist toggle">
<div class="inner">
</div>
</div>
<div class="col-right">
<div class="main">
<div class="ui massive icon input input-search">
<input placeholder="Search for a song or artist..." type="text">
<i aria-hidden="true" class="search icon">
</i>
</div>
<i aria-hidden="true" class="icon js-submit">
</i>
<button class="ui button clear" role="button">Clear Playlist
</button>
<button id="toggle" class="ui button hide-toggle" role="button">Show/Hide Playlist
</button>
<div class="ui card js-search-results search-results">
</div>
</div>
</div>
</div>
</div>
I'm trying to figure out why the localStorageClear function does not show up for the first button in the actual output. Is there wrong I am doing at the top inside of the Semantic-UI-React code inside of the Demo Component?
The way you are setting up your handler function is not correct. You are also binding in your constructor AND inline with an arrow function inside of the onClick event for the button. You only need to bind in one place.
Take a look at the codesandbox example I made so you can see how to declare a class method handler function and use it with a click event. Notice that there is no constructor here or arrow function to bind on the onClick event? That is because the binding is happening on the class method. handleClick = () => {}
class App extends React.Component {
handleClick = e => {
console.log(e.target + " was clicked.");
// Do whatever functionality you need here.
// In your example you do not show that it matters what the element is,
// so you don't need to pass the event (e) into your class method.
};
render() {
return (
<Container>
<Divider hidden />
<Button content="Click Me" onClick={this.handleClick} />
<Divider hidden clearing />
<Message info>
Look in your console and you will see that the click function is
working.
</Message>
</Container>
);
}
}
Here is a working codesandbox example.