Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add custom Next and Previous Buttons #232

Closed
jahil-khalfe opened this issue Mar 30, 2018 · 12 comments
Closed

Add custom Next and Previous Buttons #232

jahil-khalfe opened this issue Mar 30, 2018 · 12 comments

Comments

@jahil-khalfe
Copy link

It would be nice to customize next and previous buttons.

@leandrowd
Copy link
Owner

leandrowd commented Mar 30, 2018 via email

@leandrowd
Copy link
Owner

Can this be closed?

@danielkrich
Copy link

Hi @leandrowd. I honestly don't think that it would be an "overkill" to implement such a thing.
This is pretty basic stuff. More options == dynamic == better third party library.
As I see it, there are 2 things that needs the option to be customised: the dots and the arrows. (There will still be default controls of course)

Implementing like you suggested, with the external controls, is a bit hacky. I would need to disable the arrows and position my own arrows OUTSIDE the component, absolutely, relatively to the carousel... It's not native and not fun.

I'll try to make a PR if you're OK with that

@driskell
Copy link
Collaborator

Hi @danielkrich
I tend to agree with @leandrowd that it can make the library a lot larger as well - however I can envision there are ways to keep that under wraps so it’s minimal as possible. They key thing for me here is that I’m aware there’s difficulties keeping things moving as time sponsorship for big fixing is limited and it’s pretty important to make the API for this clean so as not to leak internals in such a way it prevents changes. I’m happy to help out with ideas. I can see there’s a PR forming so can take some ideas over there.
Jason

@driskell
Copy link
Collaborator

Would the goal here be to allow adding components within the carousel container that are not slides, like the dots and buttons are at the moment?

I’m seeing that if we have properties it doesn’t make that much sense as we can render the buttons ourselves next to the carousel, and we have acces to the slide count there anyway since we are rendering it as children of the Carousel, solving hasNext and hasPrev. External like this gives us more control too as we can enhance behaviour anyway we like (skip two, random slide, etc).

I wonder if it just a case of allowing children somehow that aren’t slides so you can place inside. One other bit I’ve thought of before is some way to expose Carousel state without the boilerplate “updateCurrentSlide”. I guess that’s where having that state provided for you in a callback helps simplify things.

@danielkrich
Copy link

danielkrich commented Jul 19, 2018

Hey @driskell, thanks for the replies.
The goal here, is to customise the controls - the simple ability to replace them with my own component.
For example, what if I don't want a button for the arrow control? What if I want a clickable text instead, shaped like a star?
It's not about adding components within the carousel, it's about customising controls.

If you take a look at my PR #257 , you can see that I've added 3 props: leftArrow, rightArrow and indicator. They need to be functions, in order to easily get the needed "actions" to be able to use them.

like so: (this is a usage example of customising the dot element)

<ReactCarousel showThumbs={false}
                       showStatus={false}
                       showIndicators={participants.length > NUMBER_OF_PARTICIPANTS_PER_SLIDE}
                       indicator={({onClick, isSelected}) =>
                          <span onClick={onClick} className={isSelected && 'selected'}>myDot</span>
                       }
        >
          {getSlides(participants, NUMBER_OF_PARTICIPANTS_PER_SLIDE)}
</ReactCarousel>

@driskell
Copy link
Collaborator

Thanks for adding detail it helps. I guess my first thought here is that the click handler and selected option are exposed where previously not, so it’s added to the API and might mean need to add a test to ensure it not changed accidentally in future. It also assumes a click which wouldn’t make sense in some cases so I can see it being called without an event object or a non click.

I’ve not had much time to think yet but with a better official API not tied to internals it might work out best for long run. The external controls can do all this at the moment via properties without increasing API but it is a bit arduous compared to say React-router where you just pass a component name and it receives an history object with APIs. Maybe something similar here better so you pass a component and it is rendered with a single property containing navigation APIs - means it separately linked to the internals and might be nicer having single property.

@danielkrich
Copy link

danielkrich commented Jul 19, 2018

Thanks for adding detail it helps. I guess my first thought here is that the click handler and selected option are exposed where previously not, so it’s added to the API and might mean need to add a test to ensure it not changed accidentally in future.

It is sort-of added to the API, but in a different way. If you want to change the element that should be used for the arrow, you have to give the user the relevant actions, such as "onClick", "selected" etc... so the element could be functional.
Can you think of another way to expose these functions? It's not like React-router, because React-router gives you HOC that wraps a component, to give the component its abilities.
In our case, we render a visual component, so we sometimes want to change the elements inside of it. Thats different.

I'm not getting your bottom line here. Right now, using the external controls means:

  1. You have to implement the actions yourself ("changeItem", "decrement", "increment") and manage your own state.
  2. You can't put it exactly where the control should be. You have to "position: absolute" it and disable the original controls.

What do you suggest?

@mhesham32
Copy link

I think to implement costume features the whole library need to be rewritten with render props pattern

@varunyn
Copy link

varunyn commented Apr 5, 2019

Is customizing control arrow feature add to the library?

leandrowd added a commit that referenced this issue Apr 5, 2020
#232: Add support for custom arrows and custom indicators
@leandrowd
Copy link
Owner

Not sure if anyone still needs it but I added support for custom arrows and indicators: #413

@wulinjie122
Copy link

Not sure if anyone still needs it but I added support for custom arrows and indicators: #413

Very nice and useful for me, i implement prev/next like below:

const carouselProp = {
    showStatus: false,
    useKeyboardArrows: true,
    infiniteLoop: true,
    autoPlay: true,
    stopOnHover: true,
    emulateTouch: true,
    transitionTime: 400,
    showArrows: true,
    renderArrowPrev: (clickHandler, hasPrev, label) => {
      return (
        <span className="arrow-left" onClick={clickHandler}>
          <span className="icon-keyboard_arrow_left"></span>
        </span>
      )
    },
    renderArrowNext: (clickHandler, hasNext, label) => {
      return (
        <span className="arrow-right" onClick={clickHandler}>
          <span className="icon-keyboard_arrow_right"></span>
        </span>
      )
    },
  }

and my CSS file is:

/* disable Carousel original black background color*/
.carousel .slide {
  background-color: #f8f9fa !important;
}

/* style for prev/next button */
.carousel-slider .arrow-left {
  position: absolute;
  top: 50%;
  color: #fff;
  padding: 0;
  left: 10px !important;
  background: #c7c7c8;
  transform: translateY(-50%);
  height: 50px;
  width: 50px;
  border-radius: 50%;
  -webkit-transition: .3s all ease-in-out;
  -o-transition: .3s all ease-in-out;
  transition: .3s all ease-in-out;
  line-height: 0;
  text-align: center;
  font-size: 25px;
  z-index: 99;
}

.carousel-slider .arrow-left > span {
  line-height: 0;
  position: absolute;
  top: 50%;
  left: 50%;
  -webkit-transform: translate(-50%, -50%);
  -ms-transform: translate(-50%, -50%);
  transform: translate(-50%, -50%);
}

.carousel-slider .arrow-right {
  position: absolute;
  top: 50%;
  color: #fff;
  padding: 0;
  right: 10px !important;
  background: #c7c7c8;
  transform: translateY(-50%);
  height: 50px;
  width: 50px;
  border-radius: 50%;
  -webkit-transition: .3s all ease-in-out;
  -o-transition: .3s all ease-in-out;
  transition: .3s all ease-in-out;
  line-height: 0;
  text-align: center;
  font-size: 25px;
}

.carousel-slider .arrow-right > span {
  line-height: 0;
  position: absolute;
  top: 50%;
  left: 50%;
  -webkit-transform: translate(-50%, -50%);
  -ms-transform: translate(-50%, -50%);
  transform: translate(-50%, -50%);
}

/* hide prev/next button in mobile client */
@media (max-width: 991.98px) {
  .carousel-slider .arrow-left {
    display: none;
  }

  .carousel-slider .arrow-right {
    display: none;
  }
}

and my React Component like this:

<Carousel {...carouselProp} >
</Carousel>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants