├── .gitignore
├── .new-component-config.json
├── LICENSE.md
├── README.md
├── docs
├── ex1-solution.gif
├── ex2-solution.gif
├── ex3-solution.gif
└── original-desktop.png
├── package-lock.json
├── package.json
├── public
├── assets
│ ├── flyknit.jpg
│ ├── joyride.jpg
│ ├── lebron.jpg
│ ├── legend-academy.jpg
│ ├── metcon-5.jpg
│ ├── pegasus.jpg
│ ├── phantom-flyknit.jpg
│ ├── phantom.jpg
│ ├── react-infinity.jpg
│ ├── react-vision.jpg
│ ├── stefan-janoski.jpg
│ └── tech-challenge.jpg
├── favicon.ico
├── index.html
├── logo192.png
├── logo512.png
├── manifest.json
└── robots.txt
└── src
├── components
├── App
│ ├── App.js
│ └── index.js
├── Breadcrumbs
│ ├── Breadcrumbs.js
│ └── index.js
├── GlobalStyles
│ ├── GlobalStyles.js
│ └── index.js
├── Header
│ ├── Header.js
│ └── index.js
├── Icon
│ ├── Icon.js
│ └── index.js
├── Logo
│ ├── Logo.js
│ └── index.js
├── MobileMenu
│ ├── MobileMenu.js
│ └── index.js
├── SearchInput
│ ├── SearchInput.js
│ └── index.js
├── Select
│ ├── Select.js
│ └── index.js
├── ShoeCard
│ ├── ShoeCard.js
│ └── index.js
├── ShoeGrid
│ ├── ShoeGrid.js
│ └── index.js
├── ShoeIndex
│ ├── ShoeIndex.js
│ └── index.js
├── ShoeSidebar
│ ├── ShoeSidebar.js
│ └── index.js
├── Spacer
│ ├── Spacer.js
│ └── index.js
├── SuperHeader
│ ├── SuperHeader.js
│ └── index.js
├── UnstyledButton
│ ├── UnstyledButton.js
│ └── index.js
└── VisuallyHidden
│ ├── VisuallyHidden.js
│ └── index.js
├── constants.js
├── data.js
├── index.js
└── utils.js
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
25 | .eslintcache
26 |
--------------------------------------------------------------------------------
/.new-component-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "functional",
3 | "prettierConfig": {
4 | "semi": true,
5 | "singleQuote": true,
6 | "trailingComma": "es5"
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | # Josh's Course Materials License
2 |
3 | Version 1, November 2020
4 | Copyright (c) Josh Comeau, 2020
5 |
6 | The files in this repository are meant to be used as part of a paid course, and are not intended for public distribution. They're open-source because it's the simplest form of distribution, and provides the best experience for students enrolled in the course.
7 |
8 | All are welcome to create personal copies of this repository, and modify its contents for educational use. Please experiment with the code, and see what you can build!
9 |
10 | It is forbidden to use these contents in any sort of commercial endeavour, including but not limited to:
11 |
12 | • Reselling its contents as part of a different course
13 | • Incorporating the code into a pre-existing business or project
14 | • Selling your solution to students enrolled in the course
15 |
16 | Exemptions can be made, on a case-by-case basis. Contact Josh Comeau (me@joshwcomeau.com) for more information.
17 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Sole&Ankle, Animated — Module 8 workshop
2 |
3 | Once again, we're working on the sneaker store!
4 |
5 | 
6 |
7 | In this workshop, we're going to use our newly-acquired animation skills to breathe some life into this application.
8 |
9 | **Some parts of this workshop are unguided.** Each exercise will challenge you to go beyond the stated goal, to come up with your own twist on the interaction.
10 |
11 | Also, **don't forget about accessibility.** Significant motion should be disabled by default, and only enabled based on the `prefers-reduced-motion` media query.
12 |
13 | ## Troubleshooting
14 |
15 | If you run into problems running a local development server, check out our [Troubleshooting Guide](https://courses.joshwcomeau.com/troubleshooting) on the course platform.
16 |
17 | This guide addresses the common `Digital Envelope Routine` error you may have seen.
18 |
19 | ---
20 |
21 | ## Exercise 1: Sneaker Zoom
22 |
23 | Add a hover/focus interaction to the sneakers so that the image zooms in slightly:
24 |
25 | 
26 |
27 | This might seem like a small task, but there are lots of little details that make it tricky. Pay close attention to the GIF. Some things to watch out for:
28 |
29 | - The enter transition should be faster than the exit transition
30 | - The "flags" for new releases and sales should hang over the edge of the photo, as they do initially.
31 | - The corners should remain perfectly round at all times.
32 | - The shoes aren't centered within the photos, so if you zoom into the center of the photo, the shoe will appear to drop lower. Tweak the animation so that it zooms in on the shoe.
33 |
34 | The relevant component is `ShoeCard.js`.
35 |
36 | ### Stretch Goal
37 |
38 | Once you've matched the GIF above, it's time to get creative. Change or extend the animation. Experiment with different techniques and properties!
39 |
40 | Here are some ideas:
41 |
42 | - In addition to the photo zoom, tweak the new/sale flags in some way.
43 | - Use a CSS filter on the photo.
44 |
45 | ---
46 |
47 | ## Exercise 2: Navigation link flip-up
48 |
49 | When hovering over the navigation links on desktop, they should "flip up", revealing a bold copy underneath:
50 |
51 | 
52 |
53 | In order to accomplish this challenge, **you'll need to tweak the JSX.** There's no way to solve this problem in CSS alone. In particular, you'll need to duplicate the text inside each navigation link.
54 |
55 | The relevant component is `Header.js`. You may wish to create a new `NavLink` component, though it isn't required.
56 |
57 | ### Stretch Goal
58 |
59 | Here's a list of over a dozen link hover animations: https://tympanus.net/Development/CreativeLinkEffects/
60 |
61 | Try and implement another effect from the list!
62 |
63 | ---
64 |
65 | ## Exercise 3: Modal enter animation
66 |
67 | On mobile, add the following animations to the hamburger menu:
68 |
69 | 
70 |
71 | This effect consists of 3 individual animations:
72 |
73 | 1. The backdrop fades in.
74 | 2. The drawer slides in from the right.
75 | 3. The drawer's contents fade in.
76 |
77 | For bonus points, use a custom easing curve on the slide-in animation. You can configure one using this tool: https://cubic-bezier.com.
78 |
79 | Don't worry about the exit animation; exit animations are difficult in React, and require a library like [React transition group](https://reactcommunity.org/react-transition-group/).
80 |
81 | The relevant component is `MobileMenu.js`.
82 |
83 | ### Stretch Goal
84 |
85 | Here are some ideas:
86 |
87 | - Experiment with different orchestrations, animating different elements at different times
88 | - Use a 3D transform on the drawer so that it swings in like a door closing rather than sliding in from offscreen
89 | - Instead of fading in all of the drawer's contents at once, add a staggered fade to the individual navigation links so that they fade in one by one, from the top down
90 |
--------------------------------------------------------------------------------
/docs/ex1-solution.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/css-for-js/sole-and-ankle-animated/d0debedce9c4101b6f32955e54dda1ca3d1d706e/docs/ex1-solution.gif
--------------------------------------------------------------------------------
/docs/ex2-solution.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/css-for-js/sole-and-ankle-animated/d0debedce9c4101b6f32955e54dda1ca3d1d706e/docs/ex2-solution.gif
--------------------------------------------------------------------------------
/docs/ex3-solution.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/css-for-js/sole-and-ankle-animated/d0debedce9c4101b6f32955e54dda1ca3d1d706e/docs/ex3-solution.gif
--------------------------------------------------------------------------------
/docs/original-desktop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/css-for-js/sole-and-ankle-animated/d0debedce9c4101b6f32955e54dda1ca3d1d706e/docs/original-desktop.png
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sole-and-ankle-animated",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@reach/dialog": "0.15.0",
7 | "date-fns": "2.16.1",
8 | "react": "17.0.1",
9 | "react-dom": "17.0.1",
10 | "react-feather": "2.0.9",
11 | "react-scripts": "4.0.1",
12 | "styled-components": "5.2.1"
13 | },
14 | "scripts": {
15 | "start": "react-scripts start",
16 | "build": "react-scripts build",
17 | "test": "react-scripts test",
18 | "eject": "react-scripts eject"
19 | },
20 | "eslintConfig": {
21 | "extends": [
22 | "react-app",
23 | "react-app/jest"
24 | ]
25 | },
26 | "browserslist": {
27 | "production": [
28 | ">0.2%",
29 | "not dead",
30 | "not op_mini all"
31 | ],
32 | "development": [
33 | "last 1 chrome version",
34 | "last 1 firefox version",
35 | "last 1 safari version"
36 | ]
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/public/assets/flyknit.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/css-for-js/sole-and-ankle-animated/d0debedce9c4101b6f32955e54dda1ca3d1d706e/public/assets/flyknit.jpg
--------------------------------------------------------------------------------
/public/assets/joyride.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/css-for-js/sole-and-ankle-animated/d0debedce9c4101b6f32955e54dda1ca3d1d706e/public/assets/joyride.jpg
--------------------------------------------------------------------------------
/public/assets/lebron.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/css-for-js/sole-and-ankle-animated/d0debedce9c4101b6f32955e54dda1ca3d1d706e/public/assets/lebron.jpg
--------------------------------------------------------------------------------
/public/assets/legend-academy.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/css-for-js/sole-and-ankle-animated/d0debedce9c4101b6f32955e54dda1ca3d1d706e/public/assets/legend-academy.jpg
--------------------------------------------------------------------------------
/public/assets/metcon-5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/css-for-js/sole-and-ankle-animated/d0debedce9c4101b6f32955e54dda1ca3d1d706e/public/assets/metcon-5.jpg
--------------------------------------------------------------------------------
/public/assets/pegasus.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/css-for-js/sole-and-ankle-animated/d0debedce9c4101b6f32955e54dda1ca3d1d706e/public/assets/pegasus.jpg
--------------------------------------------------------------------------------
/public/assets/phantom-flyknit.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/css-for-js/sole-and-ankle-animated/d0debedce9c4101b6f32955e54dda1ca3d1d706e/public/assets/phantom-flyknit.jpg
--------------------------------------------------------------------------------
/public/assets/phantom.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/css-for-js/sole-and-ankle-animated/d0debedce9c4101b6f32955e54dda1ca3d1d706e/public/assets/phantom.jpg
--------------------------------------------------------------------------------
/public/assets/react-infinity.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/css-for-js/sole-and-ankle-animated/d0debedce9c4101b6f32955e54dda1ca3d1d706e/public/assets/react-infinity.jpg
--------------------------------------------------------------------------------
/public/assets/react-vision.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/css-for-js/sole-and-ankle-animated/d0debedce9c4101b6f32955e54dda1ca3d1d706e/public/assets/react-vision.jpg
--------------------------------------------------------------------------------
/public/assets/stefan-janoski.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/css-for-js/sole-and-ankle-animated/d0debedce9c4101b6f32955e54dda1ca3d1d706e/public/assets/stefan-janoski.jpg
--------------------------------------------------------------------------------
/public/assets/tech-challenge.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/css-for-js/sole-and-ankle-animated/d0debedce9c4101b6f32955e54dda1ca3d1d706e/public/assets/tech-challenge.jpg
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/css-for-js/sole-and-ankle-animated/d0debedce9c4101b6f32955e54dda1ca3d1d706e/public/favicon.ico
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |