I am trying to populate ListItems( ListItemIcon and ListItemText) on Material UI mini Drawer in vertical align mode. Some how my ListItemText not aligning properly to the ListItemIcons.
Here is my styles:
link: {
textDecoration: "none",
"&:hover, &:focus": {
backgroundColor: theme.palette.background.yellow
}
},
linkActive: {
backgroundColor: theme.palette.background.light
},
linkIcon: {
marginRight: theme.spacing(1),
marginBottom: theme.spacing(4),
color: theme.palette.text.secondary + "99",
transition: theme.transitions.create("color"),
width: 24,
display: "flex",
justifyContent: "center"
},
linkText: {
marginTop: theme.spacing(1),
color: theme.palette.text.secondary + "CC",
transition: theme.transitions.create(["opacity", "color"]),
fontSize: 13,
display: "flex",
justifyContent: "flex-end"
}
Component
import React from "react";
import {
ListItem,
ListItemIcon,
ListItemText,
} from "#material-ui/core";
import { Link } from "react-router-dom";
import classnames from "classnames";
// styles
import useStyles from "./styles";
export default function SidebarLink({
link,
icon,
label,
location,
}) {
var classes = useStyles();
var isLinkActive =
link &&
(location.pathname === link || location.pathname.indexOf(link) !== -1);
return (
<ListItem
button
component={link && Link}
to={link}
className={classes.link}
>
<ListItemIcon
className={classnames(classes.linkIcon, {
[classes.linkIconActive]: isLinkActive
})}
>
{icon}
</ListItemIcon>
<ListItemText
classes={{
primary: classnames(classes.linkText, {
[classes.linkIconActive]: isLinkActive
})
}}
primary={label}
></ListItemText>
</ListItem>
);
}
How to align ListItems in vertical mode properly? I tried adding textAlign and alignItems to center to linkText css class but not them worked.
Any Help is Appreciated
Thanks,
react-router-dom Link uses html < a > tag under the hood.
< a > children will be displayed in column as default.
You just need to style your link properly:
link: {
display: 'flex',
flexDirection: 'row',
textDecoration: "none",
"&:hover, &:focus": {
backgroundColor: theme.palette.background.yellow
}
},
Related
I have created MyComponent( called 'InnerContainer' ) by using MUI system; styled-component. But onClick under the styled component is not working. It is working outside 'InnerContainer' but not working inside 'InnerContainer'. Don't know the reason.. please help me why it's not working.
import { useSortable } from "#dnd-kit/sortable";
import { CSS } from "#dnd-kit/utilities";
import { styled } from "#mui/system";
// import styled from '#emotion/styled'
import DeleteIcon from "#mui/icons-material/Delete";
function DraggableBox(props) {
const { attributes, listeners, setNodeRef, transform, transition } =
useSortable({ id: props.id });
// console.log("props", props);
const outerContainer = {
transform: CSS.Transform.toString(transform),
transition,
backgroundColor: props.color,
width: "20%",
height: "25%",
display: "inline-block",
};
const InnerContainer = styled("div")({
width: "100%",
height: "100%",
display: "flex",
justifyContent: "space-between",
alignItems: "end",
fontWeight: "600",
"&:hover svg": {
color: "white",
transform: "scale(1.3)",
transition: "0.5s",
},
" .inBoxName": {
marginLeft: "0.5rem",
},
" .inBoxTrash": {
marginRight: "0.5rem",
},
});
return (
<div style={outerContainer} ref={setNodeRef} {...attributes} {...listeners}>
<InnerContainer>
<div className="inBoxName">{props.name}</div>
<div className="inBoxTrash">
<DeleteIcon onClick={() => props.removeColorBox(props.id)} />
</div>
</InnerContainer>
</div>
);
}
export default DraggableBox;
I am new in material UI.
somehow my code doesn't recognize the theme parameter.
the error is in this line of code on " [theme.breakpoints.up("sm")]"
const Icons = styled(Box)(({ theme }) => ({
display: "none",
gap: "20px",
alignItems: "center",
[theme.breakpoints.up("sm")]: {
display: "flex",
},
}));
It seems that theme is a parameter and nothing more, how can I implement the "theme"?
here is my full page:
import styled from "#emotion/styled";
import { Notifications, Pets } from "#mui/icons-material";
import {
AppBar,
Avatar,
Badge,
Box,
InputBase,
Toolbar,
Typography,
} from "#mui/material";
import MailIcon from "#mui/icons-material/Mail";
import React from "react";
const StyledToolbar = styled(Toolbar)({
display: "flex",
justifyContent: "space-between",
});
const Search = styled("div")(({ theme }) => ({
backgroundColor: "white",
padding: "0 10px",
borderRadius: 10,
width: "40%",
}));
const Icons = styled(Box)(({ theme }) => ({
display: "none",
gap: "20px",
alignItems: "center",
[theme.breakpoints.up("sm")]: {
display: "flex",
},
}));
const UserBox = styled(Box)(({ theme }) => ({
display: "flex",
gap: "10px",
alignItems: "center",
}));
const Navbar = () => {
return (
<AppBar position="sticky">
<StyledToolbar>
<Typography variant="h6" sx={{ display: { xs: "none", sm: "block" } }}>
My App
</Typography>
<Pets sx={{ display: { xs: "block", sm: "none" } }} />
<Search>
<InputBase placeholder="search..." />
</Search>
<Icons>
<Badge badgeContent={4} color="error">
<MailIcon />
</Badge>
<Badge badgeContent={4} color="error">
<Notifications />
</Badge>
<Avatar
sx={{ width: 30, height: 30 }}
src="https://images.pexels.com/photos/846741/pexels-photo-846741.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2"
/>
</Icons>
<UserBox>
<Avatar
sx={{ width: 30, height: 30 }}
src="https://images.pexels.com/photos/846741/pexels-photo-846741.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2"
/>
<Typography variant="span">Jhon</Typography>
</UserBox>
</StyledToolbar>
</AppBar>
);
};
export default Navbar;
The Error:
Uncaught TypeError: Cannot read properties of undefined (reading 'up')
at Navbar.js:31:1
at handleInterpolation (emotion-serialize.browser.esm.js:137:1)
at serializeStyles (emotion-serialize.browser.esm.js:251:1)
at emotion-styled-base.browser.esm.js:131:1
at emotion-element-cbed451f.browser.esm.js:36:1
at renderWithHooks (react-dom.development.js:16141:1)
at updateForwardRef (react-dom.development.js:19968:1)
at beginWork (react-dom.development.js:22391:1)
at HTMLUnknownElement.callCallback (react-dom.development.js:4157:1)
at Object.invokeGuardedCallbackDev (react-dom.development.js:4206:1)
You should import it as named import. Try importing it like this.
import { styled } from '#mui/system';
The problem is that you are destructuring the theme object and passing a theme property who doesn't exist, you should pass the breakpoint property to the destructured parameter, like so:
const Icons = styled(Box)(({ breakpoints }) => ({
display: "none",
gap: "20px",
alignItems: "center",
[breakpoints.up("sm")]: {
display: "flex",
},
}));
See the theme object to know more about the available properties.
The problem is Styled should be in "#mui/material"; not in "#emotion/styled"
enter image description here
enter image description here
I implementing TabsBar in my Appbar for my React Desktop Application.
But I really have a hard time stylizing the Tabs part. If anyone can help me with clear explanations, that would be great. I want to add Icons to the right of the text. Change the color of the tab indicator and put it on top as on the picture example. I'm a beginner. I searched for 4 days but the I ask because I block
We have two colors :(#738889) & (#006F85) for actived Tab.
AppBar with Tabs Designed
Voici Mon code actuel ci-dessous :
import React from 'react';
import PropTypes from 'prop-types';
import AppBar from '#material-ui/core/AppBar';
import Toolbar from '#material-ui/core/Toolbar';
import Tabs from '#material-ui/core/Tabs';
import Tab from '#material-ui/core/Tab';
import Button from '#material-ui/core/Button';
import IconButton from '#material-ui/core/IconButton';
import SearchIcon from '#material-ui/icons/Search';
import InputBase from '#material-ui/core/InputBase';
import Icon from '#material-ui/core/Icon';
import { fade, makeStyles } from '#material-ui/core/styles';
import { withStyles } from '#material-ui/core/styles';
import { ReactComponent as BrandLogo } from '../Assets//PriceWanted/BrandLogo.svg';
import { ReactComponent as Icon_MicroPhone } from '../Icons/Icon_MicroPhone.svg';
import { ReactComponent as Icon_Separation } from '../Icons/Icon_Separation.svg';
import { ReactComponent as Icon_Global } from '../Icons/Icon_Global.svg';
import { ReactComponent as Icon_Lightning } from '../Icons/Icon_Lightning.svg';
import { ReactComponent as Icon_Shipment_Boat } from '../Icons/Icon_Shipment_Boat.svg';
const useStyles = makeStyles((theme) => ({
root: {
flexGrow: 1,
width: '100%',
backgroundColor: theme.palette.background.paper,
},
Tabs: {
marginLeft: 50,
},
search: {
position: 'relative',
borderRadius: theme.shape.borderRadius,
transition: theme.transitions.create('backgroundColor'),
marginRight: 10,
width: '100%',
backgroundColor: fade(theme.palette.common.black, 0.15),
'&:hover': {
backgroundColor: fade(theme.palette.common.black, 0.70),
boxShadow: '0 3px 5px 2px rgba(25, 1, 12, .2)',
},
[theme.breakpoints.up('sm')]: {
marginLeft: theme.spacing(3),
width: 'auto',
},
},
inputRoot: {
color: '#2F6164',
'&:hover': {
color: '#b2ebf2',
},
},
inputInput: {
padding: theme.spacing(1),
paddingLeft: `calc(1em + ${theme.spacing(2.5)}px)`,
paddingRight: `calc(1em + ${theme.spacing(2.5)}px)`,
transition: theme.transitions.create('width'),
width: '90%',
flex: 1,
[theme.breakpoints.up('sm')]: {
borderColor: 'grey',
'&:focus': {
borderColor: 'green',
},
width: '35ch',
'&:focus': {
width: '50ch',
},
},
},
searchIcon: {
padding: theme.spacing(0, 1),
color: '#889FA0',
height: '100%',
position: 'absolute',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
},
iconButton: {
padding:5,
marginRight: 6,
marginLeft: 6,
},
Toolbar: {
alignItems:'center'
},
}));
TabPanel.propTypes = {children: PropTypes.node,index: PropTypes.any.isRequired,value: PropTypes.any.isRequired,};
function TabPanel(props) {const { children, value, index, ...other } = props;}
function a11yProps(index) {return{id: `simple-tab-${index}`,'aria-controls': `simple-tabpanel-${index}`,};}
export default function SimpleTabs() {
const classes = useStyles();
const StyledButton = withStyles({
root : {background: 'linear-gradient(270deg,#00DBFF 0%, #021118 61.57%, #000000 100%)',
'&:hover': {background:'linear-gradient(90deg, #00DBFF 0%, #000000 100%)',},
position: 'relative',
borderRadius: 4,
border: 1,
color: 'White',
height: 35,
padding: '10 5px',
boxShadow: '0 3px 5px 2px rgba(0px 4px 4px #CBCBCB)',
marginLeft: 1,
justifyContent:'center'},
textTransform: 'capitalize',})(Button);
const [value, setValue] = React.useState(0);
const handleChange = (event,newValue) => {setValue(newValue);};
return (
<div className={classes.grow}>
<AppBar position="static">
<AppBar style={{background: '#FFFFFF'}}>
<Toolbar>
<BrandLogo/>
<div className={classes.search}>
<div className={classes.searchIcon}>
<SearchIcon />
</div>
<InputBase placeholder="Marque,Modèle..."classes={{ root: classes.inputRoot,input: classes.inputInput,}}
inputProps={{ 'aria-label': 'search' }}/>
<IconButton className={classes.iconButton} aria-label="menu">
<Icon_MicroPhone/>
</IconButton>
</div>
<Icon_Separation style={{ flex: 1 }}/>
<Tabs
value={value}
onChange={handleChange}
variant="fullWidth"
indicatorColor="secondary"
textColor="secondary"
aria-label="icon label tabs example">
<Tab label="LIVE DEALS" {...a11yProps(0)} icon={<Icon_Lightning />}/>
<Tab label="GLOBAL STOCK" {...a11yProps(1)} icon={<Icon_Global/>}/>
<Tab label="TRANSPORT" {...a11yProps(2)} icon={<Icon_Shipment_Boat/>}/>
</Tabs>
<StyledButton
variant="contained"
color="primary"
className={classes.StyledButton}
endIcon={<Icon>power_settings_new&style</Icon>}>
CONNEXION
</StyledButton>
</Toolbar>
</AppBar>
</AppBar>
</div>);}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
In my app I am using React material-ui and I am heavily relying on storybooks. However, I have some overrides of themes settings.
Here is the settings:
import { createMuiTheme } from '#material-ui/core/styles';
export const egColorScheme = {
darkGray: '#494949',
transparent: 'transparent',
white: '#FFF',
};
const edvengoFont = {
fontFamily: "'Montserrat', sans-serif",
};
export const edvengoTheme = createMuiTheme({
overrides: {
MuiCssBaseline: {
'#global': {
'#font-face': [edvengoFont],
},
},
},
typography: {
fontFamily: "'Montserrat', sans-serif",
},
});
Now, in some of the components when I create a storybook and wrapping with ThemeProvider it works perfectly fine. Like in this component:
import { createStyles, List, ListItem, ListItemIcon, ListItemText, Theme } from '#material-ui/core';
import Card from '#material-ui/core/Card';
import CardActions from '#material-ui/core/CardActions';
import CardContent from '#material-ui/core/CardContent';
import makeStyles from '#material-ui/core/styles/makeStyles';
import Typography from '#material-ui/core/Typography';
import React from 'react';
import { egColorScheme } from '../../../../utils/styles/edvengo-theme';
import { EgButtonOutlined } from '../EgButton';
import { EmailIcon, PhoneIcon, SkypeIcon } from '../Icons';
const useStyles = makeStyles((theme: Theme) =>
createStyles({
actions: {
marginTop: '10px',
paddingBottom: '30px',
paddingLeft: '30px',
},
content: {
padding: '30px 30px 0',
},
itemIcon: {
minWidth: '16px',
paddingRight: '11px',
},
itemText: {
color: egColorScheme.darkGray,
fontSize: '14px',
fontStyle: 'normal',
fontWeight: 'normal',
letterSpacing: '0.02em',
},
list: {
marginTop: '10px',
},
root: {
backgroundColor: egColorScheme.white,
borderRadius: '10px',
width: '100%',
},
title: {
color: egColorScheme.darkGray,
fontSize: '22px',
fontStyle: 'normal',
fontWeight: 'bold',
lineHeight: '27px',
},
}),
);
export interface InPageContactBoxProps {
phone?: string;
email?: string;
skype?: string;
buttonUrl?: string;
}
export const InPageContactBox: React.FC<InPageContactBoxProps> = ({ phone, email, skype, buttonUrl }) => {
const styles = useStyles();
return (
<Card className={styles.root} elevation={0}>
<CardContent className={styles.content}>
<Typography gutterBottom variant="h5" component="span" className={styles.title}>
Contact Us
</Typography>
<List className={styles.list}>
{phone ? (
<ListItem component={'a'} href={`tel:${phone}`} disableGutters={true}>
<ListItemIcon className={styles.itemIcon}>
<PhoneIcon />
</ListItemIcon>
<ListItemText className={styles.itemText} primary={phone} />
</ListItem>
) : (
<></>
)}
{email ? (
<ListItem component={'a'} href={`mailto:${email!}`} target={'_blank'} disableGutters={true}>
<ListItemIcon className={styles.itemIcon}>
<EmailIcon />
</ListItemIcon>
<ListItemText className={styles.itemText} primary={email} />
</ListItem>
) : (
<></>
)}
{skype ? (
<ListItem component={'a'} href={`skype:${skype!}?chat`} disableGutters={true}>
<ListItemIcon className={styles.itemIcon}>
<SkypeIcon />
</ListItemIcon>
<ListItemText className={styles.itemText} primary={skype} />
</ListItem>
) : (
<></>
)}
</List>
</CardContent>
<CardActions className={styles.actions}>
<EgButtonOutlined href={buttonUrl}>Submit Message</EgButtonOutlined>
</CardActions>
</Card>
);
};
And here is it's storybook:
const contactBox = () => (
<ThemeProvider theme={edvengoTheme}>
<div style={{ width: '300px', border: '5px solid lightgray', backgroundColor: 'lightgray' }}>
<InPageContactBox
phone={text('Phone #', '+1 (778) 668-1811')}
email={text('Email', 'contact#edvengo.com')}
skype={text('Skype', 'shurik_a')}
buttonUrl={text('Button Url', 'http://google.coms')}
/>
</div>
</ThemeProvider>
);
storiesOf('Web|Common', module)
.addDecorator(withKnobs)
.add('Contact Box', contactBox);
The problem begins here...
One of my components look like this:
import { createStyles, Paper, Theme } from '#material-ui/core';
import Link from '#material-ui/core/Link';
import makeStyles from '#material-ui/core/styles/makeStyles';
import React from 'react';
import { egColorScheme } from '../../../../utils/styles/edvengo-theme';
const useStyles = makeStyles((theme: Theme) =>
createStyles({
root: {
backgroundColor: egColorScheme.white,
borderRadius: '10px',
display: 'flex',
height: '100%',
overflow: 'hidden',
},
title: {
alignItems: 'center',
color: egColorScheme.darkGray,
fontSize: '22px',
fontStyle: 'normal',
fontWeight: 'bold',
lineHeight: '28px',
padding: '36px 23px',
textAlign: 'center',
textDecoration: 'none',
width: '100%',
},
}),
);
export interface TitleBlockProps {
title: string;
href?: string;
}
export const TitleBlock: React.FC<TitleBlockProps> = ({ title, href }) => {
const styles = useStyles();
return (
<Paper className={styles.root} elevation={0}>
<Link className={styles.title} href={href}>
{title}
</Link>
</Paper>
);
};
with a storybook as follows:
import { ThemeProvider } from '#material-ui/core/styles';
import { text, withKnobs } from '#storybook/addon-knobs';
import { storiesOf } from '#storybook/react';
import React from 'react';
import { edvengoTheme } from '../../../../utils/styles/edvengo-theme';
import { TitleBlock } from './TitleBlock';
const titleBlock = () => (
<ThemeProvider theme={edvengoTheme}>
<div style={{ width: '300px', border: '5px solid lightgray', backgroundColor: 'lightgray' }}>
<TitleBlock title={text('Title', 'Ontario')} href={text('Url', 'http://edvengo.com')} />
</div>
</ThemeProvider>
);
storiesOf('Web|Common', module)
.addDecorator(withKnobs)
.add('Title Block', titleBlock);
For some reason, the styling from the edvengoTheme are not applied. Specifically font-family.
What am I missing here?
I encountered a similar issue where my dev environment was not the same as the build/deployed version.
This article was helpful for config preferences using Storybook & Material UI.
Storybook/MaterialUI/StyledComponents
In short, some important storybook configuration should include:
styles-decorator.js
export const StylesDecorator = storyFn => (
<ThemeProvider theme={customTheme}>
<StylesProvider injectFirst>
{storyFn()}
</StylesProvider>
</ThemeProvider>
);
config.js
addDecorator(StylesDecorator)
configure(require.context('../src/stories', true, /\.stories\.js$/), module);
In your case, you may just be missing StyleProvider 'injectFirst' inside of your ThemeProvider
I'm doing an implementation of material-ui steppers more specifically the "small dot stepper" and the challenge I'm facing at the moment is connecting the dots with a line. I tried by setting the StepConnector position to absolute but it does not behave that well when changing screens, does anyone know a solution to this?
sandbox: https://op1l9.csb.app/
Link to stepper in question:
https://material-ui.com/components/steppers/
Most of this code is already in the link I provided
import styles from "./styles";
import {
Paper,
Grid,
Typography,
Stepper,
Step,
StepLabel,
StepContent,
StepConnector,
makeStyles,
withStyles,
} from "#material-ui/core";
import { MoreHoriz } from '#material-ui/icons'
import PropTypes from "prop-types";
import React from "react";
const useQontoStepIconStyles = makeStyles({
root: {
color: '#2e5bff',
display: 'flex',
height: 28,
marginLeft: 8,
alignItems: 'center',
},
active: {
color: '#2e5bff',
},
circle: {
zIndex: 2,
width: 8,
height: 8,
borderRadius: '50%',
backgroundColor: 'currentColor',
},
completed: {
color: '#2e5bff',
zIndex: 1,
fontSize: 18,
},
});
function QontoStepIcon(props) {
const classes = useQontoStepIconStyles();
return (
<div
className={classes.root}
>
<div style={{color: props.color}} className={classes.circle} />
</div>
);
}
QontoStepIcon.propTypes = {
active: PropTypes.bool,
completed: PropTypes.bool,
};
const QontoConnector = withStyles({
alternativeLabel: {
top: 10,
left: 'calc(-50% + 16px)',
right: 'calc(50% + 16px)',
},
lineVertical: {
height: 20
},
active: {
'& $line': {
borderColor: '#2e5bff',
},
},
completed: {
'& $line': {
borderColor: '#2e5bff',
},
},
line: {
borderColor: '#eaeaf0',
borderTopWidth: 3,
borderRadius: 1,
},
})(StepConnector);
<Stepper orientation="vertical" connector={<QontoConnector />}>
{steps.map((step, index) => (
<Step key={step.label}>
<StepLabel
optional={<Typography className={classes.description}>{step.description}</Typography>}
StepIconComponent={() => <QontoStepIcon color={step.color}/>}
>
<Typography className={classes.title}>
{step.title}
</Typography>
</StepLabel>
</Step>
))}
</Stepper>
I solved this with pseudo elements playing with ::after and ::before. It is not responsive but works for my needs.