Added images to the first step

This commit is contained in:
cagsun 2025-06-27 00:41:25 +02:00
parent e3cd2c7f00
commit 08cac5f022
20 changed files with 154 additions and 89 deletions

View file

@ -11,24 +11,25 @@ import StepWithCarousel from '@site/src/components/StepWithCarousel';
<StepWithCarousel <StepWithCarousel
images={[ images={[
{ src: '/img/sink1.jpg', caption: 'Sorting plastic' }, { src: '/img/step1/1_box.webp', caption: 'Unboxing' },
{ src: '/img/try.jpg', caption: 'Heating in oven' }, { src: '/img/step1/2_toptray.webp', caption: 'Customise tray walls to make it more like a sink' },
{ src: '/img/step1/2_mark.webp', caption: 'Mark the required holes for the new combination' },
{ src: '/img/step1/3_plastic_piece.webp', caption: 'Use provided plastic pieces to fit the additional holes' },
{ src: '/img/step1/4_top_done.webp', caption: 'When done, top tray looks like this' },
{ src: '/img/step1/6_trays.webp', caption: 'Rest of the trays adjusted like this' },
]} ]}
> >
<p> <p>
**Unpack**: Open the Ikea Nissafors box and follow the included manual to build the base structure. There are some changes you need to make in order to customise it into a sink that are explained in this page. * **1.1 Unpack**: Open the Ikea Nissafors box and follow the included manual to build the base structure. There are some changes you need to make in order to customise it into a sink that are explained in this page.
* **1.2 Adjust height**: Position top tray at your child's height. The washbasin should be below their elbow height. In this heaight, see if you can use the existing holes of the top tray. We were able to make use of the existing holes as my son was sufficiently high.
* **1.3 Modify top tray combination**: Use the higher wall pieces from the bottom tray as the side and back walls for the washbasin (top tray). Keeping a lower front piece will allow easier access to the faucet.
* **1.4 Mark location of additional holes to drill**: The new combination of the top tray walls requires at least 4 additional holes, if you make use of the existing holes. If not, you need to drill all 8 holes yourself. Mark the locations for the holes. If you're using existing holes, measure the distances of the new holes to the existing ones using a side piece of the tray.
* **1.5 Drill the additional holes**: Only drill on the inside of metal frame (no need to drill all the way through). Use a 5.5mm bit (or use 5mm and expand the hole slightly) to be able to use the provided plastic pieces.
* **1.6 Install the top tray**: Only install the sides, and not the central surface since well insert the washbasin there. For existing holes, use the scres Ikea provided.
* **1.7 Install the middle and bottom trays**: Given the customisation on the top tray, we used the pieces originally for the top tray on the bottom tray.
**2** **Modify top tray (Turn it into a washbasin)**: **Result**: The trolley is customized and ready for washbasin installation.
* Position top tray at your child's height. The washbasin should be below their elbow height. In this heaight, see if you can use the existing holes of the top tray. We were able to make use of the existing holes as my son was sufficiently high.
* Use the higher wall pieces from the bottom tray as the side and back walls for the washbasin (top tray). Keeping a lower front piece will allow easier access to the faucet.
* This new combination of the top tray requires at least 4 additional holes, if you make use of the existing holes. If not, you need to drill all 8 holes yourself.
* Mark the locations for the holes. If you're using existing holes, measure the distances of the new holes to the existing ones using a side piece of the tray.
* Drill the additional holes. Only drill on the inside of metal frame (no need to drill all the way through). Use a 5.5mm bit (or use 5mm and expand the hole slightly) to be able to use the provided plastic pieces.
* Install the top tray. Only install the sides, and not the central surface since well insert the washbasin there. For existing holes, use the scres Ikea provided.
- Install the other trays as in original instructions with the remaining pieces.
**Result**: A customized cart ready for washbasin installation.
</p> </p>
</StepWithCarousel> </StepWithCarousel>

View file

@ -1,44 +1,77 @@
// src/components/ImageCarousel.js // src/components/ImageCarousel.js
import React from 'react';
import clsx from 'clsx'; import clsx from 'clsx';
import React, { useState, useEffect, useCallback } from 'react';
import styles from './ImageCarousel.module.css'; import styles from './ImageCarousel.module.css';
export default function ImageCarousel({ images }) { export default function ImageCarousel({ images }) {
const [current, setCurrent] = React.useState(0); const [currentIndex, setCurrentIndex] = useState(0);
const [isOpen, setIsOpen] = useState(false);
if (!images || images.length === 0) return null; const currentImage = images[currentIndex];
const closeLightbox = () => setIsOpen(false);
const handleKeyDown = useCallback((e) => {
if (!isOpen) return;
switch (e.key) {
case 'Escape':
closeLightbox();
break;
case 'ArrowRight':
setCurrentIndex((prev) => (prev + 1) % images.length);
break;
case 'ArrowLeft':
setCurrentIndex((prev) => (prev - 1 + images.length) % images.length);
break;
}
}, [isOpen, images.length]);
useEffect(() => {
document.addEventListener('keydown', handleKeyDown);
return () => document.removeEventListener('keydown', handleKeyDown);
}, [handleKeyDown]);
return ( return (
<>
<div className={styles.carousel}> <div className={styles.carousel}>
<div className={styles.viewport}> <img
{images.map((img, idx) => ( src={currentImage.src}
<div alt={currentImage.caption}
key={idx} className={styles.mainImage}
className={clsx(styles.slide, { [styles.active]: idx === current })} onClick={() => setIsOpen(true)}
> />
<img src={img.src} alt={img.alt || `Slide ${idx + 1}`} /> <div className={styles.thumbnails}>
{img.caption && <div className={styles.caption}>{img.caption}</div>} {images.map((img, i) => (
</div> <img
key={i}
src={img.src}
alt={img.caption}
className={`${styles.thumbnail} ${i === currentIndex ? styles.active : ''}`}
onClick={() => setCurrentIndex(i)}
/>
))} ))}
</div> </div>
</div>
<div className={styles.thumbnails}> {isOpen && (
{images.map((img, idx) => ( <div className={styles.lightbox} onClick={closeLightbox}>
<button className={styles.closeButton} onClick={closeLightbox}>&times;</button>
<button <button
key={idx} className={`${styles.navButton} ${styles.left}`}
onClick={() => setCurrent(idx)} onClick={(e) => { e.stopPropagation(); setCurrentIndex((prev) => (prev - 1 + images.length) % images.length); }}
className={clsx(styles.thumbnailWrapper, {
[styles.activeThumbnail]: idx === current,
})}
> >
<img &#10094;
src={img.src} </button>
alt={`Thumbnail ${idx + 1}`} <img src={currentImage.src} alt={currentImage.caption} className={styles.lightboxImage} />
className={styles.thumbnail} <button
/> className={`${styles.navButton} ${styles.right}`}
onClick={(e) => { e.stopPropagation(); setCurrentIndex((prev) => (prev + 1) % images.length); }}
>
&#10095;
</button> </button>
))}
</div>
</div> </div>
)}
</>
); );
} }

View file

@ -1,66 +1,97 @@
.carousel { .carousel {
max-width: 600px; display: flex;
margin: 2rem auto; flex-direction: column;
text-align: center; align-items: center;
} }
.viewport { .mainImage {
position: relative; max-width: 100%;
min-height: 300px; max-height: 300px;
} cursor: zoom-in;
border-radius: 8px;
.slide { box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
display: none;
}
.slide.active {
display: block;
}
.slide img {
width: 100%;
height: auto;
border-radius: 0.5rem;
}
.caption {
margin-top: 0.5rem;
font-size: 0.9rem;
color: #666;
} }
.thumbnails { .thumbnails {
margin-top: 1rem;
display: flex; display: flex;
justify-content: center;
flex-wrap: wrap;
gap: 0.5rem; gap: 0.5rem;
} margin-top: 1rem;
flex-wrap: wrap;
.thumbnailWrapper { justify-content: center;
border: none;
background: none;
padding: 0;
cursor: pointer;
outline: none;
border-radius: 0.375rem;
transition: box-shadow 0.2s ease;
} }
.thumbnail { .thumbnail {
width: 60px; width: 60px;
height: 40px; height: 60px;
object-fit: cover; object-fit: cover;
border-radius: 0.375rem; opacity: 0.6;
opacity: 0.8; border-radius: 4px;
transition: opacity 0.2s ease; cursor: pointer;
transition: 0.2s;
border: 2px solid transparent;
} }
.thumbnailWrapper:hover .thumbnail, .thumbnail:hover,
.thumbnailWrapper.activeThumbnail .thumbnail { .thumbnail.active {
opacity: 1; opacity: 1;
border-color: #0078e7;
} }
.activeThumbnail { /* Lightbox overlay */
box-shadow: 0 0 0 2px #333; .lightbox {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background-color: rgba(0, 0, 0, 0.85);
display: flex;
justify-content: center;
align-items: center;
z-index: 9999;
cursor: default;
overflow: hidden;
}
.lightboxImage {
max-width: 90vw;
max-height: 90vh;
border-radius: 8px;
z-index: 1;
}
/* Close (×) button */
.closeButton {
position: absolute;
top: 20px;
right: 30px;
font-size: 2.5rem;
color: white;
background: none;
border: none;
cursor: pointer;
z-index: 2;
}
/* Left/right arrows */
.navButton {
position: absolute;
top: 50%;
font-size: 3rem;
color: white;
background: none;
border: none;
cursor: pointer;
padding: 0 1rem;
z-index: 2;
transform: translateY(-50%);
user-select: none;
}
.left {
left: 20px;
}
.right {
right: 20px;
} }

BIN
static/img/step1/1_box.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 428 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 934 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

BIN
static/img/step1/screw.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.