React-MaterialUI: Horizontally aligning single tab to right and others to left in App Bar ->Tabs -> Tab - css

In my React application, I have a Navigation bar where in there are multiple Tabs, which are created with the use of Marerial UI's AppBar, Tabs and Tab component (in sequence), as below:
function associatedProps(index) {
return {
id: `nav-tab-${index}`,
'aria-controls': `nav-tabpanel-${index}`
};
}
function LinkTab(props) {
const history = useHistory();
const route = props.route;
console.log(props);
return (
<>
<Tab
component="a"
onClick={(event) => {
event.preventDefault();
history.push(route)
}}
{...props}
/>
</>
);
}
const useStyles = makeStyles((theme) => ({
root: {
flexGrow: 1,
backgroundColor: theme.palette.background.paper,
height: theme.navBarHeight
},
tabIndicator: {
backgroundColor: PRIMARY_RED.default
},
tabBar: {
top: '80px'
}
}));
export default function NavTabs() {
const classes = useStyles();
const [value, setValue] = React.useState(0);
const handleChange = (event, newValue) => {
setValue(newValue);
};
return (
<div className={classes.root}>
<AppBar position="fixed" className={classes.tabBar}>
<Tabs
variant=""
classes={{indicator: classes.tabIndicator}}
value={value}
onChange={handleChange}
aria-label="nav tabs example"
>
<LinkTab {...PRIMARY_NAVIGATION.MY_LIST} {...associatedProps(0)} />
<LinkTab {...PRIMARY_NAVIGATION.MY_REQUESTS} {...associatedProps(1)} />
<LinkTab {...PRIMARY_NAVIGATION.REPORT} {...associatedProps(2)} />
</Tabs>
</AppBar>
</div>
);
}
Now herein this setup I wanted my REPORT tab to be aligned right of the App Bar. I do not see any CSS Rule or Prop which in Documentation, which can help me here.
Please suggest how can I achieve this in current setup.

You should set a class for Tabs like this:
const useStyles = makeStyles((theme) => ({
tabs: {
'&:last-child': {
position: 'absolute',
right: '0'
}
}
}));
export default function NavTabs() {
...
return (
<div className={classes.root}>
<AppBar position="fixed" className={classes.tabBar}>
<Tabs
variant=""
classes={classes.tabs}
value={value}
onChange={handleChange}
aria-label="nav tabs example"
>
<LinkTab {...PRIMARY_NAVIGATION.MY_LIST} {...associatedProps(0)} />
<LinkTab {...PRIMARY_NAVIGATION.MY_REQUESTS} {...associatedProps(1)} />
<LinkTab {...PRIMARY_NAVIGATION.REPORT} {...associatedProps(2)} />
</Tabs>
</AppBar>
</div>
);

Tabs do not provide a property to align a specific item to the start or end. But you can leverage css to achieve your result.
Add a className to the item to be right aligned and define a marginLeft property on it
const useStyles = makeStyles((theme) => ({
root: {
flexGrow: 1,
backgroundColor: theme.palette.background.paper,
height: theme.navBarHeight
},
tabIndicator: {
backgroundColor: PRIMARY_RED.default
},
tabBar: {
top: '80px'
},
rightAlign: {
marginLeft: 'auto',
}
}));
export default function NavTabs() {
const classes = useStyles();
const [value, setValue] = React.useState(0);
const handleChange = (event, newValue) => {
setValue(newValue);
};
return (
<div className={classes.root}>
<AppBar position="fixed" className={classes.tabBar}>
<Tabs
variant=""
classes={{indicator: classes.tabIndicator}}
value={value}
onChange={handleChange}
aria-label="nav tabs example"
>
<LinkTab {...PRIMARY_NAVIGATION.MY_LIST} {...associatedProps(0)} />
<LinkTab {...PRIMARY_NAVIGATION.MY_REQUESTS} {...associatedProps(1)} />
<LinkTab {...PRIMARY_NAVIGATION.REPORT} {...associatedProps(2)} className={classes.rightAlign}/>
</Tabs>
</AppBar>
</div>
);
}
Sample working demo

Related

MUI 5 Tab Label Custom Thickness

I need to change the thickness of label inside a tab using MUI 5.
Here are what I tried:
interface TabPanelProps {
children?: React.ReactNode;
index: number;
value: number;
}
function TabPanel(props: TabPanelProps) {
const { children, value, index, ...other } = props;
return (
<div
role="tabpanel"
hidden={value !== index}
id={`simple-tabpanel-${index}`}
aria-labelledby={`simple-tab-${index}`}
{...other}
>
{value === index && (
<Box sx={{ p: 3 }}>
<Typography>{children}</Typography>
</Box>
)}
</div>
);
}
function a11yProps(index: number) {
return {
id: `simple-tab-${index}`,
'aria-controls': `simple-tabpanel-${index}`,
};
}
export default function UsersGroupsManagement() {
const [value, setValue] = React.useState(0);
const handleChange = (event: React.SyntheticEvent, newValue: number) => {
setValue(newValue);
};
const StyledTab = styled(Tab)<TabProps>(({theme}) => ({
'& .MuiButtonBase-root-MuiTab-root': {
fontWeight: 'bold'
}
}));
const styledLabel = styled('label')({
color: 'darkslategray',
backgroundColor: 'aliceblue',
padding: 8,
borderRadius: 4,
});
return (
<Box sx={styles.userAccounts}>
<Box sx={styles.tabbox}>
<Tabs value={value} onChange={handleChange} aria-label="User Management Tabs" >
<Tab label="ADD NEW USER" {...a11yProps(0)} sx={{
'& .MuiButtonBase-root-MuiTab-root': {
color: 'black',
backgroundColor: 'red',
fontWeight: 'bold'
}
}}/>
<Tab label="MANAGE USERS" {...a11yProps(1)} sx={{
'& .MuiButtonBase-root-MuiTab-root': {
fontWeight: 'bold'
}
}}/>
</Tabs>
</Box>
<TabPanel value={value} index={0}>
<AddNewUser />
</TabPanel>
<TabPanel value={value} index={1}>
Item Two
</TabPanel>
</Box>
);
}
I tried to create a StyledTab but didnt work.
I tried to create a styled label didnt work at all.
I tried to give css from sx props using but didnt work.
Can you please explain me how can I manage to make thicker labeled tabs in Material UI v5?
u can follow something like this..
<Tabs
sx={{
"& .MuiTabs-indicator": { backgroundColor: "#E86826" },
"& .MuiTab-root.Mui-selected": { color: "#E86826", fontWeight:"700" },
}}
value={value}
onChange={handleChange}
aria-label="nav tabs example"
centered
>
Just Edit the tabs and u work is done...hope it helps

Only Show Text on Selection - MUI

I only want to show the text of the tab on selection.
This is from the MUI documentation. How can I only show labels on selection? I assume I can use the state below and translate it somehow, how on the selection the color appears with the element.
Please see the code where I have tried to establish. I am new to this framework. If anyone can provide tips let me know!
function TabPanel(props) {
const { children, value, index, ...other } = props;
return (
<div
role="tabpanel"
hidden={value !== index}
id={`vertical-tabpanel-${index}`}
aria-labelledby={`vertical-tab-${index}`}
{...other}
>
{value === index && (
<Box sx={{ p: 3 }}>
<Typography>{children}</Typography>
</Box>
)}
</div>
);
}
TabPanel.propTypes = {
children: PropTypes.node,
index: PropTypes.number.isRequired,
value: PropTypes.number.isRequired,
};
function a11yProps(index) {
return {
id: `vertical-tab-${index}`,
'aria-controls': `vertical-tabpanel-${index}`,
};
}
//
const JobPostBuild = () => {
const [value, setValue] = React.useState(0);
const handleChange = (event, newValue) => {
setValue(newValue);
};
return (
<Box
sx={{ flexGrow: 1, bgcolor: 'gray', display: 'flex', height: 500 }}
>
<Tabs
orientation="vertical"
variant="scrollable"
centered
value={value}
onChange={handleChange}
sx={{ borderRight: 1, borderColor: 'divider' }}
>
<Tab icon={<WorkIcon/>} label={"Role"} {...a11yProps(0)} />
<Tab icon={<AccountBoxIcon/>} label="People" {...a11yProps(1)} />
<Tab icon={<ViewCompactIcon/>} label="Build" {...a11yProps(2)} />
<Tab icon={<PostAddIcon/>} label="Post" {...a11yProps(3)} />
</Tabs>
<TabPanel value={value} index={0}>
Role
</TabPanel>
<TabPanel value={value} index={1}>
People
</TabPanel>
<TabPanel value={value} index={2}>
Build
</TabPanel>
<TabPanel value={value} index={3}>
Post
</TabPanel>
</Box>
);
}
export default JobPostBuild
Happy to discuss this over Discord please let me know!
You can check the value of selected tab to set a condition for displaying tab label:
<Tab label={value === 0 ? "Role" : ""} {...a11yProps(0)} />
Demo

How to remove lines from Router Link? style={{'textDecoration': 'none'}} is not working

I m using textdecoration none in my link but when run the app it's not working can anyone state me solution for it?
Tysm for help in advance!
Navbar.js file
import React,{useState} from "react";
import { makeStyles } from "#material-ui/core/styles";
import {AppBar, Toolbar, Tab, Tabs, IconButton, Menu, MenuItem, useMediaQuery, useTheme, Button} from "#material-ui/core";
import MenuIcon from "#material-ui/icons/Menu";
import { Link } from "react-router-dom";
import {navlinks} from './navbarlinks';
import {FaFacebook} from 'react-icons/fa';
import {FaInstagram} from 'react-icons/fa';
import {FaLinkedinIn} from 'react-icons/fa';
import {FaTwitter} from 'react-icons/fa';
const useStyles = makeStyles((theme) => ({
root: {
flexGrow: 1
},
menuButton: {
marginRight: theme.spacing(2)
},
tab : {
color : '#000000',
'textDecoration': 'none'
},
appBarTransparent: {
backgroundColor: 'rgba(255,255,255,0.1);'
},
appBarSolid:{
}
}));
const Navbar = () => {
const classes = useStyles();
const [anchorEl, setAnchorEl] = React.useState(null);
const [anchorE2, setAnchorE2] = React.useState(null);
const open = Boolean(anchorEl);
const [value,setValue] = useState(0);
const handleMenu = (event) => {
setAnchorEl(event.currentTarget);
};
const handleOpenMenu = e => {
setAnchorE2(e.currentTarget);
}
const handleMenuClose = e => {
setAnchorE2(null);
}
const handleClose = () => {
setAnchorEl(null);
};
function a11yProps(index) {
return {
id: `simple-tab-${index}`,
'aria-controls': `simple-tabpanel-${index}`,
};
}
const handleClickTab = (e, newValue) => {
setValue(newValue);
}
const theme = useTheme();
const isMatch = useMediaQuery(theme.breakpoints.down('sm') );
return (
<div>
<AppBar position="sticky" className={classes.appBarTransparent}>
<Toolbar>
<Link to='/'><img src="/images/image2vector.svg" alt='logo' style={{'border-radius' : '33%', 'maxHeight' : 'auto', 'maxWidth':'112px'}}/></Link>
{ !isMatch ?
<div className={classes.root}>
<Tabs onChange={handleClickTab} indicatorColor='secondary' value={value} aria-label="icon tabs example">
{
navlinks.map( link => {
return <Link to={link.to}><Tab className={classes.tab} style={{'textDecoration': 'none'}}label={link.title} {...a11yProps(link.id)} /></Link>
})
}
</Tabs>
</div>
:
<div className={classes.root}>
<IconButton
aria-label="account of current user"
aria-controls="menu-appbar"
aria-haspopup="true"
onClick={handleMenu}
color="inherit"
>
<MenuIcon />
</IconButton>
<Menu
id="menu-appbar"
anchorEl={anchorEl}
anchorOrigin={{
vertical: "top",
horizontal: "right"
}}
keepMounted
transformOrigin={{
vertical: "top",
horizontal: "right"
}}
open={open}
onClose={handleClose}
disableRipple
>
{ navlinks.map(link => {
return <MenuItem onClick={handleClose}><Link to={link.to}>{link.title}</Link></MenuItem>
})
}
</Menu>
</div>
}
<div>
<Button
color="secondary"
onClick={handleOpenMenu}
aria-controls='menu'
>
Contact Us
</Button>
</div>
<Menu
id='menu'
anchorE2={anchorE2}
open={Boolean(anchorE2)}
onClose={handleMenuClose}
anchorOrigin={{
vertical: "bottom",
horizontal: "right"
}}
keepMounted
transformOrigin={{
vertical: "top",
horizontal: "center"
}}
> <MenuItem>+91 9426231824</MenuItem>
<MenuItem><FaFacebook /></MenuItem>
<MenuItem><FaInstagram /></MenuItem>
<MenuItem><FaLinkedinIn /></MenuItem>
<MenuItem><FaTwitter /></MenuItem>
</Menu>
</Toolbar>
</AppBar>
</div>
);
};
export default Navbar;
navbarlink.js
export const navlinks = [
{
title: 'Home',
to : '/',
id:0
},
{
title: 'About US',
to : '/aboutus',
id:1
},
{
title: 'Projects',
to : '/projects',
id:2
},
{
title: 'Services',
to : '/services',
id:3
},
{
title: 'Get A Quote',
to : '/contactus',
id:4
}
]
I m using textdecoration none in my link but when run the app it's not working can anyone state me solution for it?
Tysm for help in advance!
I solved it with installing styled-componets and then putting following code
const StyledLink = styled(Link) `
text-decoration: none;
&:focus, &:hover, &:visited, &:link, &:active {
text-decoration: none;
`;
Remove the quotes from 'textDecoration'
So replace this line:
return <Link to={link.to}><Tab className={classes.tab} style={{'textDecoration': 'none'}}label={link.title} {...a11yProps(link.id)} /></Link>
to this:
return <Link to={link.to}><Tab className={classes.tab} style={{textDecoration: 'none'}}label={link.title} {...a11yProps(link.id)} /></Link>

Material UI using tabs panel and CSS

I can not change the color and CSS from the TAB PANEL using material-ui Some ideas? :(
Looks like useStyle and theme are not working. I could change some other properties like scrollable but not the colors. I wonder if there is some conflict con other CSS, but I don't think so because the colors I see from the TABs are blue, I'm not using blue in my Web-App.
import PropTypes from 'prop-types';
import { makeStyles } from '#material-ui/core/styles';
import AppBar from '#material-ui/core/AppBar';
import Tabs from '#material-ui/core/Tabs';
import Tab from '#material-ui/core/Tab';
import Typography from '#material-ui/core/Typography';
import Box from '#material-ui/core/Box';
function TabPanel(props) {
const { children, value, index, ...other } = props;
return (
<div
role="tabpanel"
hidden={value !== index}
id={`scrollable-auto-tabpanel-${index}`}
aria-labelledby={`scrollable-auto-tabpanel-${index}`}
{...other}
>
{value === index && (
<Box p={3}>
<Typography>{children}</Typography>
</Box>
)}
</div>
);
}
TabPanel.propTypes = {
children: PropTypes.node,
index: PropTypes.any.isRequired,
value: PropTypes.any.isRequired,
};
function a11yProps(index) {
return {
id: `scrollable-auto-tabpanel-${index}`,
'aria-controls': `scrollable-auto-tabpanel-${index}`,
};
}
function LinkTab(props) {
return (
<Tab
component="a"
onClick={(event) => {
event.preventDefault();
}}
{...props}
/>
);
}
const useStyles = makeStyles((theme) => ({
root: {
flexGrow: 1,
margin: 0,
background: 'white',
},
}));
export default function NavTabs() {
const classes = useStyles();
const [value, setValue] = React.useState(0);
const handleChange = (event, newValue) => {
setValue(newValue);
};
return (
<AppBar position="static">
<Tabs
variant="container-fluid"
value={value}
onChange={handleChange}
variant="scrollable"
scrollButtons="auto"
aria-label="scrollable auto tabs example"
centered
>
It's actually the AppBar that has that blue color. Upon reviewing the stylesheet, the individual tab items actually have transparent as a default value for background-color. So to solve this, just override the background of the root element of AppBar
const useStyles = makeStyles((theme) => ({
root: {
flexGrow: 1,
margin: 0,
background: "white"
}
}));
export default function NavTabs() {
const classes = useStyles();
<AppBar position="static" classes={{ root: classes.root }}>
...

Element positioned absolute inside Dialog Material UI React

I have Dialog component where I have a button(bottom right corner) which shows another div with an item list. The problem I'm facing is that the list is being rendered inside the Dialog component and it's being cropped. I set the position: absolute, z-index and set the position: relative to the parent but it does not work. Here is how it looks like. Any helpful tips I would appreciate it.
1) Before I click the button to show the list
2) After I click the button. Highlighted css properties for the list element
And the code for Dialog component :
import React, { useState } from "react";
import { makeStyles } from "#material-ui/core";
import Button from "#material-ui/core/Button";
import Dialog from "#material-ui/core/Dialog";
import DialogContent from "#material-ui/core/DialogContent";
import DialogContentText from "#material-ui/core/DialogContentText";
import DialogTitle from "#material-ui/core/DialogTitle";
import IconButton from "#material-ui/core/IconButton";
import CloseIcon from "#material-ui/icons/Close";
import Typography from "#material-ui/core/Typography";
import OutlinedInput from "#material-ui/core/OutlinedInput";
import { ProjectTreeWindow } from "../index";
const useStyles = makeStyles(theme => ({
addTaskButton: {
marginTop: 10
},
dialog: {
width: "40%",
maxHeight: 435
},
closeButton: {
position: "absolute",
right: theme.spacing(1),
top: theme.spacing(1),
color: theme.palette.grey[500]
},
controlsWrapper: {
display: "flex",
alignItems: "center",
justifyContent: "space-between"
}
}));
const AddQuickTaskDialog = props => {
const classes = useStyles(props);
const { open, close } = props;
const [quickTaskDescription, setQuickTaskDescription] = useState("");
const [textInputRef, setTextInputRef] = useState(null);
const handleChangeQuickTaskDescription = event => {
setQuickTaskDescription(event.target.value);
};
const handleAddQuickTaskSubmit = () => {
alert("Quick task submitted");
close(textInputRef);
};
return (
<Dialog
data-testid="add-task-quick"
classes={{
paper: classes.dialog
}}
maxWidth="lg"
open={open}
keepMounted
onClose={() => {
close(textInputRef);
}}
aria-labelledby="quick-task-dialog"
aria-describedby="quick-task-dialog-description"
>
<DialogTitle id="quick-task-dialog-title">
<Typography variant="h6">Quick Add Task</Typography>
{close ? (
<IconButton
aria-label="close"
className={classes.closeButton}
onClick={() => {
close(textInputRef);
}}
>
<CloseIcon />
</IconButton>
) : null}
</DialogTitle>
<DialogContent>
<div className={classes.wrapper}>
<OutlinedInput
onChange={handleChangeQuickTaskDescription}
inputRef={input => {
setTextInputRef(input);
return input && input.focus();
}}
fullWidth
// className={showAddTaskInput ? classes.show : classes.hide}
placeholder="e.g. Take the dog out for a walk"
inputProps={{ "aria-label": "add task" }}
/>
<div className={classes.controlsWrapper}>
<Button
className={classes.addTaskButton}
disabled={quickTaskDescription.length === 0}
data-testId="quick-add-task-submit"
// onClick={handleAddTaskSubmit}
color="primary"
onClick={handleAddQuickTaskSubmit}
>
Add Task
</Button>
<ProjectTreeWindow />
</div>
</div>
</DialogContent>
</Dialog>
);
};
export default AddQuickTaskDialog;
and for the List component:
import React, { useState } from "react";
import { makeStyles } from "#material-ui/core";
import ListAltTwoToneIcon from "#material-ui/icons/ListAltTwoTone";
import IconButton from "#material-ui/core/IconButton";
import { CustomizedToolTip } from "../index";
import OutlinedInput from "#material-ui/core/OutlinedInput";
import DoneTwoToneIcon from "#material-ui/icons/DoneTwoTone";
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 FiberManualRecordTwoToneIcon from "#material-ui/icons/FiberManualRecordTwoTone";
import { useProjectsValue, useSelectedProjectValue } from "../../context";
const useStyles = makeStyles(theme => ({
root: {
position: "absolute",
zIndex: 9999,
top: 200,
left: 0,
display: "flex",
flexDirection: "column",
"&:hover $child": {
visibility: "visible"
}
},
wrapper: {
position: "relative !important"
},
selected: {
"& $child": {
visibility: "visible !important"
}
},
hidden: {
visibility: "hidden"
},
listItemIcon: {
minWidth: 30
}
}));
const ProjectTreeWindowList = props => {
const [textInputRef, setTextInputRef] = useState(null);
const [typeProject, setTypedProject] = useState("");
const classes = useStyles(props);
const { projects } = useProjectsValue();
return (
<div className={classes.root}>
<OutlinedInput
// onChange={handleChangeQuickTaskDescription}
inputRef={input => {
setTextInputRef(input);
return input && input.focus();
}}
placeholder="Type a project"
inputProps={{ "aria-label": "select project" }}
/>
<List>
{projects &&
projects.map((project, index) => (
<ListItem
onClick={() => {
alert("move selected project to input");
}}
// selected={active === project.projectId}
button
// classes={{
// root: classes.root,
// selected: classes.selected
// }}
>
<ListItemIcon
className={classes.listItemIcon}
style={{ color: project.color }}
>
<FiberManualRecordTwoToneIcon />
</ListItemIcon>
<ListItemText primary={project.name} />
<ListItemIcon
className={`${classes.listItemIcon} ${classes.hidden}`}
>
<DoneTwoToneIcon />
</ListItemIcon>
</ListItem>
))}
</List>
</div>
);
};
const ProjectTreeWindow = props => {
const classes = useStyles(props);
const [showProjectTreeWindow, setShowProjectTreeWindow] = useState(false);
const handleShowProjectWindow = () => {
setShowProjectTreeWindow(!showProjectTreeWindow);
};
const handleCloseProjectWindow = () => {
setShowProjectTreeWindow(false);
};
return (
<div className={classes.wrapper}>
<CustomizedToolTip title="Select a project">
<IconButton onClick={handleShowProjectWindow} aria-label="add-project">
<ListAltTwoToneIcon />
</IconButton>
</CustomizedToolTip>
{showProjectTreeWindow ? <ProjectTreeWindowList /> : null}
</div>
);
};
export default ProjectTreeWindow;
It is because of the combinaison of position: relative and overflow-y: auto from the <Paper> component. If you override one of this property, it won't be hidden anymore.
To do this, there is a PaperProps property in <Dialog>.
Example:
<Dialog {...otherProps} PaperProps={{style: {position: 'static'} }}/>

Resources