It's a frontend dev portfolio project (FrontEnd mentor challenge). Build in React using isolated components to the best of my current ability, deployed to Netlify.
From the FrontEnd Mentor challenge description:
Your users should be able to:
- Click the "About Me" call-to-action on the homepage and have the screen scroll down to the next section
- Receive an error message when the contact form is submitted if:
- The Name, Email Address or Message fields are empty should show "This field is required"
- The Email Address is not formatted correctly should show "Please use a valid email address"
- View the optimal layout for the interface depending on their device's screen size
- See hover and focus states for all interactive elements on the page
Despite I could easily build it in vanilla JS, I decided to push myself to practice React, routing and isolated components.
- React (using React Router)
- SCSS and Bootstrap
- Isolated components (CSS modules library)
I've been reading about frontend architecture called atomic design and the principle really stick to me, because when left unchecked CSS styles can quickly get very messy. I wanted to put this principle into practice, starting with isolated components.
- Introduction to what CSS modules are
- How to deal with multiple classes using CSS modules
- GH repo with the library
What I quickly learned:
- BEM naming practices don't really work here, either using "--" for variantions or kebab-case caused errors, so I had to rename all the classes to use underscores instead.
.box--red {
BAD (compilation errors)
}
.box-red {
still BAD (doesn't compile)
}
.box__red {
GOOD (compiles)
}
- when using multiple classes in JSX one has to precede the className declaration with the dollar sign and basically template literals syntax. Like this:
<header className={`${styles.home__intro} ${styles.padding_2}`}>
As it turned out (I learned it by chance upon watching this video) styles in css.modules are a JavaScript object. And this explains why -
are not accepted in the class names and why we need template literals for declaring multiple classes on an element. Voila!
To move from one component to another. I used if for the page which displays details of each project and has those two buttons at the bottom. useNavigate
helps to go to the specific URL, forward or backward pages.
const navigate = useNavigate()
navigate('/')
Useful hook to render a component based on the path. I am conditionally rendering the CTA component: it is displayed on every page BUT the /contact
.
How to set it up:
{/* define the location in question */}
const location = useLocation();
const isContactPage = location.pathname === "/contact";
{/* ... */}
return (
<Routes>
{/* ... */}
{!isContactPage && <CTA />}
{/* ... */}
</Routes>
)
When using this the <Router>
has to wrap the whole <App>
.
- FrontEnd Mentor - design
- Freepik/Flaticon - icon for the favicon
- Favicon converter - generated favicon pack
- Form Bold - free form backend
Needs work, but I don't know how to improve it. Can it be blamed on create-react-app
?