I am trying to display a tooltip when user hover mouse over the logo. Not sure if it's possible to achieve that in Twilio.
flex.MainHeader.defaultProps.logoUrl = `https://${serviceBaseUrl}/assets/MyApp.png`;
One way to achieve this would be to use the onMouseOver and onMouseOut event handlers to toggle the visibility of the tooltip when the logo is hovered over. You can add these event handlers to the img element that represents the logo, and use them to set the state of the component that renders the tooltip. The state would contain a boolean value that indicates whether the tooltip should be visible or not, and the render method of the component would use this value to conditionally render the tooltip.
constructor(props) {
super(props);
this.state = { showTooltip: false };
}
render() {
return (
<div>
<img
src={flex.MainHeader.defaultProps.logoUrl}
onMouseOver={() => this.setState({ showTooltip: true })}
onMouseOut={() => this.setState({ showTooltip: false })}
/>
{this.state.showTooltip && <div>This is the tooltip</div>}
</div>
);
}
}
This way the tooltip will only be visible when the user hover the mouse over the logo.
Related
I have a reactstrap Collapse component that I'm trying to toggle state from an external Button that sits within a loop of mapped items using custom state variables.
My question:
Why does it only open and not toggle the collapse component when I have the state on my openCollapse method to setState to !state.collapse?
My code:
// some_items.js (brief example)
// State
this.state = {
toggleCollapse: false
}
// my custom state variable that I want to have toggle
openCollapse(itemId) {
this.setState(state => ({
[`toggleCollapse-${itemId}`]: !state.collapse
}));
}
// mapped item with button trigger for toggling the collapse
<div key={item.id>
<Button
onClick={() => {
this.openCollapse(item.id);
}}
>
View Listed Item Info
</Button>
//
// Some extra content that belongs here in between..
//
<ItemInfoCollapse
show={this.state[`toggleCollapse-${item.id}`]}
item={item}
/>
</div>
// My item_collapse.js
class ItemInfoCollapse extends React.Component {
constructor(props, context) {
super(props, context);
this.state = {
collapse: false,
isOpen: this.props.show
};
}
componentWillReceiveProps(nextProps) {
this.setState({ isOpen: nextProps.show });
}
toggle = () => {
this.setState({ collapse: !this.state.collapse });
};
render() {
return (
<Collapse isOpen={this.state.isOpen} className={this.props.className}>
// Some JSX markup
</Collapse>
)
}
What dictates whether your Collapse component gets open or closed is based on the show prop that you are passing into it from your parent component.
It appears you have everything set up correctly, with the exception of your state variable that you're using in your openToggle function - !state.collapse. I don't see the collapse variable anywhere which means it's undefined so it's actually running !undefined which always evaluates to true (you can test this in a browser console).
I think what you mean is !state[toggleCollapse-${itemId}] instead of !state.collapse
I want to display h4 photo title on photo, but only if photo hovered. I was trying do this using onMouseEnter and onMouseLeave, but if I using many the same components, and when I hovered one of them, every components on page displaying photo title. Can I do something in my code to display title only on hovered photo?
Single Photo:
const Photo = props => (
<div onMouseEnter={props.onMouseEvent}
onMouseLeave={props.onMouseEvent}
style={props.backgroundImage}>
<h4>{props.hovered && props.title}</h4>
</div>
);
Displaying many Photo components:
class Gallery extends Component {
state = {
photos: [], // fetched photos here
hovered: false
};
toggleMouseHover = () => this.setState(prev => ({ hovered: !prev.hovered }));
render() {
return (
{this.state.photos.map(photo => {
<Photo
backgroundImage={{ backgroundImage: `url(${photo.src})` }}
title={photo.title}
onMouseEvent={this.toggleMouseHover}
hovered={this.state.hovered}
/>
})}
);
}
}
I was thinking about using content in CSS ::before or ::after, but I can not do it in React.
You can do this with pure css, it shouldn't matter that you are using react.
Single Photo:
const Photo = props => (
<div style={props.backgroundImage} className="div-photo">
<h4 className="photo-title">{props.title}</h4>
</div>
);
Css:
div.div-photo:hover > h4.photo-title {
display: block;
}
div.div-photo > h4.photo-title {
display: none;
}
I think this should work. You can use attribute visibility if you prefer it. Also, as mentioned in the comments, attribute opacity is a good option if you want to use fade-in/fade-out effects.
I have an input that users type keywords and a function is triggered to fetch data. The data is then populated in a 'suggested results' div right under the input. All this works great.
I am attempting to make it so when the user clicks inside the input or the div (when visible) at any time, they both have focus. When an item in the div is clicked a function is run depending on the item selected and the menu closes. If they click on anything, not the input or the div, the div should hide, or not show. I've been experimenting with where to place onBlur, onFocus, onClick to no success. Just partials to what I want.
I have a state property that is called 'inputFocused' that is set to false initially, when onFocus runs, it is set to true and that boolean determines if the div is shown.
I've attempted to use onBlur on the input that sets inputFocused to false, which of course hides the div. I removed that and placed it in the div, but because it doesn't have focus, it never runs. Only when I put an onclick that sets the state of inputFocused to false does it hide. But when a user clicks anywhere outside the input, the state doesn't change, onBlur isn't triggered.
class Hello extends React. Component {
constructor() {
super()
this.state = {
inputFocused: false,
visible: false
}
this.onFocus = this.onFocus.bind(this);
this.onBlur = this.onBlur.bind(this);
this.select = this.select.bind(this)
}
onFocus() {
this.setState({inputFocused: false})
console.log("FOCUS: ", this.state.inputFocused)
this.setState({ inputFocused: !this.state.inputFocused, visible: !this.state.visible })
}
onBlur() {
console.log("Blur: ", this.state.inputFocused)
this.setState({ inputFocused: !this.state.inputFocused })
}
select(){
console.log("SELECTED")
this.setState({ inputFocused: !this.state.inputFocused, visible: !this.state.visible })
}
render() {
return (
<div>
<div onFocus={this.onFocus}>
<input placeholder="MyList"></input>
{this.state.inputFocused && this.state.visible ? (
<ul>
<li onClick={() => this.select()}>abc</li>
<li onClick={() => this.select()}>123</li>
<li onClick={() => this.select()}>xyz</li>
</ul>
) : null}
</div>
</div>
);
}
}
ReactDOM.render(
<Hello initialName="World"/>,
document.getElementById('container')
);
Here is a JSFIDDLE that I've put together to show what I currently have.
You don't ever call onBlur and you're not resetting visible in onBlur either.
onBlur() {
console.log("Blur: ", this.state.inputFocused)
this.setState({ inputFocused: !this.state.inputFocused, visible: !this.state.visible })
}
and
<div onFocus={this.onFocus} onBlur={this.onBlur}>
Here's an updated fiddle: http://jsfiddle.net/sellmeadog/pwujfmk0/
Say you have multiple <Toggle /> components for an app that filters clothes by size. You toggle through the sizes and then you want to clear all the filters by clicking a button rather than uncheck all the toggles.
How can this be accomplished specifically with materials-ui Toggles? There's nothing in the documentation that says how you can uncheck the toggles using an outside element, such as a button.
For this functionality, you have to maintain the state for all the Toggle component. When you click the button, then you have to update the state of all the toggles.
for eg.
constructor(props) {
super(props);
this.state = {
toggle1: false,
toggle2: false,
};
}
uncheckAllToggle = () => {
this.setState({
toggle1: false,
toggle2: false
});
}
render() {
return (
<div>
<Toggle
label="toggle1"
toggled={this.state.toggle1}
onToggle={() => this.setState({toggle1: !this.state.toggle1})}
/>
<Toggle
label="toggle2"
toggled={this.state.toggle2}
onToggle={() => this.setState({toggle2: !this.state.toggle2})}
/>
<FlatButton
label={'UnCheck All Toggle'}
onClick={this.uncheckAllToggle}
/>
</div>
)
}
I need to change the url of the img on hover.
But the function trigger all of the children thats render.
I couldn't find a way to make the function trigger each children separate.
I try to make some new state to handle the indexes, but it didn't work...
const Team = React.createClass ({
getInitialState : function() {
return { hovered: false }
},
componentDidMount(){
this.props.fetchTeam();
document.title = "Equipe | [ Adesign";
},
onMouseOver : function () {
this.setState({ hovered:true });
},
onMouseOut : function () {
this.setState({ hovered:false });
},
render(){
return (
<div className="wrapper">
<div className="Team">
<HeaderAbout />
<h1>EQUIPE</h1>
<div className="content-team">
{this.props.posts.team.map((singleTeam, i) => {
var imgUrl = singleTeam.acf.photo.url;
if (this.state.hovered) {
imgUrl = singleTeam.acf.gif.url;
} else {
imgUrl = singleTeam.acf.photo.url;
}
return(
<div key={i} className="single-team col-xs-12 col-sm-6 col-md-4" onMouseOver={this.onMouseOver} onMouseOut={this.onMouseOut}>
<img className="img-responsive" src={imgUrl}/>
<p>{singleTeam.title.rendered}</p>
</div>
)
})}
</div>
</div>
</div>
)
}
});
You want to checkout the shouldComponentUpdate method:
Invoked before rendering when new props or state are being received.
This method is not called for the initial render or when forceUpdate
is used.
Use this as an opportunity to return false when you're certain that
the transition to the new props and state will not require a component
update.
In order to avoid rerendering all the images you can create a component to render an image that contains the state and the event handlers. By doing so, you prevent to rerender the parent component and its siblings whenever an image is hovered.
Edit: I just realized that your code changes all the images when any of them is hovered. Are you sure that it is what you want? In that case, you need to rerender everything. My solution is only valid if you only want to change the hovered image, leaving the others intact.