This is a solution to the Intro section with dropdown navigation challenge on Frontend Mentor. Frontend Mentor challenges help you improve your coding skills by building realistic projects.
Users should be able to:
- View the relevant dropdown menus on desktop and mobile when interacting with the navigation links
- View the optimal layout for the content depending on their device's screen size
- See hover states for all interactive elements on the page
- Solution URL: https://github.com/EthanChenYen-Peng/frontend-pratice-Intro-section-with-dropdown-navigation
- Live Site URL: https://frontend-pratice-intro-section-with-dropdown-navigation.vercel.app/
- Flexbox
- Mobile-first workflow
- React - JS library
- TailwindCSS - For styles
The trickiest bit of the project is the dropdown menu in the mobile navbar.
Given that links and content within each dropdown menu are more likely to change, separating the data source from its presentation makes sense.
Here I extracted the data source into its own module, src/utils/navlinks.js
, which is used in both mobile and desktop navbar.
import todoIcon from '../../images/icon-todo.svg'
import calendarIcon from '../../images/icon-calendar.svg'
import reminderIcon from '../../images/icon-reminders.svg'
import planningIcon from '../../images/icon-planning.svg'
export const featuresNavLinks = [
[todoIcon, 'Todo List'],
[calendarIcon, 'Calendar'],
[reminderIcon, 'Reminder'],
[planningIcon, 'Planning'],
]
export const companyNavLinks = ['Histroy', 'Our team', 'Blog']
I attempted the render props pattern to build the dropdown menu container for better component reuse.
MobileDropdownLink
: is responsible for animation and handling user events (open and close).
CompanyLinks
and FeatureDropdownLinks
: are responsible for presenting navigation links.
import { companyNavLinks, featuresNavLinks } from '../utils/navlinks'
import MobileDropdownLink from './MobileDropdownLink'
function FeatureDropdownLinks() {
return (
<>
{featuresNavLinks.map(([icon, item]) => (
<li key={item} className="flex min-w-max items-center gap-4 pl-8">
<img src={icon} className="w-4" />
<span className="text-sm font-thin">{item}</span>
</li>
))}
</>
)
}
function CompanyLinks() {
return (
<>
{companyNavLinks.map((item) => (
<li key={item} className="flex min-w-max items-center gap-4 pl-8">
<span className="text-sm font-thin">{item}</span>
</li>
))}
</>
)
}
function MobileOverlay({ menuOpen }) {
return (
<div
className={`${
menuOpen ? 'translate-x-0' : 'translate-x-full'
} fixed top-0 bottom-0 right-0 left-0 bg-almost-black opacity-80 transition-transform duration-500 ease-in-out desktop:hidden`}
></div>
)
}
function MobileMenu({ menuOpen }) {
return (
<>
<MobileOverlay menuOpen={menuOpen} />
<div
className={`${
menuOpen ? 'translate-x-0' : 'translate-x-full'
} fixed top-0 bottom-0 right-0 w-8/12 bg-almost-white px-6 transition-transform duration-500 desktop:hidden`}
>
<ul className="mt-32 flex flex-col gap-5 text-xl text-medium-gray">
<MobileDropdownLink
title="Features"
render={() => <FeatureDropdownLinks />}
/>
<MobileDropdownLink title="Company" render={() => <CompanyLinks />} />
<li>Careers</li>
<li>About</li>
</ul>
<ul className="mt-10 flex flex-col items-center gap-5 text-medium-gray">
<li>Login</li>
<li className="rounded-2xl border-2 py-2 px-7">Register</li>
</ul>
</div>
</>
)
}
export default MobileMenu
- https://tailwindcss.com/docs/configuration - This helped me with configure custom color theme and breakpoints when using TailwindCSS.
- https://www.patterns.dev/posts/render-props-pattern/ - More about
render props
pattern.
- Website - https://www.ypcethan.com/
- Frontend Mentor - https://www.frontendmentor.io/profile/EthanChenYen-Peng