1

I'm building an app with Meteor, React and Material-UI. I have a custom left nav component based on Drawer.

class LeftNav extends Component {

    constructor(props){
        super(props);
    }

    render() {

        return (
            <Drawer open={this.props.open}
                            docked={false}
                            onRequestChange={this.props.handleOnRequestChange}
            >
                <Card >
                    <CardMedia overlay={<div><Avatar src='avatar.png' size={50}  style={styles.avatar} /> <CardTitle title="Phil Cruz" subtitle="phil@philcruz.com" titleColor={darkWhite} subtitleColor={lightWhite}/></div>} >
                        <img src="/left_nav_wallpaper.jpg" />
                    </CardMedia>
                </Card>
                <MenuItem primaryText="testdomain1.com" leftIcon={<ActionGrade />}  />
                <MenuItem primaryText="testdomain2.com" leftIcon={<ActionHttp />}/>
                <MenuItem primaryText="Add site..." leftIcon={<ContentAdd />} />
                <Divider />
                <MenuItem primaryText="Settings" leftIcon={<Settings />} />
                <MenuItem primaryText="Help & About" leftIcon={<HelpOutline />} />
        </Drawer>
        );
    }
};

I want to make it so it behaves like the Google InBox left nav/drawer. It has 3 sections: The top with the cover image and avatar, middle section and the bottom section.

enter image description here

I want the same behavior where:

  • the bottom menu items are fixed to the bottom (in red in the below image)
  • the top section can scroll

How can I do that?

philcruz
  • 8,265
  • 5
  • 25
  • 28
  • Is it okay if i give a HTML based solution because I can't use material ui in the snippet. So, using the HTML you can structure your material-ui components? – Pranesh Ravi Oct 29 '16 at 15:39

1 Answers1

3

By reading these questions/answers:

How to create a sticky footer inside the LeftNav?

Get viewport/window height in ReactJS

Reactjs - Rerender on browser resize

I was able to come up with a solution. Basically, you need to put the content in 2 divs. Use absolute positioning in the bottom div to make it fixed to the bottom. You then need to calculate the height of the top div based on the height of the window minus the height of the footer div. Listen to the resize window event so you can update the div height manually as the browser is resized.

Here's the code:

class LeftNav extends Component {

    constructor(props){
        super(props);
        this.state = { };
        this.updateDimensions = this.updateDimensions.bind(this);
    }

    componentDidMount(){
            this.updateDimensions();
            window.addEventListener("resize", this.updateDimensions);
    }

    updateDimensions() {
        this.setState({
            height: window.innerHeight,
            footerHeight: document.getElementById('leftNavFooter').clientHeight
         });
    }

    render() {

        return (
            <Drawer open={this.props.open}
                            docked={false}
                            onRequestChange={this.props.handleOnRequestChange}
            >
            <div style={{overflowY: 'auto', overflowX: 'hidden', height: (this.state.height - this.state.footerHeight) + 'px'}}>
                <Card >
                    <CardMedia overlay={<div><Avatar src='avatar.png' size={50}  style={{ marginLeft: 16 }} /> <CardTitle title="Phil Cruz" subtitle="phil@philcruz.com" titleColor={darkWhite} subtitleColor={lightWhite}/></div>} >
                        <img src="/left_nav_wallpaper.jpg" />
                    </CardMedia>
                </Card>
                <Menu>
                    <MenuItem primaryText="testdomain1.com" leftIcon={<ActionGrade />}  />
                    <MenuItem primaryText="testdomain2.com" leftIcon={<ActionHttp />}/>
                    <MenuItem primaryText="Add site..." leftIcon={<ContentAdd />} />
                </Menu>
            </div>
            <div id="leftNavFooter" style={{position: 'absolute', bottom: 0, width: '100%', overflow: 'hidden'}}>
                <Divider />
                <Menu>
                    <MenuItem primaryText="Settings" leftIcon={<Settings />} />
                    <MenuItem primaryText="Help & About" leftIcon={<HelpOutline />}  />
                </Menu>
            </div>
            </Drawer>
        );
    }
};
philcruz
  • 8,265
  • 5
  • 25
  • 28
  • What is `styles.avatar` in `style={styles.avatar}`? Where is it defined? What is the value? – Joerg Aug 29 '17 at 14:05
  • 1
    styles.avatar is simply a style object to define some left margin. I replaced the reference to style.avatar with a literal object to clarify. – philcruz Aug 30 '17 at 15:16
  • Thanks for your awesome guide. I upvoted both posts. really thanks. – AmerllicA Feb 26 '21 at 11:07