Tooltip with content in Material-UI - material-ui

I have following tooltip:
export const EstimateTableActions = () => {
return (
<>
<Tooltip title="Actions" aria-label="add">
<Fab color="primary">
<MoreVertIcon />
</Fab>
</Tooltip>
</>
);
};
which looks like:
And I want to add content to the tooltip, I want to have some div with my actions after click, in the documentation there is no any example on that, any idea?

You can use speed dial component to add actions of your choice --
import React from 'react';
import { makeStyles } from '#material-ui/core/styles';
import Button from '#material-ui/core/Button';
import Backdrop from '#material-ui/core/Backdrop';
import SpeedDial from '#material-ui/lab/SpeedDial';
import SpeedDialIcon from '#material-ui/lab/SpeedDialIcon';
import SpeedDialAction from '#material-ui/lab/SpeedDialAction';
import FileCopyIcon from '#material-ui/icons/FileCopyOutlined';
import SaveIcon from '#material-ui/icons/Save';
import PrintIcon from '#material-ui/icons/Print';
import ShareIcon from '#material-ui/icons/Share';
import FavoriteIcon from '#material-ui/icons/Favorite';
const useStyles = makeStyles((theme) => ({
root: {
height: 380,
transform: 'translateZ(0px)',
flexGrow: 1,
},
speedDial: {
position: 'absolute',
bottom: theme.spacing(2),
right: theme.spacing(2),
},
}));
const actions = [
{ icon: <FileCopyIcon />, name: 'Copy' },
{ icon: <SaveIcon />, name: 'Save' },
{ icon: <PrintIcon />, name: 'Print' },
{ icon: <ShareIcon />, name: 'Share' },
{ icon: <FavoriteIcon />, name: 'Like' },
];
export default function SpeedDialTooltipOpen() {
const classes = useStyles();
const [open, setOpen] = React.useState(false);
const [hidden, setHidden] = React.useState(false);
const handleVisibility = () => {
setHidden((prevHidden) => !prevHidden);
};
const handleOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
return (
<div className={classes.root}>
<Button onClick={handleVisibility}>Toggle Speed Dial</Button>
<Backdrop open={open} />
<SpeedDial
ariaLabel="SpeedDial tooltip example"
className={classes.speedDial}
hidden={hidden}
icon={<SpeedDialIcon />}
onClose={handleClose}
onOpen={handleOpen}
open={true}
>
{actions.map((action) => (
<SpeedDialAction
key={action.name}
icon={action.icon}
tooltipTitle={action.name}
tooltipOpen
onClick={handleClose}
/>
))}
</SpeedDial>
</div>
);
}
Working sandbox here - https://codesandbox.io/s/qogpp

Related

Cannot override default Material UI Icon styling

I have an AccountCircleIcon Material UI icon and I want to increase the size, I've tried several things:
import AccountCircleIcon from '#material-ui/icons/AccountCircle';
import {withStyles} from '#material-ui/styles';
const StyledIcon = withStyles({
root: {
fontSize: '50rem',
},
})(AccountCircleIcon);
const login = () => {
return (
<div><StyledIcon /></div>
);
};
import AccountCircleIcon from '#material-ui/icons/AccountCircle';
import {makeStyles} from '#material-ui/styles';
const useStyles = makeStyles({
root: {
fontSize: '50rem',
},
});
const login = () => {
const classes = useStyles();
return (
<div><AccountCircleIcon classes={{root: classes.root}} /></div>
);
};
import AccountCircleIcon from '#material-ui/icons/AccountCircle';
import {makeStyles} from '#material-ui/styles';
const useStyles = makeStyles({
avatarIcon: {
fontSize: '50rem',
},
});
const login = () => {
const classes = useStyles();
return (
<div><AccountCircleIcon className={classes.avatarIcon} /></div>
);
};
But each time the default icon styling overrides the added styling:
I missed the StyledEngineProvider https://mui.com/guides/interoperability/ wrapping that around your app assures the custom css is injected first:
import * as React from 'react';
import { StyledEngineProvider } from '#mui/material/styles';
export default function GlobalCssPriority() {
return (
<StyledEngineProvider injectFirst>
{/* Your component tree. Now you can override MUI's styles. */}
</StyledEngineProvider>
);
}
https://codesandbox.io/s/laughing-alex-nyszr?file=/src/Demo.tsx

Next.js with MUI v4 styles flicker

First of all, sorry for my English.
I tried to setup correctly MUI v4 for Next.js but I’ve always styles flicker.
I’ve :
Next: 10.0.5
Material-ui/core: 4.9.14
And I use Material-UI's styling solution.
No solution found on the web can’t correct this behavior for now.
In my _app.js :
import { useEffect } from 'react';
import { ThemeProvider } from '#material-ui/core/styles';
import CssBaseline from '#material-ui/core/CssBaseline';
import { AuthProvider } from '#lib/useAuth';
import DefaultLayout from '#layouts/DefaultLayout';
import theme from '#assets/styles/jss/theme';
import '#assets/styles/scss/toastify.scss';
const MyApp = ({ Component, pageProps }) => {
const Layout = Component.Layout || DefaultLayout;
useEffect(() => {
// Remove the server-side injected CSS.
const jssStyles = document.querySelector('#jss-server-side');
if (jssStyles) {
jssStyles.parentElement.removeChild(jssStyles);
}
}, []);
return (
<ThemeProvider theme={theme}>
<AuthProvider>
<CssBaseline />
<Layout>
<Component {...pageProps}> </Component>
</Layout>
</AuthProvider>
</ThemeProvider>
);
};
export default MyApp;
In my _document.js :
import React from 'react';
import Document, {
Html,
Head,
Main,
NextScript,
} from 'next/document';
import { ServerStyleSheets } from '#material-ui/core/styles';
class MyDocument extends Document {
render() {
return (
<Html lang="fr">
<Head>
<link rel="icon" href="/favicon.ico" />
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}
MyDocument.getInitialProps = async (ctx) => {
const sheets = new ServerStyleSheets();
const originalRenderPage = ctx.renderPage;
ctx.renderPage = () => originalRenderPage({
enhanceApp: (App) => (props) => sheets.collect(<App {...props} />),
});
const initialProps = await Document.getInitialProps(ctx);
return {
...initialProps,
// Styles fragment is rendered after the app and page rendering finish.
styles: [...React.Children.toArray(initialProps.styles), sheets.getStyleElement()],
};
};
export default MyDocument;
For example, in navbar component I’m doing :
import { makeStyles } from '#material-ui/core/styles';
import styles from '#assets/styles/jss/components/navbarStyle';
const useStyles = makeStyles(styles, { name: 'MuiCustomNavbar' });
const Navbar = () => {
const classes = useStyles();
[…]
}
But i’v always styles flicker in production when I reload page.
Anyone can help me please ?
Thanks !

Use the Facebook Login function in a React Native Component

I'm trying to implement the Facebook login in my react native application.
I'm following this tutorial : https://dev.to/rishikeshvedpathak/react-native-login-with-facebook-4mmi
and that's working great, I have the Facebook login button and everything works.
But he did it in a function and I want to implement it into a component.
I have a component with a Facebook login button and I want this button to call the FacebookLogin function from my Facebook.js file which contains the code from the tutorial above.
I tried to import it like this:
import App from './Facebook.js'
and then call the function like this using the 'onPress' in my TouchableOpacity:
App.FacebookLogin, but nothing worked.
Here is the code from the tutorial:
import React, { useState } from 'react';
import { StyleSheet, Text, View, Image, TouchableOpacity, ActivityIndicator } from 'react-native';
import * as Facebook from 'expo-facebook';
console.disableYellowBox = true;
export default function App() {
const [isLoggedin, setLoggedinStatus] = useState(false);
const [userData, setUserData] = useState(null);
const [isImageLoading, setImageLoadStatus] = useState(false);
facebookLogIn = async () => {
Facebook.initializeAsync('My_App_id', 'My_App_name');
try {
const {
type,
token,
expires,
permissions,
declinedPermissions,
} = await Facebook.logInWithReadPermissionsAsync('My_App_id', 'My_App_name', {
permissions: ['public_profile'],
});
if (type === 'success') {
// Get the user's name using Facebook's Graph API
fetch(`https://graph.facebook.com/me?access_token=${token}&fields=id,name,email,picture.height(500)`)
.then(response => response.json())
.then(data => {
setLoggedinStatus(true);
setUserData(data);
})
.catch(e => console.log(e))
} else {
// type === 'cancel'
}
} catch ({ message }) {
alert(`Facebook Login Error: ${message}`);
}
}
logout = () => {
setLoggedinStatus(false);
setUserData(null);
setImageLoadStatus(false);
}
return (
isLoggedin ?
userData ?
<View style={styles.container}>
<Image
style={{ width: 200, height: 200, borderRadius: 50 }}
source={{ uri: userData.picture.data.url }}
onLoadEnd={() => setImageLoadStatus(true)} />
<ActivityIndicator size="large" color="#0000ff" animating={!isImageLoading} style={{ position: "absolute" }} />
<Text style={{ fontSize: 22, marginVertical: 10 }}>Hi {userData.name}!</Text>
<TouchableOpacity style={styles.logoutBtn} onPress={this.logout}>
<Text style={{ color: "#fff" }}>Logout</Text>
</TouchableOpacity>
</View> :
null
:
<View style={styles.container}>
<Image
style={{ width: 200, height: 200, borderRadius: 50, marginVertical: 20 }}
source={require("../assets/logo_yorder.png")} />
<TouchableOpacity style={styles.loginBtn} onPress={this.facebookLogIn}>
<Text style={{ color: "#fff" }}>Login with Facebook</Text>
</TouchableOpacity>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#e9ebee',
alignItems: 'center',
justifyContent: 'center',
},
loginBtn: {
backgroundColor: '#4267b2',
paddingVertical: 10,
paddingHorizontal: 20,
borderRadius: 20
},
logoutBtn: {
backgroundColor: 'grey',
paddingVertical: 10,
paddingHorizontal: 20,
borderRadius: 20,
position: "absolute",
bottom: 0
},
});
And here is the TouchableOpacity from my component :
<View style={styles.connexionServices}>
<TouchableOpacity style={[styles.connexionFacebook, styles.connexionCommon]}>
<Text style={styles.textButton}>Facebook</Text>
</TouchableOpacity>
<TouchableOpacity style={[styles.connexionGoogle, styles.connexionCommon]}>
<Text style={styles.textButton}>Google</Text>
</TouchableOpacity>
</View>
Here it is, I would like to implement Google login too so if you have some tips, it would be nice.
PS : I'm using react-native-cli: 2.0.1 and react-native: 0.61.4 with expo 3.18.6
OK I did it, i juste declared the function before the component declaration so i can call it in my component. It was a little tricky to call some of the functions in my component in the function but everything work now and i can log to facebook throught my Login component !

IconButton with label

Is there something I can use in/with IconButton to define a label below the icon?
Maybe something similar to BottomNavigationAction but without it having to be inside of a BottomNavigation.
You can add your label as a direct child of the IconButton (sibling of the Icon itself), and override the IconButton-label style to have flexDirection: column
import React from 'react';
import {IconButton} from '#material-ui/core';
import { makeStyles } from '#material-ui/core/styles';
import SaveIcon from '#material-ui/icons/Save';
const useStyles = makeStyles(theme => ({
iconButtonLabel: {
display: 'flex',
flexDirection: 'column',
},
}));
export default function IconButtonWithLabel() {
const classes = useStyles();
return (
<IconButton classes={{label: classes.iconButtonLabel}}>
<SaveIcon/>
<div>
hello
</div>
</IconButton>
);
}

Clipped drawer in Material ui

According to docs, material-ui supports persistant drawer.
But my expected behaviour is a clipped persistant drawer like the photo.
My Sidebar component:
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { withStyles } from 'material-ui/styles';
import Drawer from 'material-ui/Drawer';
import List, { ListItem, ListItemIcon, ListItemText } from 'material-ui/List';
import Face from 'material-ui-icons/Face';
import Person from 'material-ui-icons/Person';
import Assignment from 'material-ui-icons/Assignment';
import NavLink from 'react-router-dom/NavLink';
import { FormattedMessage } from 'react-intl';
import styles from '../../../../style/components/global/Sidebar.scss';
const cx = require('classnames/bind').bind(styles);
const rootStyles = theme => ({
list: {
width: 250,
flex: 'initial',
},
drawer: {
top: 30,
},
});
class UndockedDrawer extends Component {
render() {
const { classes } = this.props;
const sidebarListItems = (
<div>
<NavLink
to="/users"
className={cx('noStyle')}
>
<ListItem button>
<ListItemIcon>
<Person />
</ListItemIcon>
<ListItemText primary={<FormattedMessage id="user" />} />
</ListItem>
</NavLink>
</div>
);
const sidebarList = (
<div>
<List className={classes.list}>
{sidebarListItems}
</List>
</div>
);
return (
<div>
<Drawer
open={this.props.open}
onRequestClose={this.props.onRequestClose}
onClick={this.props.onRequestClose()}
type="permanent">
{sidebarList}
</Drawer>
</div>
);
}
}
export default withStyles(rootStyles)(UndockedDrawer);
So far, I've tried to make top property as much as AppBar's height but this behaviour wasn't what I needed.
Is there any way to achieve this?
You need to provide the right styles for the AppBar. Taking the example from the docs you provided:
Instead of:
const styles = theme => ({
...
appBar: {
position: 'absolute',
width: `calc(100% - ${drawerWidth}px)`,
marginLeft: drawerWidth,
},
...
});
Use:
const styles = theme => ({
...
appBar: {
position: 'absolute',
width: '100%',
zIndex: '1400',
},
...
});
Why zIndex is 1400? It's just an arbitrary number that is higher than the zIndex of the Drawer, which is 1300.