diff --git a/packages/core/components.d.ts b/packages/core/components.d.ts
index 829d2fd7..232d1a4f 100644
--- a/packages/core/components.d.ts
+++ b/packages/core/components.d.ts
@@ -47,6 +47,12 @@ declare module 'vue' {
ElTimelineItem: typeof import('element-plus/es')['ElTimelineItem']
ElTooltip: typeof import('element-plus/es')['ElTooltip']
ElUpload: typeof import('element-plus/es')['ElUpload']
+ ELXButton: typeof import('./src/components/ELXButton/index.vue')['default']
+ ELXClearButton: typeof import('./src/components/ELXButton/components/ELXClearButton.vue')['default']
+ ELXLoadingButton: typeof import('./src/components/ELXButton/components/ELXLoadingButton.vue')['default']
+ ELXSendButton: typeof import('./src/components/ELXButton/components/ELXSendButton.vue')['default']
+ ELXSpeechButton: typeof import('./src/components/ELXButton/components/ELXSpeechButton.vue')['default']
+ ELXSpeechLoadingButton: typeof import('./src/components/ELXButton/components/ELXSpeechLoadingButton.vue')['default']
Excel: typeof import('./src/components/FilesCard/fileSvg/excel.vue')['default']
File: typeof import('./src/components/FilesCard/fileSvg/file.vue')['default']
FilesCard: typeof import('./src/components/FilesCard/index.vue')['default']
diff --git a/packages/core/src/components.ts b/packages/core/src/components.ts
index 0c93aa1e..2b42e742 100644
--- a/packages/core/src/components.ts
+++ b/packages/core/src/components.ts
@@ -5,6 +5,7 @@ export { default as BubbleList } from './components/BubbleList/index.vue';
export { default as ConfigProvider } from './components/ConfigProvider/index.vue';
export { default as Conversations } from './components/Conversations/index.vue';
export { default as EditorSender } from './components/EditorSender/index.vue';
+export { default as ELXButton } from './components/ELXButton/index.vue';
export { default as FilesCard } from './components/FilesCard/index.vue';
export { default as MentionSender } from './components/MentionSender/index.vue';
export { default as Prompts } from './components/Prompts/index.vue';
diff --git a/packages/core/src/components/ELXButton/components/ELXClearButton.vue b/packages/core/src/components/ELXButton/components/ELXClearButton.vue
new file mode 100644
index 00000000..8ffbe2ec
--- /dev/null
+++ b/packages/core/src/components/ELXButton/components/ELXClearButton.vue
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
diff --git a/packages/core/src/components/ELXButton/components/ELXLoadingButton.vue b/packages/core/src/components/ELXButton/components/ELXLoadingButton.vue
new file mode 100644
index 00000000..764c827a
--- /dev/null
+++ b/packages/core/src/components/ELXButton/components/ELXLoadingButton.vue
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
diff --git a/packages/core/src/components/ELXButton/components/ELXSendButton.vue b/packages/core/src/components/ELXButton/components/ELXSendButton.vue
new file mode 100644
index 00000000..367aa115
--- /dev/null
+++ b/packages/core/src/components/ELXButton/components/ELXSendButton.vue
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
diff --git a/packages/core/src/components/ELXButton/components/ELXSpeechButton.vue b/packages/core/src/components/ELXButton/components/ELXSpeechButton.vue
new file mode 100644
index 00000000..92510fd8
--- /dev/null
+++ b/packages/core/src/components/ELXButton/components/ELXSpeechButton.vue
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
diff --git a/packages/core/src/components/ELXButton/components/ELXSpeechLoadingButton.vue b/packages/core/src/components/ELXButton/components/ELXSpeechLoadingButton.vue
new file mode 100644
index 00000000..d885a4c3
--- /dev/null
+++ b/packages/core/src/components/ELXButton/components/ELXSpeechLoadingButton.vue
@@ -0,0 +1,68 @@
+
+
+
+
+
+
+
diff --git a/packages/core/src/components/ELXButton/index.ts b/packages/core/src/components/ELXButton/index.ts
new file mode 100644
index 00000000..c2c0b1db
--- /dev/null
+++ b/packages/core/src/components/ELXButton/index.ts
@@ -0,0 +1,60 @@
+import type { SetupContext } from 'vue';
+import { buttonEmits, buttonProps } from 'element-plus';
+
+export const elxButtonTypes = [
+ 'clear',
+ 'loading',
+ 'send',
+ 'speech',
+ 'speechLoading',
+ ''
+] as const;
+
+export const elxButtonProps = {
+ /**
+ * @description xButton type
+ */
+ elxButtonType: {
+ type: String,
+ values: elxButtonTypes,
+ default: ''
+ },
+ ...buttonProps
+};
+
+export const elxButtonEmits = {
+ clear: (evt: MouseEvent) => evt instanceof MouseEvent,
+ cancel: (evt: MouseEvent) => evt instanceof MouseEvent,
+ submit: (evt: MouseEvent) => evt instanceof MouseEvent,
+ ...buttonEmits
+};
+
+export type ELXButtonProps = Partial>;
+export type ELXButtonEmits = typeof elxButtonEmits;
+export type ELXButtonType = ELXButtonProps['elxButtonType'];
+
+export function useButton(
+ props: ELXButtonProps,
+ emit: SetupContext['emit']
+) {
+ const handleClick = (evt: MouseEvent) => {
+ if (props.disabled || props.loading) {
+ evt.stopPropagation();
+ return;
+ }
+ if (props.elxButtonType?.trim()?.length) {
+ if (props.elxButtonType === 'clear') {
+ return emit('clear', evt);
+ } else if (['loading', 'speechLoading'].includes(props.elxButtonType)) {
+ return emit('cancel', evt);
+ } else if (props.elxButtonType === 'send') {
+ return emit('submit', evt);
+ }
+ }
+ emit('click', evt);
+ };
+
+ return {
+ handleClick
+ };
+}
diff --git a/packages/core/src/components/ELXButton/index.vue b/packages/core/src/components/ELXButton/index.vue
new file mode 100644
index 00000000..b1133d82
--- /dev/null
+++ b/packages/core/src/components/ELXButton/index.vue
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
diff --git a/packages/core/src/components/ELXButton/style.scss b/packages/core/src/components/ELXButton/style.scss
new file mode 100644
index 00000000..af286fb9
--- /dev/null
+++ b/packages/core/src/components/ELXButton/style.scss
@@ -0,0 +1,32 @@
+.elx-button {
+ &.elx-button-type-clear {
+ .el-icon {
+ // 旋转180
+ transform: rotate(180deg);
+ }
+ }
+
+ &.elx-button-type-loading {
+ padding: 0;
+
+ .loading-svg {
+ color: var(--el-color-primary);
+ width: 100%;
+ }
+ }
+
+ &.elx-button-type-send {
+ }
+
+ &.elx-button-type-speech {
+ }
+
+ &.elx-button-type-speechLoading {
+ padding: 0;
+
+ .loading-svg {
+ color: var(--el-color-primary);
+ width: 16px;
+ }
+ }
+}
diff --git a/packages/core/src/stories/ELXButton/ELXButton.stories.ts b/packages/core/src/stories/ELXButton/ELXButton.stories.ts
new file mode 100644
index 00000000..3bc2e06b
--- /dev/null
+++ b/packages/core/src/stories/ELXButton/ELXButton.stories.ts
@@ -0,0 +1,75 @@
+import type ELXButtonSource from '@components/ELXButton/index.vue';
+import type { Meta, StoryObj } from '@storybook/vue3';
+import ELXButtonSlot from './ELXButtonSlot.vue';
+import ELXButton from './index.vue';
+
+const meta: Meta = {
+ title: 'Example/ELXButton',
+ component: ELXButton,
+ argTypes: {
+ size: {
+ control: { type: 'select' },
+ options: ['large', 'default', 'small']
+ },
+ disabled: {
+ control: 'boolean'
+ }
+ },
+ args: {}
+} satisfies Meta;
+
+export default meta;
+
+type Story = StoryObj;
+
+export const ELXButtonDemo: Story = {
+ render: _args => ({
+ setup() {
+ return {
+ attrs: _args
+ };
+ },
+ components: { ELXButton },
+ template: `
+
+ `
+ })
+};
+
+export const ELXButtonSlotDemo: Story = {
+ argTypes: {
+ type: {
+ control: { type: 'select' },
+ options: ['primary', 'success', 'warning', 'danger', 'info']
+ },
+ loading: {
+ control: 'boolean'
+ },
+ circle: {
+ control: 'boolean'
+ },
+ round: {
+ control: 'boolean'
+ },
+ color: {
+ control: 'text'
+ },
+ icon: {
+ control: 'text'
+ }
+ },
+ args: {
+ type: 'primary'
+ },
+ render: _args => ({
+ setup() {
+ return {
+ attrs: _args
+ };
+ },
+ components: { ELXButtonSlot },
+ template: `
+
+ `
+ })
+};
diff --git a/packages/core/src/stories/ELXButton/ELXButtonSlot.vue b/packages/core/src/stories/ELXButton/ELXButtonSlot.vue
new file mode 100644
index 00000000..28d9e482
--- /dev/null
+++ b/packages/core/src/stories/ELXButton/ELXButtonSlot.vue
@@ -0,0 +1,88 @@
+
+
+
+
+
+
+
diff --git a/packages/core/src/stories/ELXButton/index.vue b/packages/core/src/stories/ELXButton/index.vue
new file mode 100644
index 00000000..590ecd26
--- /dev/null
+++ b/packages/core/src/stories/ELXButton/index.vue
@@ -0,0 +1,69 @@
+
+
+
+
+
+
+
+
+