generated from deco-sites/fashion
-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
21 changed files
with
772 additions
and
238 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import { ProductDetailsPage } from "apps/commerce/types.ts"; | ||
import Image from "apps/website/components/Image.tsx"; | ||
|
||
export interface Props { | ||
/** @title Integration */ | ||
page: ProductDetailsPage | null; | ||
|
||
layout: { | ||
width: number; | ||
height: number; | ||
}; | ||
} | ||
|
||
/** | ||
* @title Product Image Front Back | ||
* @description Renders two images side by side both on mobile and on desktop. On mobile, the overflow is reached causing a scrollbar to be rendered. | ||
*/ | ||
function GalleryFrontBack(props: Props) { | ||
if (props.page === null) { | ||
throw new Error("Missing Product Details Page Info"); | ||
} | ||
|
||
const { | ||
page: { product: { image: images = [] } }, | ||
layout: { width, height }, | ||
} = props; | ||
const aspectRatio = `${width} / ${height}`; | ||
|
||
return ( | ||
<ul class="carousel carousel-center gap-6"> | ||
{[images[0], images[1] ?? images[0]].map((img, index) => ( | ||
<li class="carousel-item min-w-[100vw] sm:min-w-[24vw]"> | ||
<Image | ||
sizes="(max-width: 640px) 100vw, 24vw" | ||
style={{ aspectRatio }} | ||
src={img.url!} | ||
alt={img.alternateName} | ||
width={width} | ||
height={height} | ||
// Preload LCP image for better web vitals | ||
preload={index === 0} | ||
loading={index === 0 ? "eager" : "lazy"} | ||
/> | ||
</li> | ||
))} | ||
</ul> | ||
); | ||
} | ||
|
||
export default GalleryFrontBack; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
import Icon from "$store/components/ui/Icon.tsx"; | ||
import Slider from "$store/components/ui/Slider.tsx"; | ||
import ProductImageZoom from "$store/islands/ProductImageZoom.tsx"; | ||
import SliderJS from "$store/islands/SliderJS.tsx"; | ||
import { useId } from "$store/sdk/useId.ts"; | ||
import { ProductDetailsPage } from "apps/commerce/types.ts"; | ||
import Image from "apps/website/components/Image.tsx"; | ||
|
||
export interface Props { | ||
/** @title Integration */ | ||
page: ProductDetailsPage | null; | ||
|
||
layout: { | ||
width: number; | ||
height: number; | ||
}; | ||
} | ||
|
||
/** | ||
* @title Product Image Slider | ||
* @description Creates a three columned grid on destkop, one for the dots preview, one for the image slider and the other for product info | ||
* On mobile, there's one single column with 3 rows. Note that the orders are different from desktop to mobile, that's why | ||
* we rearrange each cell with col-start- directives | ||
*/ | ||
export default function GallerySlider(props: Props) { | ||
const id = useId(); | ||
|
||
if (props.page === null) { | ||
throw new Error("Missing Product Details Page Info"); | ||
} | ||
|
||
const { | ||
page: { product: { image: images = [] } }, | ||
layout: { width, height }, | ||
} = props; | ||
const aspectRatio = `${width} / ${height}`; | ||
|
||
return ( | ||
<div id={id} class="grid grid-flow-row sm:grid-flow-col"> | ||
{/* Image Slider */} | ||
<div class="relative order-1 sm:order-2"> | ||
<Slider class="carousel carousel-center gap-6 w-screen sm:w-[40vw]"> | ||
{images.map((img, index) => ( | ||
<Slider.Item | ||
index={index} | ||
class="carousel-item w-full" | ||
> | ||
<Image | ||
class="w-full" | ||
sizes="(max-width: 640px) 100vw, 40vw" | ||
style={{ aspectRatio }} | ||
src={img.url!} | ||
alt={img.alternateName} | ||
width={width} | ||
height={height} | ||
// Preload LCP image for better web vitals | ||
preload={index === 0} | ||
loading={index === 0 ? "eager" : "lazy"} | ||
/> | ||
</Slider.Item> | ||
))} | ||
</Slider> | ||
|
||
<Slider.PrevButton | ||
class="no-animation absolute left-2 top-1/2 btn btn-circle btn-outline" | ||
disabled | ||
> | ||
<Icon size={24} id="ChevronLeft" strokeWidth={3} /> | ||
</Slider.PrevButton> | ||
|
||
<Slider.NextButton | ||
class="no-animation absolute right-2 top-1/2 btn btn-circle btn-outline" | ||
disabled={images.length < 2} | ||
> | ||
<Icon size={24} id="ChevronRight" strokeWidth={3} /> | ||
</Slider.NextButton> | ||
|
||
<div class="absolute top-2 right-2 bg-base-100 rounded-full"> | ||
<ProductImageZoom | ||
images={images} | ||
width={700} | ||
height={Math.trunc(700 * height / width)} | ||
/> | ||
</div> | ||
</div> | ||
|
||
{/* Dots */} | ||
<ul class="carousel carousel-center gap-1 px-4 sm:px-0 sm:flex-col order-2 sm:order-1"> | ||
{images.map((img, index) => ( | ||
<li class="carousel-item min-w-[63px] sm:min-w-[100px]"> | ||
<Slider.Dot index={index}> | ||
<Image | ||
style={{ aspectRatio }} | ||
class="group-disabled:border-base-300 border rounded " | ||
width={63} | ||
height={87.5} | ||
src={img.url!} | ||
alt={img.alternateName} | ||
/> | ||
</Slider.Dot> | ||
</li> | ||
))} | ||
</ul> | ||
|
||
<SliderJS rootId={id} /> | ||
</div> | ||
); | ||
} |
Oops, something went wrong.
340fe3d
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An internal server error occurred.