feat: Toast 轻提示组件支持使用组件库内置和自定义图标

 Closes: #444
This commit is contained in:
weisheng 2024-07-18 23:22:29 +08:00
parent 0e835fa03d
commit 723c51bac9
15 changed files with 153 additions and 71 deletions

View File

@ -30,25 +30,40 @@
## 自定义图标
如果需要在现有 Icon 的基础上使用更多图标,可以引入第三方 iconfont 对应的字体文件和 CSS 文件,之后就可以在 Icon 组件中直接使用。
``` scss
/* 引入第三方或自定义的字体图标样式 */
``` css
/* 路径 src/iconfont/index.css */
@font-face {
font-family: 'my-icon';
src: url('./my-icon.ttf') format('truetype');
font-family: "fish";
src: url('//at.alicdn.com/t/c/font_4626013_vwpx4thmin.woff2?t=1721314121733') format('woff2'),
url('//at.alicdn.com/t/c/font_4626013_vwpx4thmin.woff?t=1721314121733') format('woff'),
url('//at.alicdn.com/t/c/font_4626013_vwpx4thmin.ttf?t=1721314121733') format('truetype');
}
.my-icon {
font-family: 'my-icon';
.fish {
font-family: "fish" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.my-icon-extra::before {
content: '\e626';
.fish-kehuishouwu:before {
content: "\e627";
}
```
```html
<!-- app.vue -->
<style>
@import '@/iconfont/index.css';
</style>
```
```html
<!-- 通过 class-prefix 指定类名为 my-icon -->
<wd-icon class-prefix="my-icon" name="extra" />
<!-- 通过 class-prefix 指定类名为 fish -->
<wd-icon class-prefix="fish" name="kehuishouwu" />
```
## Attributes

View File

@ -31,6 +31,25 @@ toast.warning('提示信息')
toast.info('常规提示信息')
```
## 使用图标
可以使用`iconClass`指定图标,结合`classPrefix`可以使用自定义图标,参见[icon](/component/icon#自定义图标)。
```ts
// 使用组件库内部图标
toast.show({
iconClass: 'star',
msg: '使用组件库内部图标'
})
```
```ts
// 使用自定义图标
toast.show({
iconClass: 'kehuishouwu',
classPrefix: 'fish',
msg: '使用自定义图标'
})
```
## 提示位置
```typescript
@ -89,9 +108,9 @@ toast.close()
| msg | 消息内容 | string | - | - | - |
| duration | 持续时间,单位 ms为 0 时表示不自动关闭 | number | - | 2000 | - |
| iconName | 图标类型 | string | success / error / warning | - | - |
| iconSize | 左侧图标尺寸 | string | - | 42px | - |
| iconSize | 左侧图标尺寸 | string | - | - | - |
| iconClass | 图标类目,自定义图标,可以使用 Icon 章节的那些图标类名iconName 优先级更高 | string | - | - | - |
| customIcon | 自定义图标,开启后可以通过 custom-icon-class 类名自定义图标 | Boolean | - | false | - |
| classPrefix | 类名前缀,用于使用自定义图标 | string | - | - | - |
| position | 提示信息框的位置 | string | top / middle / bottom | middle | - |
| zIndex | toast 层级 | number | - | 100 | - |
| loadingType | [加载中图标类型](/component/loading) | string | ring | outline | - |
@ -116,4 +135,3 @@ toast.close()
| 类名 | 说明 | 最低版本 |
| ----------------- | -------------- | -------- |
| custom-class | 根节点样式 | - |
| custom-icon-class | 自定义图标类名 | - |

View File

@ -33,6 +33,8 @@ onHide(() => {
})
</script>
<style lang="scss">
@import '@/iconfont/index.css';
::-webkit-scrollbar {
width: 0;
height: 0;

18
src/iconfont/index.css Normal file
View File

@ -0,0 +1,18 @@
@font-face {
font-family: "fish"; /* Project id 4626013 */
src: url('//at.alicdn.com/t/c/font_4626013_vwpx4thmin.woff2?t=1721314121733') format('woff2'),
url('//at.alicdn.com/t/c/font_4626013_vwpx4thmin.woff?t=1721314121733') format('woff'),
url('//at.alicdn.com/t/c/font_4626013_vwpx4thmin.ttf?t=1721314121733') format('truetype');
}
.fish {
font-family: "fish" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.fish-kehuishouwu:before {
content: "\e627";
}

View File

@ -1,12 +1,3 @@
<!--
* @Author: weisheng
* @Date: 2023-09-20 11:10:44
* @LastEditTime: 2024-04-11 13:13:28
* @LastEditors: weisheng
* @Description:
* @FilePath: \wot-design-uni\src\pages\toast\Index.vue
* 记得注释
-->
<template>
<view>
<page-wraper>
@ -20,6 +11,10 @@
<wd-button @click="showWarnToast">警告toast</wd-button>
<wd-button @click="showNormalToast">常规toast</wd-button>
</demo-block>
<demo-block title="使用图标">
<wd-button @click="showInnerIconToast">内部图标</wd-button>
<wd-button @click="showCustomIconToast">自定义图标</wd-button>
</demo-block>
<demo-block title="提示位置">
<wd-button @click="showTopToast">顶部toast</wd-button>
<wd-button @click="showBottomToast">底部toast</wd-button>
@ -54,6 +49,7 @@ function showNormalToast() {
function showTopToast() {
toast.show({
position: 'top',
iconClass: 'star',
msg: '提示信息',
closed() {
console.log(232)
@ -88,6 +84,21 @@ function showLoadingToast2() {
function showLongToast() {
toast.show('这是一段很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长的文案')
}
function showInnerIconToast() {
toast.show({
iconClass: 'star',
msg: '使用组件库内部图标'
})
}
function showCustomIconToast() {
toast.show({
iconClass: 'kehuishouwu',
classPrefix: 'fish',
msg: '使用自定义图标'
})
}
</script>
<style lang="scss" scoped>
:deep(button) {

View File

@ -630,10 +630,14 @@ $-toast-radius: var(--wot-toast-radius, 8px) !default; // 圆角大小
$-toast-bg: var(--wot-toast-bg, $-overlay-bg) !default; // 背景色
$-toast-fs: var(--wot-toast-fs, $-fs-content) !default; // 字号
$-toast-with-icon-min-width: var(--wot-toast-with-icon-min-width, 150px) !default; // 有图标的情况下最小宽度
$-toast-icon-size: var(--wot-toast-icon-size, 39px) !default; // 图标大小
$-toast-icon-size: var(--wot-toast-icon-size, 32px) !default; // 图标大小
$-toast-icon-margin-right: var(--wot-toast-icon-margin-right, 12px) !default; // 图标右边距
$-toast-loading-padding: var(--wot-toast-loading-padding, 10px) !default; // loading 下的padding
$-toast-box-shadow: var(--wot-toast-box-shadow, 0px 6px 16px 0px rgba(0, 0, 0, 0.08)) !default; // 外部阴影
/* loading */
$-loading-size: var(--wot-loading-size, 32px) !default; // loading 大小
/* tooltip */
$-tooltip-bg: var(--wot-tooltip-bg, rgba(38, 39, 40, 0.8)) !default; // 背景色
$-tooltip-color: var(--wot-tooltip-color, $-color-white) !default; // 文字颜色
@ -890,4 +894,4 @@ $-text-success-color: var(--wot-text-success-color, $-color-success) !default;
/* video-preview */
$-video-preview-bg: var(--wot-video-preview-bg, rgba(0, 0, 0, 0.8)) !default; // 背景色
$-video-preview-close-color: var(--wot-video-preview-close-color, #fff) !default; // 图标颜色
$-video-preview-close-font-size: var(--wot-video-preview-close-font-size, 20px) !default; // 图标大小
$-video-preview-close-font-size: var(--wot-video-preview-close-font-size, 20px) !default; // 图标大小

View File

@ -22,7 +22,7 @@ function s4() {
* @return {string} num+px
*/
export function addUnit(num: number | string) {
return Number.isNaN(Number(num)) ? num : `${num}px`
return !isNumber(num) ? num : `${num}px`
}
/**

View File

@ -648,10 +648,15 @@ export type toastThemeVars = {
toastFs?: string
toastWithIconMinWidth?: string
toastIconSize?: string
toastIconMarginRight?: string
toastLoadingPadding?: string
toastBoxShadow?: string
}
export type loadingThemeVars = {
loadingSize?: string
}
export type tooltipThemeVars = {
tooltipBg?: string
tooltipColor?: string
@ -966,6 +971,7 @@ export type ConfigProviderThemeVars = baseThemeVars &
tabsThemeVars &
tagThemeVars &
toastThemeVars &
loadingThemeVars &
tooltipThemeVars &
popoverThemeVars &
gridItemThemeVars &

View File

@ -6,6 +6,8 @@
line-height: 0;
vertical-align: middle;
display: inline-block;
width: $-loading-size;
height: $-loading-size;
@include e(body) {
width: 100%;

View File

@ -1,10 +1,10 @@
/*
* @Author: weisheng
* @Date: 2024-03-15 20:40:34
* @LastEditTime: 2024-05-27 18:49:28
* @LastEditTime: 2024-07-18 22:09:12
* @LastEditors: weisheng
* @Description:
* @FilePath: \wot-design-uni\src\uni_modules\wot-design-uni\components\wd-loading\types.ts
* @FilePath: /wot-design-uni/src/uni_modules/wot-design-uni/components/wd-loading/types.ts
*
*/
import type { ExtractPropTypes } from 'vue'
@ -25,7 +25,7 @@ export const loadingProps = {
/**
*
*/
size: makeNumericProp('32px')
size: makeNumericProp('')
}
export type LoadingProps = ExtractPropTypes<typeof loadingProps>

View File

@ -1,5 +1,5 @@
<template>
<view :class="rootClass" :style="rootStyle">
<view :class="`wd-loading ${props.customClass}`" :style="rootStyle">
<view class="wd-loading__body">
<view class="wd-loading__svg" :style="`background-image: url(${svg});`"></view>
</view>
@ -17,7 +17,7 @@ export default {
</script>
<script lang="ts" setup>
import { computed, onBeforeMount, ref, watch } from 'vue'
import { computed, onBeforeMount, ref, watch, type CSSProperties } from 'vue'
import base64 from '../common/base64'
import { gradient, context, objToStyle, addUnit, isDef } from '../common/util'
import { loadingProps } from './types'
@ -39,7 +39,7 @@ const props = defineProps(loadingProps)
const svg = ref<string>('')
const intermediateColor = ref<string>('')
const iconSize = ref<string | number>('32px')
const iconSize = ref<string | number | null>(null)
watch(
() => props.size,
@ -64,17 +64,14 @@ watch(
)
const rootStyle = computed(() => {
const style: Record<string, string | number> = {
width: iconSize.value,
height: iconSize.value
const style: CSSProperties = {}
if (isDef(iconSize.value)) {
style.height = addUnit(iconSize.value)
style.width = addUnit(iconSize.value)
}
return `${objToStyle(style)}; ${props.customStyle}`
})
const rootClass = computed(() => {
return `wd-loading ${props.customClass}`
})
onBeforeMount(() => {
intermediateColor.value = gradient(props.color, '#ffffff', 2)[1]
buildSvg()

View File

@ -19,9 +19,10 @@
text-align: left;
font-family: "San Francisco", Rotobo, arial, "PingFang SC", "Noto SansCJK", "Microsoft Yahei", sans-serif;
}
@include e(icon) {
@include edeep(icon) {
display: inline-block;
margin-right: 16px;
margin-right: $-toast-icon-margin-right;
font-size: $-toast-icon-size;
}
@include e(iconWrap){
font-size: 0;
@ -34,6 +35,8 @@
height: 100%;
}
@include e(iconSvg){
width: $-toast-icon-size;
height: $-toast-icon-size;
background-size: cover;
background-repeat: no-repeat;
}

View File

@ -1,10 +1,10 @@
/*
* @Author: weisheng
* @Date: 2024-03-29 13:29:57
* @LastEditTime: 2024-04-10 20:18:47
* @LastEditTime: 2024-07-18 23:16:16
* @LastEditors: weisheng
* @Description:
* @FilePath: \wot-design-uni\src\uni_modules\wot-design-uni\components\wd-toast\index.ts
* @FilePath: /wot-design-uni/src/uni_modules/wot-design-uni/components/wd-toast/index.ts
*
*/
import { provide, ref } from 'vue'
@ -25,9 +25,6 @@ export const defaultOptions: ToastOptions = {
loadingType: 'outline',
loadingColor: '#4D80F0',
iconColor: '#4D80F0',
iconSize: 42,
loadingSize: 42,
customIcon: false,
position: 'middle',
show: false,
zIndex: 100

View File

@ -1,10 +1,10 @@
/*
* @Author: weisheng
* @Date: 2023-06-19 12:47:57
* @LastEditTime: 2024-04-11 13:03:38
* @LastEditTime: 2024-07-18 22:18:07
* @LastEditors: weisheng
* @Description:
* @FilePath: \wot-design-uni\src\uni_modules\wot-design-uni\components\wd-toast\types.ts
* @FilePath: /wot-design-uni/src/uni_modules/wot-design-uni/components/wd-toast/types.ts
*
*/
import type { ExtractPropTypes } from 'vue'
@ -24,9 +24,8 @@ export type ToastOptions = {
iconSize?: number
loadingType?: ToastLoadingType
loadingColor?: string
iconColor?: string
loadingSize?: number
customIcon?: boolean
iconColor?: string
position?: ToastPositionType
show?: boolean
zIndex?: number
@ -34,6 +33,14 @@ export type ToastOptions = {
*
*/
cover?: boolean
/**
*
*/
iconClass?: string
/**
* 使
*/
classPrefix?: string
/**
*
*/
@ -63,7 +70,6 @@ export interface Toast {
export const toastProps = {
...baseProps,
customIconClass: makeStringProp(''),
selector: makeStringProp('')
}

View File

@ -3,17 +3,16 @@
<wd-transition name="fade" :show="show" :custom-style="transitionStyle" @after-enter="handleAfterEnter" @after-leave="handleAfterLeave">
<view :class="rootClass">
<!--iconName优先级更高-->
<wd-loading v-if="iconName === 'loading'" :type="loadingType" :color="loadingColor" custom-class="wd-toast__icon" :customStyle="loadingStyle" />
<wd-loading v-if="iconName === 'loading'" :type="loadingType" :color="loadingColor" :size="loadingSize" custom-class="wd-toast__icon" />
<view
class="wd-toast__iconWrap wd-toast__icon"
v-else-if="iconName === 'success' || iconName === 'warning' || iconName === 'info' || iconName === 'error'"
:style="`width:${iconSize}px; height:${iconSize}px`"
>
<view class="wd-toast__iconBox">
<view class="wd-toast__iconSvg" :style="`background-image: url(${svgStr}); width:${iconSize}px; height:${iconSize}px`"></view>
<view class="wd-toast__iconSvg" :style="svgStyle"></view>
</view>
</view>
<view v-else-if="customIcon" class="wd-toast__icon custom-icon-class" />
<wd-icon v-else-if="iconClass" custom-class="wd-toast__icon" :size="iconSize" :class-prefix="classPrefix" :name="iconClass"></wd-icon>
<!--文本-->
<view v-if="msg" class="wd-toast__msg">{{ msg }}</view>
</view>
@ -36,21 +35,23 @@ import { computed, inject, onBeforeMount, ref, watch, type CSSProperties } from
import base64 from '../common/base64'
import { defaultOptions, toastDefaultOptionKey, toastIcon } from '.'
import { toastProps, type ToastLoadingType, type ToastOptions } from './types'
import { isDef, isFunction, objToStyle } from '../common/util'
import { addUnit, isDef, isFunction, objToStyle } from '../common/util'
const props = defineProps(toastProps)
const iconName = ref<string>('') //
const customIcon = ref<boolean>(false)
const msg = ref<string>('') //
const position = ref<string>('middle')
const show = ref<boolean>(false)
const zIndex = ref<number>(100)
const loadingType = ref<ToastLoadingType>('outline')
const loadingColor = ref<string>('#4D80F0')
const iconSize = ref<number>(42)
const iconSize = ref<string>() //
const loadingSize = ref<string>() // loading
const svgStr = ref<string>('') //
const cover = ref<boolean>(false) //
const classPrefix = ref<string>('wd-icon') //
const iconClass = ref<string>('') //
let opened: (() => void) | null = null
@ -99,23 +100,23 @@ const transitionStyle = computed(() => {
return objToStyle(style)
})
/**
* 加载自定义样式
*/
const loadingStyle = computed(() => {
const style: CSSProperties = {
display: 'inline-block',
'margin-right': '16px'
}
return objToStyle(style)
})
const rootClass = computed(() => {
return `wd-toast ${props.customClass} wd-toast--${position.value} ${
(iconName.value !== 'loading' || msg.value) && (iconName.value || customIcon.value) ? 'wd-toast--with-icon' : ''
(iconName.value !== 'loading' || msg.value) && (iconName.value || iconClass.value) ? 'wd-toast--with-icon' : ''
} ${iconName.value === 'loading' && !msg.value ? 'wd-toast--loading' : ''}`
})
const svgStyle = computed(() => {
const style: CSSProperties = {
backgroundImage: `url(${svgStr.value})`
}
if (isDef(iconSize.value)) {
style.width = iconSize.value
style.height = iconSize.value
}
return objToStyle(style)
})
onBeforeMount(() => {
buildSvg()
})
@ -149,14 +150,16 @@ function reset(option: ToastOptions) {
if (show.value) {
iconName.value = isDef(option.iconName!) ? option.iconName! : ''
customIcon.value = isDef(option.customIcon!) ? option.customIcon! : false
iconClass.value = isDef(option.iconClass!) ? option.iconClass! : ''
msg.value = isDef(option.msg!) ? option.msg! : ''
position.value = isDef(option.position!) ? option.position! : 'middle'
zIndex.value = isDef(option.zIndex!) ? option.zIndex! : 100
loadingType.value = isDef(option.loadingType!) ? option.loadingType! : 'outline'
loadingColor.value = isDef(option.loadingColor!) ? option.loadingColor! : '#4D80F0'
iconSize.value = isDef(option.iconSize!) ? option.iconSize! : 42
iconSize.value = isDef(option.iconSize) ? addUnit(option.iconSize) : option.iconSize
loadingSize.value = isDef(option.loadingSize) ? addUnit(option.loadingSize) : option.loadingSize
cover.value = isDef(option.cover!) ? option.cover! : false
classPrefix.value = isDef(option.classPrefix) ? option.classPrefix : 'wd-icon'
closed = isFunction(option.closed) ? option.closed : null
opened = isFunction(option.opened) ? option.opened : null
}