feat: implement carousel navigation buttons for improved user interaction
This commit is contained in:
parent
82c0894ccd
commit
cd3637bf03
24
app/components/ui/button-slide.tsx
Normal file
24
app/components/ui/button-slide.tsx
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { CarouselNextIcon } from '~/components/icons/carousel-next'
|
||||||
|
import { CarouselPreviousIcon } from '~/components/icons/carousel-previous'
|
||||||
|
|
||||||
|
type TCarouselButton = {
|
||||||
|
direction: 'prev' | 'next'
|
||||||
|
isEnabled: boolean
|
||||||
|
onClick: () => void
|
||||||
|
}
|
||||||
|
export const CarouselButton = ({
|
||||||
|
direction,
|
||||||
|
isEnabled,
|
||||||
|
onClick,
|
||||||
|
}: TCarouselButton) => {
|
||||||
|
const Icon = direction === 'prev' ? CarouselPreviousIcon : CarouselNextIcon
|
||||||
|
return (
|
||||||
|
<Icon
|
||||||
|
color={isEnabled ? '#2E2F7C' : '#DCDCDC'}
|
||||||
|
className={isEnabled ? 'cursor-pointer' : 'cursor-not-allowed'}
|
||||||
|
width={45}
|
||||||
|
height={45}
|
||||||
|
onClick={onClick}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -1,25 +1,41 @@
|
|||||||
import useEmblaCarousel from 'embla-carousel-react'
|
import useEmblaCarousel from 'embla-carousel-react'
|
||||||
import { useCallback } from 'react'
|
import { useCallback, useEffect, useState } from 'react'
|
||||||
import { Link } from 'react-router'
|
import { Link } from 'react-router'
|
||||||
|
|
||||||
import { CarouselNextIcon } from '~/components/icons/carousel-next'
|
|
||||||
import { CarouselPreviousIcon } from '~/components/icons/carousel-previous'
|
|
||||||
import { Button } from '~/components/ui/button'
|
import { Button } from '~/components/ui/button'
|
||||||
|
import { CarouselButton } from '~/components/ui/button-slide'
|
||||||
import { useNewsContext } from '~/contexts/news'
|
import { useNewsContext } from '~/contexts/news'
|
||||||
import type { TNews } from '~/types/news'
|
import type { TNews } from '~/types/news'
|
||||||
|
|
||||||
export const CarouselHero = (properties: TNews) => {
|
export const CarouselHero = (properties: TNews) => {
|
||||||
const { setIsSuccessOpen } = useNewsContext()
|
const { setIsSuccessOpen } = useNewsContext()
|
||||||
const { title, description, items } = properties
|
const { title, description, items } = properties
|
||||||
const [emblaReference, emblaApi] = useEmblaCarousel({ loop: true })
|
const [emblaReference, emblaApi] = useEmblaCarousel({ loop: false })
|
||||||
|
|
||||||
|
const [canScrollNext, setCanScrollNext] = useState(false)
|
||||||
|
const [canScrollPrevious, setCanScrollPrevious] = useState(false)
|
||||||
|
|
||||||
|
const updateButtons = useCallback(() => {
|
||||||
|
if (emblaApi) {
|
||||||
|
setCanScrollPrevious(emblaApi.canScrollPrev())
|
||||||
|
setCanScrollNext(emblaApi.canScrollNext())
|
||||||
|
}
|
||||||
|
}, [emblaApi])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (emblaApi) {
|
||||||
|
updateButtons()
|
||||||
|
emblaApi.on('select', updateButtons)
|
||||||
|
}
|
||||||
|
}, [emblaApi, updateButtons])
|
||||||
|
|
||||||
const previousSlide = useCallback(() => {
|
const previousSlide = useCallback(() => {
|
||||||
if (emblaApi) emblaApi.scrollPrev()
|
if (canScrollPrevious && emblaApi) emblaApi.scrollPrev()
|
||||||
}, [emblaApi])
|
}, [emblaApi, canScrollPrevious])
|
||||||
|
|
||||||
const nextSlide = useCallback(() => {
|
const nextSlide = useCallback(() => {
|
||||||
if (emblaApi) emblaApi.scrollNext()
|
if (canScrollNext && emblaApi) emblaApi.scrollNext()
|
||||||
}, [emblaApi])
|
}, [emblaApi, canScrollNext])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="">
|
<div className="">
|
||||||
@ -33,18 +49,14 @@ export const CarouselHero = (properties: TNews) => {
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex gap-2.5">
|
<div className="flex gap-2.5">
|
||||||
<CarouselPreviousIcon
|
<CarouselButton
|
||||||
color="#DCDCDC"
|
direction="prev"
|
||||||
className="cursor-pointer"
|
isEnabled={canScrollPrevious}
|
||||||
width={45}
|
|
||||||
height={45}
|
|
||||||
onClick={previousSlide}
|
onClick={previousSlide}
|
||||||
/>
|
/>
|
||||||
<CarouselNextIcon
|
<CarouselButton
|
||||||
color="#2E2F7C"
|
direction="next"
|
||||||
className="cursor-pointer"
|
isEnabled={canScrollNext}
|
||||||
width={45}
|
|
||||||
height={45}
|
|
||||||
onClick={nextSlide}
|
onClick={nextSlide}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,25 +1,46 @@
|
|||||||
import useEmblaCarousel from 'embla-carousel-react'
|
import useEmblaCarousel from 'embla-carousel-react'
|
||||||
import { useCallback } from 'react'
|
import { useCallback, useEffect, useState } from 'react'
|
||||||
import { Link } from 'react-router'
|
import { Link } from 'react-router'
|
||||||
|
|
||||||
import { CarouselNextIcon } from '~/components/icons/carousel-next'
|
|
||||||
import { CarouselPreviousIcon } from '~/components/icons/carousel-previous'
|
|
||||||
import { Button } from '~/components/ui/button'
|
import { Button } from '~/components/ui/button'
|
||||||
|
import { CarouselButton } from '~/components/ui/button-slide'
|
||||||
import { useNewsContext } from '~/contexts/news'
|
import { useNewsContext } from '~/contexts/news'
|
||||||
import type { TNews } from '~/types/news'
|
import type { TNews } from '~/types/news'
|
||||||
|
|
||||||
export const CarouselSection = (properties: TNews) => {
|
export const CarouselSection = (properties: TNews) => {
|
||||||
const { setIsSuccessOpen } = useNewsContext()
|
const { setIsSuccessOpen } = useNewsContext()
|
||||||
const { title, description, items } = properties
|
const { title, description, items } = properties
|
||||||
const [emblaReference, emblaApi] = useEmblaCarousel({ loop: false })
|
const [emblaReference, emblaApi] = useEmblaCarousel({
|
||||||
|
loop: false,
|
||||||
|
slidesToScroll: 1,
|
||||||
|
align: 'start',
|
||||||
|
})
|
||||||
|
|
||||||
|
const [canScrollNext, setCanScrollNext] = useState(false)
|
||||||
|
const [canScrollPrevious, setCanScrollPrevious] = useState(false)
|
||||||
|
|
||||||
|
const updateButtons = useCallback(() => {
|
||||||
|
if (emblaApi) {
|
||||||
|
setCanScrollPrevious(emblaApi.canScrollPrev())
|
||||||
|
setCanScrollNext(emblaApi.canScrollNext())
|
||||||
|
}
|
||||||
|
}, [emblaApi])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (emblaApi) {
|
||||||
|
updateButtons()
|
||||||
|
emblaApi.on('select', updateButtons)
|
||||||
|
}
|
||||||
|
}, [emblaApi, updateButtons])
|
||||||
|
|
||||||
const previousSlide = useCallback(() => {
|
const previousSlide = useCallback(() => {
|
||||||
if (emblaApi) emblaApi.scrollPrev()
|
if (canScrollPrevious && emblaApi) emblaApi.scrollPrev()
|
||||||
}, [emblaApi])
|
}, [emblaApi, canScrollPrevious])
|
||||||
|
|
||||||
const nextSlide = useCallback(() => {
|
const nextSlide = useCallback(() => {
|
||||||
if (emblaApi) emblaApi.scrollNext()
|
if (canScrollNext && emblaApi) emblaApi.scrollNext()
|
||||||
}, [emblaApi])
|
}, [emblaApi, canScrollNext])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="">
|
<div className="">
|
||||||
<div className="mt-3 mb-3 flex items-center justify-between border-b border-black pb-3 sm:mb-[30px] sm:pb-[30px]">
|
<div className="mt-3 mb-3 flex items-center justify-between border-b border-black pb-3 sm:mb-[30px] sm:pb-[30px]">
|
||||||
@ -33,18 +54,14 @@ export const CarouselSection = (properties: TNews) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex gap-2.5">
|
<div className="flex gap-2.5">
|
||||||
<CarouselPreviousIcon
|
<CarouselButton
|
||||||
color="#DCDCDC"
|
direction="prev"
|
||||||
className="cursor-pointer"
|
isEnabled={canScrollPrevious}
|
||||||
width={45}
|
|
||||||
height={45}
|
|
||||||
onClick={previousSlide}
|
onClick={previousSlide}
|
||||||
/>
|
/>
|
||||||
<CarouselNextIcon
|
<CarouselButton
|
||||||
color="#2E2F7C"
|
direction="next"
|
||||||
className="cursor-pointer"
|
isEnabled={canScrollNext}
|
||||||
width={45}
|
|
||||||
height={45}
|
|
||||||
onClick={nextSlide}
|
onClick={nextSlide}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user