From c06374e497576cbe38d68dabde6e6ff404505d84 Mon Sep 17 00:00:00 2001 From: Robert Reinhard Date: Fri, 19 Jan 2024 15:35:25 -0800 Subject: [PATCH 01/10] Add RTL demo --- README.md | 1 + demo/components/demos/accessibility/rtl.vue | 11 +++++++++++ demo/content/accessibility.md | 16 ++++++++++++++++ 3 files changed, 28 insertions(+) create mode 100644 demo/components/demos/accessibility/rtl.vue diff --git a/README.md b/README.md index 1e0dde9..779ab3f 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,7 @@ For more examples, see the demo: https://vue-ssr-carousel.netlify.app. | `no-drag` | `false` | Disables the ability to drag the carousel. | `show-arrows` | `false` | Whether to show back/forward arrows. See https://vue-ssr-carousel.netlify.app/ui. | `show-dots` | `false` | Whether to show dot style pagination dots. See https://vue-ssr-carousel.netlify.app/ui. +| `rtl` | `false` | Adjust layout for right to left sites. See https://vue-ssr-carousel.netlify.app/accessibility. | `value` | `undefined` | Used as part of `v-model` to set the initial slide to show. See https://vue-ssr-carousel.netlify.app/events. | `responsive` | `[]` | Adjust settings at breakpoints. See https://vue-ssr-carousel.netlify.app/responsive. Note, `loop` and `paginate-by-slide` cannot be set responsively. diff --git a/demo/components/demos/accessibility/rtl.vue b/demo/components/demos/accessibility/rtl.vue new file mode 100644 index 0000000..338734e --- /dev/null +++ b/demo/components/demos/accessibility/rtl.vue @@ -0,0 +1,11 @@ + diff --git a/demo/content/accessibility.md b/demo/content/accessibility.md index d9f09f7..b1d205d 100644 --- a/demo/content/accessibility.md +++ b/demo/content/accessibility.md @@ -43,3 +43,19 @@ By default, pages are referred to as "Page" in aria labels unless using `paginat Story 3 ``` + +## Support RTL + +The `rtl` boolean props adjusts the layout and drag behavior for right-to-left sites (like when the `direction: rtl` CSS property has been set). + + + +```vue +
+ + + + + +
+``` From cdc6da2c0f79c747565f9559e1da9362526d67b4 Mon Sep 17 00:00:00 2001 From: Robert Reinhard Date: Fri, 19 Jan 2024 15:35:33 -0800 Subject: [PATCH 02/10] Add rtl prop --- src/concerns/rtl.coffee | 7 +++++++ src/ssr-carousel.vue | 2 ++ 2 files changed, 9 insertions(+) create mode 100644 src/concerns/rtl.coffee diff --git a/src/concerns/rtl.coffee b/src/concerns/rtl.coffee new file mode 100644 index 0000000..77a7f5a --- /dev/null +++ b/src/concerns/rtl.coffee @@ -0,0 +1,7 @@ +### +Code related to supporting RTL layout +### +export default + + # Add RTL prop + props: rtl: Boolean diff --git a/src/ssr-carousel.vue b/src/ssr-carousel.vue index a8e7ca7..1892190 100644 --- a/src/ssr-carousel.vue +++ b/src/ssr-carousel.vue @@ -92,6 +92,7 @@ import looping from './concerns/looping' import pagination from './concerns/pagination' import peeking from './concerns/peeking' import responsive from './concerns/responsive' +import rtl from './concerns/rtl' import tweening from './concerns/tweening' import variableWidth from './concerns/variable-width' @@ -112,6 +113,7 @@ export default pagination responsive peeking # After `responsive` so prop can access `gutter` prop + rtl tweening variableWidth ] From a76c0f5ed1718286178c924cc883b4bccc206d59 Mon Sep 17 00:00:00 2001 From: Robert Reinhard Date: Fri, 19 Jan 2024 16:57:08 -0800 Subject: [PATCH 03/10] Show UI in the demo --- demo/components/demos/accessibility/rtl.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demo/components/demos/accessibility/rtl.vue b/demo/components/demos/accessibility/rtl.vue index 338734e..6cfd962 100644 --- a/demo/components/demos/accessibility/rtl.vue +++ b/demo/components/demos/accessibility/rtl.vue @@ -1,7 +1,7 @@ @@ -32,12 +38,18 @@ export default pages: Number shouldLoop: Boolean pageLabel: String + rtl: Boolean computed: + # Make the labels + backLabel: -> "Previous #{@pageLabel}" + nextLabel: -> "Next #{@pageLabel}" + # Determine if button should be disabled because we're at the limits - backDisabled: -> @index == 0 unless @shouldLoop - nextDisabled: -> @index == @pages - 1 unless @shouldLoop + leftDisabled: -> @index == 0 unless @shouldLoop + rightDisabled: -> @index == @pages - 1 unless @shouldLoop + @@ -48,20 +60,20 @@ export default @import './utils' // Vertically center buttons -.ssr-carousel-back-button -.ssr-carousel-next-button +.ssr-carousel-left-button +.ssr-carousel-right-button v-center() resetButton() // Align buttons near the edges -.ssr-carousel-back-button +.ssr-carousel-left-button left 2% -.ssr-carousel-next-button +.ssr-carousel-right-button right 2% // Make a default icon -.ssr-carousel-back-icon -.ssr-carousel-next-icon +.ssr-carousel-left-icon +.ssr-carousel-right-icon // Make a circle shape display inline-block @@ -88,12 +100,12 @@ export default position relative // Make triangle icons in the buttons -.ssr-carousel-back-icon +.ssr-carousel-left-icon &:before triangle 12px, 18px, white, 'left' left -2px // Massage center -.ssr-carousel-next-icon +.ssr-carousel-right-icon &:before triangle 12px, 18px, white, 'right' left 2px // Massage center diff --git a/src/ssr-carousel.vue b/src/ssr-carousel.vue index 4c5aa41..0f48e6d 100644 --- a/src/ssr-carousel.vue +++ b/src/ssr-carousel.vue @@ -53,7 +53,7 @@ //- Back / Next navigation ssr-carousel-arrows( v-if='showArrows' - v-bind='{ index, pages, shouldLoop, pageLabel }' + v-bind='{ index, pages, shouldLoop, pageLabel, rtl }' @back='back' @next='next') template(#back='props'): slot(name='back-arrow' v-bind='props') From 60579b9fb1f4b11997008db7ead4cc30b1cc4868 Mon Sep 17 00:00:00 2001 From: Robert Reinhard Date: Fri, 19 Jan 2024 17:07:50 -0800 Subject: [PATCH 06/10] Reverse page number labels --- src/ssr-carousel-dots.vue | 8 +++++++- src/ssr-carousel.vue | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/ssr-carousel-dots.vue b/src/ssr-carousel-dots.vue index 745d1ef..bc6afc6 100644 --- a/src/ssr-carousel-dots.vue +++ b/src/ssr-carousel-dots.vue @@ -5,7 +5,7 @@ .ssr-carousel-dots button.ssr-carousel-dot-button( v-for='i in pages' :key='i' - :aria-label='`Go to ${pageLabel} ${i}`' + :aria-label='makeLabel(i)' :aria-disabled='isDisabled(i)' @click='$emit("goto", i - 1)') @@ -29,9 +29,15 @@ export default boundedIndex: Number pages: Number pageLabel: String + rtl: Boolean methods: + # Make the label for the dot + makeLabel: (index) -> + pageNumber = if @rtl then @pages - index + 1 else @index + "Go to #{@pageLabel} #{pageNumber}" + # Check if dot index shuold be disabled isDisabled: (index) -> @boundedIndex == index - 1 diff --git a/src/ssr-carousel.vue b/src/ssr-carousel.vue index 0f48e6d..55c181b 100644 --- a/src/ssr-carousel.vue +++ b/src/ssr-carousel.vue @@ -62,7 +62,7 @@ //- Dots navigation ssr-carousel-dots( v-if='showDots' - v-bind='{ boundedIndex, pages, pageLabel }' + v-bind='{ boundedIndex, pages, pageLabel, rtl }' @goto='gotoDot') template(#dot='props'): slot(name='dot' v-bind='props') From 27652fe4917956228a96b05c97353a42616047f1 Mon Sep 17 00:00:00 2001 From: Robert Reinhard Date: Fri, 19 Jan 2024 17:14:44 -0800 Subject: [PATCH 07/10] =?UTF-8?q?Don=E2=80=99t=20reverse=20slide=20order?= =?UTF-8?q?=20until=20width=20is=20known?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/concerns/rtl.coffee | 4 +--- src/ssr-carousel-track.vue | 9 ++++++++- src/ssr-carousel.vue | 1 + 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/concerns/rtl.coffee b/src/concerns/rtl.coffee index 9c6873b..3072abe 100644 --- a/src/concerns/rtl.coffee +++ b/src/concerns/rtl.coffee @@ -8,7 +8,5 @@ export default # As an easy way to support rtl, update the index to the final value # when RTL is enabled. This is change is combined with reversing the order - # of the slides in `ssr-carousel-track`. The downside of this appraoch is - # that it's not SSR friendly; the x position of the track can't be calcualted - # until the component mounts and it's internal width can be measured. + # of the slides in `ssr-carousel-track` created: -> @index = @pages - @value - 1 if @rtl diff --git a/src/ssr-carousel-track.vue b/src/ssr-carousel-track.vue index ce7be6b..12f4494 100644 --- a/src/ssr-carousel-track.vue +++ b/src/ssr-carousel-track.vue @@ -12,6 +12,7 @@ export default leftPeekingSlideIndex: Number rightPeekingSlideIndex: Number rtl: Boolean + slideWidth: Number data: -> @@ -112,7 +113,13 @@ export default getSlideComponents: -> slides = [...(@$slots.default || []), ...(@$slots.clones || [])] .filter (vnode) -> !vnode.text - if @rtl then slides = slides.reverse() + + # Reverses the slide if rtl and if the slide slide width is known. This + # second condition exists to prevent the reversal from happening on SSR. + # Which is important because this logic is paired with setting the + # intial index to the last page which can't be known until the slide + # width is known. + if @rtl and @slideWidth then slides = slides.reverse() return slides # Makes a clone of the vnode properties we'll be updating so the changes diff --git a/src/ssr-carousel.vue b/src/ssr-carousel.vue index 55c181b..b473ec4 100644 --- a/src/ssr-carousel.vue +++ b/src/ssr-carousel.vue @@ -42,6 +42,7 @@ leftPeekingSlideIndex, rightPeekingSlideIndex, rtl, + slideWidth, }`) //- Render the slotted slides From 40bc51bf933a4691a71840d9ead9f5f52648d3a6 Mon Sep 17 00:00:00 2001 From: Robert Reinhard Date: Fri, 19 Jan 2024 17:35:02 -0800 Subject: [PATCH 08/10] Wait to set the initial index until width is known --- src/concerns/rtl.coffee | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/concerns/rtl.coffee b/src/concerns/rtl.coffee index 3072abe..fae069b 100644 --- a/src/concerns/rtl.coffee +++ b/src/concerns/rtl.coffee @@ -8,5 +8,23 @@ export default # As an easy way to support rtl, update the index to the final value # when RTL is enabled. This is change is combined with reversing the order - # of the slides in `ssr-carousel-track` - created: -> @index = @pages - @value - 1 if @rtl + # of the slides in `ssr-carousel-track`. We're testing for the + # carouselWidth value as way to ensure that the final pages count is known + # since it depends on knowing the width of the carousel. + mounted: -> + return unless @rtl + if @carouselWidth + then @setInitialRtlIndex() + else unwatch = @$watch 'carouselWidth', => + @setInitialRtlIndex() + unwatch() + + methods: + + # This should only be called once. Wait a tick so we're sure that the + # pages value has been calculated + setInitialRtlIndex: -> + setTimeout => + @index = @pages - @value - 1 + @jumpToIndex @index + , 0 From 2766e52bb3660ec260d4275f639016e57b79efdd Mon Sep 17 00:00:00 2001 From: Robert Reinhard Date: Fri, 19 Jan 2024 17:37:40 -0800 Subject: [PATCH 09/10] Add dimensionsKnown helper computed prop --- src/concerns/dimensions.coffee | 4 ++++ src/concerns/rtl.coffee | 6 +++--- src/ssr-carousel-track.vue | 6 +++--- src/ssr-carousel.vue | 2 +- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/concerns/dimensions.coffee b/src/concerns/dimensions.coffee index f8d3e70..3258b42 100644 --- a/src/concerns/dimensions.coffee +++ b/src/concerns/dimensions.coffee @@ -64,6 +64,10 @@ export default # Check if the drag is currently out bounds isOutOfBounds: -> @currentX > 0 or @currentX < @endX + # Helper for things that are triggered once dimensions are known so + # they can be more specific about their dependencies + dimensionsKnown: -> @carouselWidth and @viewportWidth + methods: # Measure the component width for various calculations. Using diff --git a/src/concerns/rtl.coffee b/src/concerns/rtl.coffee index fae069b..2f8a4b7 100644 --- a/src/concerns/rtl.coffee +++ b/src/concerns/rtl.coffee @@ -9,13 +9,13 @@ export default # As an easy way to support rtl, update the index to the final value # when RTL is enabled. This is change is combined with reversing the order # of the slides in `ssr-carousel-track`. We're testing for the - # carouselWidth value as way to ensure that the final pages count is known + # dimensionsKnown value as way to ensure that the final pages count is known # since it depends on knowing the width of the carousel. mounted: -> return unless @rtl - if @carouselWidth + if @dimensionsKnown then @setInitialRtlIndex() - else unwatch = @$watch 'carouselWidth', => + else unwatch = @$watch 'dimensionsKnown', => @setInitialRtlIndex() unwatch() diff --git a/src/ssr-carousel-track.vue b/src/ssr-carousel-track.vue index 12f4494..2c4dbb7 100644 --- a/src/ssr-carousel-track.vue +++ b/src/ssr-carousel-track.vue @@ -12,7 +12,7 @@ export default leftPeekingSlideIndex: Number rightPeekingSlideIndex: Number rtl: Boolean - slideWidth: Number + dimensionsKnown: Number data: -> @@ -114,12 +114,12 @@ export default slides = [...(@$slots.default || []), ...(@$slots.clones || [])] .filter (vnode) -> !vnode.text - # Reverses the slide if rtl and if the slide slide width is known. This + # Reverses the slide if rtl and if the dimensions are known. This # second condition exists to prevent the reversal from happening on SSR. # Which is important because this logic is paired with setting the # intial index to the last page which can't be known until the slide # width is known. - if @rtl and @slideWidth then slides = slides.reverse() + if @rtl and @dimensionsKnown then slides = slides.reverse() return slides # Makes a clone of the vnode properties we'll be updating so the changes diff --git a/src/ssr-carousel.vue b/src/ssr-carousel.vue index b473ec4..565f037 100644 --- a/src/ssr-carousel.vue +++ b/src/ssr-carousel.vue @@ -42,7 +42,7 @@ leftPeekingSlideIndex, rightPeekingSlideIndex, rtl, - slideWidth, + dimensionsKnown, }`) //- Render the slotted slides From deaa20135a3c995cb98d4c075e66b5c9801d66b5 Mon Sep 17 00:00:00 2001 From: Robert Reinhard Date: Fri, 19 Jan 2024 17:40:53 -0800 Subject: [PATCH 10/10] Fix dot label when not RTL --- src/ssr-carousel-dots.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ssr-carousel-dots.vue b/src/ssr-carousel-dots.vue index bc6afc6..550471d 100644 --- a/src/ssr-carousel-dots.vue +++ b/src/ssr-carousel-dots.vue @@ -35,7 +35,7 @@ export default # Make the label for the dot makeLabel: (index) -> - pageNumber = if @rtl then @pages - index + 1 else @index + pageNumber = if @rtl then @pages - index + 1 else index "Go to #{@pageLabel} #{pageNumber}" # Check if dot index shuold be disabled