React-bootstrap :- is it possible to have MenuItem inside Popover - reactjs

is it possible to have MenuItem inside Popover component and still retain style. Right now I get menuitem (without style), when I just use MenuItem component. When I wrap it inside , nothing get visible.
<Overlay
show={this.state.isOpen}
target={this.state.target}
placement="bottom"
container={this}
>
<Popover
id="profilePopover"
title={`Hello ${givenName || ''}${surname || ''}`}
>
<strong>Holy guacamole!</strong> Check this info.
<Clearfix>
<ul className="dropdown-menu open">
<MenuItem>link</MenuItem>
</ul>
</Clearfix>
</Popover>
</Overlay>

You are returning more than 1 item inside the popover class.
<Overlay
show={this.state.isOpen}
target={this.state.target}
placement="bottom"
container={this}
>
<Popover
id="profilePopover"
title={`Hello ${givenName || ''}${surname || ''}`}
>
{
<div>
<strong>Holy guacamole!</strong> Check this info.
<Clearfix>
<ul className="dropdown-menu open" style={{display:"block", position: "relative"}}>
<MenuItem>Test</MenuItem>
<MenuItem>Test2</MenuItem>
</ul>
</Clearfix> </div> }
</Popover>
</Overlay>
and it got something to do with the classname "dropdown-menu open" try add a style in it

Thanks guys, I created custom popover element, and threw some custom .css, and I can see menuItem inside popover. Though I am yet to correct arrowOffset values and top alignment not working... separate question for them.
<Overlay
show={this.state.isOpen}
target={this.state.target}
container={this}
placement="bottom"
arrowOffsetTop="-6px;"
arrowOffsetLeft="79%;"
>
<PopoverAligned
links={links}
givenName={givenName}
surname={surname}
greetingText={greetingText}
/>
</Overlay>
const PopoverAligned = props => (
<Popover
id="profilePopover"
title={`${props.greetingText} ${props.givenName || ''} ${props.surname || ''}`}
className="dropdown-menu open"
placement="bottom"
style={{ top: '43px;', left: '-100px' }}
>
{
props.links.map(link => (
<li className="menuitem">
<a href={link.url} target={link.target} className="dropdown-link">
{link.title}
</a>
</li>
))
}
</Popover>
);

Related

Can you add HTML to react-tippy tooltip

I want to add a to a react-tippy tooltip.
Is it possible?
I only get it to show [object Object]
Look at title bellow
<Tooltip
// title={this.renderTicks(idx, row)}
title={<div>
<h4>Hello</h4>
<span>This is a span</span>
</div>}
position="right"
trigger="click"
theme="light"
arrow="true"
arrowSize="big"
distance="3"
style={{fontSize:14}}
>
<div>Click Here</div>
</Tooltip>
I didn't use it before but reading the documentation said that you can use html props.
"Tooltip content. If you don't define html, the title will be used"
Something like this:
<Tooltip
html={(
<div>
<h4>Hello</h4>
<span>This is a span</span>
</div>
)}
>
OK seems easy enough
instead of title just use 'html'
<Tooltip
// title={this.renderTicks(idx, row)}
html={<div>
<h4>Hello</h4>
<span>This is a span</span>
</div>}
position="right"
trigger="click"
theme="light"
arrow="true"
arrowSize="big"
distance="3"
style={{fontSize:14}}
>
<div>Click Here</div>
</Tooltip>

TypeError: Cannot set properties of undefined (setting 'hook')

TypeError: Cannot set properties of undefined (setting 'hook')
I am working on a Nextjs application but getting this error with antd library. I'm using the modal component and tooltip component which causes a re-render on open and close and spits out this error multiple times. Same goes for the tooltip when I mouse over it. Has anyone experienced this? and how did you fix it?. Answers appreciated!
import { Button, Modal, Tooltip } from 'antd';
const [isModalOpen, setIsModalOpen] = useState(false);
<div className="d-flex gap-2">
<Tooltip title="Edit">
<EditOutlined className="h5 pointer text-warning" />
</Tooltip>
<Tooltip title="Publish">
<CheckOutlined className="h5 pointer text-success ml-2" />
</Tooltip>
</div>
<Button
className="w-100"
onClick={() => setIsModalOpen(true)}
type="primary"
shape="round"
size="large"
icon={<UploadOutlined />}
>
Open modal
</Button>
<Modal
title="Modal title"
centered
open={isModalOpen}
onCancel={() => setIsModalOpen(false)}
footer={null}
>
<p>Some contents...</p>
</Modal>

Why div in a form is a problem for react?

I have a following button which is connected to recaptcha according to docs
<Button
onClick={() => setShowSpinner(true)}
size="lg"
className="g-recaptcha"
data-sitekey="XYZ"
data-callback="handleFormSend"
data-action='submit'
>
{showSpinner && <Spinner
as="span"
animation="grow"
size="sm"
role="status"
aria-hidden="true"
/>}
Send
</Button>
I don't understand why in chrome I got
"Warning: Did not expect server HTML to contain a <div> in <form>."
Of course I checked HTML code and don't see any div? In Mozilla there is no warning.
I use next and react.
What may be wrong?
Looks like a SSR/hydration issue. Try removing spaces between tags.
<Button
onClick={() => setShowSpinner(true)}
size="lg"
className="g-recaptcha"
data-sitekey="XYZ"
data-callback="handleFormSend"
data-action='submit'
>
{showSpinner &&
<Spinner
as="span"
animation="grow"
size="sm"
role="status"
aria-hidden="true"
/>
}
Send
</Button>
Check this answer

Influence tab order of Material UI controls

I have an app built up with React and Material UI. Within one view it is possible to have several text fields and several buttons. Now, when I have the focus on one text field and then press Tab I cannot reliably anticipate which one of the controls will be the next one to get the focus. I want to first tab through all the text fields and then secondly tab through all the buttons.
<DialogContent>
<DialogContentText>
The username and password that were used are incorrect. Please provide the correct credentials in order to login to the API.
<Stepper activeStep={this.state.credentialsStep} orientation='vertical'>
{
this.steps.map((label, index) => (
<Step key={label}>
<StepLabel>{label}</StepLabel>
<StepContent>
<Typography>{this.stepContent[index]}</Typography>
{this.stepAction[index]}
<Grid container direction='row' className='m-t-26'>
<Button color='primary'
onClick={() => {
this.state.credentialsStep === 0 ? this.onClickCancel() : this.onClickBack();
}}>
{this.state.credentialsStep === 0 ? 'Cancel' : 'Back'}
</Button>
<Button variant='contained'
color='primary'
onClick={() => {
this.state.credentialsStep === this.steps.length - 1 ? this.onClickLogin() : this.onClickNext();
}}>
{this.state.credentialsStep === this.steps.length - 1 ? 'Login' : 'Next'}
</Button>
</Grid>
</StepContent>
</Step>
))
}
</Stepper>
</DialogContentText>
</DialogContent>
Is there a way to set the tab order of controls?
You can control this with the tabIndex property, but you may be better off to figure out how to have the elements appear in the source in the order you would want the focus to go.
I have found this resource handy: https://bitsofco.de/how-and-when-to-use-the-tabindex-attribute/
When to use a positive tabindex value
There is almost no reason to
ever use a positive value to tabindex, and it is actually considered
an anti-pattern. If you’re finding the need to use this value to
change the order in which elements become focusable, it is likely that
what you actually need to do is change the source order of the HTML
elements.
One of the problems with explicitly controlling tabindex order is that any elements with a positive value are going to come before any other focusable elements that you haven't explicitly put a tabindex on. This means that you could end up with very confusing focus order if you miss any elements that you would want in the mix.
If you want to have the button on the right come before the button on the left in the focus order, there are various CSS options that would allow the button on the right to come first in the source order.
If, however, you decide that explicitly specifying the tabindex is your best option, here is an example showing how to do this for TextField and Button:
import React from "react";
import ReactDOM from "react-dom";
import TextField from "#material-ui/core/TextField";
import Button from "#material-ui/core/Button";
function App() {
return (
<div className="App">
<TextField label="1" inputProps={{ tabIndex: "1" }} />
<br />
<TextField label="3" inputProps={{ tabIndex: "3" }} />
<br />
<TextField label="2" inputProps={{ tabIndex: "2" }} />
<br />
<Button tabIndex="5">Button 5</Button>
<Button tabIndex="4">Button 4</Button>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
You may want to use the html attribute tabindex. This allows you to specify the order that tabbing will go through in your form. You can read more about it here and I've put a small example below, setting the tab index of your button to #1
<StepContent>
<Typography>{this.stepContent[index]}</Typography>
{this.stepAction[index]}
<Grid container direction="row" className="m-t-26">
<Button
tabIndex="1" // This will make the button the first tab index for the form.
color="primary"
onClick={() => {
this.state.credentialsStep === 0
? this.onClickCancel()
: this.onClickBack();
}}
>
{this.state.credentialsStep === 0 ? "Cancel" : "Back"}
</Button>
<Button
variant="contained"
color="primary"
onClick={() => {
this.state.credentialsStep === this.steps.length - 1
? this.onClickLogin()
: this.onClickNext();
}}
>
{this.state.credentialsStep === this.steps.length - 1 ? "Login" : "Next"}
</Button>
</Grid>
</StepContent>;
You can use a css trick to render the buttons in reverse order, but with css to reverse the buttons in UI.
<DialogContent>
<DialogContentText>
The username and password that were used are incorrect. Please provide the correct credentials in order to login to the API.
<Stepper activeStep={this.state.credentialsStep} orientation='vertical'>
{
this.steps.map((label, index) => (
<Step key={label}>
<StepLabel>{label}</StepLabel>
<StepContent>
<Typography>{this.stepContent[index]}</Typography>
{this.stepAction[index]}
<Grid container direction='row' className='m-t-26'>
// Box wrapper added <Box style={{ display: 'flex', flexDirection: 'row-reverse', justifyContent: 'flex-end' }}>
// First Button is now "Next in JSX <Button variant='contained'
color='primary'
onClick={() => {
this.state.credentialsStep === this.steps.length - 1 ? this.onClickLogin() : this.onClickNext();
}}>
{this.state.credentialsStep === this.steps.length - 1 ? 'Login' : 'Next'}
</Button>
<Button color='primary'
onClick={() => {
this.state.credentialsStep === 0 ? this.onClickCancel() : this.onClickBack();
}}>
{this.state.credentialsStep === 0 ? 'Cancel' : 'Back'}
</Button>
</Box>
</Grid>
</StepContent>
</Step>
))
}
</Stepper>
</DialogContentText>
</DialogContent>

Close React-Bootstrap Popover with a button that's inside popover

I'm using React-Bootstrap Popover. I would like the popover to close once a user clicks on a close button located inside the popover. I would prefer a solution that doesn't use refs as facebook doesn't recommend using them. Here is my code
const popoverTop = (
<Popover id="popover-positioned-top" title="Popover top">
<button type="button" className="close">×</button>
<strong>Holy guacamole!</strong> Check this info.
</Popover>
);
<OverlayTrigger trigger="click" placement="top" overlay={popoverTop}>
<Button>Holy guacamole!</Button>
</OverlayTrigger>
Here is what helped me :
<OverlayTrigger
container={this}
trigger="click"
placement="right"
overlay={this.popoverClick}
rootClose={true}
>
<Button aria-label="Get Info" bsSize="medium">
Button Name
</Button>
</OverlayTrigger>
where popoverClick is:
<Popover id="popover-positioned-scrolling-right" className="popover-main">
<div className="popover-custom-header">
<h3 className="popover-title">Your Title</h3>
<IconButton aria-label="Close" className="icon-button"
onClick={() => document.body.click()}>
<Close fontSize="small"/>
</IconButton>
</div>
<div class="popover-custom-content">
{/* ... the content you need */}
</div>
</Popover>
document.body.click() -> does all the work.
Ref: https://stackoverflow.com/a/47636953/9743227
I hope it will help you, too!
I know that a lot of time has passed, today I had this same problem and I arrived here. I found a way to fix it.
<OverlayTrigger trigger = 'your-trigger' placement = 'auto' rootClose
ref = 'overlay'>
<Popover title='' >
------
</Popover>
<Button onClick={ this.hidePopover } ></Button>
</OverlayTrigger>
then in the method
hidePopover = ( ) =>
{
this.refs.overlay.handleHide();
}
I hope I have helped

Resources