dev
dev

Reputation: 257

Applying css transition to width of an element so that it covers the 100% width of its container div [ReactJS]

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:

  1. 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.

  2. 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

Upvotes: 0

Views: 2222

Answers (1)

Ryan Cogswell
Ryan Cogswell

Reputation: 80996

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:

Edit Search Grow on Focus

Upvotes: 1

Related Questions