Materialiui Paper api with close button - javascript

I am implementing Paper from Material UI: https://mui.com/components/paper/
And here is the code I have written so far:
<Paper className="modal" elevation={3}>
{..Content..}
</Paper>
The current UI makes it open a special pane which closes only when I click on area outside of it. I want to add a close button to close the Paper. Is it possible to add a custom onClose action on it?
Edit: Here is a codesandbox that I have replicated: https://codesandbox.io/s/black-surf-r1yz87?file=/src/App.js

Paper is just a surface to render components on, it does not support any functionality. For this use case, a state variable can be used to hide and unhide the Paper component. You may make it a reusable component.
const [shouldShowPaper, setShouldShowPaper] = useState(true);
...
{
shouldShowPaper &&
<Paper elevation={props.elevation} style={{position: "relative"}}>
<button
style={{position:"absolute", top: "10px", right: "10px"}}
onClick={() => setShouldShowPaper(false)}
>
X
</button>
{props.children}
</Paper>
}
You may toggle classes to show transitions instead of abrupt removal of the paper component.

Related

React Bootstrap- Overlay Tooltip rendering in wrong position initially

I am writing a react bootstrap app where a button appears at the end of an animation. When the button first appears, I want a tooltip to appear next to it. Once the user hovers over and off the button, the tooltip should go away and re-appear whenever the user hovers over the button again. I've gotten this to work as desired, but when I position the button where I want it to be (fixed to the bottom of the screen), the tooltip initially renders in the wrong position (where the button was before being positioned).
I have created two simple examples to demonstrate this behavior.
In the first example, the button is positioned at the top of the screen and the tooltip behaves as this desire:
function Testing(){
const refLink = useRef(null);
const [overlayOpen, setOverlayOpen] = useState(true); // Initially open
const [textDone, setTextDone] = useState(false);
useEffect(() => {
const timeoutId = setTimeout(() => {
setTextDone(true)
},1000)
return () => clearTimeout(timeoutId)
},[])
return(
<Container>
<Row>
{textDone ?
<>
<Button ref={refLink} onMouseOver={() => setOverlayOpen(true)}
onMouseOut={() => setOverlayOpen(false)}
>
<FaComment/>
</Button>
<Overlay target={refLink.current} show={overlayOpen}
onHide={() => setOverlayOpen(false)} rootClose placement={"bottom"}>
<Tooltip>
Submit a personal response!
</Tooltip>
</Overlay>
</>
: ''
}
</Row>
</Container>
)
}
export default Testing
The textDone state is set to true once the "animation" finishes. To simplify the example, I omitted the animation itself and recreated the delay with setTimeout.
The second example is identical except for the following .css class added to the Row element in which the button, overlay, and tooltip are nested inside of.
.fixed-button{
position:fixed;
right: 20px;
bottom: 20px;
}
With this addition, the button ends up where I want it, but the tooltip first appears at the top of the screen. Once I hover over the button, the tooltip moves to the correct position.
Here are some gifs of the two examples.
Example 1 (tooltip behaving as intended but button not positioned in right spot)
Example 2 (button positioned where I want it but tooltip initially showing up in wrong spot)
My question is: how can I get the tooltip to initially appear in the correct position?

HeaderRight Buttons are not clickable (React Native)

I am experiencing an odd bug with the React Native Navigation v5 headerRight Buttons. I currently have a TouchableOpacity set as a headerRight component in the react native navigation screen; however, the onPress event is not being triggered. There seems to be an invisible object in the middle of the header (title area) that has an absolute position, which prevents the onPress event from being registered. I tried playing around with the zIndex and headerMode values; however, the button is still not pressable. I can only press the button when it is placed on the far right of the screen (i.e. marginRight: 0). Any help would be greatly appreciated.
For reference, I am encountering the same issues as the following thread: https://github.com/react-navigation/react-navigation/issues/7052
Example of my Code
<StackNavigator.Navigator headerMode='screen'>
<StackNavigator.Screen
name='Home'
component={HomeScreen}
options={{
headerRight: () => (
<TouchableOpacity
onPress={() => {}}
>
<Text>Button Text</Text>
</TouchableOpacity>
),
}}
/>
</StackNavigator.Navigator>
Updating to the following packages seems to have resolved it for me:
"#react-navigation/stack": "5.9.3",
"#react-navigation/drawer": "5.9.3",
"#react-navigation/native": "5.7.4",
Try to give higher values to zIndex may be 100 or give headerMode: float if that not also not works try updating your packages .

How to use a component to act as clickable alternative?

hey I have designed a rectangle using css and it displays a text inside of it , How can I convert this whole component as a means to navigate to some other url (i have tried using the Link from reactrouterDOM but it changed the shape and also an underline appeared just below the text, which defeated the whole point of it not looking like a link text ).
Any Approach Would be helpful as I am quite new to React.Thanks!
If you want to use Link from react-router:
<Link to="/url" style={{
textDecoration: 'none',
color: 'inherit',
display: 'inline-block',
}}>
<Rectangle/>
</Link>
If you just want to handle onClick in rectangle:
export const Rectangle = (props) => (
<div onClick={props.onClick}>whatever</div>
);
and then use it as:
<Rectangle onClick={() => console.log('whatever')}/>
PS: https://reactjs.org/docs/handling-events.html

Setting hovered style for material-ui IconButton

According to React Material-UI docs, I have a prop hoveredStyle to work with: http://www.material-ui.com/#/components/icon-button
I want to use IconButton for two purposes:
Utilize its tooltip prop for accessibility
I can wrap Material-UI svg icons directly
However, I don't want the cursor to change to a pointer when I hover (which is default behavior I believe), so I changed it like so.
import DeleteIcon from 'material-ui/svg-icons/action/delete
const hoveredStyle = {
cursor: 'initial'
}
render() {
return (
<IconButton tooltip="Description here" hoveredStyle={hoveredStyle}>
<DeleteIcon />
</IconButton>
)
}
This works fine, except that the split millisecond that I enter hover mode on the icon, I still see the default hand pointer before it gets set to the normal mouse pointer. How do I approach this?
I just tested adding a cursor: default to the style of both IconButton and DeleteIcon and it seems to have the functionality you want. (No pointer cursor on hover.)
const noPointer = {cursor: 'default'};
return (
<div>
<IconButton tooltip="Description here" style={noPointer}>
<DeleteIcon style={noPointer} />
</IconButton>
</div>
);
Some notes for people stumbling upon this thread. If you are having a problem with hover styles for an icon if you are using Material-ui you might have forgot something.
In my case I used a <KeyboardArrowLeft/> and wrapped it in a <Tooltip/>. I could not get hover styles in there at all including a simple hand "cursor". I had to wrap the icon with <IconButton>. It is in that element where you can pass styles.
While the example that was provided before as the "accepted answer" does solve the initial problem, it is not production level.
If you are using reactjs you will need to import the following into your component, switch with your respective icon
import Tooltip from '#material-ui/core/Tooltip';
import IconButton from '#material-ui/core/IconButton';
import KeyboardArrowLeft from '#material-ui/icons/KeyboardArrowLeft';
In the icon wrap as follows
<Tooltip title="">
<IconButton
aria-label=""
style={componentStyle.iconBack}
>
<KeyboardArrowLeft
style={componentStyle.eventHeadingBack}
onClick={}
/>
</IconButton>
</Tooltip>
In the Tooltip, give it a title of what the user should expect when clicking the button.
In the IconButton, add some description for aria (screen readers) like "back to home page". In the style, use a class. You will have a const that you can use for that component you are working on, then give the classname for the actual element a descriptive title. This is where you can control the cursor and hover actions.
In the actual icon, give it a class so you can do things like change color.
Now you will need to style the component, name it however you want but ideally according to the components purpose.
const componentStyle = {
container: {
display: 'flex',
width: '100%',
height: '100vh',
backgroundColor: '#212121',
},
iconBack: {
cursor: 'crosshair'
},
eventHeadingBack: {
color: '#fff',
marginRight: '16px'
}
}

How to add ripple effect when clicking Card in MUI

Is there a way I can add ripple effect to MUI Card component on click.
And I would also like to know, is it possible to make ripple effect to come on top of the content of Card component, rather that it showing as background.
I noticed that TouchRipple has been moved out of the internal directory.
It's now available in the ButtonBase folder.
Here is how I was able to add ripple effect by using the ButtonBase component -
Basically, you wrap your component, let's say <Card> inside the <ButtonBase> like so, and the ButtonBase takes care of the TouchRipple setting up for you -
<ButtonBase>
<Card>
....
</Card>
</ButtonBase>
Here is a Codesandbox link to working demo.
I know this is not the best way. You could directly use the TouchRipple/Ripple component, but I found this way to be very easy to use.
Hope this helps.
I can see this question was not answered, so I'll provide an up-to-date solution (writing this as material-ui is v. 0.18.7 (stable):
You need to import the ripple higher-order comp. (HOC) as:
import TouchRipple from '#material-ui/core/ButtonBase/TouchRipple';
Then you can wrap any component of you choice with TouchRipple, like:
<TouchRipple>
<div>
MY RIPPLING DIV
</div>
</TouchRipple>
Or, if you need a CSS class-based apporach, you can use materialize lib -> https://react-materialize.github.io/#/
In that case, it's as simple as adding a value to waves prop on a material-ui Button, like:
<Button waves='light'>EDIT ME<Icon left>save</Icon></Button>
2021 Update
The most idiomatic way to add the ripple effect when clicking the Card is using the CardActionArea. This component inherits the props of ButtonBase. It also changes the Card background color when hovered and focused (unlike ButtonBase):
<Card>
<CardActionArea>
<CardContent>
{...}
</CardContent>
</CardActionArea>
</Card>
The approach taken in #xiaofan2406 never worked for me, not to mention passing height, width and position seems easily breakable and might not be possible when using flexbox.
However I managed to make it work like:
<YourComponent>
<TouchRipple>
{children}
</TouchRipple>
</YourComponent>
Here is a Solution 2021 updated
simple You need wrap your custom components with component from material ui .
Then add style padding: 0 that solve.
Here I want my Image should react with ripple effect.
You can customize by wrapping with Grid and props container
import { Button } from "#material-ui/core";
function ImageCard(props){
return (
<Button style={{ padding: 0, borderRadius: "16px" }}>
{/*my custom component you can use any component even material ui component also*/}
<img
src={yourImageUrl}
alt="img"
style={{
height: 200,
width: 400,
borderRadius: "16px",//optional
}}
/>
</Button>
);
}
Using component attribute
Instead of wrapping, you can specify the component attribute as the desired component you want it to be. That is, for this use-case;
import ButtonBase from '#material-ui/core/ButtonBase';
...
<Card component = {ButtonBase}>
<CardContent>
...
</CardContent>
</Card>
If you have issues with height or width of the card, add the sx attribute;
<Card component={ButtonBase} sx={{height:'100%', width:'100%'}}>
...
</Card>
If ButtonBase messes up all other buttons on the page, it's better to use just the Button;
import Button from '#mui/material/Button';
...
<Card component = {Button}>
<CardContent>
...
</CardContent>
</Card>
Using MUI V5 (2022)
You can get the benefit of the component prop, use the <ButtonBase> component to get the ripple effect.
Create a React HOC or simply copy this code into a new file:
import React, { forwardRef } from 'react'
import { ButtonBase } from '#mui/material'
export default function WithTouchRipple(OriginalComponent) {
return (props) => {
const Wrapper = !props.component
? ButtonBase
: forwardRef((ButtonBaseProps, ref) => <ButtonBase component={props.component} {...ButtonBaseProps} ref={ref} />)
return <OriginalComponent {...props} component={Wrapper} />
}
}
Then use it as follows on any component you like:
import { Chip, Card, Stack } from '#mui/material'
import WithTouchRipple from '../WithTouchRipple'
const RippleChip = WithTouchRipple(Chip)
const RippleCard = WithTouchRipple(Card)
const RippleStack = WithTouchRipple(Stack)
<RippleChip component={Link} to={`/users/${id}`} {...chipProps} />
<RippleStack>...</RippleStack>
<RippleCard>...</RippleCard>
If you want the ripple effect to appear on the <Card> component, there is a built-in component for that called <CardActionArea>, and you can use it as follows:
<Card>
<CardActionArea>
<CardContent>
{...}
</CardContent>
</CardActionArea>
</Card>
The official api doesn't seem to support it.
But this is what I do, when I want to use material-ui ripple affect:
Use material-ui/internal/TouchRipple, have a look at its source code
Usage example:
<YourComponent>
<TouchRipple style={style}/>
{children}
</YourComponent>
You need to pass the inline style to specify its height, width and position that matches YourComponent's height, width and postion

Categories

Resources