fix(Carousel): arrows & indicators are broken in RTL (#2251)

This commit is contained in:
Malik-Jouda
2024-10-02 12:16:00 +03:00
committed by GitHub
parent 474accbefb
commit db5e5c4907
3 changed files with 17 additions and 9 deletions

View File

@@ -20,12 +20,12 @@ const items = [
:prev-button="{ :prev-button="{
color: 'gray', color: 'gray',
icon: 'i-heroicons-arrow-left-20-solid', icon: 'i-heroicons-arrow-left-20-solid',
class: '-left-12' class: '-start-12'
}" }"
:next-button="{ :next-button="{
color: 'gray', color: 'gray',
icon: 'i-heroicons-arrow-right-20-solid', icon: 'i-heroicons-arrow-right-20-solid',
class: '-right-12' class: '-end-12'
}" }"
arrows arrows
class="w-64 mx-auto" class="w-64 mx-auto"

View File

@@ -1,5 +1,5 @@
<template> <template>
<div :class="ui.wrapper" v-bind="attrs"> <div :class="ui.wrapper" v-bind="attrs" :dir="dir">
<div ref="carouselRef" :class="ui.container" class="no-scrollbar"> <div ref="carouselRef" :class="ui.container" class="no-scrollbar">
<div <div
v-for="(item, index) in items" v-for="(item, index) in items"
@@ -89,6 +89,10 @@ export default defineComponent({
type: Boolean, type: Boolean,
default: false default: false
}, },
dir: {
type: String as PropType<'ltr' | 'rtl'>,
default: 'ltr'
},
prevButton: { prevButton: {
type: Object as PropType<Button & { class?: string }>, type: Object as PropType<Button & { class?: string }>,
default: () => config.default.prevButton as Button & { class?: string } default: () => config.default.prevButton as Button & { class?: string }
@@ -124,12 +128,16 @@ export default defineComponent({
itemWidth.value = entry?.target?.firstElementChild?.clientWidth || 0 itemWidth.value = entry?.target?.firstElementChild?.clientWidth || 0
}) })
const isRtl = computed(() => props.dir === 'rtl')
const currentPage = computed(() => { const currentPage = computed(() => {
if (!itemWidth.value) { if (!itemWidth.value) {
return 0 return 0
} }
return Math.round(x.value / itemWidth.value) + 1 return isRtl.value
? Math.round(-x.value / itemWidth.value) + 1
: Math.round(x.value / itemWidth.value) + 1
}) })
const pages = computed(() => { const pages = computed(() => {
@@ -144,15 +152,15 @@ export default defineComponent({
const isLast = computed(() => currentPage.value === pages.value) const isLast = computed(() => currentPage.value === pages.value)
function onClickNext () { function onClickNext () {
x.value += itemWidth.value x.value += isRtl.value ? -itemWidth.value : itemWidth.value
} }
function onClickPrev () { function onClickPrev () {
x.value -= itemWidth.value x.value -= isRtl.value ? -itemWidth.value : itemWidth.value
} }
function onClick (page: number) { function onClick (page: number) {
x.value = (page - 1) * itemWidth.value x.value = (page - 1) * itemWidth.value * (isRtl.value ? -1 : 1)
} }
expose({ expose({

View File

@@ -14,12 +14,12 @@ export default {
default: { default: {
prevButton: { prevButton: {
color: 'black' as const, color: 'black' as const,
class: 'rtl:[&_span:first-child]:rotate-180 absolute left-4 top-1/2 transform -translate-y-1/2 rounded-full', class: 'rtl:[&_span:first-child]:rotate-180 absolute start-4 top-1/2 transform -translate-y-1/2 rounded-full',
icon: 'i-heroicons-chevron-left-20-solid' icon: 'i-heroicons-chevron-left-20-solid'
}, },
nextButton: { nextButton: {
color: 'black' as const, color: 'black' as const,
class: 'rtl:[&_span:last-child]:rotate-180 absolute right-4 top-1/2 transform -translate-y-1/2 rounded-full', class: 'rtl:[&_span:last-child]:rotate-180 absolute end-4 top-1/2 transform -translate-y-1/2 rounded-full',
icon: 'i-heroicons-chevron-right-20-solid' icon: 'i-heroicons-chevron-right-20-solid'
} }
} }