diff --git a/components.json b/components.json
index 62d748707..36137a640 100644
--- a/components.json
+++ b/components.json
@@ -86,5 +86,6 @@
"empty": "./packages/empty/index.js",
"descriptions": "./packages/descriptions/index.js",
"descriptions-item": "./packages/descriptions-item/index.js",
- "result": "./packages/result/index.js"
+ "result": "./packages/result/index.js",
+ "chat-message": "./packages/chat-message/index.js"
}
diff --git a/examples/docs/en-US/chat-message.md b/examples/docs/en-US/chat-message.md
new file mode 100644
index 000000000..25ccef0d2
--- /dev/null
+++ b/examples/docs/en-US/chat-message.md
@@ -0,0 +1,223 @@
+## ChatMessage
+
+Message component for creating full-fledged chats
+
+### Basic usage
+
+:::demo Use `type` and `size` to define style and size
+```html
+
+
+
+
+
+
+
+
+```
+:::
+
+### Positioning
+
+:::demo Use `position` to define the side of the correspondence
+```html
+
+
+```
+:::
+
+### Personalization
+
+:::demo Use `name` and `avatar` to personalize the message
+```html
+
+
+```
+:::
+
+### Status and time stamp
+
+You can add one of the statuses `sending`, `delivered`, `read` and time to the message
+
+:::demo Use `status` and` stamp` to set time and status
+```html
+
+
+
+
+```
+:::
+
+### Message Stacks
+
+Consecutive messages from the same person can be displayed in a grouped stack
+
+:::demo Now we pass an array of messages into `text`
+```html
+
+
+
+
+
+
+
+```
+:::
+
+### Slots
+
+Using slots in message elements
+
+:::demo
+```html
+
+
+
+
+
+
+
+ Taylor Otwell
+
+
+
+ {{ message.text }} When will Vue 4 be released?
+
+
+
+ 11:36
+
+
+
+
+
+ {{ $index }}: {{ message.text }}
+
+
+
+
+
+```
+:::
+
+### Attributes
+| Attribute | Description | Type | Accepted values | Default |
+|-----------|--------------------------------- |--------------- |-----------------------------------------|-------- |
+| size | Message size | string | large / default / medium / small / mini | default |
+| type | Message type | string | primary / success / warning / danger | — |
+| text | Message or stack of messages | string / array | — | — |
+| name | Username | string | — | — |
+| avatar | Avatar url | string | — | — |
+| stamp | Time stamp | string | — | — |
+| status | Message status | string | none / sending / delivered / read | none |
+| position | Side of the message box | string | left / right | left |
+
+### Scoped Slot
+| Name | Description |
+|---------- |--------------------------------------------------------------- |
+| name | Username. The scope parameter is { row: { name }, $index } |
+| avatar | User avatar. The scope parameter is { row: { avatar }, $index } |
+| text | Message Text. The scope parameter is { message, $index } |
+| stamp | Time stamp. The scope parameter is { message, $index } |
+| status | Message status. The scope parameter is { message, $index } |
diff --git a/examples/docs/es/chat-message.md b/examples/docs/es/chat-message.md
new file mode 100644
index 000000000..e6ea217cc
--- /dev/null
+++ b/examples/docs/es/chat-message.md
@@ -0,0 +1 @@
+## ChatMessage
diff --git a/examples/docs/fr-FR/chat-message.md b/examples/docs/fr-FR/chat-message.md
new file mode 100644
index 000000000..e6ea217cc
--- /dev/null
+++ b/examples/docs/fr-FR/chat-message.md
@@ -0,0 +1 @@
+## ChatMessage
diff --git a/examples/docs/zh-CN/chat-message.md b/examples/docs/zh-CN/chat-message.md
new file mode 100644
index 000000000..70ca72946
--- /dev/null
+++ b/examples/docs/zh-CN/chat-message.md
@@ -0,0 +1 @@
+## ChatMessage chat-message
diff --git a/examples/nav.config.json b/examples/nav.config.json
index 3377ac933..e330f1479 100644
--- a/examples/nav.config.json
+++ b/examples/nav.config.json
@@ -307,6 +307,10 @@
{
"path": "/drawer",
"title": "Drawer 抽屉"
+ },
+ {
+ "path": "/chat-message",
+ "title": "ChatMessage"
}
]
}
@@ -621,6 +625,10 @@
{
"path": "/drawer",
"title": "Drawer"
+ },
+ {
+ "path": "/chat-message",
+ "title": "ChatMessage"
}
]
}
@@ -935,6 +943,10 @@
{
"path": "/drawer",
"title": "Drawer"
+ },
+ {
+ "path": "/chat-message",
+ "title": "ChatMessage"
}
]
}
@@ -1249,6 +1261,10 @@
{
"path": "/drawer",
"title": "Drawer"
+ },
+ {
+ "path": "/chat-message",
+ "title": "ChatMessage"
}
]
}
diff --git a/packages/chat-message/index.js b/packages/chat-message/index.js
new file mode 100644
index 000000000..a82fc9711
--- /dev/null
+++ b/packages/chat-message/index.js
@@ -0,0 +1,8 @@
+import ChatMessage from './src/chat-message';
+
+/* istanbul ignore next */
+ChatMessage.install = function(Vue) {
+ Vue.component(ChatMessage.name, ChatMessage);
+};
+
+export default ChatMessage;
diff --git a/packages/chat-message/src/chat-message.vue b/packages/chat-message/src/chat-message.vue
new file mode 100644
index 000000000..49dc04178
--- /dev/null
+++ b/packages/chat-message/src/chat-message.vue
@@ -0,0 +1,111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ name }}
+
+
+
+ {{ message.text }}
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/theme-chalk/src/chat-message.scss b/packages/theme-chalk/src/chat-message.scss
new file mode 100644
index 000000000..1bad2ef6f
--- /dev/null
+++ b/packages/theme-chalk/src/chat-message.scss
@@ -0,0 +1,143 @@
+@import "mixins/mixins";
+@import "mixins/chat-message";
+@import "common/var";
+
+@include b(chat-message) {
+ @include e(list) {
+ display: flex;
+ flex-direction: column;
+
+ @include e(box) {
+ display: flex;
+ align-items: flex-end;
+
+ @include e(body) {
+ color: $--chat-message--color;
+ background-color: $--color-info-light;
+
+ @include e(name) {
+ margin-bottom: 2px;
+ font-weight: bold;
+ }
+
+ @include e(footer) {
+ float: right;
+ display: flex;
+ justify-content: flex-end;
+
+ color: darken($--color-info-light, 20);
+
+ @include e(check-icon){
+ color: #11c711;
+ position: relative;
+
+ .el-icon-check {
+ font-weight: bold;
+ }
+
+ }
+ }
+ }
+ }
+ }
+
+ @include when(left) {
+ @include e(list) {
+ align-items: flex-start;
+ }
+
+ @include e(name) {
+ text-align: left;
+ }
+ }
+
+ @include when(right) {
+ @include e(list) {
+ align-items: flex-end;
+
+ @include e(box) {
+ flex-direction: row-reverse;
+ }
+ }
+
+ @include e(name) {
+ text-align: right;
+ }
+ }
+
+ @include m('primary') {
+ @include chat-message-variant($--chat-message-primary-font-color, $--chat-message-primary-background-color)
+ }
+
+ @include m('success') {
+ @include chat-message-variant($--chat-message-success-font-color, $--chat-message-success-background-color)
+ }
+
+ @include m('warning') {
+ @include chat-message-variant($--chat-message-warning-font-color, $--chat-message-warning-background-color)
+ }
+
+ @include m('danger') {
+ @include chat-message-variant($--chat-message-danger-font-color, $--chat-message-danger-background-color)
+ }
+
+ @include m('default') {
+ @include chat-message-size(
+ $--chat-message-avatar-size,
+ $--chat-message-margin-gutter,
+ $--chat-message-font-size,
+ $--chat-message-font-size-footer,
+ $--chat-message-padding-vertical,
+ $--chat-message-padding-horizontal,
+ $--chat-message-border-radius
+ )
+ }
+
+ @include m('large') {
+ @include chat-message-size(
+ $--chat-message-large-avatar-size,
+ $--chat-message-large-margin-gutter,
+ $--chat-message-large-font-size,
+ $--chat-message-large-font-size-footer,
+ $--chat-message-large-padding-vertical,
+ $--chat-message-large-padding-horizontal,
+ $--chat-message-large-border-radius
+ )
+ }
+
+ @include m('medium') {
+ @include chat-message-size(
+ $--chat-message-medium-avatar-size,
+ $--chat-message-medium-margin-gutter,
+ $--chat-message-medium-font-size,
+ $--chat-message-medium-font-size-footer,
+ $--chat-message-medium-padding-vertical,
+ $--chat-message-medium-padding-horizontal,
+ $--chat-message-medium-border-radius
+ )
+ }
+
+ @include m('small') {
+ @include chat-message-size(
+ $--chat-message-small-avatar-size,
+ $--chat-message-small-margin-gutter,
+ $--chat-message-small-font-size,
+ $--chat-message-small-font-size-footer,
+ $--chat-message-small-padding-vertical,
+ $--chat-message-small-padding-horizontal,
+ $--chat-message-small-border-radius
+ )
+ }
+
+ @include m('mini') {
+ @include chat-message-size(
+ $--chat-message-mini-avatar-size,
+ $--chat-message-mini-margin-gutter,
+ $--chat-message-mini-font-size,
+ $--chat-message-mini-font-size-footer,
+ $--chat-message-mini-padding-vertical,
+ $--chat-message-mini-padding-horizontal,
+ $--chat-message-mini-border-radius
+ )
+ }
+}
diff --git a/packages/theme-chalk/src/common/var.scss b/packages/theme-chalk/src/common/var.scss
index 142838c05..bcd530f29 100644
--- a/packages/theme-chalk/src/common/var.scss
+++ b/packages/theme-chalk/src/common/var.scss
@@ -147,6 +147,97 @@ $--disabled-border-base: $--border-color-light !default;
$--icon-color: #666 !default;
$--icon-color-base: $--color-info !default;
+/* ChatMessage
+-------------------------- */
+$--chat-message--color: $--color-black !default;
+
+$--icon-color-base: $--color-info !default;
+
+
+$--chat-message-avatar-size: 40px;
+$--chat-message-margin-gutter: 10px;
+$--chat-message-font-size-footer: 12px;
+/// fontSize||Font|1
+$--chat-message-font-size: $--font-size-base !default;
+/// borderRadius||Border|2
+$--chat-message-border-radius: 20px;
+/// padding||Spacing|3
+$--chat-message-padding-vertical: 12px !default;
+/// padding||Spacing|3
+$--chat-message-padding-horizontal: 20px !default;
+
+
+$--chat-message-large-avatar-size: 50px;
+$--chat-message-large-margin-gutter: 10px;
+$--chat-message-large-font-size-footer: 13px;
+/// fontSize||Font|1
+$--chat-message-large-font-size: 15px !default;
+/// borderRadius||Border|2
+$--chat-message-large-border-radius: 20px;
+/// padding||Spacing|3
+$--chat-message-large-padding-vertical: 14px !default;
+/// padding||Spacing|3
+$--chat-message-large-padding-horizontal: 20px !default;
+
+
+$--chat-message-medium-avatar-size: 36px;
+$--chat-message-medium-margin-gutter: 10px;
+$--chat-message-medium-font-size-footer: 11px;
+/// fontSize||Font|1
+$--chat-message-medium-font-size: 13px !default;
+/// borderRadius||Border|2
+$--chat-message-medium-border-radius: 20px;
+/// padding||Spacing|3
+$--chat-message-medium-padding-vertical: 6px !default;
+/// padding||Spacing|3
+$--chat-message-medium-padding-horizontal: 14px !default;
+
+
+$--chat-message-small-avatar-size: 30px;
+$--chat-message-small-margin-gutter: 8px;
+$--chat-message-small-font-size-footer: 11px;
+/// fontSize||Font|1
+$--chat-message-small-font-size: 13px !default;
+/// borderRadius||Border|2
+$--chat-message-small-border-radius: 20px;
+/// padding||Spacing|3
+$--chat-message-small-padding-vertical: 6px !default;
+/// padding||Spacing|3
+$--chat-message-small-padding-horizontal: 14px !default;
+
+
+$--chat-message-mini-avatar-size: 26px;
+$--chat-message-mini-margin-gutter: 6px;
+$--chat-message-mini-font-size-footer: 11px;
+/// fontSize||Font|1
+$--chat-message-mini-font-size: 12px !default;
+/// borderRadius||Border|2
+$--chat-message-mini-border-radius: 20px;
+/// padding||Spacing|3
+$--chat-message-mini-padding-vertical: 6px !default;
+/// padding||Spacing|3
+$--chat-message-mini-padding-horizontal: 10px !default;
+
+/// color||Color|0
+$--chat-message-primary-font-color: $--color-white !default;
+/// color||Color|0
+$--chat-message-primary-background-color: $--color-primary !default;
+/// color||Color|0
+$--chat-message-success-font-color: $--color-white !default;
+/// color||Color|0
+$--chat-message-success-background-color: $--color-success !default;
+/// color||Color|0
+$--chat-message-warning-font-color: $--color-white !default;
+/// color||Color|0
+$--chat-message-warning-background-color: $--color-warning !default;
+/// color||Color|0
+$--chat-message-danger-font-color: $--color-white !default;
+/// color||Color|0
+$--chat-message-danger-background-color: $--color-danger !default;
+
+$--chat-message-hover-tint-percent: 20% !default;
+$--chat-message-active-shade-percent: 10% !default;
+
/* Checkbox
-------------------------- */
/// fontSize||Font|1
@@ -978,7 +1069,7 @@ $--descriptions-title-font-size: 16px !default;
$--descriptions-table-border: 1px solid $--border-color-lighter !default;
$--descriptions-item-bordered-label-background: #fafafa !default;
-/* Skeleton
+/* Skeleton
--------------------------*/
$--skeleton-color: #f2f2f2 !default;
$--skeleton-to-color: #e6e6e6 !default;
diff --git a/packages/theme-chalk/src/index.scss b/packages/theme-chalk/src/index.scss
index 0d81c5311..3e9f79d08 100644
--- a/packages/theme-chalk/src/index.scss
+++ b/packages/theme-chalk/src/index.scss
@@ -84,3 +84,4 @@
@import "./descriptions.scss";
@import "./descriptions-item.scss";
@import "./result.scss";
+@import "./chat-message.scss";
diff --git a/packages/theme-chalk/src/mixins/_chat-message.scss b/packages/theme-chalk/src/mixins/_chat-message.scss
new file mode 100644
index 000000000..b5bb9674b
--- /dev/null
+++ b/packages/theme-chalk/src/mixins/_chat-message.scss
@@ -0,0 +1,106 @@
+@import "../common/var";
+@import "mixins";
+
+@mixin chat-message-variant($color, $background-color) {
+ @include e(list) {
+ @include e(box) {
+ @include e(body) {
+ color: $color;
+ background-color: $background-color;
+
+ @include e(footer) {
+ color: mix($--color-white, $background-color, 70);
+
+ @include e(check-icon){
+ color: mix($--color-white, $background-color, 70);
+ }
+ }
+ }
+ }
+ }
+}
+
+@mixin chat-message-size(
+ $avatar-size,
+ $margin-gutter,
+ $font-size,
+ $font-size-footer,
+ $padding-vertical,
+ $padding-horizontal,
+ $border-radius
+) {
+ @include e(list) {
+ @include e(box) {
+ margin-bottom: $margin-gutter;
+ @include e(avatar) {
+ width: $avatar-size;
+ margin-right: $margin-gutter;
+
+ .el-avatar {
+ width: $avatar-size;
+ height: $avatar-size;
+ }
+ }
+
+ @include e(body) {
+ padding: $padding-vertical $padding-horizontal;
+ border-radius: $border-radius;
+ font-size: $font-size;
+
+ @include e(name) {
+ margin-bottom: 2px;
+ font-size: $font-size;
+ font-weight: bold;
+ }
+
+ @include e(footer) {
+ font-size: $font-size-footer;
+ margin-left: 10px;
+ line-height: $font-size + 2;
+
+ @include pseudo(last-child) {
+ @include e(check-icon) {
+ .el-icon-check.second {
+ position: absolute;
+ left: 4px;
+ top: $font-size - $font-size-footer;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @include when(left) {
+ @include e(list) {
+ @include e(box) {
+ @include e(avatar) {
+ margin-left: $margin-gutter;
+ }
+
+ @include pseudo(first-child) {
+ @include e(body) {
+ border-radius: $border-radius $border-radius $border-radius 5px;
+ }
+ }
+ }
+ }
+ }
+
+ @include when(right) {
+ @include e(list) {
+ @include e(box) {
+ @include e(avatar) {
+ margin-left: $margin-gutter;
+ }
+
+ @include pseudo(first-child) {
+ @include e(body) {
+ border-radius: $border-radius $border-radius 5px $border-radius;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/index.js b/src/index.js
index b32222f6f..b93d1eaf1 100644
--- a/src/index.js
+++ b/src/index.js
@@ -88,6 +88,7 @@ import Empty from '../packages/empty/index.js';
import Descriptions from '../packages/descriptions/index.js';
import DescriptionsItem from '../packages/descriptions-item/index.js';
import Result from '../packages/result/index.js';
+import ChatMessage from '../packages/chat-message/index.js';
import locale from 'element-ui/src/locale';
import CollapseTransition from 'element-ui/src/transitions/collapse-transition';
@@ -175,6 +176,7 @@ const components = [
Descriptions,
DescriptionsItem,
Result,
+ ChatMessage,
CollapseTransition
];
@@ -302,5 +304,6 @@ export default {
Empty,
Descriptions,
DescriptionsItem,
- Result
+ Result,
+ ChatMessage
};
diff --git a/test/unit/specs/chat-message.spec.js b/test/unit/specs/chat-message.spec.js
new file mode 100644
index 000000000..96f6dc355
--- /dev/null
+++ b/test/unit/specs/chat-message.spec.js
@@ -0,0 +1,51 @@
+import { createTest, destroyVM } from '../util';
+import ChatMessage from 'packages/chat-message';
+
+const testProps = {
+ text: 'Test text',
+ name: 'Evan You'
+};
+
+describe('ChatMessage', () => {
+ let vm;
+ afterEach(() => {
+ destroyVM(vm);
+ });
+
+ it('create', () => {
+ vm = createTest(ChatMessage, {
+ ...testProps,
+ type: 'primary'
+ }, true);
+ let messageElm = vm.$el;
+ expect(messageElm.classList.contains('el-chat-message--primary')).to.be.true;
+ });
+
+ it('size medium', () => {
+ vm = createTest(ChatMessage, {
+ ...testProps,
+ size: 'medium'
+ }, true);
+ let messageElm = vm.$el;
+ expect(messageElm.classList.contains('el-chat-message--medium')).to.be.true;
+ });
+
+ it('type primary', () => {
+ vm = createTest(ChatMessage, {
+ ...testProps,
+ type: 'primary'
+ }, true);
+ let messageElm = vm.$el;
+ expect(messageElm.classList.contains('el-chat-message--primary')).to.be.true;
+ });
+
+ it('position right', () => {
+ vm = createTest(ChatMessage, {
+ ...testProps,
+ position: 'right'
+ }, true);
+ let messageElm = vm.$el;
+ expect(messageElm.classList.contains('is-right')).to.be.true;
+ });
+});
+
diff --git a/types/chat-message.d.ts b/types/chat-message.d.ts
new file mode 100644
index 000000000..e392a9233
--- /dev/null
+++ b/types/chat-message.d.ts
@@ -0,0 +1,44 @@
+import {ElementUIComponent, ElementUIComponentSize} from './component'
+
+/** ChatMessage type */
+export type ChatMessageType = 'primary' | 'success' | 'warning' | 'danger'
+
+/** ChatMessage status */
+export type ChatMessageStatus = 'none' | 'sending' | 'delivered' | 'read'
+
+/** ChatMessage position */
+export type ChatMessagePosition = 'left' | 'right'
+
+/** ChatMessage text */
+export interface ChatMessageText {
+ text: string,
+ stamp?: string,
+ status?: ChatMessageStatus
+}
+
+/** ChatMessage Component */
+export declare class ElChatMessage extends ElementUIComponent {
+ /** ChatMessage size */
+ size: ElementUIComponentSize
+
+ /** ChatMessage status */
+ status: ChatMessageStatus
+
+ /** ChatMessage type */
+ type: ChatMessageType
+
+ /** ChatMessage position */
+ position: ChatMessagePosition
+
+ /** Sender name */
+ name: string
+
+ /** Datetime message */
+ stamp: string
+
+ /** Array of message */
+ text: Array | string
+
+ /** Sender avatar */
+ avatar: string
+}
diff --git a/types/element-ui.d.ts b/types/element-ui.d.ts
index 9657a652a..4f218333d 100644
--- a/types/element-ui.d.ts
+++ b/types/element-ui.d.ts
@@ -88,6 +88,7 @@ import { ElSpinner } from './spinner'
import { ElDescriptions } from './descriptions'
import { ElDescriptionsItem } from './descriptions-item'
import { ElResult } from './result'
+import { ElChatMessage } from './chat-message'
export interface InstallationOptions {
locale: any,
@@ -375,4 +376,7 @@ export class Descriptions extends ElDescriptions {}
export class DescriptionsItem extends ElDescriptionsItem {}
/** Result Component */
-export class Result extends ElResult {}
\ No newline at end of file
+export class Result extends ElResult {}
+
+/** ChatMessage Component */
+export class ChatMessage extends ElChatMessage {}