How can I apply styling to Material UI tabs in React? - css

I am trying to style my material UI tabs in my react component but I can seem to get them applied correctly. How can I do so?
I would like to set the background color and box shadow of the entire bar, and and indicator background color and underline for the active tab. Thank you!
Here's what I have so far:
const routes = ["/tab1", "/tab2"];
function MainNavigation() {
const styles = {
backgroundColor: "white",
boxShadow: '0 2px 2px -2px rgba(0,0,0,.2)'
};
return (
<IonToolbar >
<BrowserRouter >
<Route
path="/"
render={(history) => (
<div className="toolbar">
<Tabs
TabIndicatorProps={{style: {background:'primary'}}}
indicatorColor="primary"
color="primary"
variant="scrollable"
scrollButtons="auto"
aria-label="scrollable auto tabs"
value={history.location.pathname !== "/" ? history.location.pathname : false}
>
<Tab className="mat-tab"
label="Tab1"
value={routes[1]}
component={Link}
to={routes[1]}
></Tab>
<Tab className="mat-tab"
label="Tab2"
value={routes[0]}
component={Link}
to={routes[0]}
></Tab>
</Tabs>
</div>
)}
></Route>
<Switch >
<Route path="/scutes" component={Tab2}></Route>
<Route path="/gateways" component={Tab1}></Route>
<Redirect exact from="/" to="/tab2" />
</Switch>
</BrowserRouter>
</IonToolbar>
);
}
export default MainNavigation;
function handleTabChange(index: any) {
throw new Error("Function not implemented.");
}

Import styled
import styled from "styled-components";
declare your styles
const NewTab = styled(Tab)`
font-size: 100px;
`
Use new element instead of default Tab
import styled from "styled-components";
const routes = ["/tab1", "/tab2"];
const NewTab = styled(Tab)`
font-size: 100px;
`
function MainNavigation() {
const styles = {
backgroundColor: "white",
boxShadow: '0 2px 2px -2px rgba(0,0,0,.2)'
};
return (
<IonToolbar >
<BrowserRouter >
<Route
path="/"
render={(history) => (
<div className="toolbar">
<Tabs
TabIndicatorProps={{style: {background:'primary'}}}
indicatorColor="primary"
color="primary"
variant="scrollable"
scrollButtons="auto"
aria-label="scrollable auto tabs"
value={history.location.pathname !== "/" ? history.location.pathname : false}
>
<NewTab className="mat-tab"
label="Tab1"
value={routes[1]}
component={Link}
to={routes[1]}
></NewTab>
<NewTab className="mat-tab"
label="Tab2"
value={routes[0]}
component={Link}
to={routes[0]}
></NewTab>
</Tabs>
</div>
)}
></Route>
<Switch >
<Route path="/scutes" component={Tab2}></Route>
<Route path="/gateways" component={Tab1}></Route>
<Redirect exact from="/" to="/tab2" />
</Switch>
</BrowserRouter>
</IonToolbar>
);
}
export default MainNavigation;
function handleTabChange(index: any) {
throw new Error("Function not implemented.");
}

Related

React / CSS : Nightmode button that dosnt changes my navbar background color

I'm new on React. I just added a theme color to my page.
Everything goes from black to white and vice versa when I click my button "Change Theme".
But .. the navbar that was initially lightblue colored, isnt changing !
That navbar is the only element that isnt changed by my button " Change Theme ".
I dont quite clearly understand, because the body color was supposed to be changed.
Im really bad at CSS.
App.js
import './App.css';
import React, { useState } from 'react';
import {BrowserRouter as Router, Switch, Route, Link} from 'react-router-dom';
import About from './Pages/About';
import Home from './Pages/Home';
import Works from './Pages/Works';
import PageNotFound from './Pages/PageNotFound';
import StudyCase from './Pages/StudyCase';
import styled, { ThemeProvider } from "styled-components";
import { lightTheme, darkTheme, GlobalStyles } from './Components/Themes';
const StyledApp = styled.div`
color: ${props => props.theme.fontColor}
`;
function App() {
const [theme, setTheme] = useState('light')
const themeToggler = () => {
theme === 'light' ? setTheme("dark") : setTheme("light");
}
return (
<ThemeProvider theme={theme === 'light' ? lightTheme : darkTheme} >
<GlobalStyles />
<StyledApp>
<Router>
// NAVBAR
<div style={{width: 100 + "vw", height: 80, backgroundColor: "lightblue"}}>
<button onClick={() => themeToggler()}>Change Theme</button>
<Link to="/" style={{margin: 50}}>Home</Link>
<Link to="/works" style={{margin: 50}}>Projets</Link>
<Link to="/about" >L'agence</Link>
</div>
// END OF NAVBAR
<Switch>
<Route path="/" exact component={Home} />
<Route path="/about" exact component={About} />
<Route path="/works" exact component={Works} />
<Route path="/works/:name-study-case" exact component={StudyCase} />
<Route path="*" exact component={PageNotFound} />
</Switch>
</Router>
</StyledApp>
</ThemeProvider>
)
}
export default App;
Themes.js
import {createGlobalStyle} from 'styled-components';
export const lightTheme = {
body: "#fff",
fontColor: "#000"
}
export const darkTheme = {
body: "#000",
fontColor: "#fff"
}
export const GlobalStyles = createGlobalStyle`
body {
background-color: ${props => props.theme.body}
}
`
You set the styling "manually" here:
style={{width: 100 + "vw", height: 80, backgroundColor: "lightblue"}
That will always override your theme stylesheet due to CSS precedence rules. Get rid of that and it should all work fine.
Is Pass Object in style?
let styles = {
backgoungColor: "red;
}
return(<div style={styles}></div>);

How can i center the content of my footer?

I am new to react material ui.
I am using this table here
https://material-ui.com/components/tables/
under Custom pagination actions section.
Inside, there is a contenet in the footer with Rows per page text buttons for next previous etc...
I can't find a way to center that content in the middle.Right not is it is 'aligned' to the right by default
I tried adding
align="center"
justify="center"
but without success
My footer code looks like this
<TablePagination
className=""
align="center"
justify="center"
text-align="center"
rowsPerPageOptions={[5, 10, {label: 'All', value: -1}]}
// colSpan={12}
count={props.rowsCount}
rowsPerPage={props.rowsPerPage}
page={props.page}
SelectProps={{
inputProps: {'aria-label': 'rows per page'},
native: true,
}}
onChangePage={props.onChangePage}
onChangeRowsPerPage={props.onChangeRowsPerPage}
ActionsComponent={TablePaginationActions}
/>
Table pagination actions
import KeyboardArrowLeft from '#material-ui/icons/KeyboardArrowLeft';
import KeyboardArrowRight from '#material-ui/icons/KeyboardArrowRight';
import FirstPageIcon from '#material-ui/icons/FirstPage';
import LastPageIcon from '#material-ui/icons/LastPage';
import {makeStyles, useTheme} from '#material-ui/core/styles';
import {IconButton} from '#material-ui/core';
const useStyles = makeStyles((theme) => ({
root: {
flexShrink: 0,
marginLeft: theme.spacing(2.5),
},
}));
function TablePaginationActions(props) {
const classes = useStyles();
const theme = useTheme();
const {count, page, rowsPerPage, onChangePage} = props;
const c = console;
// c.table(props);
const handleFirstPageButtonClick = (event) => {
onChangePage(event, 0);
};
const handleBackButtonClick = (event) => {
onChangePage(event, page - 1);
};
const handleNextButtonClick = (event) => {
onChangePage(event, page + 1);
};
const handleLastPageButtonClick = (event) => {
onChangePage(event, Math.max(0, Math.ceil(count / rowsPerPage) - 1));
};
return (
<div className={classes.root}>
<IconButton
onClick={handleFirstPageButtonClick}
disabled={page === 0}
aria-label="first page"
>
{theme.direction === 'rtl' ? <LastPageIcon /> : <FirstPageIcon />}
</IconButton>
<IconButton
onClick={handleBackButtonClick}
disabled={page === 0}
aria-label="previous page"
>
{theme.direction === 'rtl' ? <KeyboardArrowRight /> : <KeyboardArrowLeft />}
</IconButton>
<IconButton
onClick={handleNextButtonClick}
disabled={page >= Math.ceil(count / rowsPerPage) - 1}
aria-label="next page"
>
{theme.direction === 'rtl' ? <KeyboardArrowLeft /> : <KeyboardArrowRight />}
</IconButton>
<IconButton
onClick={handleLastPageButtonClick}
disabled={page >= Math.ceil(count / rowsPerPage) - 1}
aria-label="last page"
>
{theme.direction === 'rtl' ? <FirstPageIcon /> : <LastPageIcon />}
</IconButton>
</div>
);
}
export default TablePaginationActions;
I found a way.The problem was that react used out of the box class - MuiTablePagination-spacer
which had this css
MuiTablePagination-spacer {
flex: 1 1 100%;
}
that maked the other sibling div go to the right
with this css applied i justified my content in the center
.MuiToolbar-root {
justify-content: center !important;
border:2px solid red;
}
.MuiTablePagination-spacer {
flex: 0 !important;
}
MuiToolbar-root already has display:flex so i applied only justify-content. We must disable the spaces on MuiTablePagination-spacer, otherwise it won't work.

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

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

How to change the position of an Icon component, within a Tab component?

I'm using MaterialUI's tabs in my React project.
This is the JSX for the tabs:
<AppBar color="default" position="static">
<Tabs indicatorColor="primary" textColor="primary" value={tabIndex} onChange={this.handleChange}>
{instances.map(instance =>
<StyledTab
style={{ textTransform: 'initial' }}
onClick={() => { this.changeActiveInstance(instance.id) }}
label={this.getTabAddress(instance)}
icon={<ClearIcon ></ClearIcon>}
>
</StyledTab>
)}
</Tabs>
This is how i inject the css:
const StyledTab = withStyles({
root: {
textTransform: 'initial'
},
})(Tab);
The result is this:
I would like to position the "ClearIcon" elsewhere. I tried playing with the style injection a bit, with no success.
Can somebody point me to the right direction?
When trying to customize any Material-UI component, the starting point is the CSS portion of the API documentation. The most relevant classes that you may want to override in this case are wrapper, labelContainer, and label.
The best way to fully understand how these are used and how they are styled by default (and therefore what you may want to override) is to look at the source code.
Here are the most relevant portions of the styles from Tab.js:
/* Styles applied to the `icon` and `label`'s wrapper element. */
wrapper: {
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
width: '100%',
flexDirection: 'column',
},
/* Styles applied to the label container element if `label` is provided. */
labelContainer: {
width: '100%', // Fix an IE 11 issue
boxSizing: 'border-box',
padding: '6px 12px',
[theme.breakpoints.up('md')]: {
padding: '6px 24px',
},
},
And here is the relevant code for understanding how these are used:
if (labelProp !== undefined) {
label = (
<span className={classes.labelContainer}>
<span
className={classNames(classes.label, {
[classes.labelWrapped]: this.state.labelWrapped,
})}
ref={ref => {
this.labelRef = ref;
}}
>
{labelProp}
</span>
</span>
);
}
<span className={classes.wrapper}>
{icon}
{label}
</span>
Below are some examples of possible ways to customize this.
import React from "react";
import PropTypes from "prop-types";
import Paper from "#material-ui/core/Paper";
import { withStyles } from "#material-ui/core/styles";
import Tabs from "#material-ui/core/Tabs";
import Tab from "#material-ui/core/Tab";
import PhoneIcon from "#material-ui/icons/Phone";
import FavoriteIcon from "#material-ui/icons/Favorite";
import PersonPinIcon from "#material-ui/icons/PersonPin";
const styles = {
root: {
flexGrow: 1,
maxWidth: 700
},
firstIcon: {
paddingLeft: 70
},
labelContainer: {
width: "auto",
padding: 0
},
iconLabelWrapper: {
flexDirection: "row"
},
iconLabelWrapper2: {
flexDirection: "row-reverse"
}
};
class IconLabelTabs extends React.Component {
state = {
value: 0
};
handleChange = (event, value) => {
this.setState({ value });
};
render() {
const { classes } = this.props;
return (
<Paper square className={classes.root}>
<Tabs
value={this.state.value}
onChange={this.handleChange}
variant="fullWidth"
indicatorColor="secondary"
textColor="secondary"
>
<Tab
icon={<PhoneIcon className={classes.firstIcon} />}
label="Class On Icon"
/>
<Tab
classes={{
wrapper: classes.iconLabelWrapper,
labelContainer: classes.labelContainer
}}
icon={<FavoriteIcon />}
label="Row"
/>
<Tab
classes={{
wrapper: classes.iconLabelWrapper2,
labelContainer: classes.labelContainer
}}
icon={<PersonPinIcon />}
label="Row-Reverse"
/>
<Tab icon={<PersonPinIcon />} label="Default" />
</Tabs>
</Paper>
);
}
}
IconLabelTabs.propTypes = {
classes: PropTypes.object.isRequired
};
export default withStyles(styles)(IconLabelTabs);
We have a inbuilt property to set the icon position of tab in material ui. Document link
iconPosition:'bottom' | 'end' | 'start' | 'top'

Display dynamic content on click on menu item using semantic-ui-react

I want to display dynamic content in Sidebar.Pusher based on the item clicked from the menu. Here is my code -
<Sidebar.Pushable >
<Sidebar as={Menu} animation='push' width='thin' visible={visible} icon='labeled' vertical inverted>
<Menu.Item name='home' >
<Icon name='tasks' />
Manage categories
</Menu.Item>
<Menu.Item name='home' >
<Icon name='tasks' />
Manage products
</Menu.Item>
</Sidebar>
<Sidebar.Pusher >
<Segment basic>
Display Dynamic content
</Segment>
</Sidebar.Pusher>
Any leads will be highly appreciated.
If I understand the question correctly, there are a few possible solutions. In one of my projects I'm using it with React Router, so in the <Sidebar /> component I have <Menu.Item as={Link} to='/path' /> and then the <Route path='/path' /> is in a <Switch /> statement in <Sidebar.Pusher />.
If you want to change rendered components without React Router, here is an example of how I implemented it.
import React, { Component } from 'react'
import { Sidebar, Segment, Menu } from 'semantic-ui-react'
export default class SideNav extends Component {
constructor(props) {
super(props)
this.state = {
renderTab: 'home'
}
}
changeTab(tabName) {
this.setState({ renderTab: tabName })
}
render() {
const { renderTab } = this.state
return (
<Sidebar.Pushable as={Segment}>
<Sidebar as={Menu} visible vertical>
<Menu.Item onClick={() => this.changeTab('home')} as='a' name='home'>
Home
</Menu.Item>
<Menu.Item onClick={() => this.changeTab('about')} as='a' name='about'>
About
</Menu.Item>
</Sidebar>
<Sidebar.Pusher>
<RenderedContent tabName={renderTab} />
</Sidebar.Pusher>
</Sidebar.Pushable>
)
}
}
const RenderedContent = ({ tabName }) => {
if (tabName === 'home') {
return <Home />
}
if (tabName === 'about') {
return <About />
}
}
const Home = () => (
<div>This is the home page</div>
)
const About = () => (
<div>This is the about page</div>
)

Resources