From f05e60e161badebc41e0e6cda296d4e428ff44d0 Mon Sep 17 00:00:00 2001 From: "X.Q. Chen" <31237954+brenner8023@users.noreply.github.com> Date: Tue, 16 Nov 2021 13:08:50 +0800 Subject: [PATCH] feat(comp:alert): add alert component --- .../__snapshots__/alert.spec.ts.snap | 13 ++ .../components/alert/__tests__/alert.spec.ts | 114 +++++++++++++++ packages/components/alert/demo/Basic.md | 9 ++ packages/components/alert/demo/Basic.vue | 6 + packages/components/alert/demo/Close.md | 9 ++ packages/components/alert/demo/Close.vue | 53 +++++++ packages/components/alert/demo/Description.md | 9 ++ .../components/alert/demo/Description.vue | 15 ++ packages/components/alert/demo/Icon.md | 9 ++ packages/components/alert/demo/Icon.vue | 13 ++ packages/components/alert/demo/LongText.md | 9 ++ packages/components/alert/demo/LongText.vue | 5 + packages/components/alert/demo/Pagination.md | 9 ++ packages/components/alert/demo/Pagination.vue | 30 ++++ packages/components/alert/docs/Index.zh.md | 33 +++++ packages/components/alert/index.ts | 16 +++ packages/components/alert/src/Alert.tsx | 133 ++++++++++++++++++ packages/components/alert/src/types.ts | 37 +++++ packages/components/alert/style/index.less | 57 ++++++++ packages/components/alert/style/index.ts | 5 + packages/components/alert/style/mixin.less | 27 ++++ .../alert/style/themes/default.less | 20 +++ packages/components/components.less | 1 + .../components/config/src/defaultConfig.ts | 7 + packages/components/config/src/types.ts | 6 + packages/components/index.ts | 2 + 26 files changed, 647 insertions(+) create mode 100644 packages/components/alert/__tests__/__snapshots__/alert.spec.ts.snap create mode 100644 packages/components/alert/__tests__/alert.spec.ts create mode 100644 packages/components/alert/demo/Basic.md create mode 100644 packages/components/alert/demo/Basic.vue create mode 100644 packages/components/alert/demo/Close.md create mode 100644 packages/components/alert/demo/Close.vue create mode 100644 packages/components/alert/demo/Description.md create mode 100644 packages/components/alert/demo/Description.vue create mode 100644 packages/components/alert/demo/Icon.md create mode 100644 packages/components/alert/demo/Icon.vue create mode 100644 packages/components/alert/demo/LongText.md create mode 100644 packages/components/alert/demo/LongText.vue create mode 100644 packages/components/alert/demo/Pagination.md create mode 100644 packages/components/alert/demo/Pagination.vue create mode 100644 packages/components/alert/docs/Index.zh.md create mode 100644 packages/components/alert/index.ts create mode 100644 packages/components/alert/src/Alert.tsx create mode 100644 packages/components/alert/src/types.ts create mode 100644 packages/components/alert/style/index.less create mode 100644 packages/components/alert/style/index.ts create mode 100644 packages/components/alert/style/mixin.less create mode 100644 packages/components/alert/style/themes/default.less diff --git a/packages/components/alert/__tests__/__snapshots__/alert.spec.ts.snap b/packages/components/alert/__tests__/__snapshots__/alert.spec.ts.snap new file mode 100644 index 000000000..5d7bc1389 --- /dev/null +++ b/packages/components/alert/__tests__/__snapshots__/alert.spec.ts.snap @@ -0,0 +1,13 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Alert render work 1`] = ` +" +
+
+ +
+ + +
+
" +`; diff --git a/packages/components/alert/__tests__/alert.spec.ts b/packages/components/alert/__tests__/alert.spec.ts new file mode 100644 index 000000000..9ef5e8ccf --- /dev/null +++ b/packages/components/alert/__tests__/alert.spec.ts @@ -0,0 +1,114 @@ +import { MountingOptions, mount } from '@vue/test-utils' +import { h } from 'vue' + +import { renderWork } from '@tests' + +import IxAlert from '../src/Alert' +import { AlertProps } from '../src/types' + +describe('Alert', () => { + const AlertMount = (options?: MountingOptions>) => mount(IxAlert, { ...options }) + + renderWork(IxAlert) + + test('props type work', async () => { + const wrapper = AlertMount({ props: { type: 'success' } }) + + expect(wrapper.find('.ix-alert').classes()).toContain('ix-alert-success') + + await wrapper.setProps({ type: 'warning' }) + expect(wrapper.find('.ix-alert').classes()).toContain('ix-alert-warning') + + await wrapper.setProps({ type: 'error' }) + expect(wrapper.find('.ix-alert').classes()).toContain('ix-alert-error') + + await wrapper.setProps({ type: 'info' }) + expect(wrapper.find('.ix-alert').classes()).toContain('ix-alert-info') + }) + + test('props icon work', async () => { + const wrapper = AlertMount({ props: { icon: 'bug' } }) + + expect(wrapper.find('.ix-icon').classes()).toContain('ix-icon-bug') + + await wrapper.setProps({ icon: '' }) + expect(wrapper.find('.ix-icon').exists()).toBeFalsy() + }) + + test('props title description work', async () => { + const wrapper = AlertMount({ props: { title: 'alert title' } }) + + expect(wrapper.find('.ix-alert-content').text()).toContain('alert title') + expect(wrapper.find('.ix-alert').classes()).not.toContain('ix-alert-with-description') + + await wrapper.setProps({ title: ['title1', 'title2'] }) + expect(wrapper.find('.ix-alert-content').text()).toContain('title1title2') + + await wrapper.setProps({ description: 'alert description' }) + expect(wrapper.find('.ix-alert-content').text()).toContain('alert description') + expect(wrapper.find('.ix-alert').classes()).toContain('ix-alert-with-description') + }) + + test('props closable work', async () => { + const onClose = jest.fn() + const wrapper = AlertMount({ props: { closable: false, onClose } }) + + expect(wrapper.find('.ix-alert-close-icon').exists()).toBeFalsy() + + await wrapper.setProps({ closable: true }) + await wrapper.find('.ix-alert-close-icon').trigger('click') + expect(onClose).toHaveBeenCalledTimes(1) + }) + + test('props onBeforeClose work', async () => { + const onBeforeClose = jest.fn().mockResolvedValue(false) + const onClose = jest.fn() + const wrapper = AlertMount({ + props: { + closable: true, + onBeforeClose, + onClose, + }, + }) + + await wrapper.find('.ix-alert-close-icon').trigger('click') + expect(onBeforeClose).toHaveBeenCalledTimes(1) + expect(onClose).toHaveBeenCalledTimes(0) + + onBeforeClose.mockReturnValue(true) + await wrapper.find('.ix-alert-close-icon').trigger('click') + expect(onBeforeClose).toHaveBeenCalledTimes(2) + expect(onClose).toHaveBeenCalledTimes(1) + }) + + test('multiple message work', async () => { + const wrapper = AlertMount({ + slots: { + default: () => [h('div', 'message1'), h('div', 'message2')], + }, + }) + + expect(wrapper.find('.ix-alert-content').text()).toBe('message1message2') + + await wrapper.setProps({ showPagination: true }) + expect(wrapper.find('.ix-alert-content').text()).toBe('message1') + expect(wrapper.find('.ix-icon-left').classes()).toContain('ix-alert-disabled-icon') + expect(wrapper.find('.ix-icon-right').classes()).not.toContain('ix-alert-disabled-icon') + + await wrapper.find('.ix-icon-left').trigger('click') + expect(wrapper.find('.ix-alert-content').text()).toBe('message1') + + await wrapper.find('.ix-icon-right').trigger('click') + expect(wrapper.find('.ix-alert-content').text()).toBe('message2') + expect(wrapper.find('.ix-icon-left').classes()).not.toContain('ix-alert-disabled-icon') + expect(wrapper.find('.ix-icon-right').classes()).toContain('ix-alert-disabled-icon') + + await wrapper.find('.ix-icon-right').trigger('click') + expect(wrapper.find('.ix-alert-content').text()).toBe('message2') + + await wrapper.find('.ix-icon-left').trigger('click') + expect(wrapper.find('.ix-alert-content').text()).toBe('message1') + expect(wrapper.find('.ix-icon-left').classes()).toContain('ix-alert-disabled-icon') + expect(wrapper.find('.ix-icon-right').classes()).not.toContain('ix-alert-disabled-icon') + }) +}) diff --git a/packages/components/alert/demo/Basic.md b/packages/components/alert/demo/Basic.md new file mode 100644 index 000000000..051049852 --- /dev/null +++ b/packages/components/alert/demo/Basic.md @@ -0,0 +1,9 @@ +--- +order: 0 +title: + zh: 基本 +--- + +## zh + +最简单的用法,一共有四种样式,适用于简短的警告提示。 diff --git a/packages/components/alert/demo/Basic.vue b/packages/components/alert/demo/Basic.vue new file mode 100644 index 000000000..a37d3d9e6 --- /dev/null +++ b/packages/components/alert/demo/Basic.vue @@ -0,0 +1,6 @@ + diff --git a/packages/components/alert/demo/Close.md b/packages/components/alert/demo/Close.md new file mode 100644 index 000000000..b2f139b0d --- /dev/null +++ b/packages/components/alert/demo/Close.md @@ -0,0 +1,9 @@ +--- +order: 5 +title: + zh: 点击关闭时触发回调 +--- + +## zh + +onBeforeClose可以判断是否生效关闭,关闭时会触发close事件。 diff --git a/packages/components/alert/demo/Close.vue b/packages/components/alert/demo/Close.vue new file mode 100644 index 000000000..6db381576 --- /dev/null +++ b/packages/components/alert/demo/Close.vue @@ -0,0 +1,53 @@ + + + diff --git a/packages/components/alert/demo/Description.md b/packages/components/alert/demo/Description.md new file mode 100644 index 000000000..6e808ed07 --- /dev/null +++ b/packages/components/alert/demo/Description.md @@ -0,0 +1,9 @@ +--- +order: 1 +title: + zh: 辅助性文字介绍 +--- + +## zh + +含有辅助性文字介绍的警告提示,可以通过插槽实现。 diff --git a/packages/components/alert/demo/Description.vue b/packages/components/alert/demo/Description.vue new file mode 100644 index 000000000..3684586cf --- /dev/null +++ b/packages/components/alert/demo/Description.vue @@ -0,0 +1,15 @@ + diff --git a/packages/components/alert/demo/Icon.md b/packages/components/alert/demo/Icon.md new file mode 100644 index 000000000..fca903979 --- /dev/null +++ b/packages/components/alert/demo/Icon.md @@ -0,0 +1,9 @@ +--- +order: 3 +title: + zh: 自定义图标 +--- + +## zh + +支持自定义图标、自定义关闭按钮。 diff --git a/packages/components/alert/demo/Icon.vue b/packages/components/alert/demo/Icon.vue new file mode 100644 index 000000000..63ceb1343 --- /dev/null +++ b/packages/components/alert/demo/Icon.vue @@ -0,0 +1,13 @@ + diff --git a/packages/components/alert/demo/LongText.md b/packages/components/alert/demo/LongText.md new file mode 100644 index 000000000..2042ba027 --- /dev/null +++ b/packages/components/alert/demo/LongText.md @@ -0,0 +1,9 @@ +--- +order: 2 +title: + zh: 长文本 +--- + +## zh + +展示超长文本内容。 diff --git a/packages/components/alert/demo/LongText.vue b/packages/components/alert/demo/LongText.vue new file mode 100644 index 000000000..a21295a56 --- /dev/null +++ b/packages/components/alert/demo/LongText.vue @@ -0,0 +1,5 @@ + diff --git a/packages/components/alert/demo/Pagination.md b/packages/components/alert/demo/Pagination.md new file mode 100644 index 000000000..e3d05c9b9 --- /dev/null +++ b/packages/components/alert/demo/Pagination.md @@ -0,0 +1,9 @@ +--- +order: 4 +title: + zh: 切换提示 +--- + +## zh + +支持配置是否切换展示多条告警提示。 diff --git a/packages/components/alert/demo/Pagination.vue b/packages/components/alert/demo/Pagination.vue new file mode 100644 index 000000000..5d5d50a64 --- /dev/null +++ b/packages/components/alert/demo/Pagination.vue @@ -0,0 +1,30 @@ + + + diff --git a/packages/components/alert/docs/Index.zh.md b/packages/components/alert/docs/Index.zh.md new file mode 100644 index 000000000..01a210398 --- /dev/null +++ b/packages/components/alert/docs/Index.zh.md @@ -0,0 +1,33 @@ +--- +category: components +type: 反馈 +title: Alert +subtitle: 警告提示 +cover: +--- + +警告提示,展现需要引起用户关注的信息。 + +何时使用: + +- 当需要提供系统级别的信息提示,较重要的平台提示或告警信息,如:系统故障、授权升级等 +- 常用于页面内容的补充说明、操作后果提示、功能作用提示等 +- 提示信息通常情况下不会自动消失,用户可以主动关闭提示 + +## API + +### IxAlert + +#### Props + +| 名称 | 说明 | 类型 | 默认值 | 全局配置 | 备注 | +| --- | --- | --- | --- | --- | --- | +| `closable` | 信息提示是否可关闭 | `boolean` | `false` | ✅ |- | +| `closeIcon` | 自定义关闭按钮 | `string \| #closeIcon` | `close` | - | - | +| `description` | 辅助性文字介绍 | `string \| #description` | - | - |- | +| `icon` | 自定义图标 | `string \| #icon` | - | ✅ | 若要隐藏图标则传空串 | +| `showPagination` | 是否开启分页切换效果 | `boolean` | `false` | - | - | +| `type` | 设置提示类型 | `'success' \| 'info' \| 'warning' \| 'error'` | `info` | - |- | +| `title` | 信息提示内容 | `string \| string[] \| #default` | - | - |- | +| `onBeforeClose` | 关闭提示前会触发的回调函数 | `() => boolean \| Promise` | - | - | - | +| `onClose` | 关闭提示会触发的回调函数 | `() => void` | - | - | - | diff --git a/packages/components/alert/index.ts b/packages/components/alert/index.ts new file mode 100644 index 000000000..463ad27a4 --- /dev/null +++ b/packages/components/alert/index.ts @@ -0,0 +1,16 @@ +/** + * @license + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://github.com/IDuxFE/idux/blob/main/LICENSE + */ + +import type { AlertComponent } from './src/types' + +import Alert from './src/Alert' + +const IxAlert = Alert as unknown as AlertComponent + +export { IxAlert } + +export type { AlertInstance, AlertPublicProps as AlertProps } from './src/types' diff --git a/packages/components/alert/src/Alert.tsx b/packages/components/alert/src/Alert.tsx new file mode 100644 index 000000000..bdd767408 --- /dev/null +++ b/packages/components/alert/src/Alert.tsx @@ -0,0 +1,133 @@ +/** + * @license + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://github.com/IDuxFE/idux/blob/main/LICENSE + */ + +import { ComputedRef, Ref, Transition, VNode, computed, defineComponent, normalizeClass, ref } from 'vue' + +import { callEmit, flattenNode, useState } from '@idux/cdk/utils' +import { AlertConfig, useGlobalConfig } from '@idux/components/config' +import { IxIcon } from '@idux/components/icon' + +import { AlertProps, alertIconMap, alertProps } from './types' + +export default defineComponent({ + name: 'IxAlert', + props: alertProps, + setup(props, { slots }) { + const common = useGlobalConfig('common') + const mergedPrefixCls = computed(() => `${common.prefixCls}-alert`) + const isVisible = ref(true) + const alertConfig = useGlobalConfig('alert') + const iconName = computed(() => props.icon ?? (alertConfig.icon || alertIconMap[props.type])) + const isShowIcon = computed(() => iconName.value !== '') + const children = computed(() => flattenNode(slots.default?.() ?? [])) + + const { pageIndex, pageText, isShowPagination, isLeftDisabled, isRightDisabled, offsetPageIndex } = usePagination( + props, + children, + ) + + const { mergedClosable, handleCloseClick } = useClose(props, alertConfig, isVisible) + + return () => { + const titleContent = Array.isArray(props.title) + ? props.title.map(item =>
{item}
) + : props.title || children.value + const title = isShowPagination.value + ? props.title?.[pageIndex.value] || children.value[pageIndex.value] + : titleContent + + const description = slots.description?.() ?? props.description + + const closeIcon = slots.closeIcon?.() ?? + const icon = ( + {slots.icon?.() ?? } + ) + + const disabledIconCls = `${mergedPrefixCls.value}-disabled-icon` + const leftIconClass = { [disabledIconCls]: isLeftDisabled.value } + const rightIconClass = { [disabledIconCls]: isRightDisabled.value } + + const alertClass = normalizeClass({ + [mergedPrefixCls.value]: true, + [`${mergedPrefixCls.value}-${props.type}`]: true, + [`${mergedPrefixCls.value}-with-description`]: !!description, + }) + + return ( + + {isVisible.value && ( +
+ {isShowIcon.value && icon} +
+ {title} + {description &&
{description}
} +
+ {isShowPagination.value && ( +
+ offsetPageIndex(-1)}> + {pageText.value} + offsetPageIndex(1)}> +
+ )} + {mergedClosable.value && ( + + {closeIcon} + + )} +
+ )} +
+ ) + } + }, +}) + +const useClose = (props: AlertProps, alertConfig: Readonly, isVisible: Ref) => { + const mergedClosable = computed(() => props.closable || alertConfig.closable) + + const handleCloseClick = async () => { + const result = await callEmit(props.onBeforeClose) + if (result === false) { + return + } + isVisible.value = false + callEmit(props.onClose) + } + + return { + mergedClosable, + handleCloseClick, + } +} + +const usePagination = (props: AlertProps, children: ComputedRef) => { + const [pageIndex, setPageIndex] = useState(0) + const pageTotal = computed(() => children.value.length) + const isShowPagination = computed(() => props.showPagination && pageTotal.value > 1) + const pageText = computed(() => `${pageIndex.value + 1}/${pageTotal.value}`) + const isLeftDisabled = computed(() => pageIndex.value <= 0) + const isRightDisabled = computed(() => pageIndex.value + 1 >= pageTotal.value) + + const offsetPageIndex = (offset: -1 | 1) => { + if (offset === -1 && isLeftDisabled.value) { + return + } + if (offset === 1 && isRightDisabled.value) { + return + } + setPageIndex(pageIndex.value + offset) + } + + return { + pageIndex, + pageText, + isShowPagination, + isLeftDisabled, + isRightDisabled, + offsetPageIndex, + } +} diff --git a/packages/components/alert/src/types.ts b/packages/components/alert/src/types.ts new file mode 100644 index 000000000..34dc5157a --- /dev/null +++ b/packages/components/alert/src/types.ts @@ -0,0 +1,37 @@ +/** + * @license + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://github.com/IDuxFE/idux/blob/main/LICENSE + */ + +import type { IxInnerPropTypes, IxPublicPropTypes } from '@idux/cdk/utils' +import type { DefineComponent, HTMLAttributes } from 'vue' + +import { IxPropTypes } from '@idux/cdk/utils' + +type AlertType = 'success' | 'info' | 'warning' | 'error' + +export const alertIconMap = { + success: 'check-circle', + error: 'info-circle', + info: 'bulb', + warning: 'exclamation-circle', +} + +export const alertProps = { + type: IxPropTypes.oneOf(['success', 'info', 'warning', 'error']).def('info'), + closable: IxPropTypes.bool.def(false), + closeIcon: IxPropTypes.string.def('close'), + icon: IxPropTypes.string, + title: IxPropTypes.string, + description: IxPropTypes.string, + showPagination: IxPropTypes.bool.def(false), + onBeforeClose: IxPropTypes.emit<() => void | boolean | Promise>(), + onClose: IxPropTypes.emit<() => void>(), +} + +export type AlertProps = IxInnerPropTypes +export type AlertPublicProps = IxPublicPropTypes +export type AlertComponent = DefineComponent & AlertPublicProps> +export type AlertInstance = InstanceType> diff --git a/packages/components/alert/style/index.less b/packages/components/alert/style/index.less new file mode 100644 index 000000000..c65041ff1 --- /dev/null +++ b/packages/components/alert/style/index.less @@ -0,0 +1,57 @@ +@import './themes/default.less'; +@import './mixin.less'; + +@alert-prefix: ~'@{idux-prefix}-alert'; + +.@{alert-prefix} { + display: flex; + align-items: center; + margin-bottom: @alert-margin-bottom; + padding: @alert-padding; + word-wrap: break-word; + font-size: @alert-font-size; + line-height: @alert-line-height; + border-radius: @alert-border-radius; + + .alert-transition(); + + .alert-status-color(success, @alert-success-color, @alert-success-background-color); + .alert-status-color(info, @alert-info-color, @alert-info-background-color); + .alert-status-color(warning, @alert-warning-color, @alert-warning-background-color); + .alert-status-color(error, @alert-error-color, @alert-error-background-color); + + &-with-description { + align-items: flex-start; + } + + &-icon { + margin-right: @alert-icon-margin-right; + } + + &-content { + flex: 1; + min-width: 0; + } + + &-pagination { + margin-left: @alert-action-margin-left; + + .@{alert-prefix}-page-text { + margin: @alert-page-text-margin; + } + + .@{idux-prefix}-icon { + cursor: pointer; + } + + .@{alert-prefix}-disabled-icon { + cursor: not-allowed; + color: @alert-disabled-icon-color; + } + } + + &-close-icon { + cursor: pointer; + margin-left: @alert-action-margin-left; + } +} diff --git a/packages/components/alert/style/index.ts b/packages/components/alert/style/index.ts new file mode 100644 index 000000000..0f8f88322 --- /dev/null +++ b/packages/components/alert/style/index.ts @@ -0,0 +1,5 @@ +import '../../style/index.less' +import './index.less' + +// style dependencies +import '../../icon/style' diff --git a/packages/components/alert/style/mixin.less b/packages/components/alert/style/mixin.less new file mode 100644 index 000000000..9d01870f7 --- /dev/null +++ b/packages/components/alert/style/mixin.less @@ -0,0 +1,27 @@ + +.alert-status-color (@type, @color, @bg-color) { + &.@{alert-prefix}-@{type} .@{alert-prefix}-icon { + color: @color; + } + + &.@{alert-prefix}-@{type} { + background-color: @bg-color; + } +} + +.alert-transition () { + + &-enter-active, &-leave-active { + transition: all .3s cubic-bezier(.4, 0, .2, 1) 0s; + } + + &-enter-from, &-leave-to { + transform: scale(0.9); + opacity: 0; + } + + &-leave-from, &-enter-to { + transform: scale(1); + opacity: 1; + } +} diff --git a/packages/components/alert/style/themes/default.less b/packages/components/alert/style/themes/default.less new file mode 100644 index 000000000..5e5635cfb --- /dev/null +++ b/packages/components/alert/style/themes/default.less @@ -0,0 +1,20 @@ +@import '../../../style/themes/default.less'; + +@alert-success-color: @color-success-d10; +@alert-info-color: @color-info-d10; +@alert-warning-color: @color-warning-d10; +@alert-error-color: @color-error-d10; +@alert-success-background-color: @color-success-l50; +@alert-info-background-color: @color-info-l50; +@alert-warning-background-color: @color-warning-l50; +@alert-error-background-color: @color-error-l50; + +@alert-font-size: @font-size-md; +@alert-line-height: @line-height-base; +@alert-border-radius: @border-radius-gutter; +@alert-margin-bottom: @spacing-lg; +@alert-padding: @spacing-sm @spacing-lg; +@alert-icon-margin-right: @spacing-sm; +@alert-action-margin-left: @spacing-lg; +@alert-page-text-margin: 0 @spacing-xs; +@alert-disabled-icon-color: @disabled-color; diff --git a/packages/components/components.less b/packages/components/components.less index fc6e09e1e..0332c66c5 100644 --- a/packages/components/components.less +++ b/packages/components/components.less @@ -1,4 +1,5 @@ @import './affix/style/index.less'; +@import './alert/style/index.less'; @import './anchor/style/index.less'; @import './avatar/style/index.less'; @import './back-top/style/index.less'; diff --git a/packages/components/config/src/defaultConfig.ts b/packages/components/config/src/defaultConfig.ts index 2842e42ba..65b35dc9b 100644 --- a/packages/components/config/src/defaultConfig.ts +++ b/packages/components/config/src/defaultConfig.ts @@ -6,6 +6,7 @@ */ import type { + AlertConfig, AnchorConfig, AvatarConfig, BackTopConfig, @@ -271,6 +272,11 @@ const modal = shallowReactive({ width: 520, }) +const alert = shallowReactive({ + closable: false, + icon: '', +}) + const drawer = shallowReactive({ closable: true, closeOnEsc: true, @@ -349,6 +355,7 @@ export const defaultConfig: GlobalConfig = { tree, popover, // Feedback + alert, message, modal, drawer, diff --git a/packages/components/config/src/types.ts b/packages/components/config/src/types.ts index 02969b13e..35437955d 100644 --- a/packages/components/config/src/types.ts +++ b/packages/components/config/src/types.ts @@ -283,6 +283,11 @@ export interface ModalConfig { zIndex?: number } +export interface AlertConfig { + closable: boolean + icon: string +} + export interface DrawerConfig { closable: boolean closeIcon: string @@ -369,6 +374,7 @@ export interface GlobalConfig { popover: PopoverConfig stepper: StepperConfig // Feedback + alert: AlertConfig message: MessageConfig modal: ModalConfig drawer: DrawerConfig diff --git a/packages/components/index.ts b/packages/components/index.ts index 0c67949cc..d6b5bb3ed 100644 --- a/packages/components/index.ts +++ b/packages/components/index.ts @@ -8,6 +8,7 @@ import type { App, Directive } from 'vue' import { IxAffix } from '@idux/components/affix' +import { IxAlert } from '@idux/components/alert' import { IxAnchor, IxAnchorLink } from '@idux/components/anchor' import { IxAvatar } from '@idux/components/avatar' import { IxBackTop } from '@idux/components/back-top' @@ -56,6 +57,7 @@ import { version } from '@idux/components/version' const components = [ IxAffix, + IxAlert, IxAnchor, IxAnchorLink, IxAvatar,