fuxingloh / vue-horizontal

An ultra simple pure vue horizontal layout for modern responsive web with zero dependencies. (SPA/SSG/SSR)
https://vue-horizontal.fuxing.dev
MIT License
228 stars 32 forks source link

RTL Support #80

Open AmirAsghary opened 3 years ago

AmirAsghary commented 3 years ago

If the parent element's direction is set to RTL, the button navigation breaks and doesn't work anymore and it can only be navigated through using touch swipes. I did try to override the button navigation using this but it didn't fix the issue.

fuxingloh commented 3 years ago

Thanks for bringing this up, I will look into how best to add RTL support.

Meantime you can temporarily override the RLT settings if this helps:

<vue-horizontal dir="ltr">
  <div dir="rtl"></div>
  <div dir="rtl"></div>
  ...
</vue-horizontal>
gotson commented 3 years ago

+1 really need this, I'm using Vuetify with translations via vue-i18n, and I do have Arabic in my project, which is in RTL.

AbdallahAlhaddad commented 3 years ago

+1 Same as @gotson

allaghi commented 3 years ago

Any solution ?!!!

Wooody82 commented 2 years ago

Try for the v-hl-container
flex-direction: row-reverse;

Wooody82 commented 2 years ago

Hi, I have fixed it by doing some changes in the code. and I noticed the prev has issue when its moving back and fixed it as well. So here the code

For RTL we will need to reverse the Next and Prev CSS code first So it will be like this:

dir["rtl"] .v-hl-btn-next.v-hl-btn-between {
    transform: scaleX(-1) !important;
    left: 0;
    right: auto !important;
}

dir["rtl"] .v-hl-btn-prev.v-hl-btn-between {
    transform: scaleX(-1) !important;
    right: 0;
    left: auto !important;
}

Then on the main code I have added new props for vue-horizontal we could use rtl="true" and its false by default. So we could write like this now <vue-horizontal scroll :button="true" class="horizontal" ref="horizontal" rtl="true" >

From line 20 to 25 I have added this RTL props

    rtl: {
      type: Boolean,
      default: function _default() {
        return false;
      }
    },

Changes for Next

next: function next() {
      this.$emit('next');
      var container = this.$refs.container;
      var left = container.getBoundingClientRect().left;
      var x = left + container.clientWidth * this.displacement + delta;
      var element = this.findNextSlot(x);

      if (element) {
        var _width2 = element.getBoundingClientRect().left - left;

        if(this.rtl){
          if (_width2 < delta) {
            this.scrollToLeft(container.scrollLeft + _width2);
            return;
          }
        }else{
          if (_width2 > delta) {
            this.scrollToLeft(container.scrollLeft + _width2);
            return;
          }
        }
      }

      var width = container.clientWidth * this.displacement;
      if(this.rtl){
        this.scrollToLeft(container.scrollLeft - width);
      }
      else{
        this.scrollToLeft(container.scrollLeft + width);
      }
    },

Changes for Prev

    prev: function prev() {
      this.$emit('prev');
      var container = this.$refs.container;
      var left = container.getBoundingClientRect().left;
      var x = left + container.clientWidth * -this.displacement - delta;
      var element = this.findPrevSlot(x);

      if (element) {
        var _width = element.getBoundingClientRect().left - left;

        if(this.rtl){
          if (_width < delta) {
            this.scrollToLeft(container.scrollLeft - _width);
            return;
          }
        }else{
          if (_width > delta) {
            this.scrollToLeft(container.scrollLeft - _width);
            return;
          }
        }
      }

      var width = container.clientWidth * this.displacement;
      if(this.rtl){
        this.scrollToLeft(container.scrollLeft + width);
      }
      else{
        this.scrollToLeft(container.scrollLeft - width);
      }
    },

And Another small fix to hide Next button if reached the end

    function hasNext() {
        return container.scrollWidth > Math.abs(container.scrollLeft) + container.clientWidth + delta
      }

attached the the file.

Regards vue-horizontal.esm.js.zip