Skip to content

Instantly share code, notes, and snippets.

@bnorton

bnorton/menu.jsx Secret

Last active April 28, 2025 20:09
Show Gist options
  • Save bnorton/be30b6e7d7f8dc1f0493e732f0540eae to your computer and use it in GitHub Desktop.
Save bnorton/be30b6e7d7f8dc1f0493e732f0540eae to your computer and use it in GitHub Desktop.
Frontend engineer @ Chameleon | Technical exercise: Menu system
/*
Thanks for your interest in a Frontend engineering role at Chameleon. We're a solid and collaborative team that
will always lend a helping hand. We prioritize asynchronousity in nearly all of our ways of working.
This exercise is meant to be a focused, high signal ~hour. Assume that if we've asked about it it's important to us. We will
evaluate your React skills, your general understanding of JavaScript, your creativity, organization, etc.
Prompt:
0. How are you today? 😊
1. Below are the parts of a basic selection menu, but there are issues and it's too specific for the single
current use case. We all more or less agree it's not that great and needs some attention. It should be
componentized/generalized so that other engineers on the team can use selection menus. We will evaluate your React
skills, your general understanding of JavaScript, your creativity, organization and clarity on communication
2. The following items (3,4,5) combined are intentionally sightly vague in the sense there’s often more than a single
possible/correct solution — a natural aspect of software engineering. Please consider possible implementation paths
you'd consider valid and pick the best one.
3. Now, make improvements to the menu; add the ability to load the contents from the backend (e.g. via `httpGet('/widgets')`)
and in the end it should meet the prompt including to be used in at least a couple different use cases
such as an Account picker, a searchable list of items, one step of a flow to configure Alerting, etc...
4. For certain use cases we would want to sync the menu selection to the server. We have an abstraction for syncing called
httpPatch. It can be used like this => httpPatch('user', { [`menu-state-${key}`]: {true,false} }). Where would this
be included and how/where best to handle this (properties needing to be synced/loaded to the backend)?
5. Assuming others will use/add to this component in the future, write a 2-3 sentence "release note"
to post into the #engineering channel in Slack (or add to the Components wiki page).
PS: No need to worry about CSS, actually making it "run" etc...
Now put youself in PR review mode...
1. Please provide a couple Pull Request comments/suggestions to the engineer who wrote the code
in pr-1.js and the other engineer who wrote pr-2.js; assume you're codeowner for the project on GitHub.
2. Identify any logic issues or things that you would consider necessary before this is released.
3. Based on what you know from 1., how would you do this differently if you were
to make these components from scratch?
*/
import React, { useState } from 'react';
import { httpGet, httpPatch } from 'lib/http';
export const Dropdown = ({ label }) => {
const [isOpen, setIsOpen] = useState(false);
httpGet(`users/${userId}`).then(d => { setIsOpen(user[`dropdown_${name}`]) });
const onToggle = (e) => {
setIsOpen(isOpen);
}
return (<>
<div className="dropdown">
<button type="button" className="dropdown-button" id="dropdownButton" aria-haspopup="true" aria-expended={isOpen} onClick={onTggle}>{label}</button>
<ul className={`${isOpen ? 'dropdown-open' : ''} dropdown-menu dropdown-section`} aria-labelledby='dropdownButton' role="menu">
<div>Items</div>
<a href="/page1">Page 1</a>
<DropdownItem href="/page2">Page 2</DropdownItem>
<DropdownItem href="/page3">Page 3</DropdownItem>
<DropdownItem href="/page4">Page 4</DropdownItem>
</ul>
<ul className={`${isOpen ? 'dropdown-open' : ''} dropdown-menu dropdown-section`}>
<div>More items</div>
<DropdownItem href="/page5">Page 5</DropdownItem>
<DropdownItem href="/page9">Page 9</DropdownItem>
</ul>
</div>
</>);
}
const DropdownItem = ({ }) => {
return '??'; // what should go here?
}
window.currentUser = { id: '19', name: 'Jane', email: '[email protected]' };
// users are like authors and profiles like commentors
// open a modal with commentor info when clicked
...
export const ActiveProfiles({ profiles, onLaunchProfile }) => {
var active = [];
for(i=0; i < profiles.length; i++) {
if(!profiles[i].disabled && profiles[i]['last_seen_time'] > new Date(new Date().getTime()-(24*60*1000)).toISOString()) { // within the last 24 hours
active.push(profiles[i]);
}
}
if(active.length == 1 && active[0].email === window.currentUser.email) {
active.length = 0;
}
return (
<div>
{active.map(function(a) { return <div onClick={() => onLaunchProfile(a.name, a.email)}>{a.name} - {a.email}</div> })}
</div>
)
}
// Example usage:
<UserLoggedInOrNotMenu handleLogin={() => httpRedirectTo('https://www.chmln.co/login?return_to=app')} />
// ---------
import React, { useState, useEffect } from 'react';
import { httpGet, httpRedirectTo } from 'lib/http';
const Menu = () => (
<ul>
<li>Home</li>
<li>{user.firstName}'s Profile</li>
<li>Settings</li>
<li>Logout</li>
</ul>
);
const LoginButton = ({ onLogin }) => (
<a onClick={onLogin}>Log In</a>
);
const UserLoggedInOrNotMenu = ({ handleLogin }) => {
const [isLoggedIn, setIsLoggedIn] = useState(false);
const [loading, setLoading] = useState(true);
useEffect(() => {
httpGet('users/ping').then(({ user }) => setIsLoggedIn(!!user.id),setLoading(false));
}, []);
if (loading) {
return <div>Loading...</div>;
}
return (
<div>
{isLoggedIn ? <Menu /> : <LoginButton onLogin={handleLogin} />}
</div>
);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment