diff --git a/completed-components/exercise-3-html/ProductBuyBoxVariantSelector.tsx b/completed-components/exercise-3-html/ProductBuyBoxVariantSelector.tsx index 4d42dd0..590243a 100644 --- a/completed-components/exercise-3-html/ProductBuyBoxVariantSelector.tsx +++ b/completed-components/exercise-3-html/ProductBuyBoxVariantSelector.tsx @@ -4,10 +4,10 @@ const ProductBuyBoxVariantSelector = ({ Product }) => { const [selectedSize, selectSize] = useState(null); return ( - - Color: + + Color: {selectedColor} - + {Product.colors.map((color, index) => ( @@ -40,9 +40,9 @@ const ProductBuyBoxVariantSelector = ({ Product }) => { - - Size: - + + Size: + {Product && Product.sizes.length === 1 && ( diff --git a/completed-components/exercise-3-html/ProductDetails.tsx b/completed-components/exercise-3-html/ProductDetails.tsx index f7131c7..64a95ab 100644 --- a/completed-components/exercise-3-html/ProductDetails.tsx +++ b/completed-components/exercise-3-html/ProductDetails.tsx @@ -44,10 +44,11 @@ const ProductDetails = ({ product, onAddToCart }: ProductDetailsProps) => { + Reviews {hasReviews && ( <> - {product.overallRating} + {product.overallRating} @@ -69,22 +70,22 @@ const ProductDetails = ({ product, onAddToCart }: ProductDetailsProps) => { - Price: + Price {product.price} - + Lowest Price Guarantee - + - Quantity: + Quantity { setProductCount(parseInt(event.target.value))} role="spinbutton" @@ -128,14 +129,14 @@ const ProductDetails = ({ product, onAddToCart }: ProductDetailsProps) => { - onAddToCart(product)}> Add to Cart - - + + Add to Wishlist - + ); diff --git a/completed-components/exercise-3-html/ProductHeader.tsx b/completed-components/exercise-3-html/ProductHeader.tsx index 85df79b..84c4eca 100644 --- a/completed-components/exercise-3-html/ProductHeader.tsx +++ b/completed-components/exercise-3-html/ProductHeader.tsx @@ -18,12 +18,13 @@ const Banner = ({ shouldAnimate = false }: BannerProps) => { } }; const incrementSlide = () => { - if (currentSlideNum <= slideCount) { + if (currentSlideNum < slideCount) { changeSlideNum(currentSlideNum + 1); } else { changeSlideNum(1); } }; + const setInert = (node, slideNumber) => { // workaround for React not recognizing inert // https://github.com/facebook/react/pull/24730 @@ -31,28 +32,43 @@ const Banner = ({ shouldAnimate = false }: BannerProps) => { node && (currentSlideNum === slideNumber ? node.removeAttribute('inert', '') : node.setAttribute('inert', '')) ); }; + useEffect(() => { updateSlidePercentage(((currentSlideNum - 1) / 3) * 100); }, [currentSlideNum]); + + async function animate() { + incrementSlide(); + } + + useEffect(() => { + if (shouldAnimate) animate(); + }, []); + + if (shouldAnimate) { + setTimeout(() => { + animate(); + }, 3000); + } + return ( - + Announcements - + - setInert(node, 1)} className="flex items-center"> + style={{ transform: `translateX(-${slidePercentage}%)` }}> + setInert(node, 1)}> - + Get It By 12/24 W/ Free Standard Shipping @@ -62,7 +78,7 @@ const Banner = ({ shouldAnimate = false }: BannerProps) => { - setInert(node, 2)} className="flex items-center text-white text-center"> + setInert(node, 2)}> { - setInert(node, 3)} className="flex items-center text-white text-center"> + setInert(node, 3)}> - + Winter’s Warmest Boots, Beanies, Mittens & More Shop Now @@ -107,12 +123,13 @@ const Logo = () => diff --git a/completed-components/exercise-3-html/ProductImageGallery.tsx b/completed-components/exercise-3-html/ProductImageGallery.tsx index 6b295f9..cc0a5c2 100644 --- a/completed-components/exercise-3-html/ProductImageGallery.tsx +++ b/completed-components/exercise-3-html/ProductImageGallery.tsx @@ -31,24 +31,24 @@ const ProductImageGallery = ({ imageData, onFullscreenOpen, onFullscreenClose }: className="grid gap-2 grid-cols-none grid-flow-row grid-cols[repeat(2, minmax(0, 1fr))] m-4 cursor-pointer"> - setFullscreenImage(imageData.mainImage)}> + setFullscreenImage(imageData.mainImage)}> - + {imageData.galleryImages.map((image, index) => ( - + - + ))} {!!fullscreenImage && ( - closeFullscreen()}> X - + )} diff --git a/completed-components/exercise-4-ARIA/ProductDetails.tsx b/completed-components/exercise-4-ARIA/ProductDetails.tsx index 928a049..2d9be0d 100644 --- a/completed-components/exercise-4-ARIA/ProductDetails.tsx +++ b/completed-components/exercise-4-ARIA/ProductDetails.tsx @@ -44,10 +44,11 @@ const ProductDetails = ({ product, onAddToCart }: ProductDetailsProps) => { + Reviews {hasReviews && ( <> - {product.overallRating} + {product.overallRating} @@ -69,21 +70,22 @@ const ProductDetails = ({ product, onAddToCart }: ProductDetailsProps) => { + Price {product.price} - + Lowest Price Guarantee - + - Quantity: + Quantity { setProductCount(parseInt(event.target.value))} role="spinbutton" @@ -128,11 +130,11 @@ const ProductDetails = ({ product, onAddToCart }: ProductDetailsProps) => { onAddToCart(product)}> Add to Cart - + Add to Wishlist diff --git a/completed-components/exercise-4-ARIA/ProductHeader.tsx b/completed-components/exercise-4-ARIA/ProductHeader.tsx index e2fde2f..051f09c 100644 --- a/completed-components/exercise-4-ARIA/ProductHeader.tsx +++ b/completed-components/exercise-4-ARIA/ProductHeader.tsx @@ -20,36 +20,57 @@ const Banner = ({ shouldAnimate = false }: BannerProps) => { } }; const incrementSlide = () => { - if (currentSlideNum <= slideCount) { + if (currentSlideNum < slideCount) { changeSlideNum(currentSlideNum + 1); } else { changeSlideNum(1); } }; + + const setInert = (node, slideNumber) => { + // workaround for React not recognizing inert + // https://github.com/facebook/react/pull/24730 + return ( + node && (currentSlideNum === slideNumber ? node.removeAttribute('inert', '') : node.setAttribute('inert', '')) + ); + }; + + useEffect(() => { + updateSlidePercentage(((currentSlideNum - 1) / 3) * 100); + }, [currentSlideNum]); + + async function animate() { + incrementSlide(); + } + + useEffect(() => { + if (shouldAnimate) animate(); + }, []); + + if (shouldAnimate) { + setTimeout(() => { + animate(); + }, 3000); + } + return ( - + - + Announcements - + - + setInert(node, 1)}> - + Get It By 12/24 W/ Free Standard Shipping @@ -59,9 +80,7 @@ const Banner = ({ shouldAnimate = false }: BannerProps) => { - + setInert(node, 2)}> { - + setInert(node, 3)}> { - + @@ -113,41 +125,39 @@ const Logo = () => - + - - - {shoppingCartItems && shoppingCartItems.length > 0 && ( - {shoppingCartItems.length} - )} - - + + {shoppingCartItems && shoppingCartItems.length > 0 && ( + {shoppingCartItems.length} + )} + Cart, contains {shoppingCartItems?.length === 1 ? 'item' : 'items'} + + {cartAnnouncementMessage} + - - {cartAnnouncementMessage || ''} - > ); }; diff --git a/completed-components/exercise-4-ARIA/ProductPage.tsx b/completed-components/exercise-4-ARIA/ProductPage.tsx index e201570..a78d372 100644 --- a/completed-components/exercise-4-ARIA/ProductPage.tsx +++ b/completed-components/exercise-4-ARIA/ProductPage.tsx @@ -16,19 +16,23 @@ const ProductPage = ({ productData }: ProductPageProps) => { const [shoppingCartItems, updateShoppingCartItems] = useState([]); const [isFullscreenShowing, setFullscreenShowing] = useState(false); - const onAddToCart = (product) => { - const items = [...shoppingCartItems, product]; - updateShoppingCartItems(items); - }; - const onFullscreen = () => { setFullscreenShowing(true); }; const onFullscreenClose = () => { setFullscreenShowing(false); }; + const onAddToCart = (product: Product) => { + const items = [...shoppingCartItems, product]; + updateShoppingCartItems(items); + }; return ( + + + {productData.productTitle} by {productData.companyName} - Background + + { - + { - + diff --git a/completed-components/exercise-5-focus/ProductImageGallery.tsx b/completed-components/exercise-5-focus/ProductImageGallery.tsx index 4410750..ec0f4f7 100644 --- a/completed-components/exercise-5-focus/ProductImageGallery.tsx +++ b/completed-components/exercise-5-focus/ProductImageGallery.tsx @@ -1,5 +1,5 @@ import { useEffect, useState } from 'react'; -import { Image, Modal, ModalOverlay, ModalContent, ModalBody, ModalCloseButton } from '@chakra-ui/react'; +import { Image, Modal, ModalHeader, ModalOverlay, ModalContent, ModalBody, ModalCloseButton } from '@chakra-ui/react'; import type { ImageData } from '../../types'; type ProductImageGalleryProps = { @@ -31,7 +31,7 @@ const ProductImageGallery = ({ imageData, onFullscreenOpen, onFullscreenClose }: className="grid gap-2 grid-cols-none grid-flow-row grid-cols[repeat(2, minmax(0, 1fr))] m-4 cursor-pointer"> - setFullscreenImage(imageData.mainImage)}> + setFullscreenImage(imageData.mainImage)} aria-label="Open image in full-screen"> @@ -41,17 +41,20 @@ const ProductImageGallery = ({ imageData, onFullscreenOpen, onFullscreenClose }: ))} - {!!fullscreenImage && ( - - - - - - - - - - )} + + {!!fullscreenImage && ( + + + + {imageData.mainImage.alt} + + + + + + + )} + > ); };
Size:
Lowest Price Guarantee
+
Announcements
Get It By 12/24 W/ Free Standard Shipping @@ -62,7 +78,7 @@ const Banner = ({ shouldAnimate = false }: BannerProps) => {
Winter’s Warmest Boots, Beanies, Mittens & More Shop Now
Get It By 12/24 W/ Free Standard Shipping @@ -59,9 +80,7 @@ const Banner = ({ shouldAnimate = false }: BannerProps) => {
Cart, contains {shoppingCartItems?.length === 1 ? 'item' : 'items'}