Skip to content
This repository has been archived by the owner on Jun 24, 2021. It is now read-only.

Web/navbar hide #41

Merged
merged 18 commits into from Aug 13, 2018
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions web/.eslintrc.json
Expand Up @@ -11,6 +11,7 @@
"jest"
],
"rules": {
"no-return-assign": 0,
"no-param-reassign": 0,
"import/prefer-default-export": 0,
"prefer-template": 0,
Expand Down
Binary file removed web/assets/logo.png
Binary file not shown.
34 changes: 34 additions & 0 deletions web/assets/logo.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion web/components/Main.js
@@ -1,5 +1,5 @@
import React from 'react';

const Main = () => (<div>HOME PAGE</div>);
const Main = () => (<div className="pad-nav">HOME PAGE</div>);

export default Main;
2 changes: 1 addition & 1 deletion web/components/application/hacker/Hacker.js
Expand Up @@ -7,7 +7,7 @@ const HackerApplication = (props) => {
const { hackerApplication } = props;
if (!hackerApplication.isLoaded) return (<div />);
if (hackerApplication.data) return (<Redirect to="/dashboard" />);
return (<div className="below-nav">o hello there pls apply</div>);
return (<div className="pad-nav">o hello there pls apply</div>);
};

const mapStateToProps = (state) => {
Expand Down
2 changes: 1 addition & 1 deletion web/components/dashboard/index.js
Expand Up @@ -12,7 +12,7 @@ const DashBoard = (props) => {
content = 'you didn\'t apply as hacker';
}

return (<div className="below-nav">{content}</div>);
return (<div className="pad-nav">{content}</div>);
};

const mapStateToProps = (state) => {
Expand Down
1 change: 1 addition & 0 deletions web/components/demo/Demo.sass
@@ -1,3 +1,4 @@
div#demo
width: 50%
margin-left: 25%
height: 90000000px
2 changes: 1 addition & 1 deletion web/components/demo/index.js
Expand Up @@ -34,7 +34,7 @@ class FrontEndComponents extends React.Component {

const { active } = this.state;
return (
<div id="demo">
<div id="demo" className="pad-nav">
<p>Buttons</p>
<br />
<div>
Expand Down
40 changes: 9 additions & 31 deletions web/components/navbar/Navbar.sass
@@ -1,43 +1,21 @@
nav
display: flex
background: $white
box-shadow: 0px 4px 6px $shadow
z-index: 500
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

curious, why is this needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This keeps the navbar above all other elements, so long as we avoid using z-index elsewhere

background: $transparent-white
height: 64px
position: fixed
width: 100%
transition: background $transition-time-long, shadow $transition-time-long, opacity $transition-time

> div
display: inline-flex
> div:last-of-type
width: 80%
justify-content: flex-end
> div:first-of-type
width: 20%
justify-content: flex-start
> div > div
display: flex
margin-top: 12px
margin-bottom: 12px
align-items: center
margin-right: 7.5%
> div > div:first-of-type
margin-left: 24px
> div > div:last-of-type
margin-right: 24px
a
display: flex
align-items: center
text-decoration: none
font-family: Apercu Pro
font-size: 18px
color: $primary
a:visited
color: $primary

a:hover
color: #00D5D5
img
margin-top: 3px
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

spaces should always be multiples of 4 - can you change this to 4px? If the design said 3px that should be an error in design. @sherryyx can you confirm?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a hack because the logo looked slightly off :(

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

4px looks fine too though - I'll make this change

width: 32px

.below-nav
padding-top: 64px
&.transparent
background: transparent

&.hide
opacity: 0
125 changes: 88 additions & 37 deletions web/components/navbar/index.js
@@ -1,13 +1,14 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Link } from 'react-router-dom';
import { DISPLAY_TYPE } from '../../containers/navbar/DisplayTypes';
import { BUTTON_TYPE } from '../../containers/navbar/ButtonTypes';
import { SecondaryButton } from '../input/buttons';

import logo from '../../assets/logo.png';
import logo from '../../assets/logo.svg';

const getLogo = () => (
<Link to="/"><img alt="" src={logo} /></Link>
<Link to="/"><img alt="nwHacks" src={logo} /></Link>
);

const getButton = (buttonType) => {
Expand All @@ -23,43 +24,93 @@ const getButton = (buttonType) => {
}
};

const Navbar = ({ displayType, buttonType }) => {
switch (displayType) {
case DISPLAY_TYPE.ONLY_LOGO:
return (
<nav>
<div>
<div>{getLogo()}</div>
</div>
</nav>
);
case DISPLAY_TYPE.LOGO_AND_BUTTON:
return (
<nav>
<div>
<div>{getLogo()}</div>
</div>
<div>
<div>{getButton(buttonType)}</div>
</div>
</nav>
);
default:
return (
<nav>
<div>
<div>{getLogo()}</div>
</div>
<div>
<div><Link to="/">About</Link></div>
<div><Link to="/">FAQ</Link></div>
<div><Link to="/">Sponsors</Link></div>
<div><Link to="/">2018</Link></div>
<div>{getButton(buttonType)}</div>
class Navbar extends React.Component {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe you need to add a componentShouldUpdate lifecycle method to update the state when new props are passed into this component.

Right now the component is not updating based on incoming props. Reproduction steps:

  • Make sure you're logged out
  • Go to /
  • Refresh and it should have logo, links, and login button
  • Click "login" button
  • The navbar still has logo, links, and login button
  • Refresh
  • The navbar is updated to just have logo

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't repro anymore after f66d3b0 - let me know if it works when you get the chance!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I can't reproduce it anymore. But wouldn't it be better to have displayType and buttonType in the state? The only reason why this component re-renders properly is because its container is re-rendering itself. If for some reason the container does not re-render itself, but the props change, then this component wouldn't re-render.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, I’ll have a closer look at this tonight

Copy link
Contributor Author

@bobheadxi bobheadxi Aug 12, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mingyokim sorry, I'm not sure I understand - doesn't a prop change force the container to re-render? From what I understand, displayType and buttonType are only manipulated from here, and the navbar itself does not change them:

https://github.com/nwhacks/nwhacks2019/blob/master/web/containers/navbar/index.js#L57

It also seems like setting props that a component doesn't manipulate into state is somewhat bad practice (https://stackoverflow.com/a/47341539), but there also seems to be some other APIs for doing this kind of stuff (https://stackoverflow.com/a/49839457, https://stackoverflow.com/a/32414771)... though to be honest this seems to be kind of murky territory, since from what I understand, this type of stuff should just be kept in props (https://stackoverflow.com/a/40330195). I could be missing something though...

Copy link
Contributor Author

@bobheadxi bobheadxi Aug 13, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Officially, react only distinguishes between class and function (potentially stateful and stateless respectively), and:

The above two components are equivalent from React’s point of view.

https://reactjs.org/docs/components-and-props.html#functional-and-class-components

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so props do cause a render on stateful components? oops i was mistaken, it's all good then

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar question: https://www.reddit.com/r/reactjs/comments/7tn79g/state_and_componentwillreceiveprops/

class Foo extends Component {
  state = { value: this.props.value }

  // If the props change, update state
  componentWillReceiveProps (nextProps) {
    if (nextProps.value !== this.props.value) {
      this.setState({ value: nextProps.value })
    }  
  } 

  render () {
    // render based on state.value
  }
}

Top response:

Why you don't render props directly?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An update can be caused by changes to props or state.

https://reactjs.org/docs/react-component.html

Okay, so clearly change in props cause a re-render, reactjs says so. My bad lol

If this is the case, definitely use props rather than state because the component is not modifying the buttonType or displayType, they're just displaying it.

Approving

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll just do one last sanity check

constructor(props) {
super(props);
const { displayType, buttonType } = props;
this.state = {
displayType,
buttonType,
hidden: false,
transparent: true,
lastY: 0,
};
}

componentDidMount() {
window.addEventListener('scroll', this.handleScroll, { passive: true });
}

componentWillUnmount() {
window.removeEventListener('scroll', this.handleScroll);
}

handleScroll = () => {
// Calculate scroll direction
const { lastY } = this.state;
const scrollingDown = (window.scrollY - lastY) >= 0;

// Calculate position
const offset = window.pageYOffset || document.documentElement.scrollTop;
const atTop = offset < 96;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we store 96 into some kind of variable?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure - 96 is in the CSS as navbar height, but I’ll replicate it here


// Calculate transparency
const transparent = scrollingDown ? offset < 256 : atTop;

// Update state
this.setState({
transparent,
hidden: (!atTop && scrollingDown),
lastY: window.scrollY,
});
}

render() {
const { displayType, buttonType, hidden, transparent } = this.state;
const button = getButton(buttonType);
const links = [
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cleaann but can we name this something like linksAndButton? it doesn't just have links

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True!

<Link to="/"><b>About</b></Link>,
<Link to="/"><b>Stories</b></Link>,
<Link to="/"><b>FAQ</b></Link>,
<Link to="/"><b>Sponsors</b></Link>,
<Link to="/"><b>2018</b></Link>,
button,
];

let linksDiv;
let key = 0;
switch (displayType) {
case DISPLAY_TYPE.ONLY_LOGO:
break;
case DISPLAY_TYPE.LOGO_AND_BUTTON:
linksDiv = <div className="flex ai-center">{button}</div>;
break;
default:
linksDiv = links.map(l => (
<div
key={key += 1}
className="flex ai-center margin-sides-large">
{l}
</div>
</nav>
);
));
}

return (
<nav className={`fill-width flex ${hidden ? 'hide' : ''} ${transparent ? 'transparent' : 'shadow'}`}>
<div className="flex ai-center jc-start margin-sides">
<div className="flex ai-center">{getLogo()}</div>
</div>
<div className="flex jc-end margin-horizontal-divs fill-width">
{linksDiv}
</div>
</nav>
);
}
}

Navbar.propTypes = {
displayType: PropTypes.symbol,
buttonType: PropTypes.symbol,
};

export default Navbar;
3 changes: 3 additions & 0 deletions web/containers/navbar/index.js
Expand Up @@ -16,6 +16,9 @@ const getDisplayType = (location) => {

let displayType = DISPLAY_TYPE.ONLY_LOGO;

// For demo only - todo: remove
if (pathname === '/ui_demo') return DISPLAY_TYPE.LOGO_BUTTON_AND_LINKS;

if (isHomePage) {
displayType = DISPLAY_TYPE.LOGO_BUTTON_AND_LINKS;
} else if (isDashBoardPage) {
Expand Down
1 change: 1 addition & 0 deletions web/styles/animations.sass
@@ -1,4 +1,5 @@
$transition-time: .2s
$transition-time-long: 1.5s

// This is a hack to allow transitions of linear-gradient backgrounds.
// https://medium.com/@dave_lunny/animating-css-gradients-using-only-css-d2fd7671e759
Expand Down
1 change: 1 addition & 0 deletions web/styles/colors.sass
Expand Up @@ -5,6 +5,7 @@ $grey-light: #BDBDBD
$grey-slate: #9195A5

/* classes */
$transparent-white: rgba(255,255,255, 0.85)
$error: #EB5757 // figma "red"
$error-dark: #D41818 // figma "dark red"
$primary: #21258A // figma "body text"
Expand Down
31 changes: 31 additions & 0 deletions web/styles/utils.sass
Expand Up @@ -11,6 +11,9 @@

// padding declarations
.pad
&-nav
padding-top: 64px

&-sides
padding-left: 44px
padding-right: 44px
Expand All @@ -21,24 +24,52 @@

// margin declarations
.margin
&-sides
margin-left: 24px
margin-right: 24px
&-large
margin-left: 36px
margin-right: 36px

&-ends
margin-top: 12px
margin-bottom: 12px

&-text-inputs
> .text-input
&:first-of-type
margin-bottom: 40px
&:last-of-type
margin-bottom: 56px

&-horizontal
&-divs
> div
&:first-of-type
margin-left: 24px
&:last-of-type
margin-right: 24px

// flexbox utility classes
.flex
display: flex

&-inline
display: inline-flex

// flex-directions
&.dir
&-col
flex-direction: column

// justify-content
&.jc
&-start
justify-content: flex-start

&-end
justify-content: flex-end

&-center
justify-content: center

Expand Down