I am struggling to get the material-ui app bar example to work as I would like to. Codesandbox (from Material-UI website).
What I Am Trying To Achieve:
What I am trying to achieve is to get the search field to grow all the way to the right (effectively taking the majority of the app bar no matter what screen size).
What I Have Tried:
I have tried using flexGrow: 1 as follows which only grows the search bar slightly (not till the end):
search: {
position: 'relative',
borderRadius: theme.shape.borderRadius,
backgroundColor: fade(theme.palette.common.white, 0.15),
'&:hover': {
backgroundColor: fade(theme.palette.common.white, 0.25),
},
marginRight: theme.spacing(2),
marginLeft: 0,
width: '100%',
[theme.breakpoints.up('sm')]: {
marginLeft: theme.spacing(3),
width: 'auto',
flexGrow:1
},}
I have also tried setting width: '100%' instead of 'width: auto' but that makes the Material-UI logo disappear.
Image of desired result:
Remove the width: 'auto' from your current code,
Add minWidth with title
title: {
display: 'none',
minWidth: '120px', // Add
[theme.breakpoints.up('sm')]: {
display: 'block',
},
},
search: {
position: 'relative',
borderRadius: theme.shape.borderRadius,
backgroundColor: fade(theme.palette.common.white, 0.15),
'&:hover': {
backgroundColor: fade(theme.palette.common.white, 0.25),
},
marginRight: theme.spacing(2),
marginLeft: 0,
width: '100%', // Keep
[theme.breakpoints.up('sm')]: {
marginLeft: theme.spacing(3),
// width: 'auto', // Remove
},
},
Related
I want to use descendant selectors with JSS to style all descendant elements with certain styles and descendant input elements with another style, but it doesn't work.
First I thought that the problem is with syntax, but I looked at this article, and the syntax was the same that in my code.
After that, I tried to remove the classes from my descendant elements, because I thought that something wrong with inheritance and style priority, but it didn't work either.
Here is my code:
React:
...
<div className={addProductContainer}>
<div className={inputsContainer}>
<input
onChange={onNewItemNameChange}
value={newItem.name}
// className={productInput}
type="text"
/>
<input
onChange={onNewItemAmountChange}
onKeyDown={keyDown}
value={newItem.amount}
// className={amountInput}
type="number"
/>
<button onClick={handleSubmit} className={submitBtn}>Add New Product</button>
</div>
</div>
...
And the JSS:
...
inputsContainer: {
width: '100%',
height: 80,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: 'rgb(255, 175, 1)',
'& *': {
height: 40,
boxSizing: 'border-box'
},
'& input': {
backgroundColor: 'black',
border: 'none',
fontFamily: ['Lexend Deca', 'sans-serif'],
width: '40%',
padding: 5,
borderRadius: [[5, 0, 0, 5]],
fontSize: '1rem',
border: 'none'
},
'& input::-webkit-outer-spin-button, &input::-webkit-inner-spin-button': {
'-webkit-appearance': 'none'
}
},
// productInput: {
// width: '40%',
// padding: 5,
// borderRadius: [[5, 0, 0, 5]],
// fontSize: '1rem',
// border: 'none'
// },
// amountInput: {
// '-moz-appearance': 'textfield',
// width: 70,
// textAlign: 'center',
// fontSize: '1.5rem',
// border: [[1, 'solid', 'black']],
// borderRadius: [[0, 5, 5, 0]]
// },
...
Here you can see that I removed the classes, and put all styles from productInput to the descendant. When it was in class, it was working fine, but as a descendant, it doesn't work.
Try this '& > *' to set style to all descendants
The strike through is not vertically centered.
My code is like this:
<Text style={{textDecorationLine: 'line-through', alignSelf: 'center', fontFamily: constants.FONTBOLD, color: constants.ORANGE, fontSize: 16}}>
well, we couldn't actually find a solution with the textDecoration property. But we did a work-around by placing absolutely a View. Like this (pseudo code)
const styles = StyleSheet.create({
parent: {
position: relative,
},
halfLine: {
width: "100%",
top: 0,
height: "35%",
borderBottomColor: "black",
borderBottomWidth: 1,
position: "absolute",
},
<View class={styles.parent}>
<View class={styles.halfLine} />
<Copy> $100 </Copy>
</View>```
import React from 'react';
import PropTypes from 'prop-types';
import SearchIcon from '#material-ui/icons/Search';
import InputBase from '#material-ui/core/InputBase';
import { AccountCircle } from '#material-ui/icons';
import { withStyles, AppBar, Toolbar, Paper, Typography, IconButton } from '#material-ui/core';
const styles = (theme) => ({
root: {
borderRadius: theme.shape.borderRadius * 0.5,
backgroundColor: theme.palette.primary.main,
display: 'flex',
},
logo: {
borderRadius: theme.shape.borderRadius * 0.5,
backgroundColor: theme.palette.secondary.main,
marginTop: theme.spacing.unit * 2,
marginBottom: theme.spacing.unit * 2,
marginLeft: theme.spacing.unit * 3,
marginRight: theme.spacing.unit * 5,
flex: 0.5,
},
logoFont: {
color: theme.palette.primary.main,
fontWeight: 'bolder',
paddingTop: theme.spacing.unit * 0.5,
paddingBottom: theme.spacing.unit * 0.5,
paddingLeft: theme.spacing.unit * 2,
paddingRight: theme.spacing.unit * 2,
},
headerPads: {
paddingTop: theme.spacing.unit * 3,
paddingBottom: theme.spacing.unit * 2,
paddingRight: theme.spacing.unit * 10,
paddingLeft: theme.spacing.unit * 10,
},
containerHorizontalAlignment: {
display: 'flex',
flexDirection: 'row',
justifyContent: 'end',
paddingTop: theme.spacing.unit,
paddingBottom: theme.spacing.unit,
flex: 10,
},
searchBar: {
marginTop: theme.spacing.unit,
marginBottom: theme.spacing.unit,
marginLeft: theme.spacing.unit,
marginRight: theme.spacing.unit * 5,
borderRadius: theme.shape.borderRadius * 0.5,
backgroundColor: theme.palette.secondary.main,
width: 'auto',
/* [theme.breakpoints.up('sm')]: {
marginLeft: theme.spacing.unit,
width: 'auto',
}, */
display: 'flex',
flexDirection: 'row',
},
searchIcon: {
color: theme.palette.primary.main,
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
marginLeft: 20,
height: '100%',
width: theme.spacing.unit * 7,
},
inputRoot: {
color: theme.palette.primary.main,
width: '100%',
},
inputInput: {
transition: theme.transitions.create('width'),
width: 'auto',
[theme.breakpoints.up('sm')]: {
width: '25%', //change it to 250(number)
'&:focus': {
width: '100%', //change it to 1000(number), it will work fine, but I need percentages.
},
},
},
loginButtonContainer: {
flex: 1,
},
loginButton: {
justifyContent: 'right',
marginTop: theme.spacing.unit * 0.5,
color: theme.palette.secondary.main,
},
});
function ExpandingSearchBar(props) {
const { classes} = props;
return (
<div className={classes.headerPads}>
<Paper square className={ classes.root }>
<div className={classes.logo}>
<Typography variant="h5" className={classes.logoFont}>
PlaceHolder
</Typography>
</div>
//Problematic div: the search bar
<div style={{border: '1px solid white'}} className={ classes.containerHorizontalAlignment }>
<div className={classes.searchBar}>
<div className={classes.searchIcon}>
<SearchIcon />
</div>
<InputBase
placeholder='Search'
classes={{
root: classes.inputRoot,
input: classes.inputInput,
}}
/>
</div>
</div>
<div className={classes.loginButton}>
<IconButton className={classes.loginButton}>
<AccountCircle fontSize='large'/>
</IconButton>
</div>
</Paper>
</div>
);
}
ExpandingSearchBar.propTypes = {
classes: PropTypes.object.isRequired,
}
export default withStyles(styles)(ExpandingSearchBar);
Problems:
in styles.inputInput I have create a transition using material-ui's theme.transition.create, the problem is, if the widths are fixed numbers it works fine, if I pass the percentages to it the component just has a fixed width no expansion or transitions at all.
One more problem is if the width searchBar it more than it's parent can accommodate it will no push the 'PlaceHolder' out of Paper but will push the button at the end out of the Paper element and itself will push the itself past the right boundary.
I have used theme.create.transitions() from material-ui but please suggest any solutions using only CSS as well.
Try it here in the sandbox, and switch the browser window of sandbox to full screen.
Thanks
The primary issue was that your "searchBar" div was constraining the meaning of "100%" for your input. The key is to use InputBase for the entire search input which means using a startAdornment for the search icon:
<div className={classes.searchBar}>
<InputBase
startAdornment={<SearchIcon />}
placeholder="Search"
classes={{
root: classes.inputRoot,
focused: classes.inputFocused
}}
/>
</div>
Then there were some adjustments necessary for the styling (moving some styling from searchBar to inputRoot and from inputInput to inputRoot):
searchBar: {
width: "100%",
display: "flex",
flexDirection: "row"
},
inputRoot: {
marginTop: theme.spacing.unit,
marginBottom: theme.spacing.unit,
marginLeft: theme.spacing.unit,
marginRight: theme.spacing.unit * 5,
borderRadius: theme.shape.borderRadius * 0.5,
backgroundColor: theme.palette.secondary.main,
color: theme.palette.primary.main,
transition: theme.transitions.create("width"),
width: "auto",
[theme.breakpoints.up("sm")]: {
width: "25%" //change it to 250(number)
},
"&$inputFocused": {
[theme.breakpoints.up("sm")]: {
width: "100%" //change it to 1000(number), it will work fine, but I need percentages.
}
}
},
inputFocused: {},
Here's a working modification of your sandbox:
I'm using material-ui's JSS implementation to styling classes.
I have a lot of duplicated code when it comes to the components' styles since I have separated my components.
For example, I have cards which all use common styling:
const styles = theme => ({
cardContainer: {
position: 'relative',
width: '50%',
padding: theme.spacing.unit / 2,
},
cardOuter: {
height: '100%',
width: '100%',
textAlign: 'start',
},
card: {
width: '100%',
background: theme.palette.backgrounds.card.off,
},
cardOn: {
background: theme.palette.backgrounds.card.on,
},
cardUnavailable: {
background: theme.palette.backgrounds.card.disabled,
},
cardContent: {
display: 'flex',
flexWrap: 'wrap',
minHeight: 98,
height: 98,
[theme.breakpoints.down('sm')]: {
minHeight: 74,
height: 74,
},
padding: `${theme.spacing.unit * 1.5}px !important`,
},
});
which I would only rarely want to extend upon the styles inside the component, but would like to import these objects into an existing styles function so I do not have to duplicate these objects.
Has anyone or does anyone know how to do this?
Thanks
Figured it out. For future viewers:
const styles = theme => ({
...card(theme),
grid: {
height: '100%',
width: 'fit-content',
paddingLeft: theme.spacing.unit * 2,
paddingRight: theme.spacing.unit * 2,
flexWrap: 'nowrap',
overflowY: 'hidden',
},
name: {
overflow: 'hidden',
textOverflow: 'ellipsis',
fontSize: '1.12rem',
fontColor: theme.palette.text.main,
[theme.breakpoints.down('sm')]: {
fontSize: '0.9rem',
}
},
state: {
textOverflow: 'ellipsis',
margin: '0 auto',
marginTop: theme.spacing.unit / 2,
fontSize: '1.0rem',
fontColor: theme.palette.text.light,
[theme.breakpoints.down('sm')]: {
fontSize: '0.8rem',
}
},
alarmArmedHome: {
background: theme.palette.backgrounds.card.alarm.home,
},
alarmArmedAway: {
background: theme.palette.backgrounds.card.alarm.away,
},
alarmTriggered: {
background: theme.palette.backgrounds.card.alarm.triggered,
},
icon: {
margin: '0 auto',
color: theme.palette.text.icon,
fontSize: '2.7rem',
[theme.breakpoints.down('sm')]: {
fontSize: '1.7rem',
}
},
});
card.js
const styles = (theme) => ({
cardContainer: {
position: 'relative',
width: '50%',
padding: theme.spacing.unit / 2,
},
cardOuter: {
height: '100%',
width: '100%',
textAlign: 'start',
},
card: {
width: '100%',
background: theme.palette.backgrounds.card.off,
},
cardOn: {
background: theme.palette.backgrounds.card.on,
},
cardUnavailable: {
background: theme.palette.backgrounds.card.disabled,
},
cardContent: {
display: 'flex',
flexWrap: 'wrap',
minHeight: 98,
height: 98,
[theme.breakpoints.down('sm')]: {
minHeight: 74,
height: 74,
},
padding: `${theme.spacing.unit * 1.5}px !important`,
},
});
export default styles;
So you pretty much have to join the objects passing in the theme if required:
...card(theme),
I’m having trouble aligning two components within another div in React. I’m using relative positioning for the parent div (snippetButtonHolder) and absolute positioning for its children (snippet and button). I want snippet to be centered in the parent and button to be under snippet and to the right, but for some reason when I use these attributes they are positioned relative to the entire page, not to the parent div. Does anyone have a suggestion as to what I should do differently?
const styles = {
module: {
marginTop: '30px',
padding: '20px',
},
snippet: {
backgroundColor: '#f2f2f2',
border: 'solid 1px #ccc',
borderRadius: '4px',
margin: '0 auto',
padding: '10px',
width: '100%',
position: 'absolute',
left: '50%',
},
snippetButtonHolder: {
width: '95%',
position: 'relative',
},
button: {
float: 'right',
marginTop: '5px',
position: 'absolute',
left: '94%',
},
};
export default class CodeSnippet extends Component {
constructor(props) {
super(props);
}
render() {
return (
<div style={styles.module}>
<div style={styles.snippetButtonHolder}>
<div style={styles.snippet}>
<div
{'text will go here'}
</div>
{this.state.showButton ?
<button
style={styles.button}>
Press me
</button>
: null}
</div>
</div>
</div>
);
}
}
Give this a try:
const styles = {
module: {
marginTop: '30px',
padding: '20px',
},
snippet: {
backgroundColor: '#f2f2f2',
border: 'solid 1px #ccc',
borderRadius: '4px',
display: 'inline-block',
overflow: 'hidden',
padding: '10px',
},
snippetButtonHolder: {
textAlign: 'center',
width: '95%',
},
button: {
float: 'right',
marginTop: '5px',
},
};