challenges

React Components: Part 6

Workshop context

Before this workshop

  • The previous workshops in this series have covered setup and props for three components, plus styling for the Button and Card components.

This workshop

  • This workshop completes the Loading component.

After this workshop

  • As a reminder, this series (React Components) builds low-level components for an application.
    • The application itself will be created in the next two series, Next.js Data Fetching and AI Style Generator.
    • For context, at the end of the AI Style Generator series, the application will look like this. You can see the spinner after clicking “use random quote” (the spinner will be replaced by the quote after the response comes back from the server).

Workshop goal

By the end of this workshop you will have a Spinner component, which will show when the quote is loading.

  • Use the Lucide React Loader component. lucide-react has already been installed for this application.
  • The icon size should be 48px.
  • Screen readers should read the text “Loading…” for the spinner. This text should not appear for people who are not using screen readers.
  • For users who have not indicated they prefer reduced motion, the component should rotate, making one complete rotation over the course of 5 seconds:
  • For users who have specifed prefers-reduced-motion , the component should not rotate. Instead it should fade in and out, going from fully showing to not showing and back to fully showing over the course of 2 seconds:

Hints

Hint 1 The Lucide React components aren’t very well documented, unfortunately. Usually, you can find the icon you’re looking for, and use upper camel case capitalization for the component. Here, the icon we want is loader , which is the Loader component in Lucide React.

Hint 2 See this example for how to use Lucide React. Use the size prop to set the size for the icon.

Hint 3 Use the VisuallyHidden component (available in /src/app/components) to specify text for screen readers. The component is based on Josh W. Comeau’s VisuallyHidden component (with the ‘press key to show text’ functionality omitted.)

Hint 4 Use keyframes for the animations. For the rotation animation, animate the transform: rotate() property. For the fade in/out animation, animate the opacity property.

For both animations, the animation-iteration-count should be infinite. For animation-timing-function , I’d suggest linear for the rotation animation, and ease-in-out for the fade in/out animation.

Hint 5 Use a prefers-reduced-motion media query to display the rotation for users who have a prefers-reduced-motion value of no-preference, and the fade in/out animation for all other users.

Hint 6 To check whether you’re displaying the correct animation for users who prefer reduced motion, you can emulate prefers-reduced-motion in Chrome or enable reduced motion for your environment.

Resources