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 { useCallback } from 'react'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
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 { CarouselButton } from '~/components/ui/button-slide'
|
||||
import { useNewsContext } from '~/contexts/news'
|
||||
import type { TNews } from '~/types/news'
|
||||
|
||||
export const CarouselHero = (properties: TNews) => {
|
||||
const { setIsSuccessOpen } = useNewsContext()
|
||||
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(() => {
|
||||
if (emblaApi) emblaApi.scrollPrev()
|
||||
}, [emblaApi])
|
||||
if (canScrollPrevious && emblaApi) emblaApi.scrollPrev()
|
||||
}, [emblaApi, canScrollPrevious])
|
||||
|
||||
const nextSlide = useCallback(() => {
|
||||
if (emblaApi) emblaApi.scrollNext()
|
||||
}, [emblaApi])
|
||||
if (canScrollNext && emblaApi) emblaApi.scrollNext()
|
||||
}, [emblaApi, canScrollNext])
|
||||
|
||||
return (
|
||||
<div className="">
|
||||
@ -33,18 +49,14 @@ export const CarouselHero = (properties: TNews) => {
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex gap-2.5">
|
||||
<CarouselPreviousIcon
|
||||
color="#DCDCDC"
|
||||
className="cursor-pointer"
|
||||
width={45}
|
||||
height={45}
|
||||
<CarouselButton
|
||||
direction="prev"
|
||||
isEnabled={canScrollPrevious}
|
||||
onClick={previousSlide}
|
||||
/>
|
||||
<CarouselNextIcon
|
||||
color="#2E2F7C"
|
||||
className="cursor-pointer"
|
||||
width={45}
|
||||
height={45}
|
||||
<CarouselButton
|
||||
direction="next"
|
||||
isEnabled={canScrollNext}
|
||||
onClick={nextSlide}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@ -1,25 +1,46 @@
|
||||
import useEmblaCarousel from 'embla-carousel-react'
|
||||
import { useCallback } from 'react'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
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 { CarouselButton } from '~/components/ui/button-slide'
|
||||
import { useNewsContext } from '~/contexts/news'
|
||||
import type { TNews } from '~/types/news'
|
||||
|
||||
export const CarouselSection = (properties: TNews) => {
|
||||
const { setIsSuccessOpen } = useNewsContext()
|
||||
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(() => {
|
||||
if (emblaApi) emblaApi.scrollPrev()
|
||||
}, [emblaApi])
|
||||
if (canScrollPrevious && emblaApi) emblaApi.scrollPrev()
|
||||
}, [emblaApi, canScrollPrevious])
|
||||
|
||||
const nextSlide = useCallback(() => {
|
||||
if (emblaApi) emblaApi.scrollNext()
|
||||
}, [emblaApi])
|
||||
if (canScrollNext && emblaApi) emblaApi.scrollNext()
|
||||
}, [emblaApi, canScrollNext])
|
||||
|
||||
return (
|
||||
<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]">
|
||||
@ -33,18 +54,14 @@ export const CarouselSection = (properties: TNews) => {
|
||||
</div>
|
||||
|
||||
<div className="flex gap-2.5">
|
||||
<CarouselPreviousIcon
|
||||
color="#DCDCDC"
|
||||
className="cursor-pointer"
|
||||
width={45}
|
||||
height={45}
|
||||
<CarouselButton
|
||||
direction="prev"
|
||||
isEnabled={canScrollPrevious}
|
||||
onClick={previousSlide}
|
||||
/>
|
||||
<CarouselNextIcon
|
||||
color="#2E2F7C"
|
||||
className="cursor-pointer"
|
||||
width={45}
|
||||
height={45}
|
||||
<CarouselButton
|
||||
direction="next"
|
||||
isEnabled={canScrollNext}
|
||||
onClick={nextSlide}
|
||||
/>
|
||||
</div>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user