JavaScript je isključen. Kod ispod je cijeli primjer.
App.jsx import { useState } from 'react' ;
import {
MotionHighlight ,
MotionPager ,
MotionSheet ,
MotionZoom ,
motionTokens,
} from '@kkwaenggwari/animated-chorus' ;
import './styles.css' ;
function scene (sky, land, sun ) {
const svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 260">
<rect width="400" height="260" fill="${sky} "/>
<circle cx="300" cy="80" r="34" fill="${sun} "/>
<path d="M0 190 Q120 110 220 180 T400 150 V260 H0Z" fill="${land} "/>
<path d="M0 225 Q150 170 260 215 T400 205 V260 H0Z" fill="#0e2e24"/>
</svg>` ;
return `data:image/svg+xml,${encodeURIComponent (svg)} ` ;
}
const photos = [
{
id : 'dawn' ,
title : 'Dawn ridge' ,
place : 'North trail' ,
src : scene ('#eaf6f0' , '#43c58f' , '#ffffff' ),
},
{
id : 'forest' ,
title : 'Deep forest' ,
place : 'Valley road' ,
src : scene ('#176b52' , '#2e8f6d' , '#eaf6f0' ),
},
{
id : 'meadow' ,
title : 'Meadow' ,
place : 'South field' ,
src : scene ('#cfe8dc' , '#176b52' , '#f4faf7' ),
},
{
id : 'night' ,
title : 'Night hills' ,
place : 'Lookout' ,
src : scene ('#0e2e24' , '#176b52' , '#43c58f' ),
},
];
export default function App ({ gap = 12 , spring = 'default' } ) {
const [page, setPage] = useState (0 );
const [details, setDetails] = useState (false );
const transition = motionTokens.spring [spring];
const photo = photos[page];
return (
<div className ="feed" >
<MotionPager
items ={photos}
index ={page}
onIndexChange ={setPage}
gap ={gap}
transition ={transition}
renderItem ={(item) => (
<MotionZoom
src ={item.src}
width ={400}
height ={260}
className ="photo"
transition ={transition}
/>
)}
/>
<div className ="bar" >
<MotionHighlight
items ={photos}
value ={photo.id}
onValueChange ={(key) => setPage(photos.findIndex((item) => item.id === key))}
transition={transition}
className="thumbs"
itemClassName="thumb"
highlightClassName="thumb-on"
renderItem={(item) => <img src ={item.src} width ={48} height ={32} /> }
/>
<button className ="info" onClick ={() => setDetails(true)}>
Details
</button >
</div >
<MotionSheet open ={details} onOpenChange ={setDetails} className ="sheet" >
<span className ="handle" />
<h2 > {photo.title}</h2 >
<p >
{photo.place} · photo {page + 1} of {photos.length}
</p >
<button onClick ={() => setDetails(false)}>Close</button >
</MotionSheet >
</div >
);
}styles.css .feed {
display : grid;
grid-template-columns : minmax (0 , 1 fr);
gap : 12px ;
max-width : 560px ;
min-height : 420px ;
margin : 0 auto;
padding : 24px 20px ;
align-content : start;
}
.photo {
display : block;
width : 100% ;
height : auto;
aspect-ratio : 400 / 260 ;
border-radius : 18px ;
object-fit : cover;
cursor : zoom-in;
user-select : none;
-webkit-user-drag: none;
}
.bar {
display : flex;
align-items : center;
justify-content : space-between;
gap : 12px ;
}
.thumbs {
display : flex;
min-width : 0 ;
gap : 6px ;
}
.thumb {
flex : 0 1 auto;
min-width : 0 ;
padding : 3px ;
border : 0 ;
border-radius : 10px ;
background : none;
cursor : pointer;
}
.thumb img {
display : block;
max-width : 100% ;
height : auto;
border-radius : 7px ;
}
.thumb-on {
border-radius : 10px ;
box-shadow : inset 0 0 0 2px #176b52 ;
}
.info {
flex : none;
min-height : 44px ;
padding : 0 18px ;
border : 1px solid #cfe8dc ;
border-radius : 999px ;
background : #fff ;
font :
600 14px system-ui,
sans-serif;
cursor : pointer;
}
.sheet {
gap : 6px ;
padding : 12px 22px 22px ;
border-radius : 22px 22px 0 0 ;
background : #fff ;
box-shadow : 0 -8px 30px rgba (14 , 46 , 36 , 0.18 );
}
.handle {
justify-self : center;
width : 44px ;
height : 5px ;
border-radius : 3px ;
background : #cfe8dc ;
}
.sheet h2 {
margin : 6px 0 0 ;
font :
750 22px system-ui,
sans-serif;
color : #0e2e24 ;
}
.sheet p {
margin : 0 ;
color : #5b616b ;
}
.sheet button {
min-height : 46px ;
margin-top : 12px ;
border : 0 ;
border-radius : 999px ;
background : #176b52 ;
color : #fff ;
font :
650 15px system-ui,
sans-serif;
cursor : pointer;
}