I have created a list in react which has the following structure:
Avatar
Text
Edit icon
Delete icon
I have created the structure fine until the delete icon. How can I add this? Currently, it is overlapping the edit icon as both are ListItemSecondaryAction but I can't find on the documentation how to add an additional object and what it should be called? https://material-ui.com/components/lists/
Current implementation:
<List>
<ListItemAvatar>
<Avatar src="image" />
</ListItemAvatar>
<ListItemText primary="name" />
<ListItemSecondaryAction>
<IconButton>
<EditIcon />
</IconButton>
</ListItemSecondaryAction>
<ListItemSecondaryAction>
<IconButton>
<DeleteIcon />
</IconButton>
</ListItemSecondaryAction>
</List>
It is almost sufficient to just put both actions in one ListItemSecondaryAction (as indicated by comments and another answer). The only issue is that if you have long content it will overlap the first icon.
Here are the styles for the secondary action from ListItem:
/* Styles applied to the `component` element if `children` includes `ListItemSecondaryAction`. */
secondaryAction: {
// Add some space to avoid collision as `ListItemSecondaryAction`
// is absolutely positioned.
paddingRight: 48,
},
The paddingRight: 48 will not be sufficient for two icons. You can customize this as follows:
const ListItemWithWiderSecondaryAction = withStyles({
secondaryAction: {
paddingRight: 96
}
})(ListItem);
Here is a full working v4 example (v5 example further down) that shows the first two list items without this customization (so overlap occurs) and the second two with the fix:
import React from "react";
import { makeStyles, withStyles } from "#material-ui/core/styles";
import List from "#material-ui/core/List";
import ListItem from "#material-ui/core/ListItem";
import ListItemIcon from "#material-ui/core/ListItemIcon";
import ListItemSecondaryAction from "#material-ui/core/ListItemSecondaryAction";
import ListItemText from "#material-ui/core/ListItemText";
import Checkbox from "#material-ui/core/Checkbox";
import IconButton from "#material-ui/core/IconButton";
import CommentIcon from "#material-ui/icons/Comment";
import DeleteIcon from "#material-ui/icons/Delete";
const useStyles = makeStyles(theme => ({
root: {
width: "100%",
maxWidth: 360,
backgroundColor: theme.palette.background.paper
}
}));
const ListItemWithWiderSecondaryAction = withStyles({
secondaryAction: {
paddingRight: 96
}
})(ListItem);
export default function CheckboxList() {
const classes = useStyles();
const [checked, setChecked] = React.useState([0]);
const handleToggle = value => () => {
const currentIndex = checked.indexOf(value);
const newChecked = [...checked];
if (currentIndex === -1) {
newChecked.push(value);
} else {
newChecked.splice(currentIndex, 1);
}
setChecked(newChecked);
};
return (
<>
<List className={classes.root}>
{[0, 1].map(value => {
const labelId = `checkbox-list-label-${value}`;
return (
<ListItem
key={value}
role={undefined}
dense
button
onClick={handleToggle(value)}
>
<ListItemIcon>
<Checkbox
edge="start"
checked={checked.indexOf(value) !== -1}
tabIndex={-1}
disableRipple
inputProps={{ "aria-labelledby": labelId }}
/>
</ListItemIcon>
<ListItemText
id={labelId}
primary={`Line item ${value +
1} with some more text to make it longer`}
/>
<ListItemSecondaryAction>
<IconButton aria-label="comments">
<CommentIcon />
</IconButton>
<IconButton edge="end" aria-label="delete">
<DeleteIcon />
</IconButton>
</ListItemSecondaryAction>
</ListItem>
);
})}
</List>
<List className={classes.root}>
{[2, 3].map(value => {
const labelId = `checkbox-list-label-${value}`;
return (
<ListItemWithWiderSecondaryAction
key={value}
role={undefined}
dense
button
onClick={handleToggle(value)}
>
<ListItemIcon>
<Checkbox
edge="start"
checked={checked.indexOf(value) !== -1}
tabIndex={-1}
disableRipple
inputProps={{ "aria-labelledby": labelId }}
/>
</ListItemIcon>
<ListItemText
id={labelId}
primary={`Line item ${value +
1} with some more text to make it longer`}
/>
<ListItemSecondaryAction>
<IconButton aria-label="comments">
<CommentIcon />
</IconButton>
<IconButton edge="end" aria-label="delete">
<DeleteIcon />
</IconButton>
</ListItemSecondaryAction>
</ListItemWithWiderSecondaryAction>
);
})}
</List>
</>
);
}
Below is an equivalent v5 example. The changes compared to the v4 version are:
Uses styled instead of withStyles and makeStyles
Uses ListItemButton instead of the deprecated ListItem button prop
Add disablePadding prop to the ListItem elements. This is needed when leveraging ListItemButton in order to keep the styling equivalent to the v4 example
Package names updated from #material-ui/core and #material-ui/icons to #mui/material and #mui/icons-material
import * as React from "react";
import { styled } from "#mui/material/styles";
import List from "#mui/material/List";
import ListItem from "#mui/material/ListItem";
import ListItemIcon from "#mui/material/ListItemIcon";
import ListItemText from "#mui/material/ListItemText";
import ListItemButton from "#mui/material/ListItemButton";
import ListItemSecondaryAction from "#mui/material/ListItemSecondaryAction";
import Checkbox from "#mui/material/Checkbox";
import IconButton from "#mui/material/IconButton";
import CommentIcon from "#mui/icons-material/Comment";
import DeleteIcon from "#mui/icons-material/Delete";
const StyledList = styled(List)(({ theme }) => ({
width: "100%",
maxWidth: 360,
backgroundColor: theme.palette.background.paper
}));
const ListItemWithWiderSecondaryAction = styled(ListItem)(({ theme }) => ({
"&.MuiListItem-secondaryAction": {
paddingRight: 96
}
}));
export default function CheckboxList() {
const [checked, setChecked] = React.useState([0]);
const handleToggle = (value) => () => {
const currentIndex = checked.indexOf(value);
const newChecked = [...checked];
if (currentIndex === -1) {
newChecked.push(value);
} else {
newChecked.splice(currentIndex, 1);
}
setChecked(newChecked);
};
return (
<>
<StyledList>
{[0, 1].map((value) => {
const labelId = `checkbox-list-label-${value}`;
return (
<ListItem key={value} disablePadding>
<ListItemButton
role={undefined}
dense
onClick={handleToggle(value)}
>
<ListItemIcon>
<Checkbox
edge="start"
checked={checked.indexOf(value) !== -1}
tabIndex={-1}
disableRipple
inputProps={{ "aria-labelledby": labelId }}
/>
</ListItemIcon>
<ListItemText
id={labelId}
primary={`Line item ${
value + 1
} with some more text to make it longer`}
/>
</ListItemButton>
<ListItemSecondaryAction>
<IconButton aria-label="comments">
<CommentIcon />
</IconButton>
<IconButton edge="end" aria-label="delete">
<DeleteIcon />
</IconButton>
</ListItemSecondaryAction>
</ListItem>
);
})}
</StyledList>
<StyledList>
{[2, 3].map((value) => {
const labelId = `checkbox-list-label-${value}`;
return (
<ListItemWithWiderSecondaryAction key={value} disablePadding>
<ListItemButton
role={undefined}
dense
onClick={handleToggle(value)}
>
<ListItemIcon>
<Checkbox
edge="start"
checked={checked.indexOf(value) !== -1}
tabIndex={-1}
disableRipple
inputProps={{ "aria-labelledby": labelId }}
/>
</ListItemIcon>
<ListItemText
id={labelId}
primary={`Line item ${
value + 1
} with some more text to make it longer`}
/>
</ListItemButton>
<ListItemSecondaryAction>
<IconButton aria-label="comments">
<CommentIcon />
</IconButton>
<IconButton edge="end" aria-label="delete">
<DeleteIcon />
</IconButton>
</ListItemSecondaryAction>
</ListItemWithWiderSecondaryAction>
);
})}
</StyledList>
</>
);
}
I removed ListItemSecondaryAction entirely and replaced it with ListItemIcon, so now the code looks something like this:
<ListItem>
<ListItemAvatar>
<Avatar src="image" />
</ListItemAvatar>
<ListItemText primary="name" />
<ListItemIcon>
<IconButton>
<EditIcon />
</IconButton>
</ListItemIcon>
<ListItemIcon>
<IconButton>
<DeleteIcon />
</IconButton>
</ListItemIcon>
</ListItem>
Related
I am trying to build a hamburger menu using Material UI List on Next.js similar to Nested List example on Material UI docs. However, I am keep getting error if I use "collapse" on my code. If I remove collapse then the other parts of the code works fine.
Can anyone tell me what am I doing wrong?
screenshot of an error message
I am trying to build similar to this
import * as React from "react";
import { useState } from "react";
import IconButton from "#mui/material/IconButton";
import ListSubheader from "#mui/material/ListSubheader";
import { Drawer } from "#mui/material";
import List from "#mui/material/List";
import ListItem from "#mui/material/ListItem";
import ListItemButton from "#mui/material/ListItemButton";
import ListItemIcon from "#mui/material/ListItemIcon";
import ListItemText from "#mui/material/ListItemText";
import MenuIcon from "#mui/icons-material/Menu";
import { ExpandLess, ExpandMore } from "#mui/icons-material";
import Collapse from "#mui/material";
const myMenu = [
{
title: "about",
},
{
title: "services",
submenu: [{ title: "Digital Marketing" }, { title: "Promotion" }],
},
{
title: "blog",
},
{
title: "contact",
},
];
const ResponsiveAppBar = () => {
const [openDrawer, setOpenDrawer] = useState(false);
const [open, setOpen] = React.useState(false);
const handleClick = () => {
setOpen(!open);
};
return (
<React.Fragment>
<Drawer
anchor="right"
open={openDrawer}
onClose={() => setOpenDrawer(false)}
>
<List
sx={{ width: "100%", maxWidth: 360, bgcolor: "background.paper" }}
component="nav"
aria-labelledby="nested-list-subheader"
subheader={
<ListSubheader component="div" id="nested-list-subheader">
Navigation
</ListSubheader>
}
>
{myMenu.map((page, index) =>
page.submenu ? (
<div>
<ListItemButton key={index} onClick={handleClick}>
<ListItemText>{page.title}</ListItemText>
{open ? <ExpandLess /> : <ExpandMore />}
</ListItemButton>
<Collapse in={open} timeout="auto" unmountOnExit>
<List component="div" disablePadding>
{page.submenu.map((sub, index) => {
return (
<ListItemButton key={index}>
<ListItem key={index}>
<ListItemText>{sub.title}</ListItemText>
</ListItem>
</ListItemButton>
);
})}
</List>
</Collapse>
</div>
) : (
<ListItemButton key={index}>
<ListItemIcon>
<ListItemText>{page.title}</ListItemText>
</ListItemIcon>
</ListItemButton>
)
)}
</List>
</Drawer>
<IconButton
sx={{ color: "black", marginLeft: "auto" }}
onClick={() => setOpenDrawer(!openDrawer)}
>
<MenuIcon color="white" />
</IconButton>
</React.Fragment>
);
};
export default ResponsiveAppBar;
The culprit is an incorrect import of Collapse:
import Collapse from "#mui/material";
Since Collapse is a named import, you must import it in one of these two ways:
import { Collapse } from "#mui/material";
// Alternatively
import Collapse from "#mui/material/Collapse";
I am trying to get the user.id of the user that I clicked on, so that I can use it as a query parameter in a fetch(). However, what setClickedUserId is passing/assigning to my clickedUserId state is the following: MuiButtonBase-root%20MuiListItem-root%201%20MuiListItem-gutters%20MuiListItem-button
----My code:
import React from 'react';
import {makeStyles} from '#material-ui/core/styles';
import List from '#material-ui/core/List';
import ListItem from '#material-ui/core/ListItem';
import ListItemIcon from '#material-ui/core/ListItemIcon';
import ListItemText from '#material-ui/core/ListItemText';
import Collapse from '#material-ui/core/Collapse';
import ExpandLess from '#material-ui/icons/ExpandLess';
import ExpandMore from '#material-ui/icons/ExpandMore';
import PersonIcon from '#material-ui/icons/Person';
import AddBoxOutlinedIcon from '#material-ui/icons/AddBoxOutlined';
// Global context
import globalContext from './globalContext';
const useStyles = makeStyles((theme) => ({
root: {
marginTop: theme.spacing(-2.0),
width: '100%',
maxWidth: 360,
backgroundColor: '#3F0E40',
color: 'white',
},
nested: {
marginLeft: theme.spacing(-3.5),
},
nestedAdd: {
marginLeft: theme.spacing(3.5),
},
nestedAddText: {
marginLeft: theme.spacing(0.5),
},
}));
/**
*#return{any} nestedList
*/
export default function DmsList() {
const classes = useStyles();
const [open, setOpen] = React.useState(true);
console.log('I am inside DmsList!!');
// Global Context
const {setMobileOpen} = React.useContext(globalContext);
const {currentDmdWith} = React.useContext(globalContext);
const {setChannel} = React.useContext(globalContext);
const {clickedDms, setClickedDms} = React.useContext(globalContext);
const {setClickedUserId} = React.useContext(globalContext);
const handleClickUser = (event) => {
setMobileOpen(false);
setClickedDms('true');
setChannel(event.target.innerText);
setClickedUserId(event.target.className);
console.log(clickedDms);
};
const handleClickAdd = () => {
setMobileOpen(false);
};
const handleClick = () => {
setOpen(!open);
};
return (
<List
component="nav"
aria-labelledby="nested-list-subheader"
className={classes.root}
>
<ListItem button
onClick={handleClick}>
{open ? <ExpandLess /> : <ExpandMore />}
<ListItemText primary="Direct Messages" />
</ListItem>
<Collapse in={open} timeout="auto" unmountOnExit>
<List component="div" disablePadding className={classes.nested}>
{currentDmdWith.map((user) => (
<ListItem button className={user.id} onClick={handleClickUser}>
<ListItemIcon className={user.id}>
</ListItemIcon>
<PersonIcon className={user.id} color='white'/>
<ListItemText className={user.id} primary={user.name} />
</ListItem>
))}
<ListItem button
onClick={handleClickAdd}
className={classes.nested}>
<ListItemIcon>
</ListItemIcon>
<AddBoxOutlinedIcon className={classes.nestedAdd}/>
<ListItemText
className={classes.nestedAddText} primary="Add Teammate" />
</ListItem>
</List>
</Collapse>
</List>
);
}
I would use event.target.id, because it actually gets the div's id and not a bunch of mumbo jumbo, but when I do put id = {user.id} in a ListItem I have to click on a very specific spot, the leftmost side, because if I click on an a person icon or the area with text, event.target.id is a assigned a blank and makes my fetch() return a 404 error.
Instead of trying to read the information out of the Event object, pass the info that you need in the handleClickUser function through the onClick prop.
<ListItem
button
className={user.id}
onClick={() => handleClickUser(user.id)}
>
const handleClickUser = (userId) => {
setClickedUserId(userId);
};
so i am trying to create a list, whereby a list is displaying many items, and two of the items are expandable, and expanding them shows more items(subitems). I have managed to display the list, and the sub-lists, however, clicking either one of the expandable items, expands both items and not just the single one i clicked.
So firstly, i have seperated the listItems as a data structure where i can retrieve them. This is the list Items:
// Skills list in the About Page
export const listItems = [
{
listText: 'Html',
listIcon: <SendIcon/>
},
{
listText: 'CSS',
listIcon: <DraftsIcon />
},
{
listText: 'JavaScript',
listIcon: <InboxIcon />
},
{
listText: 'React',
listIcon: <SendIcon/>,
expan: true,
// SubItems
firstText:'React-Router',
secondText:'React-Navigation',
thirdText:'React-Native',
},
{
listText: 'Database',
listIcon: <DraftsIcon />,
expan: true,
// SubItems
firstText:'FireBase',
secondText:'SQL',
},
{
listText: 'ReactJs',
listIcon: <DraftsIcon />
},
{
listText: 'ReactJs',
listIcon: <DraftsIcon />
}]
This is the code where i am trying to implement the list:
import React, { Fragment } from 'react'
import Styles from './Styles'
// ListItems
import List from '#material-ui/core/List';
import ListItem from '#material-ui/core/ListItem';
import ListItemIcon from '#material-ui/core/ListItemIcon';
import ListItemText from '#material-ui/core/ListItemText';
import ExpandLess from '#material-ui/icons/ExpandLess';
import ExpandMore from '#material-ui/icons/ExpandMore';
import StarBorder from '#material-ui/icons/StarBorder';
import Collapse from '#material-ui/core/Collapse';
import {listItems} from './ListItems'
const AboutSkills = () => {
const classes = Styles()
const [open, setOpen] = React.useState(false);
const handleClick = () => {
setOpen(!open);
};
const outputList = () => (
<>
<List
style={{color:'white'}}
component="nav"
className={classes.root}
>
{ //Map through the ListItems and...
listItems.map((item, index) => {
// if expandable items exist, expand them
if(item.expan)
{
{/* Use fragment instad of <></> because key attribute is required */}
return <Fragment key={index}>
<ListItem button onClick={handleClick} className={classes.aboutList}>
<ListItemIcon className={classes.aboutIcon}>
{item.listIcon}
</ListItemIcon>
<ListItemText primary={item.listText} />
{open ? <ExpandLess /> : <ExpandMore />}
</ListItem>
<Collapse in={open} timeout="auto" unmountOnExit>
<List component="div" disablePadding>
<ListItem button className={classes.nested}>
<ListItemIcon>
<StarBorder />
</ListItemIcon>
<ListItemText classes={{primary:classes.expanText}}
primary={item.firstText} />
</ListItem>
{/* {console.log(item.secondText)} */}
{ item.secondText //if seconditem exists...
? <ListItem button className={classes.nested}>
<ListItemIcon>
<StarBorder />
</ListItemIcon>
<ListItemText classes=
{{primary:classes.expanText}} primary={item.secondText} />
</ListItem>
: console.log('No Third Item')}
{ item.thirdText //if seconditem exists...
? <ListItem button className={classes.nested}>
<ListItemIcon>
<StarBorder />
</ListItemIcon>
<ListItemText classes=
{{primary:classes.expanText}} primary={item.thirdText} />
</ListItem>
: console.log('No Third Item')}
</List>
</Collapse>
</Fragment>
} else {
return <ListItem button className={classes.aboutList} key={index}>
<ListItemIcon className={classes.aboutIcon}>
{item.listIcon}
</ListItemIcon>
<ListItemText classes={{primary:classes.unExpanText}} primary=
{item.listText} />
</ListItem>
}
})}
</List>
</>
)
return (
outputList()
)
}
export default AboutSkills
My answer in this thread is pretty much what you are searching for.
Just adapt the code according to your situation.
I don't understand why the following error appears.
I'm trying to render {links}, {collapse} in a return function, but it doesn't work.
links and collapse is about opening sub menus.
Thank you for your help.
The error message:
Objects are not valid as a React child (found: object with keys
{$$typeof, type, compare, displayName, muiName}). If you meant to
render a collection of children, use an array instead.
-- Sidebar.js
/*eslint-disable*/
import React from "react";
import classNames from "classnames";
import PropTypes from "prop-types";
import { NavLink } from "react-router-dom";
// #material-ui/core components
import { makeStyles } from "#material-ui/core/styles";
import {
Drawer,
Hidden,
List,
ListItem,
ListItemText,
Icon,
Collapse
} from "#material-ui/core";
import ExpandLess from "#material-ui/icons/ExpandLess";
import ExpandMore from "#material-ui/icons/ExpandMore";
import ListItemLink from "./ListItemLink";
// core components
import AdminNavbarLinks from "components/Navbars/AdminNavbarLinks.js";
import RTLNavbarLinks from "components/Navbars/RTLNavbarLinks.js";
import styles from "assets/jss/material-dashboard-react/components/sidebarStyle.js";
const useStyles = makeStyles(styles);
export default function Sidebar(props) {
const classes = useStyles();
// verifies if routeName is the one active (in browser input)
function activeRoute(routeName) {
return window.location.href.indexOf(routeName) > -1 ? true : false;
}
const { color, logo, image, logoText, routes } = props;
const [open, setOpen] = React.useState(true);
const handleClick = () => {
setOpen(!open);
};
var links = (
<div>
{routes.map((prop, key) => {
return (
<div>
{prop.submenu.length > 0 ? (
<ListItemLink
to={prop.layout + prop.path}
key={prop.id}
menuText={prop.name}
onClick={handleClick}
subOpen={open}
icon={prop.icon}
/>
) : (
<ListItemLink
to={prop.layout + prop.path}
key={prop.id}
menuText={prop.name}
icon={prop.icon}
/>
)}
</div>
);
})}
</div>
);
var collapse = (
<Collapse in={open} timeout="auto" unmountOnExit>
<List component="div" disablePadding>
{routes.map((prop, key) => {
{
prop.submenu.map((sub, index) => {
return (
<ListItemLink
key={sub.id}
to={sub.path}
menuText={sub.name}
icon={sub.icon}
className={classes.nested}
/>
);
});
}
})}
</List>
</Collapse>
);
var brand = (
<div className={classes.logo}>
<a
className={classNames(classes.logoLink, {
[classes.logoLinkRTL]: props.rtlActive
})}
target="_blank"
>
<div className={classes.logoImage}>
<img src={logo} alt="logo" className={classes.img} />
</div>
{logoText}
</a>
</div>
);
return (
<div>
<Hidden mdUp implementation="css">
<Drawer
variant="temporary"
anchor={props.rtlActive ? "left" : "right"}
open={props.open}
classes={{
paper: classNames(classes.drawerPaper, {
[classes.drawerPaperRTL]: props.rtlActive
})
}}
onClose={props.handleDrawerToggle}
ModalProps={{
keepMounted: true // Better open performance on mobile.
}}
>
{brand}
<div className={classes.sidebarWrapper}>
{props.rtlActive ? <RTLNavbarLinks /> : <AdminNavbarLinks />}
<List component="nav" className={classes.list}>
{links}
{collapse}
</List>
</div>
{image !== undefined ? (
<div
className={classes.background}
style={{ backgroundImage: "url(" + image + ")" }}
/>
) : null}
</Drawer>
</Hidden>
<Hidden smDown implementation="css">
<Drawer
anchor={props.rtlActive ? "right" : "left"}
variant="permanent"
open
classes={{
paper: classNames(classes.drawerPaper, {
[classes.drawerPaperRTL]: props.rtlActive
})
}}
>
{brand}
<div className={classes.sidebarWrapper}>
<List component="nav" className={classes.list}>
{links}
{collapse}
</List>
</div>
{image !== undefined ? (
<div
className={classes.background}
style={{ backgroundImage: "url(" + image + ")" }}
/>
) : null}
</Drawer>
</Hidden>
</div>
);
}
Sidebar.propTypes = {
rtlActive: PropTypes.bool,
handleDrawerToggle: PropTypes.func,
bgColor: PropTypes.oneOf(["purple", "blue", "green", "orange", "red"]),
logo: PropTypes.string,
image: PropTypes.string,
logoText: PropTypes.string,
routes: PropTypes.arrayOf(PropTypes.object),
open: PropTypes.bool
};
-- ListItemLink.js
import React from "react";
import { ListItem, ListItemText, ListItemIcon } from "#material-ui/core";
import ExpandLess from "#material-ui/icons/ExpandLess";
import ExpandMore from "#material-ui/icons/ExpandMore";
import { PropTypes } from "prop-types";
import { Link as RouterLink } from "react-router-dom";
function ListItemLink(props) {
const { to, menuText, icon, subOpen, ...other } = props;
return (
<ListItem button component={RouterLink} to={to} {...other}>
<ListItemIcon>{icon}</ListItemIcon>
<ListItemText primary={menuText} />
{subOpen != null ? subOpen ? <ExpandLess /> : <ExpandMore /> : null}
</ListItem>
);
}
ListItemLink.propTypes = {
subOpen: PropTypes.bool,
to: PropTypes.string.isRequired
};
export default ListItemLink;
in collapse, you have two map functions. you should return the second map function.
something like this:
const collapse = (
<Collapse in={open} timeout="auto" unmountOnExit>
<List component="div" disablePadding>
{routes.map((prop, key) => {
return prop.submenu.map((sub, index) => {
return (
<ListItemLink
key={sub.id}
to={sub.path}
menuText={sub.name}
icon={sub.icon}
className={classes.nested}
/>
);
});
})}
</List>
</Collapse>
);
I solved my question as followed:
I guess I returned the wrong object...
<List
{...rest}
className={clsx(classes.root, className)}
>
{pages.map(page => (
<React.Fragment key={page.title}>
<ListItem
className={classes.item}
disableGutters
key={page.title}
onClick={page.submenu.length > 0 ? handleClick : null}
open={page.submenu.length > 0 ? open : null}
>
<Button
activeClassName={classes.active}
className={classes.button}
component={CustomRouterLink}
to={page.href}
>
<div className={classes.icon}>{page.icon}</div>
{page.title}
{page.submenu.length > 0 ? (
open ? (
<ExpandLess />
) : (
<ExpandMore />
)
) : null}
</Button>
</ListItem>
<Collapse in={open} timeout={100} unmountOnExit>
<List component="div" disablePadding>
{page.submenu.map((sub, index) => {
return (
<React.Fragment key={sub.title}>
<ListItem
className={classes.nested}
disableGutters
key={sub.title}
>
<Button
activeClassName={classes.active}
className={classes.button}
component={CustomRouterLink}
to={sub.href}
>
<div className={classes.icon}>{sub.icon}</div>
{sub.title}
</Button>
</ListItem>
</React.Fragment>
);
})}
</List>
</Collapse>
</React.Fragment>
))}
</List>
I've got a list that consists of two items: 'label' and 'value', this is how it currently looks like:
How I can move items that are on the right side to the left, so they would stay next to the label?
This is my code sample:
<List>
{details.map((item, index) =>
<ListItem key={index} divider alignItems="flex-start">
<ListItemIcon>
<i className={item.icon}/>
</ListItemIcon>
<ListItemText className="br-break" primary={item.label} />
<ListItemSecondaryAction>
<ListItemText className="br-break" primary={item.data}/>
</ListItemSecondaryAction>
</ListItem>
)}
</List>
I've tried to remove <ListItemSecondaryAction> tag - didn't work.
One option is to use material-ui styling to override ListItemText flex value:
import React from 'react';
import { makeStyles } from '#material-ui/core/styles';
import List from '#material-ui/core/List';
import ListItem from '#material-ui/core/ListItem';
import ListItemIcon from '#material-ui/core/ListItemIcon';
import ListItemText from '#material-ui/core/ListItemText';
const useStyles = makeStyles(theme => ({
root: {
flex: '0.2',
minWidth: '100px'
},
}));
export default function ListDemo() {
const classes = useStyles();
const details = [
{
label: 'Issue Number',
data: 'CCM-1007'
},
{
label: 'Environment',
data: 'TST'
},
{
label: 'Country',
data: 'SE'
},
]
return (
<List>
{details.map((item, index) =>
<ListItem key={index} divider alignItems="flex-start">
<ListItemIcon>
<i className={item.icon} />
</ListItemIcon>
<ListItemText className={classes.root} primary={item.label} />
<ListItemText className={classes.root} primary={item.data} />
</ListItem>
)}
</List>
);
}
Another solution without makeStyles.
import React from "react";
import List from "#material-ui/core/List";
import ListItem from "#material-ui/core/ListItem";
import ListItemIcon from "#material-ui/core/ListItemIcon";
import ListItemText from "#material-ui/core/ListItemText";
export default function ListDemo() {
const details = [
{
label: "Issue Number",
data: "CCM-1007"
},
{
label: "Environment",
data: "TST"
},
{
label: "Country",
data: "SE"
}
];
return (
<List>
{details.map((item, index) => (
<ListItem key={index} divider alignItems="flex-start">
<ListItemIcon>
<i className={item.icon} />
</ListItemIcon>
<ListItemText
primary={item.label}
primaryTypographyProps={{
display: "inline"
}}
secondary={item.data}
secondaryTypographyProps={{
display: "inline"
}}
/>
</ListItem>
))}
</List>
);
}