
Invoice App - ReactJS, Styled-Components, Framer Motion, Webpack
Design comparison
Solution retrospective
Hello👋!
This is an invoicing application build with ReactJS and styled-components. The application is used to manage invoices and allows the user to create, read, update, filter by status and delete invoices. There is an option in the app to switch between a dark and a light theme. All transitions are smoothly displayed by using Framer Motion library to create animations. It was by far the largest and most comprehensive project I have done so far. It showed me how important it is to plan so that you don't have to change things that previously worked well in the middle of the project. A valuable lesson!
- The first time I used
useReducer
hook to manage application state. I noticed that my state logic getting more complex as the few elements of my state relies on the value of another element of my state. Read More - Together with useReducer, the
useContext
hook turned out to be handy. It allowed me to create common data that can be accessed throughout the component hierarchy without passing the props down manually to each level which in turn allowed me to avoid Prop drilling (also called "threading") that is the process you have to go through to get data to parts of the React Component tree. Read More(1). Read More(2) - In order to create a theme switcher and provide colors for components I used styled-components
<ThemeProvider>
wrapper component. By leveraging the theme provider I only need to write my styles in one single object and invoke them in any component that is a descendant of that provider. Read More - When creating the form I learned what Controlled Component is. In HTML, form elements such as
<input>
,<textarea>
, and<select>
typically maintain their own state and update it based on user input. In React, mutable state is typically kept in the state property of components, and only updated withsetState()
. Then the React component that renders a form also controls what happens in that form on subsequent user input. Read More - To make application more
ADA compliant
(which means the website should be entirely accessible using just keyboard) I prevent focus go outside the modal once the modal is opened. In this case, the focus trap turns on when the form or modal with invoice deletion/status change is opened. In order to create an accessible modal I followed this great tutorial that follow the WAI-ARIA Practices. - To animate the pages transitions and modals I used Framer Motion API. Framer Motion is an open source, production-ready library that's designed for creating creative animations. In order to support users who have enabled their device’s Reduced Motion setting and make accessible animations I used
useReducedMotion
hook. Based on whetheruseReducedMotion
returnstrue
or not we're passing different values toanimate
. That replace position transitions with opacity. Read More(1). Read More(2) - Handle 404 routes in React Router and provide a fallback component for displaying an imfamous
404 Page Not Found
error to the user. Try to enter a page that doesn't exist - like 'invoice-tediko.netlify.app/gotcha'
You can find more about the things I used in the project in the README on github. I just wanted to point out most important things here.
Questions:
- As I am changing the theme and many colors are changing, I wasn't sure how to make the color system. I end up with object for dark/light theme with colors of each element and a few colors that are common. How would you approach that?
- I didn't want to create a special component for my headings since they have no logic. I created helper utility called typographyStyles where I put all styles that I use across application. Not sure about that tho.
- I am curious what method you use to name your components. I personally stick to option #2 because it has the most pros for me and a little longer import doesn't bother me.
Bugs:
- Clicking twice quickly on header logo (navigate to home page, which render Invoices component) causes component not to render. I am convinced that this is related to Framer Motion and
AnimatePresence
that allows components to animate out when they're removed from the React tree. I think build in isPresent state when clicking twice quickly didn't change the state. I overcame this problem with simpleevent.preventDefault()
with asetTimeout
function but..
Additional feedback or a criticism will be appreciated Thanks! 😁!
Community feedback
Please log in to post a comment
Log in with GitHubJoin our Discord community
Join thousands of Frontend Mentor community members taking the challenges, sharing resources, helping each other, and chatting about all things front-end!
Join our Discord