davidjerleke / embla-carousel

A lightweight carousel library with fluid motion and great swipe precision.
https://www.embla-carousel.com
MIT License
5.97k stars 180 forks source link

CanScrollPrev and CanScrollNext not returning proper value with dragFree and slidesToScroll #588

Closed suriyaprakash-s closed 11 months ago

suriyaprakash-s commented 12 months ago

Bug is related to

Embla Carousel version

Describe the bug

@davidjerleke First of all thanks for creating such an awesome library and the documentation.

When I have dragFree and slideToScroll option set to { align: 'start', dragFree: true, slidesToScroll: 'auto' }, canScrollPrev and canScrollNext not returning the expected value. In below given sandbox, more than half of the first slide is not visible but canScrollPrev returns false.

CodeSandbox

The link to a CodeSandbox that demonstrates the behavior clearly

Steps to reproduce

  1. Create a carousel with { align: 'start', dragFree: true, slidesToScroll: 'auto' }
  2. Drag little bit till half of first slide moves to left(basically hidden), you will notice the previous button not being enabled

Expected behavior

canScrollPrev and canScrollNext should return true till first and last slide completely visible

Additional context

image image

davidjerleke commented 11 months ago

Hi @suriyaprakash-s,

Thank you for your bug report. This might initially come as a surprise but it's actually expected behaviour. Embla doesn't treat slides as masters. Instead snap points are masters over slides. And when using any other value than the default for slidesToScroll, slides will be grouped so each snap can include one or more slides. In your specific case, the following groups will act as artificial slides:

Please check this modified sandbox to understand it better.

⚠️ Note that I didn't have time to make the sandbox demonstration dynamic so if you change slide sizes and stuff the demonstration will break. But keep in mind it's just a demonstration. However, if you want to check which slides belong to which group, you can just log:

console.log(emblaApi.internalEngine().slideRegistry);

Best, David

suriya-10 commented 11 months ago

@davidjerleke Thanks for the detailed reply, is there any way I can handle this case?

davidjerleke commented 11 months ago

@suriyaprakash-s what do you mean by:

is there any way I can handle this case?

What do you want to achieve?

Best, David

suriyaprakash-s commented 11 months ago

@davidjerleke I want to disable the buttons only when the first/last slide completely visible when I set slidesToScroll to non default values. I understand the library build based on snap points when slidesToScroll set to non default values, if there is a way to achieve my scenario by adding some event callback or something I would really appreciate it.

davidjerleke commented 11 months ago

@suriyaprakash-s do you mean like this?

suriyaprakash-s commented 11 months ago

@davidjerleke Thanks for the demo, it does the job. Since it is achieved by the pointerUp event, there is a catch here. If the user scrolls past 2-3 cards without releasing the pointer, then the button still stays disabled. It might be an edge case, so if there is no better solution, we can stick to the above one. The ideal expectation is that whatever the state of the carousel is (settled or scrolling), the button should be disabled when the first or last card is completely visible. If it is not completely visible button should be enabled irrespective of carousel scroll state

davidjerleke commented 11 months ago

@suriyaprakash-s I made it "lazy" on purpose. As soon as the user releases their pointer the buttons will change their state.

However, if you want the buttons to react immediately as the user scrolls, you can just listen to the scroll event instead. But bear in mind that this will be more intense for the browser to handle because the scroll event fires very often.

suriyaprakash-s commented 11 months ago

@davidjerleke Ya that's the problem with scroll, what you think about listening to sildesInView with inViewThreshold: 0.98 ?

davidjerleke commented 11 months ago

@suriyaprakash-s sure. That's one way to solve it. You can listen to:


emblaApi.on('slidesInView', (emblaApi) => {
  console.log(emblaApi.slidesInView())
})
suriyaprakash-s commented 11 months ago

@davidjerleke ok thanks for all your input and for the awesome library. You can close the ticket.