Personally, I found there was diminishing returns by rolling my own, so I use SwiperJS, even though it’s bloated with a lot of features I will never use (thankfully you can import only the features you need, which helps). I initialize it with a Stimulus controller.
There’s also a simplified setup for Swiper if you’re using Stimulus: Carousel - Stimulus Components (I don’t use this simplified setup myself because I had some specific needs)
Note: You still need to write relevant markup that Swiper can use. Check their docs.