Photosnap
This is a solution to the Photosnap Website challenge on Frontend Mentor. Frontend Mentor challenges help you improve your coding skills by building realistic projects.
Skip to
Inspiration
My motivation for taking on this project was twofold: the clean, elegant design and the inherent challenge it presented. The project's aesthetics instantly appealed to me, and I saw it as a canvas to hone my skills in building reusable components, optimizing images efficiently, and upholding accessibility standards. Furthermore, embracing a mobile-first workflow was a natural step.
Stack
Next.js (App Directory): I wanted to learn how to use the new app directory and React Server Components(RSC).
TypeScript: For type safety and makes working with React fun by helping avoid runtime errors like passing the wrong data via props.
Tailwind CSS: I appreciated the utility-first approach of Tailwind CSS and its built-in utilities for colors, spacing, and media queries, making it feel like a design system that was ready to use with only minor adjustments required for customization.
Radix-UI: I took accessibility seriously, so I chose Radix UI, a collection of un-styled, composable, and accessible UI components that allowed me to build modern web applications with essential components like forms, dropdowns, and alert dialogs.
Framer Motion: I choose FM for it's spring animation engine and easy API.
Challenges
The challenge I encountered while working on the pricing page's Compare table was to balance preserving the inherent accessibility features of tables and rows with the need for a responsive design. My goal was to ensure that users with disabilities could effectively navigate the table, but traditional HTML tables posed difficulties in adapting to mobile views without sacrificing accessibility.
To overcome this challenge, I took several steps. First, in the mobile view, I hid the headers "BASIC," "PROP," and "BUSINESS" to reduce clutter and improve readability. Then, to provide screen reader users with clear labels for the check marks, I utilized the data attribute on each check mark cell and assigned it the respective label from the data source.
To visually display these labels above the check marks, I employed the "::before" pseudo-element on each check mark cell and set its content property to the label obtained from the data attribute. This approach allowed me to maintain the table's accessibility while adapting its design to various screen sizes, ensuring a seamless user experience for all.
What I've Learned
React Server Components I delved into the realm of React Server Components (RSC) and got hands-on experience with both RSC and client-side components, thanks to the 'use client' directive. One key takeaway was that RSC mounts once on the server and doesn't trigger re-renders. Additionally, I discovered that client-side components can't serve as parents to RSC, but they can certainly function as children within the context of RSC.
Next.js App Routing I learned how to use the new App directory to set up pages and dynamic routes.
Framer Motion I learned how to use the motion api to orchestrate animations, and how to tweak Spring animations for smooth and realistic motion. I also leverage the AnimatePresence components allowing me to animate components when they are removed from the React tree.
TailwindCSS I learned how to transfer all of the design tokens in the design system into the Tailwind config file. While it took a little time to set up, I think it improve my development experience and made sure that my code was very consistent with the figma designs.
What's Next?
I've decided to make the switch to Cloudinary for image optimization. I've always been curious about it, and after running some tests, it's clear that Cloudinary brings several valuable advantages over the Next.js Image component. With Cloudinary, I can tap into advanced image transformations, leverage a global Content Delivery Network (CDN) for quicker load times, benefit from automatic format conversion, robust image optimization, and compression, and even perform real-time image adjustments. Plus, it's not limited to images, offering support for various other media types as well.