Class is not applied to Material UI button component - html

I am trying to apply a class (redirectButton) to material UI button , but it is not getting applied.
here is my html
{(isDataAdapterAdmin && !dataSources?.length) &&
<Button className={classes.redirectButton} onClick={() => history.push('/settings_systems/dataSources')} >
{i18n._(buttonText)}
</Button>
}
const useStyles = makeStyles((theme: Theme) => ({
redirectButton:{
'display': 'flex',
'justify-content': 'center',
'margin-right': '400px'
}
}))
In output, the parent div is something like this
<div class>

If you want to apply the style to the root element you need to override classes:
Documentation here
classes={{ root: classes.redirectButton }}
// insted of
className={...}

Related

How to Override MUI CSS in a React Custom Component which uses MUI Component in it?

Below is the Custome Component which i created in Reactjs and used in different component :
function SearchBox({ handle, placeholder, inputType, ...props}) {
return (
<Box
sx={{
display: 'flex',
alignItems: 'flex-end',
margin: 1,
marginTop: 0,
maxHeight: '30px'
}}
>
<TextField
sx={{
fontSize: '12px',
width: '100%'
}}
variant={inputType || 'standard'}
InputProps={{
startAdornment: (
<InputAdornment position='start'>
<SearchIcon
sx={{
color: 'action.active',
mb: 0.2,
display: 'flex',
alignItems: 'flex-end'
}}
/>
</InputAdornment>
),
placeholder: placeholder || 'Search'
}}
onChange={handle}
/>
</Box>
);
}
I am using this Component in Some Other Component <SearchBox handle={Keyword}/>
so how to override css for TexField and Box of the SearchBox component? i don't want to touch the SearchBox need to override css properties from the place where i am using this component.
When i did Inspect on the Browser i saw something like this <div class="MuiBox-root css-1uqe0j">...</div>
what is css-luqe0j ?
Can Anyone Help me out with this.
If you don't want to modify the SearchBox component at all, you have a few options, the most reasonable of which (IMO) is to just wrap the SearchBox component in a styled component that then targets elements contained within the SearchBox (it's child), for example:
const SearchBoxStyleOverrides = styled("div")({
".MuiBox-root": {
padding: "2rem",
backgroundColor: "green"
},
".MuiSvgIcon-root": {
color: "red"
},
".MuiInput-input": {
backgroundColor: "yellow"
}
});
export default function YourApp() {
return (
<SearchBoxStyleOverrides>
<SearchBox />
</SearchBoxStyleOverrides>
);
}
Which produces: (ugliness is for effect)
Working CodeSandbox: https://codesandbox.io/s/peaceful-dubinsky-wjthtt?file=/demo.js
And to answer your secondary question ("what is css-luqe0j ?"), that is the generated css class name for the component -- you don't want to target an element using those because they will frequently change.

Add conditional CSS property in React

I want to add conditional CSS property to a div in such a way that if particular condition is true then only it will applied. Below is my code.
const Select = ({
handleClick,
title,
permission,
}: SelectProps) => {
return (
<div
onClick={handleClick}
style={{
marginTop: '16px',
cursor: 'pointer',
pointerEvents <-- make this property conditional
${({ permission }) => permission && `pointerEvents: none;`} <-- tried this but not working
}}
>
<Title>{title}</Title>
</div>
);
};
export const RenderSelectBlock = () => {
const checkUserPermission = checkUserPermission();
return (
<Select
handleClick={() => setSelectType('Google')}
title="Google"
checkUserPermission={checkUserPermission}
/>
<Select
handleClick={() => setSelectType('Microsoft')}
title="Microsoft"
checkUserPermission={checkUserPermission}
/>
<Select
handleClick={() => setSelectType('Apple')}
title="Apple"
checkUserPermission={checkUserPermission}
/>
<Select
handleClick={() => setSelectType('Facebook')}
title="Facebook"
checkUserPermission={checkUserPermission}
/>
)
);
};
So here in the last Select where title is Facebook, I want to disable it if the user don't have permission i.e. permission = false. Basically pointerEvents property should only be added for title= Facebook and should be set to none if permission = false.
You best option is to avoid style entirely and use className, then include a second class (maybe no-pointer-events) for the pointer-events you want to optionally include:
<div
className={`main-class ${permission ? "no-pointer-events" : ""}`}
But if you want to do it with style, you could use undefined for when you don't want to specify it:
<div
style={{
marginTop: '16px',
cursor: 'pointer',
pointerEvents: permission ? "none" : undefined,
}}
You could also define the style object before reaching this point in the code:
const style = {
marginTop: '16px',
cursor: 'pointer',
};
if (permission) {
style.pointerEvents = "none";
}
Then use it:
<div
style={style}
Sometimes you'll see people do this with multiple properties via spread syntax:
<div
style={{
marginTop: '16px',
cursor: 'pointer',
...(permission ? {pointerEvents: "none"} : undefined),
}}
...undefined is fine in an object literal (it doesn't add any properties).

css inline styles not applying to react table cells when using className

I'm trying to apply inline css to the react table cell, shown in the code by *** surrounding the div element. It works as it is declared right now, using Style=.... , but I would like to use className='textvertalign'instead, and when I try using className it doesn't seem to work. I can't seem to put my finger on why it doesn't work with className. It would be nice to be able to reference this css as I plan on applying it to more cells. Thanks in advance.
const styles = theme => ({
textvertalign:{
display:'flex', justifyContent:'center'
}
});
class UserManagement extends React.Component {
return
<div>
<ReactTable key={this.state.tablePageSize}
data={this.state.portalUsers}
filterable
defaultFilterMethod={filterCaseInsensitive}
columns={[{
columns: [{
Header: <div style={{ fontSize: '16px', textAlign: 'center', fontWeight: 'bold' }}>Edit</div>,
width: 90,
id: "Edit",
className: "align-center",
Cell: ({ row }) => (
***<div style={{display:'flex', justifyContent:'center'}}>***
<button className="FlatButton"
onClick={e => this.handleDialogOpen(e, row)}>
{
<FontAwesomeIcon style={{ color: '#FF3933' }} icon="edit" />
}
</button>
</div>
)
}....
</ReactTable>
</div>
}
UserManagement.propTypes = {
classes: PropTypes.object.isRequired,};
export default withStyles(styles)(UserManagement);
found the explanation and solution here: https://codex.happyfuncorp.com/styling-and-theming-with-material-ui-react-material-design-3ba2d2f0ef25
To be able to use the css that are in styles, I have to add:
const {classes} = this.props; //in render
className={classes.textvertalign} //to reference that css.
I think this has to do with the withStyles exporting the css, and we need to import it back in to use it.

How to avoid Bootstrap 4 NavBar from expanding when implementing an autocomplete field in React?

I use React 16.5.2 and Bootstrap 4.1.3 on my project and I want to have a typeahead on a NavBar. I have implemented the autocomplete field on the NavBar but it did not turn out the way I want it.
It seems that when the list of suggestion came out it will expand the NavBar too.
Another problem is the list of suggestion is on the right side of the input text instead of on the left side. For your information, I'm a React newbie and I'm using react-places-autocomplete to get the list of suggestion.
Most of the typeahead that I found is used outside of Navbar.
Here is the image of the NavBar with the autocomplete field.
Here are some packages that I use:-
React Places Autocomplete - https://www.npmjs.com/package/react-places-autocomplete.
bootstrap 4.1.3 - https://www.npmjs.com/package/bootstrap
Create React App - https://github.com/facebook/create-react-app
Below is a snippet of the code from my SearchForm component:-
render() {
return (
<form className="mx-2 my-auto d-inline w-100" onSubmit={this.handleSubmit}>
{this.state.gmapsLoaded && (
<PlacesAutocomplete
value={this.state.address}
onChange={this.handleChange}
onSelect={this.handleSelect}
>
{({ getInputProps, suggestions, getSuggestionItemProps, loading }) => (
<div className="input-group">
<input
{...getInputProps({
placeholder: 'Search Places ...',
className: 'form-control border border--0',
})}
/>
<div className="autocomplete-dropdown-container">
{loading && <div>Loading...</div>}
{suggestions.map(suggestion => {
const className = suggestion.active
? 'suggestion-item--active'
: 'suggestion-item';
// inline style for demonstration purpose
const style = suggestion.active
? { backgroundColor: '#fafafa', cursor: 'pointer' }
: { backgroundColor: '#ffffff', cursor: 'pointer' };
return (
<div
{...getSuggestionItemProps(suggestion, {
className,
style,
})}
>
<span>{suggestion.description}</span>
</div>
);
})}
</div>
<span className="input-group-append">
<button className="btn btn-outline-secondary border border-left-0" type="button" onClick={this.handleOnClick}>
<FontAwesomeIcon icon={faSearch} />
</button>
</span>
</div>
)}
</PlacesAutocomplete>
)}
</form>
)
}

Material UI Drawer won't move under Appbar

I have an Appbar and a drawer right beneath it. Under both components I have 3 divs with bootstrap and in each div I have a group of buttons.
The problem is that the Drawer covers the Appbar and I just can't seem to move it.
Here's my code:
<div className="App">
<AppBar position="static">
<Toolbar>
<IconButton color="inherit" aria-label="Menu">
<MenuIcon />
</IconButton>
<Typography variant="title" color="inherit" aria-label="Menu">
title
</Typography>
</Toolbar>
</AppBar>
<Drawer
variant="permanent"
style={{width: '100%', zIndex: '1400', position:'absolute'}}
>
<Button>1</Button>
<Button>2</Button>
<Divider />
<Button>1</Button>
<Button>2</Button>
</Drawer>
<br />
<div className="container-full">
<div className="row">
<div class="col-sm-6">
<GridList cellHeight={50} className={styles.gridList} cols={5}>
<Button style={{width: '150px', border: '1px solid'}} variant="raised" color="primary">
<div
style={{fontSize:'12px', display: 'flex', justifyContent: 'center', textAlign:'center'}}>
Mohnweckerl Wiener Gouda
</div>
</Button>
After the first bootstrap column, another "col-sm-4" follows and then a "col-sm-2". The buttons are in a GridList
Here's a visual
The Drawer should start where the arrows meet.
Any ideas?
The Material-UI docs call that a Drawer that's been clipped under the app bar. To achieve it, you first have to define a z-index for your AppBar your styles object:
const styles = theme => ({
appBar: {
// Make the app bar z-index always one more than the drawer z-index
zIndex: theme.zIndex.drawer + 1,
},
});
And then apply that to the AppBar component:
<AppBar position="absolute" className={classes.appBar}>
Since your drawer is now underneath the AppBar, you'll need to move the content in the drawer down the screen so that it is not hidden underneath the bar. You can accomplish that with theme.mixins.toolbar. First, add the toolbar styles:
const styles = theme => ({
appBar: {
zIndex: theme.zIndex.drawer + 1,
},
// Loads information about the app bar, including app bar height
toolbar: theme.mixins.toolbar,
});
Then, add the following div as the very first piece of content in your drawer:
<Drawer>
// Make sure this div is the first piece of content in your drawer
<div className={classes.toolbar} />
// Put your other drawer content here like you normally would
</Drawer>
The toolbar style will load information about the app bar height from the current theme and then size the div so that it ensures the content doesn't get hidden by the app bar.
You can find a full code sample here.
In MUI v5, the default zIndex values are:
const zIndex = {
mobileStepper: 1000,
fab: 1050,
speedDial: 1050,
appBar: 1100,
drawer: 1200,
modal: 1300,
snackbar: 1400,
tooltip: 1500,
};
Which explains why the drawer covers the appBar.
Another solution using ThemeProvider that simply swaps these values (Typescript):
// ./theme/index.tsx
import {
ThemeProvider as MUIThemeProvider,
createTheme,
} from "#mui/material/styles";
import { ReactNode } from "react";
interface ThemeProviderProps {
children: ReactNode;
}
export const ThemeProvider = ({ children }: ThemeProviderProps) => {
const theme = createTheme({ zIndex: { appBar: 1200, drawer: 1100 } });
return (
<MUIThemeProvider theme={theme}>
{children}
</MUIThemeProvider>
);
};
// ./App.tsx
import { ThemeProvider } from "./theme";
function App() {
return (
<div className="App">
<ThemeProvider>
// your component(s)
</ThemeProvider>
</div>
);
}