Skip to content

Commit dbaad31

Browse files
authored
feat(progress): [progress] add slot support for custom status icons (#2979)
* feat(progress): add slot support for custom status icons * test(progress): fix expect error * docs: add feature version tag
1 parent 1abe02d commit dbaad31

File tree

8 files changed

+183
-15
lines changed

8 files changed

+183
-15
lines changed

examples/sites/demos/apis/progress.js

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,20 @@ export default {
140140
],
141141
events: [],
142142
methods: [],
143-
slots: []
143+
slots: [
144+
{
145+
name: 'statusIcon',
146+
desc: {
147+
'zh-CN': '状态插槽,successIcon / exceptionIcon / warningIcon',
148+
'en-US': 'Status slot, successIcon / exceptionIcon / warningIcon'
149+
},
150+
mode: ['pc', 'mobile-first'],
151+
pcDemo: 'slot-icon-status',
152+
meta: {
153+
stable: '3.22.0'
154+
}
155+
}
156+
]
144157
}
145158
],
146159
types: [
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<template>
2+
<div>
3+
<tiny-progress class="progress" :stroke-width="12" :percentage="100" status="success">
4+
<template #successIcon>
5+
<TinyIconSmile />
6+
</template>
7+
</tiny-progress>
8+
<br />
9+
<tiny-progress class="progress" :stroke-width="12" :percentage="80" status="warning">
10+
<template #warningIcon>
11+
<TinyIconMeh />
12+
</template>
13+
</tiny-progress>
14+
<br />
15+
<tiny-progress class="progress" :stroke-width="12" :percentage="50" status="exception">
16+
<template #exceptionIcon>
17+
<TinyIconFrown />
18+
</template>
19+
</tiny-progress>
20+
</div>
21+
</template>
22+
23+
<script lang="jsx">
24+
import { TinyProgress } from '@opentiny/vue'
25+
import { IconFrown, IconMeh, IconSmile } from '@opentiny/vue-icon'
26+
27+
export default {
28+
components: {
29+
TinyProgress,
30+
TinyIconSmile: IconSmile(),
31+
TinyIconMeh: IconMeh(),
32+
TinyIconFrown: IconFrown()
33+
}
34+
}
35+
</script>
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<template>
2+
<div>
3+
<tiny-progress class="progress" :stroke-width="12" :percentage="100" status="success">
4+
<template #successIcon>
5+
<TinyIconSmile />
6+
</template>
7+
</tiny-progress>
8+
<br />
9+
<tiny-progress class="progress" :stroke-width="12" :percentage="80" status="warning">
10+
<template #warningIcon>
11+
<TinyIconMeh />
12+
</template>
13+
</tiny-progress>
14+
<br />
15+
<tiny-progress class="progress" :stroke-width="12" :percentage="50" status="exception">
16+
<template #exceptionIcon>
17+
<TinyIconFrown />
18+
</template>
19+
</tiny-progress>
20+
</div>
21+
</template>
22+
23+
<script setup>
24+
import { TinyProgress } from '@opentiny/vue'
25+
import { IconFrown, IconMeh, IconSmile } from '@opentiny/vue-icon'
26+
27+
const TinyIconSmile = IconSmile()
28+
const TinyIconMeh = IconMeh()
29+
const TinyIconFrown = IconFrown()
30+
</script>
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { test, expect } from '@playwright/test'
2+
3+
test.describe('Icon Status Slots', () => {
4+
test('should display correct icon for success status', async ({ page }) => {
5+
page.on('pageerror', (exception) => expect(exception).not.toBeNull())
6+
await page.goto('progress#slot-icon-status')
7+
8+
const progressLocator = page.getByRole('progressbar').nth(0)
9+
const iconLocator = progressLocator.locator('svg')
10+
await expect(progressLocator).toHaveClass(/is-success/)
11+
await expect(iconLocator).toBeVisible()
12+
await expect(iconLocator.locator('.smile_svg__st0').first()).toBeVisible()
13+
})
14+
15+
test('should display correct icon for warning status', async ({ page }) => {
16+
page.on('pageerror', (exception) => expect(exception).not.toBeNull())
17+
await page.goto('progress#slot-icon-status')
18+
19+
const progressLocator = page.getByRole('progressbar').nth(1)
20+
const iconLocator = progressLocator.locator('svg')
21+
22+
await expect(progressLocator).toHaveClass(/is-warning/)
23+
await expect(iconLocator).toBeVisible()
24+
await expect(iconLocator.locator('.meh_svg__st0').first()).toBeVisible()
25+
})
26+
27+
test('should display correct icon for exception status', async ({ page }) => {
28+
page.on('pageerror', (exception) => expect(exception).not.toBeNull())
29+
await page.goto('progress#slot-icon-status')
30+
31+
const progressLocator = page.getByRole('progressbar').nth(2)
32+
const iconLocator = progressLocator.locator('svg')
33+
34+
await expect(progressLocator).toHaveClass(/is-exception/)
35+
await expect(iconLocator).toBeVisible()
36+
await expect(iconLocator.locator('.frown_svg__st0').first()).toBeVisible()
37+
})
38+
})
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<template>
2+
<div>
3+
<tiny-progress class="progress" :stroke-width="12" :percentage="100" status="success">
4+
<template #successIcon>
5+
<TinyIconSmile />
6+
</template>
7+
</tiny-progress>
8+
<br />
9+
<tiny-progress class="progress" :stroke-width="12" :percentage="80" status="warning">
10+
<template #warningIcon>
11+
<TinyIconMeh />
12+
</template>
13+
</tiny-progress>
14+
<br />
15+
<tiny-progress class="progress" :stroke-width="12" :percentage="50" status="exception">
16+
<template #exceptionIcon>
17+
<TinyIconFrown />
18+
</template>
19+
</tiny-progress>
20+
</div>
21+
</template>
22+
23+
<script lang="jsx">
24+
import { TinyProgress } from '@opentiny/vue'
25+
import { IconFrown, IconMeh, IconSmile } from '@opentiny/vue-icon'
26+
27+
export default {
28+
components: {
29+
TinyProgress,
30+
TinyIconSmile: IconSmile(),
31+
TinyIconMeh: IconMeh(),
32+
TinyIconFrown: IconFrown()
33+
}
34+
}
35+
</script>

examples/sites/demos/pc/app/progress/webdoc/progress.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,18 @@ export default {
5555
},
5656
codeFiles: ['progress-status.vue']
5757
},
58+
{
59+
demoId: 'slot-icon-status',
60+
name: {
61+
'zh-CN': '图标状态插槽',
62+
'en-US': 'Icon Status Slot'
63+
},
64+
desc: {
65+
'zh-CN': '通过插槽自定义状态图标。',
66+
'en-US': 'Customize the status icon through a slot.'
67+
},
68+
codeFiles: ['slot-icon-status.vue']
69+
},
5870
{
5971
demoId: 'custom-status',
6072
name: {

packages/vue/src/progress/src/mobile-first.vue

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -108,19 +108,21 @@
108108
<span v-if="typeof format !== 'function'" :style="{ fontSize: state.percentTextSize + 'px' }">%</span>
109109
</div>
110110
</template>
111-
<component
112-
v-else
113-
:is="state.iconClass"
114-
:class="[
115-
status === 'success' && 'fill-color-success',
116-
status === 'warning' && 'fill-color-warning',
117-
status === 'exception' && 'fill-color-error',
118-
size === 'small' ? (type === 'line' ? 'w-3 h-3' : 'w-6 h-6') : '',
119-
size === 'medium' ? (type === 'line' ? 'w-4 h-4' : 'w-10 h-10') : '',
120-
size === 'large' ? (type === 'line' ? 'w-6 h-6' : 'w-20 h-20') : ''
121-
]"
122-
:style="state.iconStyle"
123-
/>
111+
112+
<slot v-else :name="status + 'Icon'">
113+
<component
114+
:is="state.iconClass"
115+
:class="[
116+
status === 'success' && 'fill-color-success',
117+
status === 'warning' && 'fill-color-warning',
118+
status === 'exception' && 'fill-color-error',
119+
size === 'small' ? (type === 'line' ? 'w-3 h-3' : 'w-6 h-6') : '',
120+
size === 'medium' ? (type === 'line' ? 'w-4 h-4' : 'w-10 h-10') : '',
121+
size === 'large' ? (type === 'line' ? 'w-6 h-6' : 'w-20 h-20') : ''
122+
]"
123+
:style="state.iconStyle"
124+
/>
125+
</slot>
124126
</div>
125127
</div>
126128
<div

packages/vue/src/progress/src/pc.vue

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,10 @@
8585
<template v-if="!status">
8686
{{ state.content }}
8787
</template>
88-
<component v-else :is="state.iconClass" class="tiny-svg-size" />
88+
89+
<slot v-else :name="status + 'Icon'">
90+
<component :is="state.iconClass" class="tiny-svg-size" />
91+
</slot>
8992
</div>
9093
</div>
9194
</template>

0 commit comments

Comments
 (0)