diff --git a/src/components/sections/Shelf/Shelf.module.css b/src/components/sections/Shelf/Shelf.module.css new file mode 100644 index 00000000..9942895b --- /dev/null +++ b/src/components/sections/Shelf/Shelf.module.css @@ -0,0 +1,39 @@ +.container { + @apply w-screen px-28; +} + +[data-store-carousel] { + @apply relative; +} + +[data-carousel-controls] [data-store-button] { + @apply absolute flex justify-center justify-items-center bg-transparent border-transparent box-border cursor-pointer text-white top-1/2; +} + +[data-carousel-controls] [data-store-button] [data-store-icon] { + @apply text-black; +} + +[data-left-arrow] { + @apply left-16; +} + +[data-right-arrow] { + @apply right-16; +} + +[data-carousel-bullets] { + @apply absolute p-0 m-0 left-0 right-0 bottom-4; +} + +[data-carousel-bullets] [data-store-bullets] { + @apply flex list-none w-full justify-center; +} + +[data-carousel-bullets] [data-store-bullets] [data-store-button] { + @apply bg-gray-300 rounded-full cursor-pointer inline-block mx-1 w-5 p-0 h-1 transition-all; +} + +[data-carousel-bullets] [data-store-bullets] [data-store-button]:disabled { + @apply bg-pink-800 w-10; +} diff --git a/src/components/sections/Shelf/index.tsx b/src/components/sections/Shelf/index.tsx new file mode 100644 index 00000000..1b991756 --- /dev/null +++ b/src/components/sections/Shelf/index.tsx @@ -0,0 +1,53 @@ +import React from 'react' +import type { FC } from 'react' +import { Carousel as UIShelf } from '@vtex/store-ui' +import useMediaQuery from 'src/utils/useMediaQuery' + +import * as styles from './Shelf.module.css' + +interface Props { + items: string[] + itemsPerPage: number[] + title?: string +} + +const Shelf: FC> = ({ + className, + items, + itemsPerPage, + title, +}) => { + const isDesktop = useMediaQuery('(min-width: 640px)') + + const mediaItemsPerPage = isDesktop ? itemsPerPage[1] : itemsPerPage[0] + + const pagesNumber = Math.ceil(items.length / mediaItemsPerPage) + + return ( +
+ {title &&

{title}

} + + {[...Array(pagesNumber)].map((x, page) => { + const firstItem = page * mediaItemsPerPage + + return ( +
+ {items + .slice(firstItem, firstItem + mediaItemsPerPage) + .map((value) => ( +
+ {value} +
+ ))} +
+ ) + })} +
+
+ ) +} + +export default Shelf diff --git a/src/components/sections/ShelfNews/ShelfNews.module.css b/src/components/sections/ShelfNews/ShelfNews.module.css new file mode 100644 index 00000000..e835990e --- /dev/null +++ b/src/components/sections/ShelfNews/ShelfNews.module.css @@ -0,0 +1,39 @@ +.container { + @apply w-screen sm:pl-28; +} + +[data-store-carousel] { + @apply relative; +} + +[data-carousel-controls] [data-store-button] { + @apply absolute flex justify-center justify-items-center bg-transparent border-transparent box-border cursor-pointer text-white top-1/2; +} + +[data-carousel-controls] [data-store-button] [data-store-icon] { + @apply text-black; +} + +[data-left-arrow] { + @apply left-16; +} + +[data-right-arrow] { + @apply right-16; +} + +[data-carousel-bullets] { + @apply absolute p-0 m-0 left-0 right-0 bottom-1/4; +} + +[data-carousel-bullets] [data-store-bullets] { + @apply flex list-none w-full justify-center; +} + +[data-carousel-bullets] [data-store-bullets] [data-store-button] { + @apply bg-gray-300 rounded-full cursor-pointer inline-block mx-1 w-5 p-0 h-1 transition-all; +} + +[data-carousel-bullets] [data-store-bullets] [data-store-button]:disabled { + @apply bg-pink-800 w-10; +} diff --git a/src/components/sections/ShelfNews/index.tsx b/src/components/sections/ShelfNews/index.tsx new file mode 100644 index 00000000..14425c3e --- /dev/null +++ b/src/components/sections/ShelfNews/index.tsx @@ -0,0 +1,75 @@ +import React from 'react' +import type { FC } from 'react' +import { Carousel as UIShelf } from '@vtex/store-ui' +import { useGetThumborImageData } from '@vtex/gatsby-plugin-thumbor' +import { withArtDirection, GatsbyImage } from 'gatsby-plugin-image' +import imagesConf from 'src/images/config' + +import * as styles from './ShelfNews.module.css' + +interface Props { + items: string[] + itemsPerPage: number[] + title?: string +} + +const ShelfNews: FC> = ({ + className, + items, + itemsPerPage, + title, +}) => { + const mediaItemsPerPage = window.matchMedia('(min-width: 640px)') + ? itemsPerPage[1] + : itemsPerPage[0] + + const pagesNumber = Math.ceil(items.length / mediaItemsPerPage) + + const getThumborImageData = useGetThumborImageData() + + const image = getThumborImageData({ + baseUrl: + 'https://fashioneurope.vtexassets.com/assets/vtex/assets-builder/fashioneurope.theme/2.7.0/images/banner-new-in___7eda5598301c61afdce56021e9e872cc.gif', + ...imagesConf['shelf.gif'], + }) + + const sectionGif = withArtDirection(image, [ + { + media: `(min-width: 640px)`, + image, + }, + ]) + + return ( +
+
+

{title}

+ + {[...Array(pagesNumber)].map((x, page) => { + const firstItem = page * mediaItemsPerPage + + return ( +
+ {items + .slice(firstItem, firstItem + mediaItemsPerPage) + .map((value) => ( +
+ {value} +
+ ))} +
+ ) + })} +
+
+
+ +
+
+ ) +} + +export default ShelfNews diff --git a/src/images/config.js b/src/images/config.js index 4430c1aa..f2774c5c 100644 --- a/src/images/config.js +++ b/src/images/config.js @@ -16,4 +16,13 @@ module.exports = { fitIn: true, }, }, + 'shelf.gif': { + sourceWidth: 600, + aspectRatio: 1, + breakpoints: [320, 480, 740, 1080], + layout: 'constrained', + options: { + fitIn: true, + }, + }, } diff --git a/src/utils/useMediaQuery.tsx b/src/utils/useMediaQuery.tsx new file mode 100644 index 00000000..3fa227ec --- /dev/null +++ b/src/utils/useMediaQuery.tsx @@ -0,0 +1,24 @@ +import { useState, useEffect } from 'react' + +export default (media: string) => { + const [query, setQuery] = useState(() => { + if (typeof window !== 'object' || !window.matchMedia) { + return false + } + + return window.matchMedia(media).matches + }) + + useEffect(() => { + const listener = (ev) => { + setQuery(ev.matches) + } + + window.matchMedia(media).addEventListener('change', listener) + + return () => + window.matchMedia(media).removeEventListener('change', listener) + }, [media]) + + return query +} diff --git a/src/views/home/index.tsx b/src/views/home/index.tsx index 56ba7d57..6469ef5e 100644 --- a/src/views/home/index.tsx +++ b/src/views/home/index.tsx @@ -1,6 +1,22 @@ import React, { lazy, Suspense, SuspenseList } from 'react' import type { Props as PageProps } from 'src/pages/index' +const Shelf = lazy( + () => + import( + /* webpackMode: "eager" */ + 'src/components/sections/Shelf' + ) +) + +const ShelfNews = lazy( + () => + import( + /* webpackMode: "eager" */ + 'src/components/sections/ShelfNews' + ) +) + const Seo = lazy( () => import( @@ -25,6 +41,22 @@ function View(props: Props) { // return { type: 'vtex:pageView', data: event } // }) + const tests = [ + 'One', + 'Two', + 'Three', + 'Four', + 'Five', + 'Six', + 'Seven', + 'Eight', + 'Nine', + 'Ten', + 'Eleven', + 'Twelve', + 'Thirteen', + ] + return ( {/* Seo Components */} @@ -34,7 +66,19 @@ function View(props: Props) { {/* Visual Sections */} -
TODO
+ + +
)