Hi I am trying to create a snackbar using material ui.
React version = 0.14
Material-ui version =0.15.0
I couldn't find anything suitable for this version of React so I decided to use material-ui. It works but only opens at the bottom of the screen. How can I change this? For example how can I get the top right.
My Code :
import Snackbar from 'material-ui/Snackbar';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider'
this.state = {
open: false,
};
handleTouchTap = () => {
this.setState({
open: true,
});
};
handleRequestClose = () => {
this.setState({
open: false,
});
};
<div>
<button
onClick={this.handleTouchTap}>
SHOW NOTIFICATION
<button>
<Snackbar
open={this.state.open}
message="Event added to your calendar"
autoHideDuration={4000}
onRequestClose={this.handleRequestClose}
/>
</div>
Image is here : [Notification image1
Just add anchorOrigin to update position:
<Snackbar
...
anchorOrigin={{ vertical: 'top', horizontal: 'right' }}
/>
Related
Good day, good people!
I want the Material-UI Snackbar component on some pages of my project to pop up in the center of the screen vertically. By default, the Material-UI allows the Snackbar to be aligned to the top or bottom of the screen.
Currently, to achieve this behavior I set height 100% manually in "sx", as suggested here. In order to use this component with its native settings, I want to implement a vertically centering Snackbar using the Material-UI features.
How can I add a custom value "center" to the "vertical"-field of the anchorOrigin property?
export default function Toast() {
const toast = useSelector((state) => state.toast);
const dispatch = useDispatch();
const handleClose = (_, reason) => {
if (reason === 'clickaway') {
return;
}
dispatch(toggleToast({ open: false }));
};
return (
<Snackbar
sx={{ height: toast.height }}//want to get rid of this property
open={true}
anchorOrigin={toast.position ? toast.position : { vertical: 'top', horizontal: 'center' }}
autoHideDuration={toast.duration === undefined ? 4500 : toast.duration}
onClose={handleClose}
>
<Alert variant="filled" severity={toast.severity}>
{toast.message}
</Alert>
</Snackbar>
);
}
"toggleToast"-action sets "open"-property of Snackbar as "true" and passes props to the Snackbar.
dispatch(
toggleToast({
message: "Saved successfully",
severity: "success",
position: { vertical: "top", horizontal: "center" },
height: "100%"
})
)
I'm trying to wrap the text of lengthy cell value. As per documentation setting autoHeight=true and wrapText=true working fine without cellRenderer components. But when using cellRendererFramework React component, seems not working. I tried to setting style inside custom cell renderer also not working. Any help would be greatly appreciated!
AgGrid component is as below,
<AgGridReact
{...configs}
onGridReady={onGridReady}
masterDetail={true}
suppressContextMenu
detailCellRenderer='agCustomDetailTimelineRenderer'
detailRowHeight={140}
frameworkComponents={{
agCustomRenderer: CustomRenderer,
}}>
{configs.columnDefs.map((columnDef) => (
<AgGridColumn {...columnDef} />
))}
</AgGridReact>
Default column definition is,
defaultColDef: {
sortable: true,
filter: true,
wrapText: true,
autoHeight: true,
menuTabs: ['filterMenuTab']
}
And my custom React component is,
import React from 'react';
const CustomRenderer = (props) => {
return (
<div
style={{ height: '100%', whiteSpace: 'normal', wordBreak: 'break-all' }}>
{props.value}
</div>
);
};
export default CustomRenderer;
For me it started working when also added fixed width, after adding below three properties to columnDef it started working for me
wrapText: true,
autoHieght: true,
width: 120
We are using createBottomTabNavigator. In one of the tab contains search bar at the top. While clicking on that search bar, we are opening the keyboard. But the keyboard pushing up the bottom tab bar also. We need the bottom tab bar remains at the bottom when opening keyboard.
One of the solution I have tried is, in android manifest, I have changed android:windowSoftInputMode="adjustPan" or "adjustNothing". It is working fine as expected. But we are using chat layout in another tab which needs "adjustResize". So I have to keep "adjustResize" for windowSoftInputMode.
As another solution, I tried to change windowSoftInputMode inside component itself. SO I have tried with this - https://www.npmjs.com/package/react-native-android-keyboard-adjust. But no use.
As another one, I tried to create a TabBarComponent like mentioned here https://github.com/react-navigation/react-navigation/issues/618. But not working as expected.
const SignedIn = createBottomTabNavigator(
{
Followers: {
screen: FollowerStack,
...
},
Search: {
screen: SearchStack,
},
Home: {
screen: HomeStack,
},
Bookmarks: {
screen: BookmarkStack,
},
Profile: {
screen: ProfileStack,
}
},
{
initialRouteName: "Home",
tabBarPosition: 'bottom',
swipeEnabled: false,
animationEnabled: false,
tabBarOptions: {
keyboardHidesTabBar: true,
showIcon: true,
showLabel: false,
activeTintColor: "red",
inactiveTintColor: "gray",
adaptive: true,
safeAreaInset: {
bottom: "always"
},
style: {
position: 'relative',
backgroundColor: "#F9F8FB",
height: TAB_NAVIGATOR_DYNAMIC_HEIGHT,
paddingTop: DeviceInfo.hasNotch() ? "5%" : "0%",
minHeight: TAB_NAVIGATOR_DYNAMIC_HEIGHT,
width: '100%',
bottom: 0
}
}
}
);
Is there any other properties existed for making the bottom tab bar sticky at the bottom?
or
Is it possible to change the android manifest windowSoftInputMode from inside component?
Please comment below if you required any other code part for reference. Thanks for any help.
I used React navigation 5, is this what you want?
<SignedIn.Navigator
tabBarOptions={{
keyboardHidesTabBar: true
}}
}>
</SignedIn.Navigator>
The document to read here.
Please use this on
<Tab.Navigator
screenOptions={{
tabBarHideOnKeyboard: true
}}
/>
I am sure it will work perfectly
Just go to AndroidManifest.xml file and change/add inside activity tag:
android:windowSoftInputMode="adjustPan"
Found it, just add your bottom navigation into a view making that view of dimensions of the screen, this way:
import React from 'react'
import { StyleSheet, Text, View, Dimensions } from 'react-native'
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
const { width, height } = Dimensions.get("window")
const Tab = createBottomTabNavigator()
export default function () {
return (
<View style={{
width,
height,
}}>
<Tab.Navigator>
<Tab.Screen
name="Screen1"
component={Component}
/>
<Tab.Screen
name="Screen2"
component={Component}
/>
<Tab.Screen
name="Screen3"
component={Component}
/>
</Tab.Navigator>
</View>
)
}
screenOptions={{
headerShown: false,
tabBarActiveTintColor: '#1a3c43',
tabBarInactiveTintColor: '#1a3c43',
tabBarActiveBackgroundColor: 'white',
tabBarInactiveBackgroundColor: '#1a3c43',
tabBarHideOnKeyboard: true,
tabBarstyle: {
backgroundColor: '#1a3c43',
paddingBottom: 3
}
}}
I was having the exact same issue. Following are the two ways I successfully tackled it.
adding "softwareKeyboardLayoutMode":"pan" to the app.json like below
"android": {
"adaptiveIcon": {
"foregroundImage": "./assets/adaptive-icon.png",
"backgroundColor": "#FFFFFF"
},
"softwareKeyboardLayoutMode":"pan"
}
by doing this, the bottom navigator was staying hidden behind the keyboard. however, the ScrollView containing TextInputs was not working the way I wanted it to. the whole app screen was getting translated by the height of the keyboard, hiding half of my ScrollView and everything above it (Header and stuff).
The second workaround I used is using useKeyboard hook.
step 1: remove "softwareKeyboardLayoutMode" so that it defaults to height
(this causes the CustomBottomTabNav to rise above the keyboard as the whole screen gets squeezed in the remaining height)
step 2: dynamically reset the position of CustomBottomTabNav when the keyboard is active.
In the screen containing TextInputs
<ScrollView style={{ height: keyboard.keyboardShown? 510 - keyboard.keyboardHeight: 510}}>
/* lots of text inputs*/
</ScrollView>
In the CustomBottomTabNav
tabBarOptions={{
...otherStuff,
style={{ bottom: keyboard.keyboardShown? -100: -10, ...otherStuff}}
}}
This second method is working much more reliably. I tried keyboardAvoidingView but was unable to wrap my head around its unpredictable behavior.
<Tab.Navigator screenOptions={{ tabBarHideOnKeyboard: Platform.OS!== 'ios'}}>
</Tab.Navigator>
It will work perfectly for both platforms in react native
I got solution for this problem. Previously, I have done a minor mistake while configuring 'react-native-android-keyboard-adjust'. Now it is working fine. So we can change the 'windowSoftInputMode' for a particular component using this library - https://www.npmjs.com/package/react-native-android-keyboard-adjust
If you are using a TextInput in the search bar you could hide the bottom tab when TextInput is focused (and the keyboard shows) like so:
const [searchBarFocused, setSearchBarFocused] = useState(false)
In the markup:
<TextInput
onFocus = {()=> setSearchBarFocused(true)}
onBlur = {()=> setSearchBarFocused(false)}
/>
//Other code
{!searchBarFocused && <CustomBottomTab/>}
For finegrained control put a ref on the textInput to blur/focus and what not programmatically.
Also, you can check out RN:s KeyboardAvoidingView
I doubt this question is ever going to be closed but in case someone stumbles over this problem and needs an answer, I'd recommend looking through the following thread:
https://github.com/react-navigation/react-navigation/issues/6700
Tl;Dr
When supplying the framework with a custom navbar, you have to take care of the hiding of the said bar on keyboard opening. This is because it is the default android behaviour.
So either change the manifest configuration as the author already described as his first solution that didn't work.
OR modify your component to listen to the react-natives KEYBOARD. keyboardDidShow & keyboardDidHide Events and either move it down with bottomMargin: -XYZ or hide it completely with a flag.
following two responses on github helped me:
https://github.com/react-navigation/react-navigation/issues/6700#issuecomment-625985764
https://github.com/react-navigation/react-navigation/issues/618#issuecomment-303975621
In case someone wnats to use my code as a reference
interface BottomTabStateProps {
// unrelated Props
}
interface BottomTabDispatchProps {
// unrelated service dispatchers
}
interface BottomTabState {
navVisible: boolean;
}
class BottomTabContainerClass extends React.Component<
BottomTabStateProps & BottomTabDispatchProps & NavigationInjectedProps, BottomTabState
> {
constructor(props: BottomTabStateProps & BottomTabDispatchProps & NavigationInjectedProps) {
super(props);
this.state = {
navVisible: true
};
}
componentDidMount() {
Keyboard.addListener('keyboardDidShow', () => this.keyboardDidShow());
Keyboard.addListener('keyboardDidHide', () => this.keyboardDidHide());
}
componentWillUnmount() {
Keyboard.removeAllListeners('keyboardDidShow');
Keyboard.removeAllListeners('keyboardDidHide');
}
keyboardDidShow() {
this.setState({ navVisible: false });
}
keyboardDidHide() {
this.setState({ navVisible: true });
}
render() {
return (
<View>
{
this.state.navVisible &&
<View>
// add custom Navbar here
</View>
}
</View>
);
}
}
Currently i have the following structure
<OverlayTrigger trigger={["hover", "focus", "click"]} placement="bottom" overlay={(
<Popover className="timeline-popover-container" id="tpc-1">
<TimelinePopover
alert={session}
previousAlert={prevSession}
nextAlert={nextSession}
status={status}
/>
</Popover>
)}>
<div className="myclass">
<div>{img}</div>
</div>
</OverlayTrigger>
So, when the popover is triggered and i try to hover over the popover, the popover dissapear.
I want to be able to click inside de popover, do things inside of that and just dissapear when i move the mouse out of it.
I did a little component to handle this use case (inspired from the answer by #AnnieP).
https://gist.github.com/lou/571b7c0e7797860d6c555a9fdc0496f9
Usage:
<PopoverStickOnHover
component={<div>Holy guacamole! I'm Sticky.</div>}
placement="top"
onMouseEnter={() => { }}
delay={200}
>
<div>Show the sticky tooltip</div>
</PopoverStickOnHover>
I manage to make that work using one of the comments that ochi posted.
<OverlayTrigger trigger={["hover"]} placement="bottom" overlay={(
<Popover onMouseOver={this.showOverlay} onMouseOut={this.hideOverlay}>
content
</Popover>
)}>
<div onMouseOver={this.showOverlay} onMouseOut={this.hideOverlay}>
<div>bla bla bla</div>
</div>
</OverlayTrigger>
adding trigger on the popover and on the div i want to trigger worked.
I was looking to do the same thing using React Bootstrap except with a tooltip instead of a popover. The answer here gave me a good jumping off point, which I mixed with the Custom Overlay example in the React Bootstrap docs.
I replaced OverlayTrigger with a custom Overlay, which wraps the Tooltip but is outside of the target element, whereas the OverlayTrigger wraps the target element and calls Tooltip through the overlay prop. I added onMouseEnter() and onMouseLeave() to both the tooltip and the target element to toggle the tooltip visibility state so that leaving either one will close the tooltip.
This is a bare-bones version of my implementation:
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { Tooltip, Overlay } from 'react-bootstrap';
const TooltipExample extends Component {
constructor(props) {
super(props);
this.state = {
showTooltip: false,
};
}
render() {
let myTooltip = (
<Tooltip
onMouseEnter={() => this.setState({ showTaskTooltip: true })}
onMouseLeave={() => this.setState({ showTaskTooltip: false })}
>
I'm a tooltip and I'll stay open when you leave the target element and hover over me!
</Tooltip>
);
return(
<div>
<h3
ref="target"
onMouseEnter={() => this.setState({ showTooltip: true })}
onMouseLeave={() => this.setState({ showTooltip: false })}
>
Hover over me!
</h3>
<Overlay
show={this.state.showTooltip}
onHide={() => this.setState({ showTooltip: false })}
placement="bottom"
target={() => ReactDOM.findDOMNode(this.refs.target)}
>
{myTooltip}
</Overlay>
</div>
);
}
}
export default TooltipExample;
I'd like to know if there is a best practice/correct way to setup a right-click menu for a React component.
I currently have this...
// nw is nw.gui from Node-Webkit
componentWillMount: function() {
var menu = new nw.Menu();
menu .append(new nw.MenuItem({
label: 'doSomething',
click: function() {
// doSomething
}
}));
// I'd like to know if this bit can be done in a cleaner/more succinct way...
// BEGIN
var that = this;
addEventListener('contextmenu', function(e){
e.preventDefault();
// Use the attributes property to uniquely identify this react component
// (so different elements can have different right click menus)
if (e.target.attributes[0].nodeValue == that.getDOMNode().attributes[0].nodeValue) {
menu.popup(e.x, e.y);
}
})
// END
},
This works, but it feels a little messy and I was wondering if there was another approach I might be able to use, any information would be greatly appreciated,
Thanks!
UPDATE:
Figured it out - here is what you can do
var addMenu;
componentWillMount: function() {
addMenu = new nw.Menu();
addMenu.append(new nw.MenuItem({
label: 'doSomething',
click: function() {
// doSomething
}
}));
},
contextMenu: function(e) {
e.preventDefault();
addMenu.popup(e.clientX, e.clientY);
},
render: function(){
return <button onClick={this.handleClick} onContextMenu={this.contextMenu}>SomethingUseful</button>
}
In render you can pass a function to onContextMenu for when a right click occurs for this react component.
There are few things to take care about with popup menus:
it should be rendered away from its parent and siblings - preferably in an overlay which is the last child of document.body
special logic should take care that it's always displayed on screen and never cropped by screen edges
if there is a hierarchy involved, child popups should be aligned to items from previous popup (opener).
I created a library which you can use to accomplish all of these:
http://dkozar.github.io/react-data-menu/
I was alsolooking for a solution while working with Material UI, So what you want to do is first disable the default behaviour of a browser on right click and then add the menu which you want, here's the working code:
import React from 'react';
import { withStyles } from '#material-ui/core/styles';
import Button from '#material-ui/core/Button';
import Menu from '#material-ui/core/Menu';
import MenuItem from '#material-ui/core/MenuItem';
import ListItemIcon from '#material-ui/core/ListItemIcon';
import ListItemText from '#material-ui/core/ListItemText';
import InboxIcon from '#material-ui/icons/MoveToInbox';
import DraftsIcon from '#material-ui/icons/Drafts';
import SendIcon from '#material-ui/icons/Send';
const StyledMenu = withStyles({
paper: {
border: '1px solid #d3d4d5',
},
})((props) => (
<Menu
elevation={0}
getContentAnchorEl={null}
anchorOrigin={{
vertical: 'bottom',
horizontal: 'center',
}}
transformOrigin={{
vertical: 'top',
horizontal: 'center',
}}
{...props}
/>
));
const StyledMenuItem = withStyles((theme) => ({
root: {
'&:focus': {
backgroundColor: theme.palette.primary.main,
'& .MuiListItemIcon-root, & .MuiListItemText-primary': {
color: theme.palette.common.white,
},
},
},
}))(MenuItem);
export default function CustomizedMenus() {
const [anchorEl, setAnchorEl] = React.useState(null);
const handleClick = (event) => {
event.preventDefault();
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
return (
<div>
<Button
aria-controls="customized-menu"
aria-haspopup="true"
variant="contained"
color="primary"
onContextMenu={handleClick}
>
Open Menu
</Button>
<StyledMenu
id="customized-menu"
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
onClose={handleClose}
>
<StyledMenuItem>
<ListItemIcon>
<SendIcon fontSize="small" />
</ListItemIcon>
<ListItemText primary="Sent mail" />
</StyledMenuItem>
<StyledMenuItem>
<ListItemIcon>
<DraftsIcon fontSize="small" />
</ListItemIcon>
<ListItemText primary="Drafts" />
</StyledMenuItem>
<StyledMenuItem>
<ListItemIcon>
<InboxIcon fontSize="small" />
</ListItemIcon>
<ListItemText primary="Inbox" />
</StyledMenuItem>
</StyledMenu>
</div>
);
}
and the sandbox project