I am trying to add a second line of the secondary text of a list react material ui component.
How can I modify it? See live demo here.
<ListItemText primary="Photos" secondary="first row" secondary="second row"/>
I edited on file demo.js of (demo link)
import React from "react";
import PropTypes from "prop-types";
import { withStyles } from "#material-ui/core/styles";
import List from "#material-ui/core/List";
import ListItem from "#material-ui/core/ListItem";
import ListItemText from "#material-ui/core/ListItemText";
import Avatar from "#material-ui/core/Avatar";
import ImageIcon from "#material-ui/icons/Image";
import WorkIcon from "#material-ui/icons/Work";
import BeachAccessIcon from "#material-ui/icons/BeachAccess";
const styles = theme => ({
root: {
width: "100%",
maxWidth: 360,
backgroundColor: theme.palette.background.paper
}
});
function FolderList(props) {
const { classes } = props;
return (
<div className={classes.root}>
<List>
<ListItem>
<Avatar>
<ImageIcon />
</Avatar>
<ListItemText
primary="Photos"
secondary={
<div>
<div>line 1</div>
<div>line 2</div>
</div>
}
/>
</ListItem>
<ListItem>
<Avatar>
<WorkIcon />
</Avatar>
<ListItemText primary="Work" secondary="Jan 7, 2014" />
</ListItem>
<ListItem>
<Avatar>
<BeachAccessIcon />
</Avatar>
<ListItemText primary="Vacation" secondary="July 20, 2014" />
</ListItem>
</List>
</div>
);
}
FolderList.propTypes = {
classes: PropTypes.object.isRequired
};
export default withStyles(styles)(FolderList);
secondary props is node type, You can pass props as:
secondary={
<div>
<div>line 1</div>
<div>line 2</div>
</div>
}
Related
I am using the Material-UI List item (https://material-ui.com/components/lists/)
And I would like to "left-justify" my items in my list item to the left. Apparantly I can do this with the flex property "flex-start" which I can set on the alignItems property of a ListItem like so :
<List>
<ListItem alignItems="flex-start">
<ListItemText primary={"First Element "} />
<ListItemText primary={" Second Element"} />
</ListItem>
</List>
However this does not seem to work as they are evenly spaced out when I see it in the browser.
Am I doing something wrong?
Try this...
import { makeStyles } from '#material-ui/core/styles';
const useStyles = makeStyles({
root: {
display:'flex',
alignItems:'flex-start',
flexDirection: "row"
},
});
export default function MyComponent(props) {
const classes = useStyles(props);
return (
<List className={classes.root}>
<ListItem>
<ListItemText primary={"First Element "} />
</ListItem>
<ListItem>
<ListItemText primary={"Second Element "} />
</ListItem>
</List>
);
}
ListItemText has default flex: 1 1 auto; style. You need to change it like:
import React from "react";
import { makeStyles } from "#material-ui/core/styles";
import { List, ListItem, ListItemText } from "#material-ui/core";
const useStyles = makeStyles((theme) => ({
root: {
"& .MuiListItemText-root": {
flex: "initial"
}
}
}));
export default function CustomStyles() {
const classes = useStyles();
return (
<List classes={classes}>
<ListItem alignItems="flex-start">
<ListItemText primary={"First Element "} />
<ListItemText primary={" Second Element"} />
</ListItem>
</List>
);
}
I am using <ListItemIcon/> from Material-UI. In one component I use two different Icons and I want them to be different sizes and other styles in general. <ListItemIcon/> is build with svg which has class name MuiSvgIcon-root - this is where I should change the fontSize of Icon. I dont know how to do it. When I do
const useStyles = makeStyles({
root:{
fontSize: "2rem"
}
},{name: 'MuiSvgIcon'});
It changes setting for every Icon size in my project.
My component
function Section(props) {
const classes = useStyles();
const { title, listInfo, icon, gridSize } = props;
return (
<List>
<ListItem>
<ListItemIcon >{icon}</ListItemIcon> //here icon bigger
<ListItemText primary={title} />
</ListItem>
<Divider variant="middle" />
<Grid container>
{listInfo.map((item, index) => {
return (
<Grid item xs={gridSize}>
<ListItem key={index}>
<ListItemIcon>
<Brightness1Icon /> //here icon smaller
</ListItemIcon>
<ListItemText
primary={item.primaryText}
secondary={item.secondaryText}
/>
</ListItem>
</Grid>
);
})}
</Grid>
</List>
);
}
By specifying name: 'MuiSvgIcon' in your makeStyles call, you are causing Material-UI to override the global MuiSvgIcon-root class. If you use the name option in makeStyles, you should never give it a Mui name since these are treated differently and intended for use within the library code.
Below is one way to customize the icon size:
const BiggerListItemIcon = withStyles({
root: {
"& .MuiSvgIcon-root": { fontSize: "2em" }
}
})(ListItemIcon);
This can then be used as in the following example:
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 ListItemText from "#material-ui/core/ListItemText";
import InboxIcon from "#material-ui/icons/Inbox";
import DraftsIcon from "#material-ui/icons/Drafts";
const useStyles = makeStyles(theme => ({
root: {
width: "100%",
maxWidth: 360,
backgroundColor: theme.palette.background.paper
}
}));
const BiggerListItemIcon = withStyles({
root: {
"& .MuiSvgIcon-root": { fontSize: "2em" }
}
})(ListItemIcon);
export default function SimpleList() {
const classes = useStyles();
return (
<div className={classes.root}>
<List component="nav" aria-label="main mailbox folders">
<ListItem button>
<ListItemIcon>
<InboxIcon />
</ListItemIcon>
<ListItemText primary="Inbox" />
</ListItem>
<ListItem button>
<BiggerListItemIcon>
<DraftsIcon />
</BiggerListItemIcon>
<ListItemText primary="Drafts" />
</ListItem>
</List>
</div>
);
}
There are many ways to do styling with material-ui, I won't say this is the best way, but personally it is my own favorite way
import { styled } from "#material-ui";
const Section = () => {
return (
...
<SmallerListItemIcon>
<Brightness1Icon />
</SmallerListItemIcon>
...
)
}
const SmallerListItemIcon = styled(ListItemIcon)({
fontSize: "<your size here>"
});
I want the primary and secondary text within a ListItemText to both be center-aligned, unlike the question here.
However, after trying alignItems, alignContent, alignSelf, and primaryTypographyProps={{ align: "center" }}, I am stumped.
What's the correct way to go about this?
Below is an example with center-aligned text.
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 ListItemText from "#material-ui/core/ListItemText";
const useStyles = makeStyles(theme => ({
root: {
width: "100%",
maxWidth: 360,
backgroundColor: theme.palette.background.paper
}
}));
const CenteredListItemText = withStyles({
root: {
textAlign: "center"
}
})(ListItemText);
export default function SimpleList() {
const classes = useStyles();
return (
<div className={classes.root}>
<List component="nav" aria-label="main mailbox folders">
<ListItem button>
<CenteredListItemText primary="Inbox" secondary="Inbox secondary" />
</ListItem>
<ListItem button>
<CenteredListItemText primary="Drafts" secondary="Drafts secondary" />
</ListItem>
</List>
</div>
);
}
So I have a route that displays the users, each user is clickable and leads to the user details route that is dynamic. When I am on the details route, if I press the layout button to go back to the list nothing happens.
I've tried create a const what uses window.location.reload(true) and pass it in the onClick but this doesn't work
users.js
import React from "react"
import { BrowserRouter as Router,Switch, Route} from "react-router-dom"
import Layout from "../components/layout"
import User from "../components/users"
import MainComponentWrapper from "../components/mainComponentWrapper"
import UserDetails from "../components/userDetails"
const userDetailsWrapper = props => {
const url = "http://localhost:5000/user/" + props.match.params.cn
return (
<MainComponentWrapper url={url}>
<UserDetails />
</MainComponentWrapper>
)
}
const userWrapper = props => {
const url = "http://localhost:5000/user"
return (
<MainComponentWrapper url={url}>
<User />
</MainComponentWrapper>
)
}
const IndexPage = () => (
<div>
<Router >
<Layout>
<Switch>
<Route exact path="/users" component={userWrapper}/>
<Route exact path="/users/:cn" component={userDetailsWrapper} />
</Switch>
</Layout>
</Router>
</div>
)
export default IndexPage
Layout.jsx
import PropTypes from "prop-types"
import React from "react"
import { makeStyles } from "#material-ui/core/styles"
import Drawer from "#material-ui/core/Drawer"
import CssBaseline from "#material-ui/core/CssBaseline"
import List from "#material-ui/core/List"
import Divider from "#material-ui/core/Divider"
import ListItem from "#material-ui/core/ListItem"
import ListItemIcon from "#material-ui/core/ListItemIcon"
import ListItemText from "#material-ui/core/ListItemText"
import ExitToApp from "#material-ui/icons/ExitToApp"
import PeopleIcon from "#material-ui/icons/People"
import ListIcon from "#material-ui/icons/List"
import ComputerIcon from "#material-ui/icons/Computer"
import { navigate } from "gatsby"
const drawerWidth = 240
const useStyles = makeStyles(theme => ({
root: {
display: "flex",
},
appBar: {
zIndex: theme.zIndex.drawer + 1,
},
drawer: {
width: drawerWidth,
flexShrink: 0,
},
drawerPaper: {
width: drawerWidth,
},
content: {
flexGrow: 1,
padding: theme.spacing(3),
},
toolbar: theme.mixins.toolbar,
}))
function Layout({ children }) {
const classes = useStyles()
const handleRefresh = event => {
window.location.replace("/");
}
const handleLogout = event => {
localStorage.removeItem("access_token")
window.location.replace("/")
}
return (
<div className={classes.root}>
<CssBaseline />
<Drawer
className={classes.drawer}
variant="permanent"
classes={{
paper: classes.drawerPaper,
}}
>
<div className={classes.toolbar} />
<List>
<ListItem button onClick={(handleRefresh) => navigate("/users")}>
<ListItemIcon>
<PeopleIcon />
</ListItemIcon>
<ListItemText primary={"Users"} />
</ListItem>
<ListItem button onClick={() => navigate("/machines")}>
<ListItemIcon>
<ComputerIcon />
</ListItemIcon>
<ListItemText primary={"Machines"} />
</ListItem>
<ListItem button onClick={() => navigate("/audits")}>
<ListItemIcon>
<ListIcon />
</ListItemIcon>
<ListItemText primary={"Audit"} />
</ListItem>
</List>
<Divider />
<List>
<ListItem button onClick={handleLogout}>
<ListItemIcon>
<ExitToApp />
</ListItemIcon>
<ListItemText primary={"Logout"} />
</ListItem>
</List>
</Drawer>
<main className={classes.content}>
<div className={classes.toolbar} />
{children}
</main>
</div>
)
}
Layout.propTypes = {
children: PropTypes.node.isRequired,
}
export default Layout
How to create sub menu in react-admin, because in admin-on-rest i can use prop menuItems in MenuItem Component.
Does react-admin have same props for this case?
I try create my own component, but with prop primary in ListItemText for give list name my app always show error Uncaught TypeError: Cannot read property '#global'
Thank you
As previously explained by the maintainers/developers of react-admin, this feature is not offered by react-admin.
If you want a sub-menu, you should create a custom menu, following the instructions given in the official react-admin documentation and implement the Material-UI's nested-list logic.
This is a simple example of what your sub-menu could look like, according to the links I provided:
<List component="nav" >
<ListItem button onClick={this.handleClick}>
<ListItemIcon>
<InboxIcon />
</ListItemIcon>
<ListItemText inset primary="YOUR-SECTION-TITLE" />
{this.state.open ? <ExpandLess /> : <ExpandMore />}
</ListItem>
<Collapse in={this.state.open} timeout="auto" unmountOnExit>
<List component="div" disablePadding>
<MenuItemLink to="/your-api-endpoint-1" primaryText="API-ENDPOINT-1" onClick={this.props.onMenuClick} />
<MenuItemLink to="/your-api-endpoint-2" primaryText="API-ENDPOINT-2" onClick={this.props.onMenuClick} />
<MenuItemLink to="/your-api-endpoint-3" primaryText="API-ENDPOINT-3" onClick={this.props.onMenuClick} />
</List>
</Collapse>
</List>
Simple submenu component compatible with React Admin v4 https://marmelab.com/react-admin/Menu.html
import * as React from 'react';
import { useState } from 'react';
import PropTypes from 'prop-types';
import ExpandMoreIcon from '#mui/icons-material/ExpandMore';
import { List, ListItem, ListItemText, Collapse } from '#mui/material';
import { useTranslate, useSidebarState } from 'react-admin';
export const SubMenu = (props: SubMenuProps) => {
const { isDropdownOpen = false, primaryText, leftIcon, children, ...rest } = props;
const translate = useTranslate();
const [open] = useSidebarState();
const [isOpen, setIsOpen] = useState(isDropdownOpen);
const handleToggle = () => {
setIsOpen(!isOpen);
};
return (
<React.Fragment>
<ListItem
dense
button
onClick={handleToggle}
sx={{
paddingLeft: '1rem',
color: 'rgba(0, 0, 0, 0.54)',
}}
>
{isOpen ? <ExpandMoreIcon /> : leftIcon}
<ListItemText
inset
disableTypography
primary={translate(primaryText)}
sx={{
paddingLeft: 2,
fontSize: '1rem',
color: 'rgba(0, 0, 0, 0.6)',
}}
/>
</ListItem>
<Collapse in={isOpen} timeout="auto" unmountOnExit>
<List
component="div"
disablePadding
sx={open ? {
paddingLeft: '25px',
transition: 'padding-left 195ms cubic-bezier(0.4, 0, 0.6, 1) 0ms',
} : {
paddingLeft: 0,
transition: 'padding-left 195ms cubic-bezier(0.4, 0, 0.6, 1) 0ms',
}}
>
{children}
</List>
</Collapse>
</React.Fragment>
)
}
export type SubMenuProps = {
children?: React.ReactNode;
isDropdownOpen?: boolean;
leftIcon?: React.ReactElement;
primaryText?: string;
};
export default SubMenu;
Usage:
import * as React from 'react';
import { Menu } from 'react-admin';
import BookIcon from '#mui/icons-material/Book';
import PeopleIcon from '#mui/icons-material/People';
import LabelIcon from '#mui/icons-material/Label';
import SubMenu from './SubMenu';
export const MainMenu = () => (
<Menu>
<Menu.DashboardItem />
<SubMenu primaryText="CMS" leftIcon={<BookIcon />}>
<Menu.Item to="/admin/pages" primaryText="Pages" leftIcon={<BookIcon />}/>
<Menu.Item to="/admin/articles" primaryText="Articles" leftIcon={<PeopleIcon />}/>
</SubMenu>
<Menu.Item to="/custom-route" primaryText="Miscellaneous" leftIcon={<LabelIcon />}/>
</Menu>
);