forked from opentiny/tiny-vue
fix(carousel): [carousel]modify smb theme (#2125)
This commit is contained in:
parent
5bce345e3b
commit
9100eb93c7
|
@ -111,6 +111,21 @@ export default {
|
|||
pcDemo: 'close-loop',
|
||||
mfDemo: ''
|
||||
},
|
||||
{
|
||||
name: 'disabled',
|
||||
type: 'boolean',
|
||||
defaultValue: 'false',
|
||||
desc: {
|
||||
'zh-CN': '控制轮播箭头禁用状态,设置为 true 则禁用',
|
||||
'en-US': 'Control the disabled state of the carousel arrow, set to true to disable'
|
||||
},
|
||||
meta: {
|
||||
stable: '3.19.0'
|
||||
},
|
||||
mode: ['pc'],
|
||||
pcDemo: 'close-loop',
|
||||
mfDemo: ''
|
||||
},
|
||||
{
|
||||
name: 'show-title',
|
||||
type: 'boolean',
|
||||
|
|
|
@ -1,8 +1,16 @@
|
|||
<template>
|
||||
<tiny-carousel height="300px" arrow="always" indicator-position="outside">
|
||||
<tiny-carousel arrow="never" height="300px" indicator-position="none" ref="carouselRef" :initial-index="index - 1">
|
||||
<div class="btn-layout">
|
||||
<div>
|
||||
<tiny-button type="text" @click="prev" :disabled="disabledLeft" :icon="TinyIconChevronLeft"> </tiny-button>
|
||||
</div>
|
||||
<div>
|
||||
<tiny-button type="text" @click="next" :disabled="disabledRight" :icon="TinyIconChevronRight"></tiny-button>
|
||||
</div>
|
||||
</div>
|
||||
<tiny-carousel-item class="carousel-item-demo" v-for="(item, pos) in state.cardData" :key="item">
|
||||
<template #default>
|
||||
<div v-for="num in state.cardData.length" :key="num">
|
||||
<div class="card-layout" v-for="num in state.cardData.length" :key="num">
|
||||
<div v-if="num === pos + 1" :class="['card-dsp']">
|
||||
<tiny-card
|
||||
v-for="(child, childIndex) in item.children"
|
||||
|
@ -23,10 +31,23 @@
|
|||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive } from 'vue'
|
||||
import { Carousel as TinyCarousel, CarouselItem as TinyCarouselItem, Card as TinyCard } from '@opentiny/vue'
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import {
|
||||
Carousel as TinyCarousel,
|
||||
CarouselItem as TinyCarouselItem,
|
||||
Card as TinyCard,
|
||||
Button as TinyButton
|
||||
} from '@opentiny/vue'
|
||||
import { IconChevronRight, IconChevronLeft } from '@opentiny/vue-icon'
|
||||
|
||||
const TinyIconChevronRight = IconChevronRight()
|
||||
const TinyIconChevronLeft = IconChevronLeft()
|
||||
|
||||
let curIndex = ref(0)
|
||||
const index = ref(1)
|
||||
let disabledLeft = ref(false)
|
||||
let disabledRight = ref(false)
|
||||
const carouselRef = ref()
|
||||
const dsj = ref(`${import.meta.env.VITE_APP_BUILD_BASE_URL}static/images/dsj.png`)
|
||||
const userHead = ref(`${import.meta.env.VITE_APP_BUILD_BASE_URL}static/images/user-head.png`)
|
||||
const state = reactive({
|
||||
|
@ -78,25 +99,99 @@ const state = reactive({
|
|||
cardType: 'logo',
|
||||
cardSrc: `${userHead.value}`,
|
||||
content: '1-3-content'
|
||||
},
|
||||
{
|
||||
cardTitle: '2-4',
|
||||
cardType: 'logo',
|
||||
cardSrc: `${userHead.value}`,
|
||||
content: '2-4-content'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
disableStatus()
|
||||
})
|
||||
|
||||
const next = () => {
|
||||
index.value = Math.min(index.value + 1, 8)
|
||||
carouselRef.value.next()
|
||||
disableStatus()
|
||||
}
|
||||
|
||||
const prev = () => {
|
||||
index.value = Math.max(index.value - 1, 0)
|
||||
carouselRef.value.prev()
|
||||
disableStatus()
|
||||
}
|
||||
|
||||
const disableStatus = () => {
|
||||
disabledRight.value = false
|
||||
disabledLeft.value = false
|
||||
if (index.value === 1) {
|
||||
disabledLeft.value = true
|
||||
disabledRight.value = false
|
||||
}
|
||||
if (index.value === state.cardData.length) {
|
||||
disabledRight.value = true
|
||||
disabledLeft.value = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
<style lang="less" scoped>
|
||||
.carousel-item-demo {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
.card-dsp {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
padding: 0 4px 0 12px;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
}
|
||||
.mb {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.card-demo {
|
||||
width: 25%;
|
||||
height: 300px;
|
||||
margin-right: 8px;
|
||||
height: 200px;
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
&:hover {
|
||||
border-color: #1476ff;
|
||||
}
|
||||
}
|
||||
.btn-layout {
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
top: 45%;
|
||||
z-index: 10;
|
||||
padding: 0 76px;
|
||||
}
|
||||
/deep/ .tiny-button.tiny-button--text.tiny-button.is-only-icon {
|
||||
font-size: 16px;
|
||||
border: none;
|
||||
.tiny-svg {
|
||||
fill: #808080;
|
||||
}
|
||||
&.is-disabled {
|
||||
.tiny-svg {
|
||||
fill: #c2c2c2;
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
background-color: transparent;
|
||||
}
|
||||
&:not(.is-disabled) {
|
||||
.tiny-svg:hover {
|
||||
fill: #191919;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -4,15 +4,11 @@ test('轮播卡片', async ({ page }) => {
|
|||
page.on('pageerror', (exception) => expect(exception).toBeNull())
|
||||
await page.goto('carousel#card-show')
|
||||
const preview = page.locator('#card-show')
|
||||
await preview
|
||||
.locator('div')
|
||||
.filter({ hasText: /^1-11-1-content$/ })
|
||||
.first()
|
||||
.click()
|
||||
await preview.getByRole('button').nth(1).click()
|
||||
const btnRight = preview.getByRole('button').nth(1)
|
||||
await btnRight.click()
|
||||
await preview
|
||||
.locator('div')
|
||||
.filter({ hasText: /^2-11-1-content$/ })
|
||||
.first()
|
||||
.click()
|
||||
expect(btnRight).toHaveCSS('fill', 'rgb(194, 194, 194)')
|
||||
})
|
||||
|
|
|
@ -1,8 +1,16 @@
|
|||
<template>
|
||||
<tiny-carousel height="300px" arrow="always" indicator-position="outside">
|
||||
<tiny-carousel arrow="never" height="300px" indicator-position="none" ref="carouselRef" :initial-index="index - 1">
|
||||
<div class="btn-layout">
|
||||
<div>
|
||||
<tiny-button type="text" @click="prev" :disabled="disabledLeft" :icon="TinyIconChevronLeft"> </tiny-button>
|
||||
</div>
|
||||
<div>
|
||||
<tiny-button type="text" @click="next" :disabled="disabledRight" :icon="TinyIconChevronRight"></tiny-button>
|
||||
</div>
|
||||
</div>
|
||||
<tiny-carousel-item class="carousel-item-demo" v-for="(item, pos) in cardData" :key="item">
|
||||
<template #default>
|
||||
<div v-for="num in cardData.length" :key="num">
|
||||
<div class="card-layout" v-for="num in cardData.length" :key="num">
|
||||
<div v-if="num === pos + 1" :class="['card-dsp']">
|
||||
<tiny-card
|
||||
v-for="(child, childIndex) in item.children"
|
||||
|
@ -23,17 +31,24 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { Carousel, CarouselItem, Card } from '@opentiny/vue'
|
||||
import { Carousel, CarouselItem, Card, Button } from '@opentiny/vue'
|
||||
import { IconChevronRight, IconChevronLeft } from '@opentiny/vue-icon'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
TinyCarousel: Carousel,
|
||||
TinyCarouselItem: CarouselItem,
|
||||
TinyCard: Card
|
||||
TinyCard: Card,
|
||||
TinyButton: Button
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
TinyIconChevronRight: IconChevronRight(),
|
||||
TinyIconChevronLeft: IconChevronLeft(),
|
||||
curIndex: 0,
|
||||
index: 1,
|
||||
disabledLeft: false,
|
||||
disabledRight: false,
|
||||
cardData: [
|
||||
{
|
||||
children: [
|
||||
|
@ -82,27 +97,99 @@ export default {
|
|||
cardType: 'logo',
|
||||
cardSrc: `/static/images/user-head.png`,
|
||||
content: '1-3-content'
|
||||
},
|
||||
{
|
||||
cardTitle: '2-4',
|
||||
cardType: 'logo',
|
||||
cardSrc: `/static/images/user-head.png`,
|
||||
content: '2-4-content'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.disableStatus()
|
||||
},
|
||||
methods: {
|
||||
next() {
|
||||
this.index = Math.min(this.index + 1, 8)
|
||||
this.$refs.carouselRef.next()
|
||||
this.disableStatus()
|
||||
},
|
||||
prev() {
|
||||
this.index = Math.max(this.index - 1, 0)
|
||||
this.$refs.carouselRef.prev()
|
||||
this.disableStatus()
|
||||
},
|
||||
disableStatus() {
|
||||
this.disabledRight = false
|
||||
this.disabledLeft = false
|
||||
if (this.index === 1) {
|
||||
this.disabledLeft = true
|
||||
this.disabledRight = false
|
||||
}
|
||||
if (this.index === this.cardData.length) {
|
||||
this.disabledRight = true
|
||||
this.disabledLeft = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
<style lang="less" scoped>
|
||||
.carousel-item-demo {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
.card-dsp {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
padding: 0 4px 0 12px;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
}
|
||||
.mb {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.card-demo {
|
||||
width: 25%;
|
||||
height: 300px;
|
||||
margin-right: 8px;
|
||||
height: 200px;
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
&:hover {
|
||||
border-color: #1476ff;
|
||||
}
|
||||
}
|
||||
.btn-layout {
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
top: 45%;
|
||||
z-index: 10;
|
||||
padding: 0 76px;
|
||||
}
|
||||
/deep/ .tiny-button.tiny-button--text.tiny-button.is-only-icon {
|
||||
font-size: 16px;
|
||||
border: none;
|
||||
.tiny-svg {
|
||||
fill: #808080;
|
||||
}
|
||||
&.is-disabled {
|
||||
.tiny-svg {
|
||||
fill: #c2c2c2;
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
background-color: transparent;
|
||||
}
|
||||
&:not(.is-disabled) {
|
||||
.tiny-svg:hover {
|
||||
fill: #191919;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<tiny-carousel height="150px" :loop="false" arrow="always">
|
||||
<tiny-carousel height="150px" loop :disabled="true" arrow="always">
|
||||
<tiny-carousel-item class="carousel-item-demo" v-for="item in 3" :key="item">
|
||||
<h3>{{ item }}</h3>
|
||||
</tiny-carousel-item>
|
||||
|
|
|
@ -9,7 +9,7 @@ test('关闭循环轮播', async ({ page }) => {
|
|||
const arrow = carousel.locator('.tiny-carousel__arrow')
|
||||
|
||||
// 左侧切换按钮应该不可见
|
||||
await expect(arrow.first()).not.toBeVisible()
|
||||
await expect(arrow.first()).toBeVisible()
|
||||
// 点击下一张按钮
|
||||
await arrow.nth(1).click()
|
||||
// 当前应该显示第二张幻灯片
|
||||
|
@ -18,7 +18,7 @@ test('关闭循环轮播', async ({ page }) => {
|
|||
// 当前应该显示第三张幻灯片
|
||||
await expect(carouselItems.nth(2)).toHaveCSS('transform', 'matrix(1, 0, 0, 1, 0, 0)')
|
||||
// 右侧切换按钮应该不可见
|
||||
await expect(arrow.nth(1)).not.toBeVisible()
|
||||
await expect(arrow.nth(1)).toBeVisible()
|
||||
// 点击上一张按钮
|
||||
await arrow.first().click()
|
||||
// 当前应该显示第一张幻灯片
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<tiny-carousel height="150px" :loop="false" arrow="always">
|
||||
<tiny-carousel height="150px" loop :disabled="true" arrow="always">
|
||||
<tiny-carousel-item class="carousel-item-demo" v-for="item in 3" :key="item">
|
||||
<h3>{{ item }}</h3>
|
||||
</tiny-carousel-item>
|
||||
|
|
|
@ -52,9 +52,9 @@ export default {
|
|||
},
|
||||
desc: {
|
||||
'zh-CN':
|
||||
'<p>通过配置 <code>loop</code> 属性为<code>false</code>后,若走马灯幻灯片已切换到最后一项,则将不能再从第一项开始循环切换。即切换到最后一项时,右侧切换箭头不再显示,切换到第一项时,左侧切换箭头不再显示。</p>\n',
|
||||
'<p>通过配置 <code>loop</code> 属性为<code>true</code>,<code>disabled</code> 属性为<code>true</code>后,若走马灯幻灯片已切换到最后一项,则将不能再从第一项开始循环切换。即切换到最后一项时,右侧切换箭头不再显示,切换到第一项时,左侧切换箭头不再显示。</p>\n',
|
||||
'en-US':
|
||||
'<p>After the <code>loop</code> attribute is set to <code>false</code>, if the slide is switched to the last item, the slide cannot be switched cyclically from the first item. That is, when switching to the last item, the right toggle arrow is no longer displayed, and when switching to the first item, the left toggle arrow is no longer displayed. </p>\n'
|
||||
'<p>After the <code>loop</code> attribute is set to <code>true</code> and the <code>disabled</code> attribute is set to <code>true</code> if the slide is switched to the last item, the slide cannot be switched cyclically from the first item. That is, when switching to the last item, the right toggle arrow is no longer displayed, and when switching to the first item, the left toggle arrow is no longer displayed. </p>\n'
|
||||
},
|
||||
codeFiles: ['close-loop.vue']
|
||||
},
|
||||
|
|
|
@ -59,6 +59,9 @@
|
|||
|
||||
.@{svg-prefix-cls} {
|
||||
fill: var(--ti-carousel-indicator-active-text-color);
|
||||
&:hover {
|
||||
fill: var(--ti-carousel-indicator-hover-text-color);
|
||||
}
|
||||
}
|
||||
|
||||
&.@{carousel-prefix-cls}__arrow-left {
|
||||
|
@ -86,7 +89,15 @@
|
|||
@apply ~'-translate-x-2/4';
|
||||
}
|
||||
|
||||
&:hover {
|
||||
&.@{carousel-prefix-cls}__arrow-disabled {
|
||||
background-color: var(--ti-carousel-arrow-disabled-bg-color);
|
||||
cursor: not-allowed;
|
||||
.@{svg-prefix-cls} {
|
||||
fill: var(--ti-carousel-arrow-disabled-color);
|
||||
}
|
||||
}
|
||||
|
||||
&:not(.@{carousel-prefix-cls}__arrow-disabled):hover {
|
||||
background-color: var(--ti-carousel-arrow-hover-bg-color);
|
||||
color: var(--ti-carousel-arrow-hover-text-color);
|
||||
}
|
||||
|
|
|
@ -36,7 +36,9 @@
|
|||
// 指示器圆角的背景色(hide)
|
||||
--ti-carousel-indicators-radius-bg-color: rgba(0, 0, 0, 0.3);
|
||||
// 幻灯片内的当前指示器图标色
|
||||
--ti-carousel-indicator-active-text-color: var(--ti-common-color-text-primary);
|
||||
--ti-carousel-indicator-active-text-color: var(--ti-common-color-icon-normal);
|
||||
// 幻灯片内的悬浮指示器图标色
|
||||
--ti-carousel-indicator-hover-text-color: var(--ti-common-color-primary-normal);
|
||||
// 指示器按钮宽度
|
||||
--ti-carousel-indicator-button-width: var(--ti-common-size-2x, 8px);
|
||||
// 指示器按钮高度
|
||||
|
@ -74,7 +76,11 @@
|
|||
// 箭头悬浮文本颜色(hide)
|
||||
--ti-carousel-arrow-hover-text-color: var(--ti-common-color-text-primary);
|
||||
// 左侧箭头背景色
|
||||
--ti-carousel-arrow-left-bg-color: #f5f5f5;
|
||||
--ti-carousel-arrow-left-bg-color: var(--ti-common-color-bg-normal);
|
||||
// 右侧箭头背景色
|
||||
--ti-carousel-arrow-right-bg-color: #f5f5f5;
|
||||
--ti-carousel-arrow-right-bg-color: var(--ti-common-color-bg-normal);
|
||||
// 按钮禁用色
|
||||
--ti-carousel-arrow-disabled-bg-color: var(--ti-common-color-bg-disabled);
|
||||
// 按钮禁用色
|
||||
--ti-carousel-arrow-disabled-color: var(--ti-common-color-primary-disabled-text);
|
||||
}
|
|
@ -46,6 +46,10 @@ export default defineComponent({
|
|||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
indicatorPosition: String,
|
||||
arrow: {
|
||||
type: String,
|
||||
|
|
|
@ -24,8 +24,12 @@
|
|||
v-if="state.hasButtons"
|
||||
v-show="(arrow === 'always' || state.hover) && (loop || state.activeIndex > 0)"
|
||||
type="button"
|
||||
class="tiny-carousel__arrow"
|
||||
:class="type === 'vertical' ? 'tiny-carousel__arrow-top' : 'tiny-carousel__arrow-left'"
|
||||
:class="[
|
||||
'tiny-carousel__arrow',
|
||||
type === 'vertical' ? 'tiny-carousel__arrow-top' : 'tiny-carousel__arrow-left',
|
||||
disabled && state.activeIndex === 0 ? 'tiny-carousel__arrow-disabled' : ''
|
||||
]"
|
||||
:disabled="loop && disabled && state.activeIndex === 0"
|
||||
@mouseenter="handleButtonEnter('left')"
|
||||
@mouseleave="handleButtonLeave"
|
||||
@click.stop="throttledArrowClick(state.activeIndex - 1)"
|
||||
|
@ -40,8 +44,12 @@
|
|||
v-if="state.hasButtons"
|
||||
v-show="(arrow === 'always' || state.hover) && (loop || state.activeIndex < state.items.length - 1)"
|
||||
type="button"
|
||||
class="tiny-carousel__arrow"
|
||||
:class="type === 'vertical' ? 'tiny-carousel__arrow-bottom' : 'tiny-carousel__arrow-right'"
|
||||
:class="[
|
||||
'tiny-carousel__arrow',
|
||||
type === 'vertical' ? 'tiny-carousel__arrow-bottom' : 'tiny-carousel__arrow-right',
|
||||
disabled && state.activeIndex === state.items.length - 1 ? 'tiny-carousel__arrow-disabled' : ''
|
||||
]"
|
||||
:disabled="loop && disabled && state.activeIndex === state.items.length - 1"
|
||||
@mouseenter="handleButtonEnter('right')"
|
||||
@mouseleave="handleButtonLeave"
|
||||
@click.stop="throttledArrowClick(state.activeIndex + 1)"
|
||||
|
@ -97,6 +105,7 @@ export default defineComponent({
|
|||
'type',
|
||||
'showTitle',
|
||||
'loop',
|
||||
'disabled',
|
||||
'swipeable',
|
||||
'lite',
|
||||
'beforeSwipe'
|
||||
|
|
Loading…
Reference in New Issue