Skip to content

Instantly share code, notes, and snippets.

@Mohsenpoureiny
Created February 10, 2022 11:56
Show Gist options
  • Save Mohsenpoureiny/0f81aed6dcfb45e7e2d65215eda31255 to your computer and use it in GitHub Desktop.
Save Mohsenpoureiny/0f81aed6dcfb45e7e2d65215eda31255 to your computer and use it in GitHub Desktop.
simple Chameleon dropdown
/*
Prompt:
We have defined a basic dropdown via the Dropdown and DropdownItem components below, with example usage
in the ExampleNav component. The Dropdown and DropdownItem components have some problems, and also
have room for improvements (doesn't everything?) A couple items TODO here (make sure to explain with comments!)
0. How are you today? 😊
1. Please fix any obvious issues you see with the dropdown and then save your gist.
2. Please then make improvements to the dropdown dnd then save your gist again.
3. Consider the different ways that this dropdown might be used and what changes would
be neccessary to make it more flexible.
4. If we wanted to sync the dropdown selection to a server with this hypothetial "syncing library"
`app.sync('PATCH', 'users/'+app.USER.id, { dropdown_1_state: {true,false} })` where would this be included? Should
the state be read again from the server to show the dropdown open/closed on page load?
5. If we wanted to pass children (like this example) OR a Promise that resolves to an array of items
what changes should be made? (just a sentence or two or some code is ok).
PS: No need to worry about CSS or about making it actually run.
*/
import React, { PureComponent } from 'react';
import "./style.scss";
const pageItems = [
{
label: "More items",
pages: [
{
title: "Page 2",
href: "/page2",
},
{
title: "Page 3",
href: "/page3",
},
{
title: "Page 4",
href: "/page4",
},
],
},
{
label: "Even more items",
pages: [
{
title: "Page 5",
href: "/page5",
},
{
title: "Page 6",
href: "/page6",
},
],
},
];
class Dropdown extends PureComponent {
constructor(props) {
super(props);
this.state = {
isOpen: false,
};
}
toggleDropDownItems() {
const { isOpen } = this.state;
this.setState({ isOpen: !isOpen });
}
render() {
const { isOpen } = this.state;
const { label } = this.props;
return (
<div className="dropdown">
<button type="button" className="dropdown-button" id="dropdownButton" aria-haspopup="true" aria-expended={isOpen} onClick={() => {
this.toggleDropDownItems();
}}>{label}</button>
<ul className={`${isOpen ? 'dropdown-open' : ''} dropdown-menu`} aria-labelledby="dropdownButton" role="menu">
{this.props.children}
</ul>
</div>
);
}
}
class DropdownItem extends PureComponent {
render() {
return <a className="nav-link lg" href={this.props?.href}>{this.props.children}</a>
}
}
class App extends PureComponent {
constructor(props) {
super(props);
this.state = {
isOpen: false,
};
}
render() {
console.log(pageItems);
return (
<nav className="nav">
<a className="nav-link lg" href="/page1">Page 1</a>
{pageItems.map((drpDwn, index) => {
return <Dropdown className="dropdown" key={index} label={drpDwn.label}>
{drpDwn.pages.map((drpDwnItem, index) => {
return <DropdownItem key={index} href={drpDwnItem.href}>{drpDwnItem.title}</DropdownItem>
})}
</Dropdown>
})}
</nav>
);
}
}
export default App;
// variables
$primary:#655D8A;
$primary-hover:#8b81b8;
$secondary:#7897AB;
$link: #D885A3;
$warning:#FDCEB9;
$white:#fff;
$border-radius: 8px;
// global
*{
font-family: sans-serif , 'Segoe UI', Tahoma, Geneva, Verdana;
}
// nav
.nav{
display: flex;
flex-direction: row;
justify-content: start;
align-items: center;
width: 100%;
background-color: $warning;
border-radius: $border-radius;
padding: 5px 10px;
a.nav-link{
background-color: $primary;
border-radius: $border-radius;
border-style: solid;
border-width: 2px;
border-color: $link;
color: $white;
margin: 3px 0;
text-decoration: none;
transition: background-color ease-in-out 0.2s;
&.lg{
padding: 10px 15px;
}
&:hover{
background-color: $primary-hover;
}
}
.dropdown{
position: relative;
.dropdown-menu{
position: absolute;
display: flex;
opacity: 0;
flex-direction: column;
background-color: $secondary;
border-radius: $border-radius;
transition: all ease-in-out 0.2s;
padding: 3px 7px;
width: 150px;
&.dropdown-open{
opacity: 1;
}
}
}
}
.dropdown-button{
border-radius: $border-radius;
border-style: solid;
border-width: 2px;
border-color: $link;
padding: 10px 15px;
margin: 3px 0;
text-decoration: none;
transition: background-color ease-in-out 0.2s;
margin: 0 5px;
cursor: pointer;
&.btn-primary{
background-color: $primary;
color: $white;
}
&:hover{
background-color: $primary-hover;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment