Browse Source

Merge branch 'release'

林艳 1 week ago
parent
commit
1f0f337688
100 changed files with 9572 additions and 99 deletions
  1. 1756 0
      content/ai/aiChatDialogue/index-en-US.md
  2. 1761 0
      content/ai/aiChatDialogue/index.md
  3. 1516 0
      content/ai/aiChatInput/index-en-US.md
  4. 1598 0
      content/ai/aiChatInput/index.md
  5. 554 0
      content/ai/aiComponent/index-en-US.md
  6. 555 0
      content/ai/aiComponent/index.md
  7. 53 1
      content/basic/button/index-en-US.md
  8. 52 0
      content/basic/button/index.md
  9. 1 1
      content/basic/divider/index-en-US.md
  10. 1 1
      content/basic/divider/index.md
  11. 240 0
      content/basic/floatbutton/index-en-US.md
  12. 240 0
      content/basic/floatbutton/index.md
  13. 87 1
      content/basic/icon/index-en-US.md
  14. 114 6
      content/basic/icon/index.md
  15. 0 1
      content/basic/resizable/index-en-US.md
  16. 0 1
      content/basic/resizable/index.md
  17. 1 1
      content/basic/space/index-en-US.md
  18. 1 1
      content/basic/space/index.md
  19. 4 0
      content/basic/tokens/index-en-US.md
  20. 25 0
      content/basic/tokens/index.md
  21. 1 1
      content/basic/typography/index-en-US.md
  22. 1 1
      content/basic/typography/index.md
  23. 1 1
      content/feedback/banner/index-en-US.md
  24. 1 1
      content/feedback/banner/index.md
  25. 358 0
      content/feedback/feedback/index-en-US.md
  26. 358 0
      content/feedback/feedback/index.md
  27. 1 1
      content/feedback/notification/index-en-US.md
  28. 1 1
      content/feedback/notification/index.md
  29. 1 1
      content/feedback/popconfirm/index-en-US.md
  30. 1 1
      content/feedback/popconfirm/index.md
  31. 1 1
      content/feedback/progress/index-en-US.md
  32. 1 1
      content/feedback/progress/index.md
  33. 1 1
      content/feedback/skeleton/index-en-US.md
  34. 1 1
      content/feedback/skeleton/index.md
  35. 1 1
      content/feedback/spin/index-en-US.md
  36. 1 1
      content/feedback/spin/index.md
  37. 1 1
      content/feedback/toast/index-en-US.md
  38. 1 1
      content/feedback/toast/index.md
  39. 1 1
      content/input/autocomplete/index-en-US.md
  40. 1 1
      content/input/autocomplete/index.md
  41. 1 1
      content/input/cascader/index-en-US.md
  42. 1 1
      content/input/cascader/index.md
  43. 1 1
      content/input/checkbox/index-en-US.md
  44. 1 1
      content/input/checkbox/index.md
  45. 1 1
      content/input/colorpicker/index-en-US.md
  46. 1 1
      content/input/colorpicker/index.md
  47. 1 1
      content/input/datepicker/index-en-US.md
  48. 1 1
      content/input/datepicker/index.md
  49. 1 1
      content/input/form/index-en-US.md
  50. 1 1
      content/input/form/index.md
  51. 1 1
      content/input/input/index-en-US.md
  52. 1 1
      content/input/input/index.md
  53. 1 1
      content/input/inputnumber/index-en-US.md
  54. 1 1
      content/input/inputnumber/index.md
  55. 1 2
      content/input/pincode/index-en-US.md
  56. 1 2
      content/input/pincode/index.md
  57. 1 1
      content/input/radio/index-en-US.md
  58. 1 1
      content/input/radio/index.md
  59. 1 1
      content/input/rating/index-en-US.md
  60. 1 1
      content/input/rating/index.md
  61. 1 1
      content/input/select/index-en-US.md
  62. 1 1
      content/input/select/index.md
  63. 1 1
      content/input/slider/index-en-US.md
  64. 1 1
      content/input/slider/index.md
  65. 1 1
      content/input/switch/index-en-US.md
  66. 1 1
      content/input/switch/index.md
  67. 1 1
      content/input/taginput/index-en-US.md
  68. 1 1
      content/input/taginput/index.md
  69. 1 1
      content/input/timepicker/index-en-US.md
  70. 1 1
      content/input/timepicker/index.md
  71. 1 1
      content/input/transfer/index-en-US.md
  72. 1 1
      content/input/transfer/index.md
  73. 1 1
      content/input/treeselect/index-en-US.md
  74. 1 1
      content/input/treeselect/index.md
  75. 1 1
      content/input/upload/index-en-US.md
  76. 1 1
      content/input/upload/index.md
  77. 1 1
      content/navigation/anchor/index-en-US.md
  78. 1 1
      content/navigation/anchor/index.md
  79. 1 1
      content/navigation/backtop/index-en-US.md
  80. 1 1
      content/navigation/backtop/index.md
  81. 1 1
      content/navigation/breadcrumb/index-en-US.md
  82. 1 1
      content/navigation/breadcrumb/index.md
  83. 1 1
      content/navigation/navigation/index-en-US.md
  84. 1 1
      content/navigation/navigation/index.md
  85. 1 1
      content/navigation/pagination/index-en-US.md
  86. 1 1
      content/navigation/pagination/index.md
  87. 1 1
      content/navigation/steps/index-en-US.md
  88. 1 1
      content/navigation/steps/index.md
  89. 1 1
      content/navigation/tabs/index-en-US.md
  90. 1 1
      content/navigation/tabs/index.md
  91. 1 1
      content/navigation/tree/index-en-US.md
  92. 1 1
      content/navigation/tree/index.md
  93. 5 0
      content/order.js
  94. 1 1
      content/other/configprovider/index-en-US.md
  95. 1 1
      content/other/configprovider/index.md
  96. 108 2
      content/other/locale/index-en-US.md
  97. 109 3
      content/other/locale/index.md
  98. 1 2
      content/plus/audioPlayer/index-en-US.md
  99. 1 2
      content/plus/audioPlayer/index.md
  100. 1 2
      content/plus/chat/index-en-US.md

+ 1756 - 0
content/ai/aiChatDialogue/index-en-US.md

@@ -0,0 +1,1756 @@
+---
+localeCode: en-US
+order: 100
+category: Plus
+title: AIChatDialogue
+icon: doc-aiDialogue
+width: 60%
+brief: Display AI chat conversation messages to users
+showNew: true
+---
+
+## When to use
+AIChatDialogue can be used together with AIChatInput to build richer, more comprehensive and easier-to-customize AI conversation experiences.
+The component message format is based on OpenAI's [Response Object](https://platform.openai.com/docs/api-reference/responses/object), and supports the OpenAI community's [Response](https://platform.openai.com/docs/api-reference/responses/create) / [Chat Completion](https://platform.openai.com/docs/api-reference/chat/create) format standards by default. Responses to GPT-5 and GPT-4o series models are supported out of the box. For details, see [Message Data Conversion](/zh-CN/ai/aiChatDialogue#%E6%B6%88%E6%81%AF%E6%95%B0%E6%8D%AE%E8%BD%AC%E6%8D%A2).
+
+## Demos
+
+### How to import
+
+```jsx import
+import { AIChatDialogue } from '@douyinfe/semi-ui';
+```
+
+### Basic Usage
+Set `chats` and `onChatsChange` to enable basic conversation display and interactions.
+
+Use `align` to control layout: `leftRight` (default) and `leftAlign`.
+
+```jsx live=true dir="column" noInline=true
+import React, { useState, useCallback } from 'react';
+import { AIChatDialogue, RadioGroup, Radio } from '@douyinfe/semi-ui';
+
+const defaultMessages = [
+    {
+        role: 'system',
+        id: '1',
+        createAt: 1715676751919,
+        content: "Hello, I'm your AI assistant.",   
+    },
+    {
+        role: 'user',
+        id: '2',
+        createAt: 1715676751919,
+        content: "Give an example of using the Semi Design Button component",
+    },
+    {
+        role: 'assistant',
+        id: '3',
+        createAt: 1715676751919,
+        content: "Here is a sample usage of a Semi component:\n```jsx \nimport React from 'react';\nimport { Button } from '@douyinfe/semi-ui';\n\nconst MyComponent = () => {\n  return (\n    <Button>Click me</Button>\n );\n};\nexport default MyComponent;\n```\n",
+    }
+];
+
+const roleConfig = {
+    user: {
+        name: 'User',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png'
+    },
+    assistant: {
+        name: 'Assistant',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+    },
+    system: {
+        name: 'System',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+    }
+};
+
+function AlignAndMode () {
+    const [messages, setMessage] = useState(defaultMessages);
+    const [mode, setMode] = useState('bubble');
+    const [align, setAlign] = useState('leftRight');
+
+    const onAlignChange = useCallback((e) => {
+        setAlign(e.target.value);
+    }, []);
+
+    const onModeChange = useCallback((e) => {
+        setMode(e.target.value);
+    }, []); 
+
+    const onChatsChange = useCallback((chats) => {
+        setMessage(chats);
+    }, []);
+
+    return (
+        <>
+            <span style={{ display: 'flex', flexDirection: 'column', rowGap: '8px' }}>
+                <span style={{ display: 'flex', alignItems: 'center', columnGap: '10px' }}>
+                    Mode
+                    <RadioGroup onChange={onModeChange} value={mode} type={"button"}>
+                        <Radio value={'bubble'}>Bubble</Radio>
+                        <Radio value={'noBubble'}>No bubble</Radio>
+                        <Radio value={'userBubble'}>User bubble</Radio>
+                    </RadioGroup>
+                </span>
+                <span style={{ display: 'flex', alignItems: 'center', columnGap: '10px' }}>
+                    Conversation layout
+                    <RadioGroup onChange={onAlignChange} value={align} type={"button"}>
+                        <Radio value={'leftRight'}>LeftRight</Radio>
+                        <Radio value={'leftAlign'}>LeftAlign</Radio>
+                    </RadioGroup>
+                </span>
+            </span>
+            <div style={{ border: '1px solid var(--semi-color-border)', borderRadius: 12, marginTop: 10, padding: 20 }}>
+                <AIChatDialogue 
+                    key={align + mode}
+                    align={align}
+                    mode={mode}
+                    chats={messages}
+                    roleConfig={roleConfig}
+                    onChatsChange={onChatsChange}
+                />
+            </div>
+        </>
+    );
+}
+
+render(AlignAndMode);
+
+```
+
+### Message Status
+`chats` is of type `Message[]`. Each `Message` contains various fields such as role `role`, content `content`, status `status`, unique identifier `id`, and creation time `createdAt`. See [Message](#Message) for details. The `status` follows the same values as the [Response API Status](https://platform.openai.com/docs/api-reference/responses/object#responses/object-status): 6 status values mapping to 3 official styles (success / in progress / failed).
+
+```jsx live=true dir="column" noInline=true
+import React, { useState, useCallback } from 'react';
+import { AIChatDialogue } from '@douyinfe/semi-ui';
+
+const defaultMessages = [
+    {
+        role: 'assistant',
+        id: '1',
+        createAt: 1715676751919,
+        content: "Success", 
+        // default status is completed
+    },
+    {
+        id: 'loading',
+        role: 'assistant',
+        status: 'in_progress' // Same visual as queued, incomplete
+    },
+    {
+        role: 'assistant',
+        id: 'error',
+        content: 'Error',
+        status: 'failed' // Same visual as cancelled
+    }
+];
+
+const roleConfig = {
+    user: {
+        name: 'User',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png'
+    },
+    assistant: {
+        name: 'Assistant',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+    },
+    system: {
+        name: 'System',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+    }
+};
+
+function StatusDemo () {
+    const [messages, setMessage] = useState(defaultMessages);
+
+    const onChatsChange = useCallback((chats) => {
+        setMessage(chats);
+    }, []);
+
+    return (
+        <AIChatDialogue 
+            chats={messages}
+            roleConfig={roleConfig}
+            onChatsChange={onChatsChange}
+        />
+    );
+}
+
+render(StatusDemo);
+
+```
+
+### Message Display
+The message content uses [ContentItem[]](https://platform.openai.com/docs/api-reference/responses/list#responses/list-data). It supports blocks such as text, file, image, code, reasoning, annotation, and tool call. `AIChatDialogue.Step` is provided for step-by-step displays (e.g., workflows or plans).
+
+```jsx live=true dir="column" noInline=true
+import React, { useState, useCallback } from 'react';
+import { AIChatDialogue } from '@douyinfe/semi-ui';
+import { IconSearchStroked, IconCodeStroked, IconBriefStroked } from '@douyinfe/semi-icons';
+
+
+const defaultMessages = [
+    {
+        role: 'assistant',
+        id: '1',
+        createAt: 1715676751919,
+        content: 'Plain text', 
+    },
+    {
+        id: '2',
+        role: 'user',
+        content: [
+            {
+                type: 'message',
+                content: [
+                    {
+                        type: 'input_text',
+                        text: 'Help me generate a similar image',
+                    },
+                    {
+                        type: 'input_image',
+                        image_url: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/edit-bag.jpeg',
+                        file_id: 'demo-file-id'
+                    },
+                    {
+                        type: 'input_text',
+                        text: 'Files preview below',
+                    },
+                    {
+                        type: 'input_file',
+                        file_url: 'https://www.semi.pdf',
+                        filename: 'semi.pdf',
+                        size: '100KB',
+                    },
+                    {
+                        type: 'input_file',
+                        file_url: 'https://www.semi.json',
+                        filename: 'semi.json',
+                        size: '100KB',
+                    },
+                    {
+                        type: 'input_file',
+                        file_url: 'https://www.semi.docx',
+                        filename: 'semi.docx',
+                        size: '100KB',
+                    }
+                ],
+            },
+        ],
+        status: 'completed',
+    },
+    {
+        id: '3',
+        role: 'assistant',
+        content: [
+            {
+                type: 'reasoning',
+                status: 'completed',
+                summary: [
+                    {
+                        'type': 'summary_text',
+                        'text': '\nI need to reason and answer the user about what the Semi component library is...'
+                    }
+                ],
+            },
+            {
+                type: 'message',
+                content: [
+                    {
+                        type: 'output_text',
+                        text: 'Semi Design is a design system built and maintained by ByteDance Frontend Team and the MED Product Design Team.'
+                    }
+                ],
+                status: 'completed',
+            },
+            {
+                id: 'fc_12345xyz',
+                call_id: 'call_12345xyz',
+                type: 'function_call',
+                name: 'get_weather',
+                status: 'completed',
+                arguments: '{\'location\':\'Paris, France\'}'
+            },
+            {
+                type: 'message',
+                content: [
+                    {
+                        type: 'output_text',
+                        text: 'Congrats! You now know everything about Semi Design!',
+                        annotations: [
+                            {
+                                title: 'semi.design',
+                                url: 'https://semi.design/',
+                                detail: 'semi design page',
+                                logo: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+                            },
+                            {
+                                title: 'semi.design',
+                                url: 'https://semi.design/',
+                                detail: 'semi design page',
+                                logo: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+                            },
+                        ]
+                    }
+                ]
+            },
+            {
+                type: 'plan',
+                content: [
+                    {
+                        summary: 'Create a comprehensive Beijing travel guide covering attractions, lodging, transport, food, and tips',
+                        steps: [
+                            {
+                                summary: 'Search introductions and ticket info for Beijing attractions',
+                                description: 'Searching: Beijing attraction introductions and ticket info',
+                                type: 'search',
+                            }, 
+                            {
+                                summary: 'Read specific lines of a given file',
+                                description: 'Creating document: Beijing Travel Guide',
+                                type: 'docs',
+                            }, 
+                            {
+                                summary: 'Create a file containing the Beijing travel guide',
+                                description: 'Creating code file: beijing_travel_guide.html',
+                                type: 'code',
+                            }, 
+                        ],
+                        statues: 'completed'
+                    },
+                    {
+                        summary: 'Summarize the created Beijing travel guide and present to the user',
+                        steps: []
+                    }
+                ],
+            }
+        ],
+        status: 'completed',
+    },
+];
+
+const roleConfig = {
+    user: {
+        name: 'User',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png'
+    },
+    assistant: {
+        name: 'Assistant',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+    },
+    system: {
+        name: 'System',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+    }
+};
+
+function AllTypeMessageDemo () {
+    const [messages, setMessage] = useState(defaultMessages);
+
+    const onChatsChange = useCallback((chats) => {
+        setMessage(chats);
+    }, []);
+
+    const mapStep = useCallback((steps) => {
+        if (!steps) {
+            return [];
+        }
+        return steps.map((item) => {
+            let icon = null;
+            switch (item.type) {
+                case 'search':
+                    icon = <IconSearchStroked />;
+                    break;
+                case 'docs':
+                    icon = <IconBriefStroked />;
+                    break;
+                case 'code':
+                    icon = <IconCodeStroked />;
+                    break;
+            }
+            return {
+                summary: item.summary,
+                description: item.description,
+                icon: icon,
+            };
+        });
+    }, []);
+
+    const customRender = useCallback((message) => {
+        return {
+            'plan': (item) => { // 'plan' is a custom user-defined type
+                let steps = item.content.map((item) => {
+                    return {
+                        summary: item.summary,
+                        actions: mapStep(item.steps),
+                        status: 'completed'
+                    };
+                });
+                return <AIChatDialogue.Step steps={steps} />;
+            },
+        };
+    }, []);
+
+    return (
+        <AIChatDialogue 
+            chats={messages}
+            roleConfig={roleConfig}
+            onChatsChange={onChatsChange}
+            renderDialogueContentItem={customRender}
+        />
+    );
+}
+
+render(AllTypeMessageDemo);
+
+```
+
+
+### References
+Use `references` to define files or text cited by the current message. `showReference` controls whether a quotable style is shown for the current message. `onReferenceClick` configures the click handler for the reference button.
+
+```jsx live=true dir="column" noInline=true
+import React, { useState, useCallback } from 'react';
+import { AIChatDialogue } from '@douyinfe/semi-ui';
+
+const defaultMessages = [
+    {
+        id: '1',
+        role: 'user',
+        content: 'This message is an example for the References demo',
+        references: [
+            {
+                id: '1',
+                type: 'text',
+                content: 'Sample text. This is a long paragraph of text repeated for demonstration purposes to show truncation and layout behavior in the reference area.',
+            },
+            {
+                id: '2',
+                name: 'Feishu Doc.docx',
+            },
+            {
+                id: '3',
+                name: 'Music.mp4',
+            },
+            {
+                id: '4',
+                name: 'Image.jpeg',
+                url: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/Resso.png'
+            },
+            {
+                id: '5',
+                name: 'code.json',
+            }
+        ]
+    }
+];
+
+const roleConfig = {
+    user: {
+        name: 'User',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png'
+    },
+    assistant: {
+        name: 'Assistant',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+    },
+    system: {
+        name: 'System',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+    }
+};
+
+function ReferencesDemo () {
+    const [messages, setMessage] = useState(defaultMessages);
+
+    const onChatsChange = useCallback((chats) => {
+        setMessage(chats);
+    }, []);
+
+    const onReferenceClick = () => {
+        console.log('You click the reference button!');
+    };
+
+    return (
+        <AIChatDialogue 
+            chats={messages}
+            roleConfig={roleConfig}
+            onChatsChange={onChatsChange}
+            showReference
+            onReferenceClick={onReferenceClick}
+        />
+    );
+}
+
+render(ReferencesDemo);
+```
+
+
+### Selection
+```jsx live=true dir="column" noInline=true
+import React, { useState, useCallback } from 'react';
+import { AIChatDialogue, RadioGroup, Radio } from '@douyinfe/semi-ui';
+
+const defaultMessages = [
+    {
+        role: 'system',
+        id: '1',
+        createAt: 1715676751919,
+        content: "Hello, I'm your AI assistant.",   
+    },
+    {
+        role: 'user',
+        id: '2',
+        createAt: 1715676751919,
+        content: "Give an example of using the Semi Design Button component",
+    },
+    {
+        role: 'assistant',
+        id: '3',
+        createAt: 1715676751919,
+        content: "Here is a sample usage of a Semi component:\n```jsx \nimport React from 'react';\nimport { Button } from '@douyinfe/semi-ui';\n\nconst MyComponent = () => {\n  return (\n    <Button>Click me</Button>\n );\n};\nexport default MyComponent;\n```\n",
+    }
+];
+
+const roleConfig = {
+    user: {
+        name: 'User',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png'
+    },
+    assistant: {
+        name: 'Assistant',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+    },
+    system: {
+        name: 'System',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+    }
+};
+
+function SelectingDemo () {
+    const ref = useRef(null);
+    const [messages, setMessage] = useState(defaultMessages);
+    const [align, setAlign] = useState('leftRight');
+    const [select, setSelect] = useState(true);
+    const [selection, setSelection] = useState('allSelect');
+
+    useEffect(() => {
+        ref.current.selectAll();
+    }, []);
+
+    const onSelectChange = useCallback((e) => {
+        setSelect(e.target.value);
+    }, []);
+
+    const onSelectionChange = useCallback((e) => {
+        if (e.target.value === 'allSelect') {
+            ref.current.selectAll();
+        } else {
+            ref.current.deselectAll();
+        }
+        setSelection(e.target.value);
+    }, []);
+
+    const onSelect = useCallback((selectionId) => {
+        console.log('onSelect', selectionId);
+    }, []);
+
+    const onAlignChange = useCallback((e) => {
+        setAlign(e.target.value);
+    }, []);
+
+    const onChatsChange = useCallback((chats) => {
+        setMessage(chats);
+    }, []);
+
+    return (
+        <div>
+            <span style={{ display: 'flex', flexDirection: 'column', rowGap: '8px' }}>
+                <span style={{ display: 'flex', alignItems: 'center', columnGap: '10px' }}>
+                    Session Layout
+                    <RadioGroup onChange={onAlignChange} value={align} type={"button"}>
+                        <Radio value={'leftRight'}>Left Right</Radio>
+                        <Radio value={'leftAlign'}>Left Align</Radio>
+                    </RadioGroup>
+                </span>
+                <span style={{ display: 'flex', alignItems: 'center', columnGap: '10px' }}>
+                    Whether to Enable Selection
+                    <RadioGroup onChange={onSelectChange} value={select} type={"button"}>
+                        <Radio value={true}>ON</Radio>
+                        <Radio value={false}>OFF</Radio>
+                    </RadioGroup>
+                </span>
+                <span style={{ display: 'flex', alignItems: 'center', columnGap: '10px' }}>
+                    Selection Method
+                    <RadioGroup onChange={onSelectionChange} value={selection} type={"button"}>
+                        <Radio value={'allSelect'}>AllSelect</Radio>
+                        <Radio value={'cancelSelect'}>CancelAllSelect</Radio>
+                    </RadioGroup>
+                </span>
+            </span>
+
+            <div style={{ border: '1px solid var(--semi-color-border)', borderRadius: 12, marginTop: 10, padding: 20 }}>
+                <AIChatDialogue 
+                    ref={ref}
+                    align={align}
+                    mode="bubble"
+                    chats={messages}
+                    selecting={select}
+                    onSelect={onSelect}
+                    roleConfig={roleConfig}
+                />
+            </div>
+        </div>
+    );
+}
+
+render(SelectingDemo);
+
+```
+
+<!-- todo -->
+<!-- ### 编辑消息 -->
+<!-- ```jsx live=true dir="column" noInline=true
+
+``` -->
+
+
+### Hints
+Use `hints` to set the hint area content. Clicking a hint populates it as the new user input and triggers `onHintClick`.
+
+```jsx live=true dir="column"
+import React, { useState, useCallback } from 'react';
+import { AIChatDialogue } from '@douyinfe/semi-ui';
+
+() => {
+    const defaultMessages = [
+        {
+            role: 'assistant',
+            id: '1',
+            createAt: 1715676751919,
+            content: 'Semi Design is a design system designed, developed, and maintained by the TikTok front-end team and the MED product design team. You can ask me any questions about Semi.',
+        }
+    ];
+
+    const hintsExample = [
+        "What are the commonly used components in the Semi component library?",
+        "Can you show an example of a page built using the Semi component library?",
+        "Is there any official documentation for the Semi component library?",
+    ];
+
+    const roleConfig = {
+        user: {
+            name: 'User',
+            avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png'
+        },
+        assistant: {
+            name: 'Assistant',
+            avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+        },
+        system: {
+            name: 'System',
+            avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+        }
+    };
+    const [messages, setMessage] = useState(defaultMessages);
+    const [hints, setHints] = useState(hintsExample);
+  
+    const onChatsChange = useCallback((chats) => {
+        console.log('onChatsChange', chats);
+        setMessage(chats);
+    }, []);
+
+    const onHintClick = useCallback((hint) => {
+        setHints([]);
+    }, []);
+
+    return (
+        <AIChatDialogue 
+            align="leftRight"
+            mode="bubble"
+            chats={messages}
+            roleConfig={roleConfig}
+            onChatsChange={onChatsChange}
+            hints={hints}
+            onHintClick={onHintClick}
+        />
+    );
+};
+
+```
+
+
+
+### Custom Hint Rendering
+Customize the hint area with `renderHintBox`. Parameters:
+
+```ts
+type renderHintBox = (props: {content: string; index: number,onHintClick: () => void}) => React.ReactNode;
+```
+
+```jsx live=true dir="column"
+import React, { useState, useCallback } from 'react';
+import { AIChatDialogue } from '@douyinfe/semi-ui';
+import { IconArrowRight } from '@douyinfe/semi-icons';
+
+
+() => {
+    const defaultMessages = [
+        {
+            role: 'assistant',
+            id: '1',
+            createAt: 1715676751919,
+            content: 'Semi Design is a design system created and maintained by ByteDance Frontend Team and the MED Product Design Team. You can ask me anything about Semi.',
+        }
+    ];
+
+    const hintsExample = [
+        "What are the commonly used components in the Semi component library?",
+        "Can you show an example of a page built using the Semi component library?",
+        "Is there any official documentation for the Semi component library?",
+    ];
+
+    const roleConfig = {
+        user: {
+            name: 'User',
+            avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png'
+        },
+        assistant: {
+            name: 'Assistant',
+            avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+        },
+        system: {
+            name: 'System',
+            avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+        }
+    };
+    const [messages, setMessage] = useState(defaultMessages);
+    const [hints, setHints] = useState(hintsExample);
+  
+    const onChatsChange = useCallback((chats) => {
+        console.log('onChatsChange', chats);
+        setMessage(chats);
+    }, []);
+
+    const onHintClick = useCallback((hint) => {
+        setHints([]);
+    }, []);
+
+    const commonHintStyle = useMemo(() => ({
+        border: '1px solid var(--semi-color-border)',
+        padding: '10px',
+        borderRadius: '10px',
+        color: 'var( --semi-color-text-1)',
+        display: 'flex',
+        justifyContent: 'space-between',
+        alignItems: 'center',
+        cursor: 'pointer',
+        fontSize: '14px'
+    }), []);
+
+    const renderHintBox = useCallback((props) => {
+        const { content, onHintClick, index } = props;
+        return (
+            <div style={commonHintStyle} onClick={onHintClick} key={index}>
+                {content}
+                <IconArrowRight style={{ marginLeft: 10 }}>click me</IconArrowRight>
+            </div>
+        );
+    }, []);
+    
+
+    return (
+        <AIChatDialogue 
+            align="leftRight"
+            mode="bubble"
+            chats={messages}
+            roleConfig={roleConfig}
+            onChatsChange={onChatsChange}
+            hints={hints}
+            onHintClick={onHintClick}
+            renderHintBox={renderHintBox}
+        />
+    );
+};
+```
+
+### Custom Chat Box Rendering
+Pass custom rendering configuration via `chatBoxRenderConfig`. Types:
+
+```ts
+export interface RenderTitleProps {
+    message?: Message;
+    role?: Metadata;
+    defaultTitle?: ReactNode
+}
+
+export interface RenderAvatarProps {
+    message?: Message; 
+    role?: Metadata, 
+    defaultAvatar?: ReactNode
+}
+
+export interface RenderContentProps {
+    message?: Message;
+    role?: Metadata | Map<string, Metadata>;
+    defaultContent?: ReactNode | ReactNode[]; 
+    className?: string;
+}
+
+export interface DefaultActionNodeObj {
+    copyNode: ReactNode;
+    likeNode: ReactNode;
+    dislikeNode: ReactNode;
+    resetNode: ReactNode;
+    moreNode: ReactNode;
+}
+
+export interface RenderActionProps {
+    message?: Message;
+    defaultActions?: ReactNode | ReactNode[];
+    className: string;
+    defaultActionsObj?: DefaultActionNodeObj;
+};
+
+export interface FullDialogueNodes {
+    avatar?: ReactNode;
+    title?: ReactNode; 
+    content?: ReactNode; 
+    action?: ReactNode
+}
+
+export interface RenderFullDialogueProps {
+    message?: Message;
+    role?: Metadata;
+    defaultNodes?: FullDialogueNodes;
+    className: string
+}
+
+
+export interface DialogueRenderConfig {
+    /* Customize message title rendering */
+    renderDialogueAction?: (props: RenderActionProps) => ReactNode;
+    /* Customize avatar rendering */
+    renderDialogueAvatar?: (props: RenderAvatarProps) => ReactNode;
+    /* Customize content rendering */
+    renderDialogueContent?: (props: RenderContentProps) => ReactNode;
+    /* Customize action bar rendering */
+    renderDialogueTitle?: (props: RenderTitleProps) => ReactNode;
+    /* Fully customize the entire chat box */
+    renderFullDialogue?: (props: RenderFullDialogueProps) => ReactNode
+}
+```
+
+You can customize the avatar and title via `renderChatBoxAvatar` and `renderChatBoxTitle`.
+```jsx live=true dir="column" 
+import React, { useState, useCallback } from 'react';
+import { AIChatDialogue, Avatar } from '@douyinfe/semi-ui';
+
+() => {
+    const defaultMessages = [
+        {
+            role: 'system',
+            id: '1',
+            createAt: 1715676751919,
+            content: "Hello, I'm your AI assistant.",   
+        },
+        {
+            role: 'user',
+            id: '2',
+            createAt: 1715676751919,
+            content: "Give an example of using the Semi Design Button component",
+        },
+        {
+            role: 'assistant',
+            id: '3',
+            createAt: 1715676751919,
+            content: "Here is a sample usage of a Semi component:\n```jsx \nimport React from 'react';\nimport { Button } from '@douyinfe/semi-ui';\n\nconst MyComponent = () => {\n  return (\n    <Button>Click me</Button>\n );\n};\nexport default MyComponent;\n```\n",
+        }
+    ];
+
+    const roleConfig = {
+        user: {
+            name: 'User',
+            avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png'
+        },
+        assistant: {
+            name: 'Assistant',
+            avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+        },
+        system: {
+            name: 'System',
+            avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+        }
+    };
+
+    const [messages, setMessage] = useState(defaultMessages);
+    const onChatsChange = useCallback((chats) => {
+        setMessage(chats);
+    }, []);
+
+    const renderConfig = {
+        renderDialogueTitle: (props) => {
+            return <div className="semi-ai-chat-dialogue-title">My-{props.role.name}</div>;
+        },
+        renderDialogueAvatar: (props) => {
+            return <Avatar
+                src={props.role.avatar}
+                size="extra-small"
+                shape="square"
+            >
+            </Avatar>;
+        },
+        renderDialogueAction: (props) => {
+            return <div className={props.className}>{props.defaultActions[0]}</div>;
+        },
+    };
+
+    return (
+        <AIChatDialogue 
+            align="leftRight"
+            mode="bubble"
+            chats={messages}
+            roleConfig={roleConfig}
+            onChatsChange={onChatsChange}
+            dialogueRenderConfig={renderConfig}
+        />
+    );
+};
+
+```
+
+### Custom Message Content Rendering
+
+Use `renderDialogueContentItem` to provide renderers by message type. Example:
+
+```jsx live=true dir="column" noInline=true
+import React, { useState, useCallback } from 'react';
+import { AIChatDialogue, MarkdownRender } from '@douyinfe/semi-ui';
+
+const defaultMessages = [
+    {
+        id: '1',
+        role: 'user',
+        content: 'Hello',
+    }, 
+    {
+        id: '2',
+        role: 'assistant',
+        content: 'Hello! How can I help you today?',
+        status: 'completed',
+    }, 
+    {
+        id: '3',
+        role: 'user',
+        content: [
+            {
+                type: 'message',
+                role: 'user',
+                content: [
+                    {
+                        type: 'input_text',
+                        text: 'Help me generate a similar image',
+                    }, 
+                    {
+                        type: 'input_image',
+                        image_url: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/edit-bag.jpeg',
+                        file_id: 'demo-file-id'
+                    }, 
+                    {
+                        type: 'input_image',
+                        image_url: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/edit-bag.jpeg',
+                        file_id: 'demo-file-id'
+                    }
+                ],
+            }],
+    }, 
+    {
+        id: '4',
+        role: 'assistant',
+        content: [{
+            type: "reasoning",
+            summary: [
+                {
+                    "type": "summary_text",
+                    "text": "\nThe user asked me to generate a similar image. I need to analyze the image first, then generate a similar one..."
+                }
+            ],
+            annotations: [
+                {
+                    title: 'semi.design',
+                    url: 'https://semi.design/',
+                    detail: 'semi design page',
+                    logo: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+                },
+                {
+                    title: 'semi.design',
+                    url: 'https://semi.design/',
+                    detail: 'semi design page',
+                    logo: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+                },
+            ],
+            status: "completed"
+        }, 
+        {
+            type: 'function_call',
+            name: 'create_travel_guide',
+            arguments: "{\n\"city\": \"Beijing\"\n}",
+            status: 'completed',
+        }
+        ],
+        status: 'completed',
+    }];
+
+const roleConfig = {
+    user: {
+        name: 'User',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png'
+    },
+    assistant: {
+        name: 'Assistant',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+    },
+    system: {
+        name: 'System',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+    }
+};
+
+function CustomRender () {
+    const [messages, setMessage] = useState(defaultMessages);
+    const onChatsChange = useCallback((chats) => {
+        setMessage(chats);
+    }, []);
+
+    const userTextStyle = {
+        backgroundColor: 'var(--semi-color-fill-1)',
+        color: 'var(--semi-color-text-0)',
+        borderRadius: '25px',
+        padding: '6px 16px',
+    };
+
+    const assistantStyle = {
+        color: 'var(--semi-color-text-0)',
+        padding: '6px 16px',
+    };
+
+    const functionCallStyle = {
+        backgroundColor: 'var(--semi-color-fill-1)',
+        padding: '6px 16px',
+        borderRadius: '25px',
+    };
+
+    const customRenderReasoningContent = useCallback((props) => {
+        return <React.Fragment>
+            <AIChatDialogue.Annotation 
+                annotation={props.annotations} 
+                description={'References'} 
+                maxCount={3}
+                onClick={(e) => {
+                    e && e.stopPropagation();
+                    Toast.success('Ready to open the sidebar!');
+                }}
+            />
+            <div style={{ marginTop: '8px' }}>
+                <MarkdownRender
+                    format='md'
+                    raw={props.summary[0].text}
+                    {...props.markdownRenderProps}
+                />
+            </div>
+        </React.Fragment>;
+    }, []);
+
+    const customRender = {
+        "function_call": {
+            "create_travel_guide": (item) => {
+                return <div style={functionCallStyle}>Function Tool Call: {item.name} {item.arguments}</div>;
+            }
+        },
+        "input_text": (item, message) => {
+            if (message.role === 'user') {
+                return <div style={userTextStyle} className={'userTextStyle'}>{item.text}</div>;
+            }
+            return <div style={assistantStyle}>{item.text}</div>;
+        },
+        "reasoning": (item) => {
+            return <AIChatDialogue.Reasoning {...item} customRenderer={customRenderReasoningContent} />;
+        },
+        "default": (item, message) => {
+            if (message.role === 'user') {
+                return <div style={userTextStyle} className={'userTextStyle'}>{item}</div>;
+            } else {
+                return <div style={assistantStyle}>{item}</div>;
+            }
+        }
+    };
+
+    return (
+        <AIChatDialogue 
+            chats={messages}
+            roleConfig={roleConfig}
+            onChatsChange={onChatsChange}
+            renderDialogueContentItem={customRender}
+        />
+    );
+}
+
+render(CustomRender);
+```
+
+
+
+### Message Data Adapters
+The current component's dialogue messages are modeled after OpenAI's [Response Object](https://platform.openai.com/docs/api-reference/responses/object). To better support users in seamlessly integrating the [Chat Completion API](https://platform.openai.com/docs/api-reference/chat/create) and [Response API](https://platform.openai.com/docs/api-reference/responses/create), we provide four `Adapter` transformation functions. Users can directly use these functions to transform the API's return results to obtain data that can be directly used for message display. Two `Adapter` functions are provided to process the data of the `ChatInput` component into an `input Message` format adapted to the `Response API` or the `Input Message` format in the `Chat Completion API`.
+
+```ts
+// Convert the data returned by the Chat Completion API into the Message format in Chat Dialogue
+function chatCompletionToMessage(chatCompletion: ChatCompletion): Message[]
+
+// Convert the Chat Completion API streaming data into Message format for Chat Dialogue.
+function streamingChatCompletionToMessage(chatCompletionChunks: ChatCompletionChunk[], state?: StreamingChatState): { messages: Message[]; state?: StreamingChatState }
+
+// Convert the data returned by the Response API into the Message format in Chat Dialogue
+function responseToMessage(response: Response): Message
+
+// Convert the streaming data returned by the Response API into the Message format in Chat Dialogue
+function streamingResponseToMessage(chunks: ResponseChunk[], prevState: StreamingResponseState): { messages: Message[]; state?: StreamingResponseState }
+
+// Convert the streaming data returned by the Response API into Message format for the Chat Dialogue.
+function chatInputToMessage(inputContent: MessageContent): Message
+
+// Convert Chat Input data to Input Message format in Chat Completion API
+function chatInputToChatCompletion(inputContent: MessageContent): ChatCompletionInput
+```
+
+For example, when a user returns non-streaming data using the [Chat Completion API](https://platform.openai.com/docs/api-reference/chat/create) interface, the `chatCompletionToMessage` function can be used to convert the Chat Completion Object into a Dialogue Message block format. Note that because the `Chat Completion API` allows control over the number of results generated for each input message via `n`, this function returns an array. (Note: If n > 1, the user needs to decide which data to add to the message for display.)
+
+```jsx live=true noInline=true dir="column"
+import React, { useState, useCallback } from 'react';
+import { AIChatDialogue } from '@douyinfe/semi-ui';
+
+const roleConfig = {
+    user: {
+        name: 'User',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png'
+    },
+    assistant: {
+        name: 'Assistant',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+    },
+    system: {
+        name: 'System',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+    }
+};
+
+function ChatCompletionToMessageDemo() {
+    const [messages, setMessage] = useState([]);
+
+    const onChatsChange = useCallback((chats) => {
+        setMessage(chats);
+    }, []);
+
+    useEffect(() => {
+        const message = chatCompletionToMessage(CHAT_COMPLETION_DATA);
+        setMessage([...message]);
+    }, []);
+  
+    return (
+        <AIChatDialogue 
+            align="leftRight"
+            mode="bubble"
+            chats={messages}
+            roleConfig={roleConfig}
+            onChatsChange={onChatsChange}
+        />
+    );
+};
+
+const CHAT_COMPLETION_DATA = {
+    "id": "chatcmpl-B9MBs8CjcvOU2jLn4n570S5qMJKcT",
+    "object": "chat.completion",
+    "created": 1741569952,
+    "model": "gpt-4.1-2025-04-14",
+    "choices": [
+        {
+            "index": 0,
+            "message": {
+                "role": "assistant",
+                "content": "Hello! How can I assist you today?",
+                "refusal": null,
+                "annotations": [],
+                "tool_calls": [
+                    {
+                        "id": "call_abc123",
+                        "type": "function",
+                        "function": {
+                            "name": "get_current_weather",
+                            "arguments": "{\n\"location\": \"Boston, MA\"\n}"
+                        }
+                    }
+                ]
+            },
+            "logprobs": null,
+            "finish_reason": "stop"
+        }
+    ],
+    // ...
+};
+
+render(ChatCompletionToMessageDemo);
+```
+
+
+For example, when a user returns streaming data using the [Chat Completion API](https://platform.openai.com/docs/api-reference/chat/create) interface, the `streamingChatCompletionToMessage` function can be used to convert the Chat Completion Chunk Object List into a Dialogue Message format.
+
+```jsx live=true noInline=true dir="column"
+import React, { useState, useCallback } from 'react';
+import { AIChatDialogue } from '@douyinfe/semi-ui';
+
+const roleConfig = {
+    user: {
+        name: 'User',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png'
+    },
+    assistant: {
+        name: 'Assistant',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+    },
+    system: {
+        name: 'System',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+    }
+};
+
+function StreamingChatCompletionToMessageDemo() {
+    const [messages, setMessage] = useState([]);
+    const [state, setState] = useState();
+
+    const onChatsChange = useCallback((chats) => {
+        setMessage(chats);
+    }, []);
+
+    useEffect(() => {
+        const total = STREAMING_CHAT_COMPLETION_DATA.length;
+        let i = 1;
+
+        const timer = setInterval(() => {
+            if (i > total) {
+                clearInterval(timer);
+                return;
+            }
+
+            const slice = STREAMING_CHAT_COMPLETION_DATA.slice(0, i);
+            const { messages: partialMessages, state: nextState } = streamingChatCompletionToMessage(slice, state);
+            setState(nextState);
+
+            const merged = [...messages, partialMessages[0]];
+            setMessage(merged);
+
+            i += 1;
+        }, 100);
+
+        return () => clearInterval(timer);
+    }, []);
+  
+    return (
+        <AIChatDialogue 
+            align="leftRight"
+            mode="bubble"
+            chats={messages}
+            roleConfig={roleConfig}
+            onChatsChange={onChatsChange}
+        />
+    );
+};
+
+const STREAMING_CHAT_COMPLETION_DATA = [
+    { "id": "chatcmpl-COjljxurV5GKrRUsg1wd7mIyQCiiT", "object": "chat.completion.chunk", "created": 1760011843, "model": "o3-mini-2025-01-31", "service_tier": "default", "system_fingerprint": "fp_6c43dcef8c", "choices": [{ "index": 0, "delta": { "role": "assistant", "content": "", "refusal": null }, "finish_reason": null }], "obfuscation": "ahPqlzj6DD" },
+    { "id": "chatcmpl-COjljxurV5GKrRUsg1wd7mIyQCiiT", "object": "chat.completion.chunk", "created": 1760011843, "model": "o3-mini-2025-01-31", "service_tier": "default", "system_fingerprint": "fp_6c43dcef8c", "choices": [{ "index": 0, "delta": { "content": "" }, "finish_reason": null }], "obfuscation": "i2PXRIwvc3D" },
+    // index 0: 输出文本增量
+    { "id": "chatcmpl-COjljxurV5GKrRUsg1wd7mIyQCiiT", "object": "chat.completion.chunk", "created": 1760011843, "model": "o3-mini-2025-01-31", "service_tier": "default", "system_fingerprint": "fp_6c43dcef8c", "choices": [{ "index": 0, "delta": { "content": " I'm using " }, "finish_reason": null }], "obfuscation": "3sslO5QylW" },
+    { "id": "chatcmpl-COjljxurV5GKrRUsg1wd7mIyQCiiT", "object": "chat.completion.chunk", "created": 1760011843, "model": "o3-mini-2025-01-31", "service_tier": "default", "system_fingerprint": "fp_6c43dcef8c", "choices": [{ "index": 0, "delta": { "content": "streamingChatCompletionToMessage" }, "finish_reason": null }], "obfuscation": "3sslO5QylW" },
+
+    // index 1: 工具调用增量(function_call / tool_calls)
+    { "id": "chatcmpl-COjljxurV5GKrRUsg1wd7mIyQCiiT", "object": "chat.completion.chunk", "created": 1760011845, "model": "o3-mini-2025-01-31", "service_tier": "default", "system_fingerprint": "fp_6c43dcef8c", "choices": [{ "index": 1, "delta": { "tool_calls": [{ "id": "call_1", "function": { "name": "searchWeather", "arguments": "{\"city\":\"Beijing\"}" } }] }, "finish_reason": null }], "obfuscation": "T1" },
+    { "id": "chatcmpl-COjljxurV5GKrRUsg1wd7mIyQCiiT", "object": "chat.completion.chunk", "created": 1760011846, "model": "o3-mini-2025-01-31", "service_tier": "default", "system_fingerprint": "fp_6c43dcef8c", "choices": [{ "index": 1, "delta": { "tool_calls": [{ "id": "call_1", "function": { "name": null, "arguments": ",\"day\":\"today\"}" } }] }, "finish_reason": null }], "obfuscation": "T2" },
+
+    { "id": "chatcmpl-COjljxurV5GKrRUsg1wd7mIyQCiiT", "object": "chat.completion.chunk", "created": 1760011844, "model": "o3-mini-2025-01-31", "service_tier": "default", "system_fingerprint": "fp_6c43dcef8c", "choices": [{ "index": 0, "delta": { "content": " transform to Chat Completion Chunks" }, "finish_reason": null }], "obfuscation": "X1" },
+    { "id": "chatcmpl-COjljxurV5GKrRUsg1wd7mIyQCiiT", "object": "chat.completion.chunk", "created": 1760011844, "model": "o3-mini-2025-01-31", "service_tier": "default", "system_fingerprint": "fp_6c43dcef8c", "choices": [{ "index": 0, "delta": { "content": " 🥳" }, "finish_reason": null }], "obfuscation": "X2" },
+
+    // 终止信号
+    { "id": "chatcmpl-COjljxurV5GKrRUsg1wd7mIyQCiiT", "object": "chat.completion.chunk", "created": 1760011843, "model": "o3-mini-2025-01-31", "service_tier": "default", "system_fingerprint": "fp_6c43dcef8c", "choices": [{ "index": 0, "delta": {}, "finish_reason": "stop" }], "obfuscation": "n13SLf" },
+    { "id": "chatcmpl-COjljxurV5GKrRUsg1wd7mIyQCiiT", "object": "chat.completion.chunk", "created": 1760011843, "model": "o3-mini-2025-01-31", "service_tier": "default", "system_fingerprint": "fp_6c43dcef8c", "choices": [{ "index": 1, "delta": {}, "finish_reason": "stop" }], "obfuscation": "jt9rDb" }
+];
+
+render(StreamingChatCompletionToMessageDemo);
+
+```
+
+When a user returns non-streaming data using the [Response API](https://platform.openai.com/docs/api-reference/responses/create) interface, the `responseToMessage` function can be used to convert the Response Object into a Dialogue Message block format.
+```jsx live=true noInline=true dir="column"
+import React, { useState, useCallback } from 'react';
+import { AIChatDialogue } from '@douyinfe/semi-ui';
+
+const roleConfig = {
+    user: {
+        name: 'User',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png'
+    },
+    assistant: {
+        name: 'Assistant',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+    },
+    system: {
+        name: 'System',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+    }
+};
+
+function ResponseToMessageDemo() {
+    const [messages, setMessage] = useState([]);
+
+    const onChatsChange = useCallback((chats) => {
+        setMessage(chats);
+    }, []);
+
+    useEffect(() => {
+        const responseMessage = responseToMessage(RESPONSE_DATA);
+
+        setMessage([responseMessage]);
+    }, []);
+  
+    return (
+        <AIChatDialogue 
+            align="leftRight"
+            mode="bubble"
+            chats={messages}
+            roleConfig={roleConfig}
+            onChatsChange={onChatsChange}
+        />
+    );
+};
+
+const RESPONSE_DATA = {
+    "id": "resp_67ccd3a9da748190baa7f1570fe91ac604becb25c45c1d41",
+    "object": "response",
+    "created_at": 1741476777,
+    "status": "completed",
+    "error": null,
+    "incomplete_details": null,
+    "instructions": null,
+    "max_output_tokens": null,
+    "model": "gpt-4o-2024-08-06",
+    "output": [
+        {
+            "id": "rs_6876cf02e0bc8192b74af0fb64b715ff06fa2fcced15a5ac",
+            "type": "reasoning",
+            "status": "completed",
+            "summary": [
+                {
+                    "type": "summary_text",
+                    "text": "**What is Semi Design?** The user asks for \"Semi Design\" which requires aggregating multiple sources. First, ByteDance's Semi Design is a design system supporting multiple platforms with Design Tokens and code conversion tools. Another result from India focuses on semiconductor training, but the user likely refers to the ByteDance one. Other results mention semi-custom design but are less relevant. We should confirm if there are other interpretations, but current info covers the main dimensions. Continuing to reason may improve completeness, but it's sufficient to answer now."
+                }
+            ]
+        },
+        {
+            "type": "message",
+            "id": "msg_67ccd3acc8d48190a77525dc6de64b4104becb25c45c1d41",
+            "status": "completed",
+            "role": "assistant",
+            "content": [
+                {
+                    "type": "output_text",
+                    "text": "Semi Design is a design system created and maintained by ByteDance's Frontend Team and the MED Product Design Team. You can ask me anything about Semi.",
+                    "annotations": [
+                        {
+                            "title": 'Semi Design',
+                            "url": 'https://semi.design/zh-CN/start/getting-started',
+                            "detail": 'Semi Design Getting Started',
+                            "logo": 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png'
+                        },
+                        {
+                            "title": 'Semi Design',
+                            "url": 'https://semi.design/zh-CN/start/getting-started',
+                            "detail": 'Semi Design Getting Started',
+                            "logo": 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png'
+                        },
+                        {
+                            "title": 'Semi Design',
+                            "url": 'https://semi.design/zh-CN/start/getting-started',
+                            "detail": 'Semi Design Getting Started',
+                            "logo": 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png'
+                        },
+                    ]
+                }
+            ]
+        },
+        {
+            "id": "fc_12345xyz",
+            "call_id": "call_12345xyz",
+            "type": "function_call",
+            "name": "get_semi_page",
+            "status": "completed",
+            "arguments": "{\"pageName\":\"AIChatDialogue\"}"
+        },
+    ],
+    // ...
+};
+
+render(ResponseToMessageDemo);
+```
+
+When a user returns streaming data using the [Response API](https://platform.openai.com/docs/api-reference/responses/create) interface, the `streamingResponseToMessage` function can be used to convert the Response Chunk Object List into a Dialogue Message format.
+```jsx live=true noInline=true dir="column"
+import React, { useState, useCallback } from 'react';
+import { AIChatDialogue } from '@douyinfe/semi-ui';
+
+const roleConfig = {
+    user: {
+        name: 'User',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png'
+    },
+    assistant: {
+        name: 'Assistant',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+    },
+    system: {
+        name: 'System',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+    }
+};
+
+const FIXED_SHUFFLED_INDICES = [
+    0,  // sequence_number: 0
+    1,  // sequence_number: 1
+    2,  // sequence_number: 2
+    3,  // sequence_number: 3
+    4,  // sequence_number: 4
+    6,  // sequence_number: 6 (块5被跳过 / chunk 5 skipped)
+    6,  // sequence_number: 6 (块6重复到达)
+    7,  // sequence_number: 7
+    5,  // sequence_number: 5 (块5延迟到达 / chunk 5 arrives late)
+    8,  // sequence_number: 8
+    9,  // sequence_number: 9
+    10, // sequence_number: 10
+    11, // sequence_number: 11
+    12, // sequence_number: 12 
+    13, // sequence_number: 13 
+    14, // sequence_number: 14
+    15, // sequence_number: 15
+    16, // sequence_number: 16
+];
+
+function StreamingResponseToMessageDemo() {
+    const [messages, setMessage] = useState([]);
+    const [currentState, setCurrentState] = useState(null);
+    const [currentLength, setCurrentLength] = useState(0);
+
+    const onChatsChange = useCallback((chats) => {
+        setMessage(chats);
+    }, []);
+
+    useEffect(() => {
+        if (currentLength > FIXED_SHUFFLED_INDICES.length) {
+            return;
+        }
+
+        const timer = setTimeout(() => {
+            if (currentLength === 0) {
+                setCurrentLength(1);
+                return;
+            }
+
+            const currentIndices = FIXED_SHUFFLED_INDICES.slice(0, currentLength);
+            const currentChunks = currentIndices.map(index => REASONING_CHUNKS[index]);
+
+            const result = streamingResponseToMessage(currentChunks, currentState);
+            
+            if (result) {
+                const { message: responseMessage, nextState } = result;
+                if (responseMessage) {
+                    setMessage([responseMessage]);
+                    // 更新状态供下次使用 / Update state for next iteration
+                    setCurrentState(nextState);
+                }
+            }
+            setCurrentLength(prev => prev + 1);
+        }, 200);
+
+        return () => clearTimeout(timer);
+    }, [currentLength, currentState]);
+  
+    return (
+        <AIChatDialogue 
+            align="leftRight"
+            mode="bubble"
+            chats={messages}
+            roleConfig={roleConfig}
+            onChatsChange={onChatsChange}
+        />
+    );
+};
+
+const REASONING_CHUNKS = [
+    { "type": "response.created", "sequence_number": 0, "response": { "id": "resp_reason_001", "object": "response", "created_at": 1760091777, "status": "in_progress", "background": false, "error": null, "incomplete_details": null, "instructions": null, "max_output_tokens": null, "max_tool_calls": null, "model": "o3-mini-2025-01-31", "output": [], "parallel_tool_calls": true, "previous_response_id": null, "prompt_cache_key": null, "reasoning": { "effort": "medium", "summary": null }, "safety_identifier": null, "service_tier": "auto", "store": true, "temperature": 1.0, "text": { "format": { "type": "text" }, "verbosity": "medium" }, "tool_choice": "auto", "tools": [], "top_logprobs": 0, "top_p": 1.0, "truncation": "disabled", "usage": null, "user": null, "metadata": {} } },
+    { "type": "response.in_progress", "sequence_number": 1, "response": { "id": "resp_reason_001", "object": "response", "created_at": 1760091777, "status": "in_progress", "background": false, "error": null, "incomplete_details": null, "instructions": null, "max_output_tokens": null, "max_tool_calls": null, "model": "o3-mini-2025-01-31", "output": [], "parallel_tool_calls": true, "previous_response_id": null, "prompt_cache_key": null, "reasoning": { "effort": "medium", "summary": null }, "safety_identifier": null, "service_tier": "auto", "store": true, "temperature": 1.0, "text": { "format": { "type": "text" }, "verbosity": "medium" }, "tool_choice": "auto", "tools": [], "top_logprobs": 0, "top_p": 1.0, "truncation": "disabled", "usage": null, "user": null, "metadata": {} } },
+
+    // reasoning item(输出索引 0)
+    { "type": "response.output_item.added", "sequence_number": 2, "output_index": 0, "item": { "id": "rs_reason_001", "type": "reasoning", "summary": [] } },
+    { "type": "response.reasoning_summary_part.added", "sequence_number": 3, "output_index": 0, "summary_index": 0, "part": { "type": "reasoning", "text": "" } },
+    { "type": "response.reasoning_summary_text.delta", "sequence_number": 4, "output_index": 0, "summary_index": 0, "delta": "T" },
+    { "type": "response.reasoning_summary_text.delta", "sequence_number": 5, "output_index": 0, "summary_index": 0, "delta": "h" },
+    { "type": "response.reasoning_summary_text.delta", "sequence_number": 6, "output_index": 0, "summary_index": 0, "delta": "i" },
+    { "type": "response.reasoning_summary_text.delta", "sequence_number": 7, "output_index": 0, "summary_index": 0, "delta": "n" },
+    { "type": "response.reasoning_summary_text.done", "sequence_number": 9, "output_index": 0, "summary_index": 0, "text": "Done thinking!" },
+    { "type": "response.output_item.done", "sequence_number": 10, "output_index": 0, "item": { "id": "rs_reason_001", "type": "reasoning", "summary": [ { "type": "reasoning", "text": "思考完成!" } ] } },
+
+    // assistant message(输出索引 1)
+    { "type": "response.output_item.added", "sequence_number": 11, "output_index": 1, "item": { "id": "msg_reason_001", "type": "message", "status": "in_progress", "content": [], "role": "assistant" } },
+    { "type": "response.content_part.added", "sequence_number": 12, "item_id": "msg_reason_001", "output_index": 1, "content_index": 0, "part": { "type": "output_text", "annotations": [], "text": "" } },
+    { "type": "response.output_text.delta", "sequence_number": 13, "item_id": "msg_reason_001", "output_index": 1, "content_index": 0, "delta": "Based on the reasoning above, " },
+    { "type": "response.output_text.delta", "sequence_number": 14, "item_id": "msg_reason_001", "output_index": 1, "content_index": 0, "delta": "the conclusions are:" },
+    { "type": "response.output_text.done", "sequence_number": 15, "item_id": "msg_reason_001", "output_index": 1, "content_index": 0, "text": "Based on the reasoning above, the conclusions are: ..." },
+
+    { "type": "response.completed", "sequence_number": 16, "response": { "id": "resp_reason_001", "object": "response", "created_at": 1760091777, "status": "completed", "background": false, "error": null, "incomplete_details": null, "instructions": null, "max_output_tokens": null, "max_tool_calls": null, "model": "o3-mini-2025-01-31", "output": [ { "id": "rs_reason_001", "type": "reasoning", "summary": [ { "type": "reasoning", "text": "思考完成!" } ] }, { "id": "msg_reason_001", "type": "message", "status": "completed", "content": [ { "type": "output_text", "annotations": [], "text": "基于上述思考,结论如下:..." } ], "role": "assistant" } ], "parallel_tool_calls": true, "previous_response_id": null, "prompt_cache_key": null, "reasoning": { "effort": "medium", "summary": null }, "safety_identifier": null, "service_tier": "default", "store": true, "temperature": 1.0, "text": { "format": { "type": "text" }, "verbosity": "medium" }, "tool_choice": "auto", "tools": [], "top_logprobs": 0, "top_p": 1.0, "truncation": "disabled", "usage": { "input_tokens": 12, "input_tokens_details": { "cached_tokens": 0 }, "output_tokens": 120, "output_tokens_details": { "reasoning_tokens": 16 }, "total_tokens": 132 }, "user": null, "metadata": {} } }
+];
+
+render(StreamingResponseToMessageDemo);
+
+```
+
+## API Reference
+| Prop | Description | Type | Default |
+|---|---|---|---|
+| align | Conversation layout | 'leftRight' \| 'leftAlign' | 'leftRight' |
+| chats | Controlled conversation messages | Message[] | - |
+| className | Custom class name | string | - |
+| disabledFileItemClick | Disable file click | boolean | false |
+| hintCls | Hint area outer wrapper class name | string | - |
+| hints | Hint texts | string[] | - |
+| hintStyle | Hint area outer wrapper style | CSSProperties | - |
+| markdownRenderProps | Props passed to the MarkdownRender used by the dialogue. See [MarkdownRenderProps](/zh-CN/plus/markdownrender#API) | MarkdownRenderProps | - |
+| messageEditRender | Custom message edit renderer | (props: MessageContent) => React.ReactNode | - |
+| mode | Conversation mode | 'bubble' \| 'noBubble' \| 'userBubble' | 'bubble' |
+| onAnnotationClick | Annotation click callback | (annotation?: Annotation) => void | - |
+| onChatsChange | Messages change callback | (chats?: Message[]) => void | - |
+| onFileClick | Attachment file click callback | (file?: InputFile) => void | - |
+| onHintClick | Hint click callback | (hint: string) => void | - |
+| onImageClick | Image click callback | (image?: InputImage) => void | - |
+| onMessageBadFeedback | Negative feedback callback | (message?: Message) => void | - |
+| onMessageCopy | Copy message callback | (message?: Message) => void | - |
+| onMessageDelete | Delete message callback | (message?: Message) => void | - |
+| onMessageEdit | Edit message callback | (message?: Message) => void | - |
+| onMessageGoodFeedback | Positive feedback callback | (message?: Message) => void | - |
+| onMessageReset | Reset message callback | (message?: Message) => void | - |
+| onMessageShare | Share message callback | (message?: Message) => void | - |
+| onReferenceClick | Reference button click callback | (message?: Message) => void | - |
+| onSelect | Selection change callback | (selectedIds: string[]) => void | - |
+| renderConfig | Custom render config for sections | DialogueRenderConfig | - |
+| renderDialogueContentItem | Renderer map by message content type | DialogueContentItemRendererMap | - |
+| renderHintBox | Custom hint item renderer | (props: { content: string; index: number; onHintClick: () => void }) => React.ReactNode | - |
+| roleConfig | Role metadata config (user/assistant/system, etc.) | [RoleConfig](/en-US/ai/aiChatDialogue#RoleConfig) | - |
+| selecting | Enable selection mode | boolean | false |
+| showReset | Show reset action | boolean | true |
+| showReference | Show quotable icon in text or file messages (user messages only) | boolean | false |
+| style | Style | CSSProperties | - |
+
+### RoleConfig
+| Prop  | Description   | Type   | Default |
+|------|--------|-------|-------|
+| user | user info | Metadata \| Map<string, Metadata> | - |
+| assistant | assistant info | Metadata \| Map<string, Metadata> | - |
+| system | system info | Metadata \| Map<string, Metadata> | - |
+
+### MetaData
+| Prop  | Description   | Type   | Default |
+|------|--------|-------|-------|
+| name | Name | string | - |
+| avatar | Avatar | string | - |
+| color | Avatar background color, same as Avatar `color` prop. Supports `amber`, `blue`, `cyan`, `green`, `grey`, `indigo`, `light-blue`, `light-green`, `lime`, `orange`, `pink`, `purple`, `red`, `teal`, `violet`, `yellow` | string | `grey` |
+
+### Message
+| Prop  | Description   | Type   | Default |
+|------|--------|-------|-------|
+| role | Role | string | - |
+| name | Name | string | - |
+| id | Unique ID | string\| number | - |
+| content | Message content | string\| ContentItem[] | - |
+| createdAt | Created at (timestamp) | number | -|
+| model | Model name | string | -|
+| status | Message status: `queued` \| `in_progress` \| `incomplete` \| `completed` \| `failed` \| `cancelled` | string | `completed` |
+
+### Reference
+| Prop  | Description   | Type   | Default |
+|------|--------|-------|-------|
+| id | Unique identifier  | string\| number | - |
+| type | type  | string | - |
+| name | name  | string | - |
+| url | url  | string | - |
+| content | text content  | string | - |
+
+### Methods
+| Method  | Description   |
+|------|--------|
+| selectAll | Select all messages |
+| deselectAll | Deselect all messages |
+| scrollToBottom(animation: boolean) | Scroll to bottom; if `true`, animate; otherwise no animation |
+
+### ContentItem
+`ContentItem` supports all OpenAI Response [InputItem](https://platform.openai.com/docs/api-reference/responses/create#responses-create-input) and [OutputItem](https://platform.openai.com/docs/api-reference/responses/object#responses/object-output) types. Definitions:
+
+```ts
+type ContentItem = InputContentItem | OutputContentItem;
+
+type InputContentItem = InputMessage | ItemReference;
+type OutputContentItem = OutputMessage | MCPToolCall | Reasoning FileSearchToolCall | 
+                        WebSearchToolCall | FunctionToolCall | CustomToolCall | ImageGenerationCall| CustomObject;
+
+interface CommonContentItem {
+    id?: string;
+    type?: string;
+    status?: string;
+    role?: string
+}
+
+interface CustomObject {
+    [key: string]: any
+}
+
+// input item
+interface InputMessage extends CommonContentItem {
+    content?: string | (InputText | InputImage | InputFile)[]
+}
+
+interface InputText extends CommonContentItem {
+    text?: string
+}
+
+interface InputImage extends CommonContentItem {
+    detail?: string;
+    file_id?: string;
+    image_url?: string
+}
+
+interface InputFile extends CommonContentItem {
+    file_id?: string;
+    file_data?: string;
+    file_url?: string;
+    filename?: string;
+    size?: string;
+    file_type?: string;
+    fileInstance?: any
+}
+
+interface ItemReference extends CommonContentItem {
+    file_id?: string
+}
+
+
+// output item
+interface OutputMessage extends CommonContentItem {
+    content?: (OutputText | Refusal)[]
+}
+
+interface OutputText {
+    text?: string;
+    type?: string;
+    annotations?: Annotation[]
+}
+
+interface Refusal extends CommonContentItem {
+    refusal?: string;
+    type?: string
+}
+
+type Annotation = URLCitation | CustomObject;
+
+interface URLCitation {
+    end_index?: number;
+    start_index?: number;
+    title?: string;
+    type?: string;
+    url?: string
+}
+
+interface Reasoning extends CommonContentItem {
+    summary?: {
+        text?: string;
+        type?: string
+    }[];
+    content?: {
+        text?: string;
+        type?: string
+    }[]
+}
+
+interface FileSearchToolCallResult {
+    attributes?: Map<string, string>;
+    score?: number;
+    file_id?: string;
+    filename?: string;
+    text?: string
+}
+
+interface FileSearchToolCall extends CommonContentItem {
+    queries?: string[];
+    results?: FileSearchToolCallResult[]
+}
+
+interface WebSearchToolCall extends CommonContentItem {
+    action?: SearchAction | OpenPageAction | FindAction
+}
+
+interface SearchAction {
+    type?: string;
+    query?: string;
+    sources?: { type: string; url: string }[]
+}
+
+interface OpenPageAction {
+    type?: string;
+    url?: string
+}
+
+interface FindAction {
+    action?: string;
+    type?: string;
+    query?: string
+}
+
+interface FunctionToolCall extends CommonContentItem {
+    call_id?: string;
+    name?: string;
+    arguments?: string
+}
+
+interface CustomToolCall extends CommonContentItem {
+    call_id?: string;
+    name?: string;
+    input?: string
+}
+
+interface ImageGenerationCall extends CommonContentItem {
+    result?: string
+}
+
+interface MCPToolCall extends CommonContentItem {
+    arguments?: string;
+    server_label?: string;
+    name?: string;
+    result?: string;
+    output?: string
+}
+
+interface FileUploadToolCall extends CommonContentItem {
+    result?: string
+}
+
+```
+
+## Design Tokens
+<DesignToken/>

+ 1761 - 0
content/ai/aiChatDialogue/index.md

@@ -0,0 +1,1761 @@
+---
+localeCode: zh-CN
+order: 100
+category: Ai
+title: AIChatDialogue AI对话
+icon: doc-aiDialogue
+width: 60%
+brief: 用户展示 AI 聊天中的对话信息
+showNew: true
+---
+
+## 使用场景
+
+AIChatDialogue 组件可搭配 AIChatInput 使用,实现更丰富的、功能覆盖更全面、定制更加便捷的 AI 会话场景。
+组件消息格式以 OpenAI 的 [Response Object](https://platform.openai.com/docs/api-reference/responses/object) 为原型,默认支持 OpenAI 社区 [Response](https://platform.openai.com/docs/api-reference/responses/create) / [Chat Completion](https://platform.openai.com/docs/api-reference/chat/create) 格式标准,对 GPT-5、GPT-4o 系列模型的响应均支持开箱即用,详见[消息数据转换](/zh-CN/ai/aiChatDialogue#%E6%B6%88%E6%81%AF%E6%95%B0%E6%8D%AE%E8%BD%AC%E6%8D%A2)。
+
+
+## 代码演示
+
+### 如何引入
+
+```jsx import
+import { AIChatDialogue } from '@douyinfe/semi-ui';
+```
+
+### 基本用法
+通过设置 `chats` 和 `onChatsChange` 实现基础对话显示和交互。
+
+使用 `align` 属性可以设置对话的布局,支持左右分布(`leftRight`, 默认)和左对齐(`leftAlign`)。
+
+```jsx live=true dir="column" noInline=true
+import React, { useState, useCallback } from 'react';
+import { AIChatDialogue, RadioGroup, Radio } from '@douyinfe/semi-ui';
+
+const defaultMessages = [
+    {
+        role: 'system',
+        id: '1',
+        createAt: 1715676751919,
+        content: "Hello, I'm your AI assistant.",   
+    },
+    {
+        role: 'user',
+        id: '2',
+        createAt: 1715676751919,
+        content: "给一个 Semi Design 的 Button 组件的使用示例",
+    },
+    {
+        role: 'assistant',
+        id: '3',
+        createAt: 1715676751919,
+        content: "以下是一个 Semi 代码的使用示例:\n\`\`\`jsx \nimport React from 'react';\nimport { Button } from '@douyinfe/semi-ui';\n\nconst MyComponent = () => {\n  return (\n    <Button>Click me</Button>\n );\n};\nexport default MyComponent;\n\`\`\`\n",
+    }
+];
+
+const roleConfig = {
+    user: {
+        name: 'User',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png'
+    },
+    assistant: {
+        name: 'Assistant',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+    },
+    system: {
+        name: 'System',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+    }
+};
+
+function AlignAndMode () {
+    const [messages, setMessage] = useState(defaultMessages);
+    const [mode, setMode] = useState('bubble');
+    const [align, setAlign] = useState('leftRight');
+
+    const onAlignChange = useCallback((e) => {
+        setAlign(e.target.value);
+    }, []);
+
+    const onModeChange = useCallback((e) => {
+        setMode(e.target.value);
+    }, []); 
+
+    const onChatsChange = useCallback((chats) => {
+        setMessage(chats);
+    }, []);
+
+    return (
+        <>
+            <span style={{ display: 'flex', flexDirection: 'column', rowGap: '8px' }}>
+                <span style={{ display: 'flex', alignItems: 'center', columnGap: '10px' }}>
+                    模式
+                    <RadioGroup onChange={onModeChange} value={mode} type={"button"}>
+                        <Radio value={'bubble'}>气泡</Radio>
+                        <Radio value={'noBubble'}>非气泡</Radio>
+                        <Radio value={'userBubble'}>用户会话气泡</Radio>
+                    </RadioGroup>
+                </span>
+                <span style={{ display: 'flex', alignItems: 'center', columnGap: '10px' }}>
+                    会话布局方式
+                    <RadioGroup onChange={onAlignChange} value={align} type={"button"}>
+                        <Radio value={'leftRight'}>左右分布</Radio>
+                        <Radio value={'leftAlign'}>左对齐</Radio>
+                    </RadioGroup>
+                </span>
+            </span>
+            <div style={{ border: '1px solid var(--semi-color-border)', borderRadius: 12, marginTop: 10, padding: 20 }}>
+                <AIChatDialogue 
+                    key={align + mode}
+                    align={align}
+                    mode={mode}
+                    chats={messages}
+                    roleConfig={roleConfig}
+                    onChatsChange={onChatsChange}
+                />
+            </div>
+        </>
+    );
+}
+
+render(AlignAndMode);
+
+```
+
+### 消息状态
+chats 类型为 `Message[]`, `Message` 包含对话的各种信息,如角色 `role`、内容 `content`、状态 `status`
+、唯一标识 `id`、创建时间 `createdAt` 等,具体见 [Message](#Message)。其中 status 和 [Response API Status](https://platform.openai.com/docs/api-reference/responses/object#responses/object-status) 相同,存在 6 种状态,对应 3 种官方样式(成功 / 请求中 / 失败)。
+
+```jsx live=true dir="column" noInline=true
+import React, { useState, useCallback } from 'react';
+import { AIChatDialogue } from '@douyinfe/semi-ui';
+
+const defaultMessages = [
+    {
+        role: 'assistant',
+        id: '1',
+        createAt: 1715676751919,
+        content: "请求成功", 
+        // 默认的 status 为 completed 
+    },
+    {
+        id: 'loading',
+        role: 'assistant',
+        status: 'in_progress' // 状态展示同 queued、incomplete
+    },
+    {
+        role: 'assistant',
+        id: 'error',
+        content: '请求错误',
+        status: 'failed' // 状态展示同 cancelled
+    }
+];
+
+const roleConfig = {
+    user: {
+        name: 'User',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png'
+    },
+    assistant: {
+        name: 'Assistant',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+    },
+    system: {
+        name: 'System',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+    }
+};
+
+function StatusDemo () {
+    const [messages, setMessage] = useState(defaultMessages);
+
+    const onChatsChange = useCallback((chats) => {
+        setMessage(chats);
+    }, []);
+
+    return (
+        <AIChatDialogue 
+            chats={messages}
+            roleConfig={roleConfig}
+            onChatsChange={onChatsChange}
+        />
+    );
+}
+
+render(StatusDemo);
+
+```
+
+### 消息展示
+消息内容展示的类型为 [ContentItem[]](https://platform.openai.com/docs/api-reference/responses/list#responses/list-data),支持文本 `text`、文件 `file`、图片 `image`、代码 `code`、思考块 `reasoning`、参考来源 `annotation`、工具调用 `tool call` 等消息块的展示,同时提供 `AIChatDialogue.Step` 组件用于步骤等信息的分步展示。
+
+```jsx live=true dir="column" noInline=true
+import React, { useState, useCallback } from 'react';
+import { AIChatDialogue } from '@douyinfe/semi-ui';
+import { IconSearchStroked, IconCodeStroked, IconBriefStroked } from '@douyinfe/semi-icons';
+
+
+const defaultMessages = [
+    {
+        role: 'assistant',
+        id: '1',
+        createAt: 1715676751919,
+        content: '普通文本', 
+    },
+    {
+        id: '2',
+        role: 'user',
+        content: [
+            {
+                type: 'message',
+                content: [
+                    {
+                        type: 'input_text',
+                        text: '帮我生成类似的图片',
+                    },
+                    {
+                        type: 'input_image',
+                        image_url: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/edit-bag.jpeg',
+                        file_id: 'demo-file-id'
+                    },
+                    {
+                        type: 'input_text',
+                        text: '以下是文件展示',
+                    },
+                    {
+                        type: 'input_file',
+                        file_url: 'https://www.semi.pdf',
+                        filename: 'semi.pdf',
+                        size: '100KB',
+                    },
+                    {
+                        type: 'input_file',
+                        file_url: 'https://www.semi.json',
+                        filename: 'semi.json',
+                        size: '100KB',
+                    },
+                    {
+                        type: 'input_file',
+                        file_url: 'https://www.semi.docx',
+                        filename: 'semi.docx',
+                        size: '100KB',
+                    }
+                ],
+            },
+        ],
+        status: 'completed',
+    },
+    {
+        id: '3',
+        role: 'assistant',
+        content: [
+            {
+                type: 'reasoning',
+                status: 'completed',
+                summary: [
+                    {
+                        'type': 'summary_text',
+                        'text': '\n我需要思考并回答用户关于什么是 Semi 组件库的问题...'
+                    }
+                ],
+            },
+            {
+                type: 'message',
+                content: [
+                    {
+                        type: 'output_text',
+                        text: 'Semi Design 是由抖音前端团队和MED产品设计团队设计、开发并维护的设计系统。'
+                    }
+                ],
+                status: 'completed',
+            },
+            {
+                id: 'fc_12345xyz',
+                call_id: 'call_12345xyz',
+                type: 'function_call',
+                name: 'get_weather',
+                status: 'completed',
+                arguments: '{\'location\':\'Paris, France\'}'
+            },
+            {
+                type: 'message',
+                content: [
+                    {
+                        type: 'output_text',
+                        text: '恭喜你,你已经掌握了 semi design 的所有知识!',
+                        annotations: [
+                            {
+                                title: 'semi.design',
+                                url: 'https://semi.design/',
+                                detail: 'semi design page',
+                                logo: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+                            },
+                            {
+                                title: 'semi.design',
+                                url: 'https://semi.design/',
+                                detail: 'semi design page',
+                                logo: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+                            },
+                        ]
+                    }
+                ]
+            },
+            {
+                type: 'plan',
+                content: [
+                    {
+                        summary: '创建一份全面的北京旅游攻略,包含景点、住宿、交通、美食和实用旅行建议',
+                        steps: [
+                            {
+                                summary: '搜索北京旅游景点介绍及门票信息',
+                                description: '正在搜索: 北京旅游景点介绍及门票信息',
+                                type: 'search',
+                            }, 
+                            {
+                                summary: '读取指定文件的指定行内容',
+                                description: '正在创建文档:  北京旅游攻略',
+                                type: 'docs',
+                            }, 
+                            {
+                                summary: '创建包含北京旅游攻略的文件',
+                                description: '正在创建代码文件: beijing_travel_guide.html',
+                                type: 'code',
+                            }, 
+                        ],
+                        statues: 'completed'
+                    },
+                    {
+                        summary: '总结北京旅游攻略的创建成果并呈现给用户',
+                        steps: []
+                    }
+                ],
+            }
+        ],
+        status: 'completed',
+    },
+];
+
+const roleConfig = {
+    user: {
+        name: 'User',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png'
+    },
+    assistant: {
+        name: 'Assistant',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+    },
+    system: {
+        name: 'System',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+    }
+};
+
+function AllTypeMessageDemo () {
+    const [messages, setMessage] = useState(defaultMessages);
+
+    const onChatsChange = useCallback((chats) => {
+        setMessage(chats);
+    }, []);
+
+    const mapStep = useCallback((steps) => {
+        if (!steps) {
+            return [];
+        }
+        return steps.map((item) => {
+            let icon = null;
+            switch (item.type) {
+                case 'search':
+                    icon = <IconSearchStroked />;
+                    break;
+                case 'docs':
+                    icon = <IconBriefStroked />;
+                    break;
+                case 'code':
+                    icon = <IconCodeStroked />;
+                    break;
+            }
+            return {
+                summary: item.summary,
+                description: item.description,
+                icon: icon,
+            };
+        });
+    }, []);
+
+    const customRender = useCallback((message) => {
+        return {
+            'plan': (item) => { // plan 为用户自定义类型
+                let steps = item.content.map((item) => {
+                    return {
+                        summary: item.summary,
+                        actions: mapStep(item.steps),
+                        status: 'completed'
+                    };
+                });
+                return <AIChatDialogue.Step steps={steps} />;
+            },
+        };
+    }, []);
+
+    return (
+        <AIChatDialogue 
+            chats={messages}
+            roleConfig={roleConfig}
+            onChatsChange={onChatsChange}
+            renderDialogueContentItem={customRender}
+        />
+    );
+}
+
+render(AllTypeMessageDemo);
+
+```
+
+
+### 引用
+通过 `references` 字段定义当前消息引用的文件或者文本, `showReference` 配置当前消息是否显示可被引用样式, `onReferenceClick` 配置引用按钮点击回调。具体和 AIChatInput 的搭配使用见 [AI 组件构建对话](/zh-CN/ai/aiComponent#AI%20%E7%BB%84%E4%BB%B6%E6%9E%84%E5%BB%BA%E5%AF%B9%E8%AF%9D)
+
+```jsx live=true dir="column" noInline=true
+import React, { useState, useCallback } from 'react';
+import { AIChatDialogue } from '@douyinfe/semi-ui';
+
+const defaultMessages = [
+    {
+        id: '1',
+        role: 'user',
+        content: '当前消息为引用 demo 的示例',
+        references: [
+            {
+                id: '1',
+                type: 'text',
+                content: '测试文本,这里是一段很长的文字,这里是一段很长的文字,这里是一段很长的文字,这里是一段很长的文字,这里是一段很长的文字,这里是一段很长的文字,这里是一段很长的文字,这里是一段很长的文字,这里是一段很长的文字,这里是一段很长的文字',
+            },
+            {
+                id: '2',
+                name: '飞书文档.docx',
+            },
+            {
+                id: '3',
+                name: 'Music.mp4',
+            },
+            {
+                id: '4',
+                name: 'Image.jpeg',
+                url: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/Resso.png'
+            },
+            {
+                id: '5',
+                name: 'code.json',
+            }
+        ]
+    }
+];
+
+const roleConfig = {
+    user: {
+        name: 'User',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png'
+    },
+    assistant: {
+        name: 'Assistant',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+    },
+    system: {
+        name: 'System',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+    }
+};
+
+function ReferencesDemo () {
+    const [messages, setMessage] = useState(defaultMessages);
+
+    const onChatsChange = useCallback((chats) => {
+        setMessage(chats);
+    }, []);
+
+    const onReferenceClick = () => {
+        console.log('You click the reference button!');
+    };
+
+    return (
+        <AIChatDialogue 
+            chats={messages}
+            roleConfig={roleConfig}
+            onChatsChange={onChatsChange}
+            showReference
+            onReferenceClick={onReferenceClick}
+        />
+    );
+}
+
+render(ReferencesDemo);
+```
+
+
+### 选择
+```jsx live=true dir="column" noInline=true
+import React, { useState, useCallback } from 'react';
+import { AIChatDialogue, RadioGroup, Radio } from '@douyinfe/semi-ui';
+
+const defaultMessages = [
+    {
+        role: 'system',
+        id: '1',
+        createAt: 1715676751919,
+        content: "Hello, I'm your AI assistant.",   
+    },
+    {
+        role: 'user',
+        id: '2',
+        createAt: 1715676751919,
+        content: "给一个 Semi Design 的 Button 组件的使用示例",
+    },
+    {
+        role: 'assistant',
+        id: '3',
+        createAt: 1715676751919,
+        content: "以下是一个 Semi 代码的使用示例:\n\`\`\`jsx \nimport React from 'react';\nimport { Button } from '@douyinfe/semi-ui';\n\nconst MyComponent = () => {\n  return (\n    <Button>Click me</Button>\n );\n};\nexport default MyComponent;\n\`\`\`\n",
+    }
+];
+
+const roleConfig = {
+    user: {
+        name: 'User',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png'
+    },
+    assistant: {
+        name: 'Assistant',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+    },
+    system: {
+        name: 'System',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+    }
+};
+
+function SelectingDemo () {
+    const ref = useRef(null);
+    const [messages, setMessage] = useState(defaultMessages);
+    const [align, setAlign] = useState('leftRight');
+    const [select, setSelect] = useState(true);
+    const [selection, setSelection] = useState('allSelect');
+
+    useEffect(() => {
+        ref.current.selectAll();
+    }, []);
+
+    const onSelectChange = useCallback((e) => {
+        setSelect(e.target.value);
+    }, []);
+
+    const onSelectionChange = useCallback((e) => {
+        if (e.target.value === 'allSelect') {
+            ref.current.selectAll();
+        } else {
+            ref.current.deselectAll();
+        }
+        setSelection(e.target.value);
+    }, []);
+
+    const onSelect = useCallback((selectionId) => {
+        console.log('onSelect', selectionId);
+    }, []);
+
+    const onAlignChange = useCallback((e) => {
+        setAlign(e.target.value);
+    }, []);
+
+    const onChatsChange = useCallback((chats) => {
+        setMessage(chats);
+    }, []);
+
+    return (
+        <div>
+            <span style={{ display: 'flex', flexDirection: 'column', rowGap: '8px' }}>
+                <span style={{ display: 'flex', alignItems: 'center', columnGap: '10px' }}>
+                    会话布局方式
+                    <RadioGroup onChange={onAlignChange} value={align} type={"button"}>
+                        <Radio value={'leftRight'}>左右分布</Radio>
+                        <Radio value={'leftAlign'}>左对齐</Radio>
+                    </RadioGroup>
+                </span>
+                <span style={{ display: 'flex', alignItems: 'center', columnGap: '10px' }}>
+                    是否开启选择
+                    <RadioGroup onChange={onSelectChange} value={select} type={"button"}>
+                        <Radio value={true}>开启</Radio>
+                        <Radio value={false}>关闭</Radio>
+                    </RadioGroup>
+                </span>
+                <span style={{ display: 'flex', alignItems: 'center', columnGap: '10px' }}>
+                    选择方式
+                    <RadioGroup onChange={onSelectionChange} value={selection} type={"button"}>
+                        <Radio value={'allSelect'}>全选</Radio>
+                        <Radio value={'cancelSelect'}>取消全选</Radio>
+                    </RadioGroup>
+                </span>
+            </span>
+
+            <div style={{ border: '1px solid var(--semi-color-border)', borderRadius: 12, marginTop: 10, padding: 20 }}>
+                <AIChatDialogue 
+                    ref={ref}
+                    align={align}
+                    mode="bubble"
+                    chats={messages}
+                    selecting={select}
+                    onSelect={onSelect}
+                    roleConfig={roleConfig}
+                />
+            </div>
+        </div>
+    );
+}
+
+render(SelectingDemo);
+
+```
+
+<!-- todo -->
+<!-- ### 编辑消息 -->
+<!-- ```jsx live=true dir="column" noInline=true
+
+``` -->
+
+
+### 提示
+通过 `hints` 可设置提示区域内容, 点击提示内容后,提示内容将成为新的用户输入内容,并触发 `onHintClick` 回调。
+
+```jsx live=true dir="column"
+import React, { useState, useCallback } from 'react';
+import { AIChatDialogue } from '@douyinfe/semi-ui';
+
+() => {
+    const defaultMessages = [
+        {
+            role: 'assistant',
+            id: '1',
+            createAt: 1715676751919,
+            content: 'Semi Design 是由抖音前端团队和MED产品设计团队设计、开发并维护的设计系统,你可以向我提问任何关于 Semi 的问题。',
+        }
+    ];
+
+    const hintsExample = [
+        "Semi 组件库有哪些常用组件?",
+        "能否展示一个使用 Semi 组件库构建的页面示例?",
+        "Semi 组件库有官方文档吗?",
+    ];
+
+    const roleConfig = {
+        user: {
+            name: 'User',
+            avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png'
+        },
+        assistant: {
+            name: 'Assistant',
+            avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+        },
+        system: {
+            name: 'System',
+            avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+        }
+    };
+    const [messages, setMessage] = useState(defaultMessages);
+    const [hints, setHints] = useState(hintsExample);
+  
+    const onChatsChange = useCallback((chats) => {
+        console.log('onChatsChange', chats);
+        setMessage(chats);
+    }, []);
+
+    const onHintClick = useCallback((hint) => {
+        setHints([]);
+    }, []);
+
+    return (
+        <AIChatDialogue 
+            align="leftRight"
+            mode="bubble"
+            chats={messages}
+            roleConfig={roleConfig}
+            onChatsChange={onChatsChange}
+            hints={hints}
+            onHintClick={onHintClick}
+        />
+    );
+};
+
+```
+
+
+
+### 自定义渲染提示
+通过 `renderHintBox` 可自定义提示区域内容, 参数如下
+
+```ts
+type renderHintBox = (props: {content: string; index: number,onHintClick: () => void}) => React.ReactNode;
+```
+
+```jsx live=true dir="column"
+import React, { useState, useCallback } from 'react';
+import { AIChatDialogue } from '@douyinfe/semi-ui';
+import { IconArrowRight } from '@douyinfe/semi-icons';
+
+
+() => {
+    const defaultMessages = [
+        {
+            role: 'assistant',
+            id: '1',
+            createAt: 1715676751919,
+            content: 'Semi Design 是由抖音前端团队和MED产品设计团队设计、开发并维护的设计系统,你可以向我提问任何关于 Semi 的问题。',
+        }
+    ];
+
+    const hintsExample = [
+        "Semi 组件库有哪些常用组件?",
+        "能否展示一个使用 Semi 组件库构建的页面示例?",
+        "Semi 组件库有官方文档吗?",
+    ];
+
+    const roleConfig = {
+        user: {
+            name: 'User',
+            avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png'
+        },
+        assistant: {
+            name: 'Assistant',
+            avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+        },
+        system: {
+            name: 'System',
+            avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+        }
+    };
+    const [messages, setMessage] = useState(defaultMessages);
+    const [hints, setHints] = useState(hintsExample);
+  
+    const onChatsChange = useCallback((chats) => {
+        console.log('onChatsChange', chats);
+        setMessage(chats);
+    }, []);
+
+    const onHintClick = useCallback((hint) => {
+        setHints([]);
+    }, []);
+
+    const commonHintStyle = useMemo(() => ({
+        border: '1px solid var(--semi-color-border)',
+        padding: '10px',
+        borderRadius: '10px',
+        color: 'var( --semi-color-text-1)',
+        display: 'flex',
+        justifyContent: 'space-between',
+        alignItems: 'center',
+        cursor: 'pointer',
+        fontSize: '14px'
+    }), []);
+
+    const renderHintBox = useCallback((props) => {
+        const { content, onHintClick, index } = props;
+        return (
+            <div style={commonHintStyle} onClick={onHintClick} key={index}>
+                {content}
+                <IconArrowRight style={{ marginLeft: 10 }}>click me</IconArrowRight>
+            </div>
+        );
+    }, []);
+    
+
+    return (
+        <AIChatDialogue 
+            align="leftRight"
+            mode="bubble"
+            chats={messages}
+            roleConfig={roleConfig}
+            onChatsChange={onChatsChange}
+            hints={hints}
+            onHintClick={onHintClick}
+            renderHintBox={renderHintBox}
+        />
+    );
+};
+```
+
+### 自定义渲染会话框
+通过 `chatBoxRenderConfig` 传入自定义渲染配置, chatBoxRenderConfig 类型如下
+
+```ts
+export interface RenderTitleProps {
+    message?: Message;
+    role?: Metadata;
+    defaultTitle?: ReactNode
+}
+
+export interface RenderAvatarProps {
+    message?: Message; 
+    role?: Metadata, 
+    defaultAvatar?: ReactNode
+}
+
+export interface RenderContentProps {
+    message?: Message;
+    role?: Metadata | Map<string, Metadata>;
+    defaultContent?: ReactNode | ReactNode[]; 
+    className?: string;
+}
+
+export interface DefaultActionNodeObj {
+    copyNode: ReactNode;
+    likeNode: ReactNode;
+    dislikeNode: ReactNode;
+    resetNode: ReactNode;
+    moreNode: ReactNode;
+}
+
+export interface RenderActionProps {
+    message?: Message;
+    defaultActions?: ReactNode | ReactNode[];
+    className: string;
+    defaultActionsObj?: DefaultActionNodeObj;
+};
+
+export interface FullDialogueNodes {
+    avatar?: ReactNode;
+    title?: ReactNode; 
+    content?: ReactNode; 
+    action?: ReactNode
+}
+
+export interface RenderFullDialogueProps {
+    message?: Message;
+    role?: Metadata;
+    defaultNodes?: FullDialogueNodes;
+    className: string
+}
+
+
+export interface DialogueRenderConfig {
+    /* 自定义渲染标题 */
+    renderDialogueAction?: (props: RenderActionProps) => ReactNode;
+    /* 自定义渲染头像 */
+    renderDialogueAvatar?: (props: RenderAvatarProps) => ReactNode;
+    /* 自定义渲染内容区域 */
+    renderDialogueContent?: (props: RenderContentProps) => ReactNode;
+    /* 自定义渲染消息操作栏 */
+    renderDialogueTitle?: (props: RenderTitleProps) => ReactNode;
+    /* 完全自定义渲染整个聊天框 */
+    renderFullDialogue?: (props: RenderFullDialogueProps) => ReactNode
+}
+```
+
+自定义渲染头像和标题,可通过 `renderChatBoxAvatar` 和 `renderChatBoxTitle` 实现。
+```jsx live=true dir="column" 
+import React, { useState, useCallback } from 'react';
+import { AIChatDialogue, Avatar } from '@douyinfe/semi-ui';
+
+() => {
+    const defaultMessages = [
+        {
+            role: 'system',
+            id: '1',
+            createAt: 1715676751919,
+            content: "Hello, I'm your AI assistant.",   
+        },
+        {
+            role: 'user',
+            id: '2',
+            createAt: 1715676751919,
+            content: "给一个 Semi Design 的 Button 组件的使用示例",
+        },
+        {
+            role: 'assistant',
+            id: '3',
+            createAt: 1715676751919,
+            content: "以下是一个 Semi 代码的使用示例:\n\`\`\`jsx \nimport React from 'react';\nimport { Button } from '@douyinfe/semi-ui';\n\nconst MyComponent = () => {\n  return (\n    <Button>Click me</Button>\n );\n};\nexport default MyComponent;\n\`\`\`\n",
+        }
+    ];
+
+    const roleConfig = {
+        user: {
+            name: 'User',
+            avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png'
+        },
+        assistant: {
+            name: 'Assistant',
+            avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+        },
+        system: {
+            name: 'System',
+            avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+        }
+    };
+
+    const [messages, setMessage] = useState(defaultMessages);
+    const onChatsChange = useCallback((chats) => {
+        setMessage(chats);
+    }, []);
+
+    const renderConfig = {
+        renderDialogueTitle: (props) => {
+            return <div className="semi-ai-chat-dialogue-title">My-{props.role.name}</div>;
+        },
+        renderDialogueAvatar: (props) => {
+            return <Avatar
+                src={props.role.avatar}
+                size="extra-small"
+                shape="square"
+            >
+            </Avatar>;
+        },
+        renderDialogueAction: (props) => {
+            return <div className={props.className}>{props.defaultActions[0]}</div>;
+        },
+    };
+
+    return (
+        <AIChatDialogue 
+            align="leftRight"
+            mode="bubble"
+            chats={messages}
+            roleConfig={roleConfig}
+            onChatsChange={onChatsChange}
+            dialogueRenderConfig={renderConfig}
+        />
+    );
+};
+
+```
+
+### 自定义渲染消息内容
+
+通过 `renderDialogueContentItem` 按照消息类型返回内容渲染,用法如下
+
+```jsx live=true dir="column" noInline=true
+import React, { useState, useCallback } from 'react';
+import { AIChatDialogue, MarkdownRender } from '@douyinfe/semi-ui';
+
+const defaultMessages = [
+    {
+        id: '1',
+        role: 'user',
+        content: '你好',
+    }, 
+    {
+        id: '2',
+        role: 'assistant',
+        content: '你好呀,请问有什么可以帮助你的吗~',
+        status: 'completed',
+    }, 
+    {
+        id: '3',
+        role: 'user',
+        content: [
+            {
+                type: 'message',
+                role: 'user',
+                content: [
+                    {
+                        type: 'input_text',
+                        text: '帮我生成类似的图片',
+                    }, 
+                    {
+                        type: 'input_image',
+                        image_url: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/edit-bag.jpeg',
+                        file_id: 'demo-file-id'
+                    }, 
+                    {
+                        type: 'input_image',
+                        image_url: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/edit-bag.jpeg',
+                        file_id: 'demo-file-id'
+                    }
+                ],
+            }],
+    }, 
+    {
+        id: '4',
+        role: 'assistant',
+        content: [{
+            type: "reasoning",
+            summary: [
+                {
+                    "type": "summary_text",
+                    "text": "\n用户问需要我帮助他生成类似图片,我需要先分析图片内容,然后生成类似的图片..."
+                }
+            ],
+            annotations: [
+                {
+                    title: 'semi.design',
+                    url: 'https://semi.design/',
+                    detail: 'semi design page',
+                    logo: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+                },
+                {
+                    title: 'semi.design',
+                    url: 'https://semi.design/',
+                    detail: 'semi design page',
+                    logo: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+                },
+            ],
+            status: "completed"
+        }, 
+        {
+            type: 'function_call',
+            name: 'create_travel_guide',
+            arguments: "{\n\"city\": \"北京\"\n}",
+            status: 'completed',
+        }
+        ],
+        status: 'completed',
+    }];
+
+const roleConfig = {
+    user: {
+        name: 'User',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png'
+    },
+    assistant: {
+        name: 'Assistant',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+    },
+    system: {
+        name: 'System',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+    }
+};
+
+function CustomRender () {
+    const [messages, setMessage] = useState(defaultMessages);
+    const onChatsChange = useCallback((chats) => {
+        setMessage(chats);
+    }, []);
+
+    const userTextStyle = {
+        backgroundColor: 'var(--semi-color-fill-1)',
+        color: 'var(--semi-color-text-0)',
+        borderRadius: '25px',
+        padding: '6px 16px',
+    };
+
+    const assistantStyle = {
+        color: 'var(--semi-color-text-0)',
+        padding: '6px 16px',
+    };
+
+    const functionCallStyle = {
+        backgroundColor: 'var(--semi-color-fill-1)',
+        padding: '6px 16px',
+        borderRadius: '25px',
+    };
+
+    const customRenderReasoningContent = useCallback((props) => {
+        return <React.Fragment>
+            <AIChatDialogue.Annotation 
+                annotation={props.annotations} 
+                description={'参考资料'} 
+                maxCount={3}
+                onClick={(e) => {
+                    e && e.stopPropagation();
+                    Toast.success('Ready to open the sidebar!');
+                }}
+            />
+            <div style={{ marginTop: '8px' }}>
+                <MarkdownRender
+                    format='md'
+                    raw={props.summary[0].text}
+                    {...props.markdownRenderProps}
+                />
+            </div>
+        </React.Fragment>;
+    }, []);
+
+    const customRender = {
+        "function_call": {
+            "create_travel_guide": (item) => {
+                return <div style={functionCallStyle}>Function Tool Call: {item.name} {item.arguments}</div>;
+            }
+        },
+        "input_text": (item, message) => {
+            if (message.role === 'user') {
+                return <div style={userTextStyle} className={'userTextStyle'}>{item.text}</div>;
+            }
+            return <div style={assistantStyle}>{item.text}</div>;
+        },
+        "reasoning": (item) => {
+            return <AIChatDialogue.Reasoning {...item} customRenderer={customRenderReasoningContent} />;
+        },
+        "default": (item, message) => {
+            if (message.role === 'user') {
+                return <div style={userTextStyle} className={'userTextStyle'}>{item}</div>;
+            } else {
+                return <div style={assistantStyle}>{item}</div>;
+            }
+        }
+    };
+
+    return (
+        <AIChatDialogue 
+            chats={messages}
+            roleConfig={roleConfig}
+            onChatsChange={onChatsChange}
+            renderDialogueContentItem={customRender}
+        />
+    );
+}
+
+render(CustomRender);
+```
+
+
+
+### 消息数据转换
+当前组件的对话消息以 OpenAI 的 [Response Object](https://platform.openai.com/docs/api-reference/responses/object) 为原型,为了支持用户更好地无缝集成 [Chat Completion API](https://platform.openai.com/docs/api-reference/chat/create) 和 [Response API](https://platform.openai.com/docs/api-reference/responses/create),我们提供了四种 `Adapter` 转换函数,用户可直接使用该函数转换 API 的返回结果,得到可直接用于消息展示的数据,提供两种 `Adapter` 用于将 `ChatInput` 组件的数据处理成适配于 `Response API` 的 `input Message` 或者 `Chat Completion API` 中的 `Input Message` 格式。 
+
+```ts
+// 将 Chat Completion API 返回的数据转换为 Chat Dialogue 中的 Message 格式
+function chatCompletionToMessage(chatCompletion: ChatCompletion): Message[]
+
+// 将 Chat Completion API 流式返回数据转换为 Chat Dialogue 中的 Message 格式
+function streamingChatCompletionToMessage(chatCompletionChunks: ChatCompletionChunk[], state?: StreamingChatState): { messages: Message[]; state?: StreamingChatState }
+
+// 将 Response API 返回的数据转换为 Chat Dialogue 中的 Message 格式
+function responseToMessage(response: Response): Message
+
+// 将 Response API 返回流式数据转换为 Chat Dialogue 中的 Message 格式
+function streamingResponseToMessage(chunks: ResponseChunk[], prevState: StreamingResponseState): { messages: Message[]; state?: StreamingResponseState }
+
+// 将 Chat Input 数据转换为 Chat Dialogue 中的 Message 格式,(同 Response API Input Message 格式)
+function chatInputToMessage(inputContent: MessageContent): Message
+
+// 将 Chat Input 数据转换为 Chat Completion API 中的 Input Message 格式
+function chatInputToChatCompletion(inputContent: MessageContent): ChatCompletionInput
+```
+
+比如,当用户使用 [Chat Completion API](https://platform.openai.com/docs/api-reference/chat/create) 接口返回非流式数据时,可以通过 `chatCompletionToMessage` 函数将 Chat Completion Object 转换为 Dialogue Message 消息块格式。注意,因为 `Chat Completion API` 可以通过 `n` 来控制每条输入消息生成多少个结果所以该函数的返回值为数组。(注意:如果 n > 1,用户需要自行决定将哪条数据添加到 message 中展示)
+
+```jsx live=true noInline=true dir="column"
+import React, { useState, useCallback } from 'react';
+import { AIChatDialogue } from '@douyinfe/semi-ui';
+
+const roleConfig = {
+    user: {
+        name: 'User',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png'
+    },
+    assistant: {
+        name: 'Assistant',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+    },
+    system: {
+        name: 'System',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+    }
+};
+
+function ChatCompletionToMessageDemo() {
+    const [messages, setMessage] = useState([]);
+
+    const onChatsChange = useCallback((chats) => {
+        setMessage(chats);
+    }, []);
+
+    useEffect(() => {
+        const message = chatCompletionToMessage(CHAT_COMPLETION_DATA);
+        setMessage([...message]);
+    }, []);
+  
+    return (
+        <AIChatDialogue 
+            align="leftRight"
+            mode="bubble"
+            chats={messages}
+            roleConfig={roleConfig}
+            onChatsChange={onChatsChange}
+        />
+    );
+};
+
+const CHAT_COMPLETION_DATA = {
+    "id": "chatcmpl-B9MBs8CjcvOU2jLn4n570S5qMJKcT",
+    "object": "chat.completion",
+    "created": 1741569952,
+    "model": "gpt-4.1-2025-04-14",
+    "choices": [
+        {
+            "index": 0,
+            "message": {
+                "role": "assistant",
+                "content": "Hello! How can I assist you today?",
+                "refusal": null,
+                "annotations": [],
+                "tool_calls": [
+                    {
+                        "id": "call_abc123",
+                        "type": "function",
+                        "function": {
+                            "name": "get_current_weather",
+                            "arguments": "{\n\"location\": \"Boston, MA\"\n}"
+                        }
+                    }
+                ]
+            },
+            "logprobs": null,
+            "finish_reason": "stop"
+        }
+    ],
+    // ...
+};
+
+render(ChatCompletionToMessageDemo);
+```
+
+
+比如,当用户使用 [Chat Completion API](https://platform.openai.com/docs/api-reference/chat/create) 接口返回流式数据时,可以通过 `streamingChatCompletionToMessage` 函数将 Chat Completion Chunk Object List 转换为 Dialogue Message 消息块格式。
+
+```jsx live=true noInline=true dir="column"
+import React, { useState, useCallback } from 'react';
+import { AIChatDialogue } from '@douyinfe/semi-ui';
+
+const roleConfig = {
+    user: {
+        name: 'User',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png'
+    },
+    assistant: {
+        name: 'Assistant',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+    },
+    system: {
+        name: 'System',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+    }
+};
+
+function StreamingChatCompletionToMessageDemo() {
+    const [messages, setMessage] = useState([]);
+    const [state, setState] = useState();
+
+    const onChatsChange = useCallback((chats) => {
+        setMessage(chats);
+    }, []);
+
+    useEffect(() => {
+        const total = STREAMING_CHAT_COMPLETION_DATA.length;
+        let i = 1;
+
+        const timer = setInterval(() => {
+            if (i > total) {
+                clearInterval(timer);
+                return;
+            }
+
+            const slice = STREAMING_CHAT_COMPLETION_DATA.slice(0, i);
+            const { messages: partialMessages, state: nextState } = streamingChatCompletionToMessage(slice, state);
+            setState(nextState);
+
+            const merged = [...messages, partialMessages[0]];
+            setMessage(merged);
+
+            i += 1;
+        }, 100);
+
+        return () => clearInterval(timer);
+    }, []);
+  
+    return (
+        <AIChatDialogue 
+            align="leftRight"
+            mode="bubble"
+            chats={messages}
+            roleConfig={roleConfig}
+            onChatsChange={onChatsChange}
+        />
+    );
+};
+
+const STREAMING_CHAT_COMPLETION_DATA = [
+    { "id": "chatcmpl-COjljxurV5GKrRUsg1wd7mIyQCiiT", "object": "chat.completion.chunk", "created": 1760011843, "model": "o3-mini-2025-01-31", "service_tier": "default", "system_fingerprint": "fp_6c43dcef8c", "choices": [{ "index": 0, "delta": { "role": "assistant", "content": "", "refusal": null }, "finish_reason": null }], "obfuscation": "ahPqlzj6DD" },
+    { "id": "chatcmpl-COjljxurV5GKrRUsg1wd7mIyQCiiT", "object": "chat.completion.chunk", "created": 1760011843, "model": "o3-mini-2025-01-31", "service_tier": "default", "system_fingerprint": "fp_6c43dcef8c", "choices": [{ "index": 0, "delta": { "content": "" }, "finish_reason": null }], "obfuscation": "i2PXRIwvc3D" },
+    // index 0: 输出文本增量
+    { "id": "chatcmpl-COjljxurV5GKrRUsg1wd7mIyQCiiT", "object": "chat.completion.chunk", "created": 1760011843, "model": "o3-mini-2025-01-31", "service_tier": "default", "system_fingerprint": "fp_6c43dcef8c", "choices": [{ "index": 0, "delta": { "content": "我正在使用 " }, "finish_reason": null }], "obfuscation": "3sslO5QylW" },
+    { "id": "chatcmpl-COjljxurV5GKrRUsg1wd7mIyQCiiT", "object": "chat.completion.chunk", "created": 1760011843, "model": "o3-mini-2025-01-31", "service_tier": "default", "system_fingerprint": "fp_6c43dcef8c", "choices": [{ "index": 0, "delta": { "content": "streamingChatCompletionToMessage" }, "finish_reason": null }], "obfuscation": "3sslO5QylW" },
+
+    // index 1: 工具调用增量(function_call / tool_calls)
+    { "id": "chatcmpl-COjljxurV5GKrRUsg1wd7mIyQCiiT", "object": "chat.completion.chunk", "created": 1760011845, "model": "o3-mini-2025-01-31", "service_tier": "default", "system_fingerprint": "fp_6c43dcef8c", "choices": [{ "index": 1, "delta": { "tool_calls": [{ "id": "call_1", "function": { "name": "searchWeather", "arguments": "{\"city\":\"北京\"" } }] }, "finish_reason": null }], "obfuscation": "T1" },
+    { "id": "chatcmpl-COjljxurV5GKrRUsg1wd7mIyQCiiT", "object": "chat.completion.chunk", "created": 1760011846, "model": "o3-mini-2025-01-31", "service_tier": "default", "system_fingerprint": "fp_6c43dcef8c", "choices": [{ "index": 1, "delta": { "tool_calls": [{ "id": "call_1", "function": { "name": null, "arguments": ",\"day\":\"today\"}" } }] }, "finish_reason": null }], "obfuscation": "T2" },
+
+    { "id": "chatcmpl-COjljxurV5GKrRUsg1wd7mIyQCiiT", "object": "chat.completion.chunk", "created": 1760011844, "model": "o3-mini-2025-01-31", "service_tier": "default", "system_fingerprint": "fp_6c43dcef8c", "choices": [{ "index": 0, "delta": { "content": " 转换 Chat Completion Chunks" }, "finish_reason": null }], "obfuscation": "X1" },
+    { "id": "chatcmpl-COjljxurV5GKrRUsg1wd7mIyQCiiT", "object": "chat.completion.chunk", "created": 1760011844, "model": "o3-mini-2025-01-31", "service_tier": "default", "system_fingerprint": "fp_6c43dcef8c", "choices": [{ "index": 0, "delta": { "content": " 🥳" }, "finish_reason": null }], "obfuscation": "X2" },
+
+    // 终止信号
+    { "id": "chatcmpl-COjljxurV5GKrRUsg1wd7mIyQCiiT", "object": "chat.completion.chunk", "created": 1760011843, "model": "o3-mini-2025-01-31", "service_tier": "default", "system_fingerprint": "fp_6c43dcef8c", "choices": [{ "index": 0, "delta": {}, "finish_reason": "stop" }], "obfuscation": "n13SLf" },
+    { "id": "chatcmpl-COjljxurV5GKrRUsg1wd7mIyQCiiT", "object": "chat.completion.chunk", "created": 1760011843, "model": "o3-mini-2025-01-31", "service_tier": "default", "system_fingerprint": "fp_6c43dcef8c", "choices": [{ "index": 1, "delta": {}, "finish_reason": "stop" }], "obfuscation": "jt9rDb" }
+];
+
+render(StreamingChatCompletionToMessageDemo);
+
+```
+
+当用户使用 [Response API](https://platform.openai.com/docs/api-reference/responses/create) 接口返回非流式数据时,可以通过 `responseToMessage` 函数将 Response Object 转换为 Dialogue Message 消息块格式。
+```jsx live=true noInline=true dir="column"
+import React, { useState, useCallback } from 'react';
+import { AIChatDialogue } from '@douyinfe/semi-ui';
+
+const roleConfig = {
+    user: {
+        name: 'User',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png'
+    },
+    assistant: {
+        name: 'Assistant',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+    },
+    system: {
+        name: 'System',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+    }
+};
+
+function ResponseToMessageDemo() {
+    const [messages, setMessage] = useState([]);
+
+    const onChatsChange = useCallback((chats) => {
+        setMessage(chats);
+    }, []);
+
+    useEffect(() => {
+        const responseMessage = responseToMessage(RESPONSE_DATA);
+
+        setMessage([responseMessage]);
+    }, []);
+  
+    return (
+        <AIChatDialogue 
+            align="leftRight"
+            mode="bubble"
+            chats={messages}
+            roleConfig={roleConfig}
+            onChatsChange={onChatsChange}
+        />
+    );
+};
+
+const RESPONSE_DATA = {
+    "id": "resp_67ccd3a9da748190baa7f1570fe91ac604becb25c45c1d41",
+    "object": "response",
+    "created_at": 1741476777,
+    "status": "completed",
+    "error": null,
+    "incomplete_details": null,
+    "instructions": null,
+    "max_output_tokens": null,
+    "model": "gpt-4o-2024-08-06",
+    "output": [
+        {
+            "id": "rs_6876cf02e0bc8192b74af0fb64b715ff06fa2fcced15a5ac",
+            "type": "reasoning",
+            "status": "completed",
+            "summary": [
+                {
+                    "type": "summary_text",
+                    "text": "**用户询问什么是 Semi Design** 用户问 “Semi Design”需整合多源信息。首先发现抖音的 Semi Design 是设计系统,支持多平台且含 Design Token 和代码转换工具。印度 Semi Design 专注半导体培训,但用户可能更关注抖音案例。其他结果涉及半定制设计,但关联性较低。需确认是否有其他解释,但当前信息已覆盖主要维度。虽然继续推理可能提高完备性,但现阶段已足够支撑答案,可以开始输出给用户。"
+                }
+            ]
+        },
+        {
+            "type": "message",
+            "id": "msg_67ccd3acc8d48190a77525dc6de64b4104becb25c45c1d41",
+            "status": "completed",
+            "role": "assistant",
+            "content": [
+                {
+                    "type": "output_text",
+                    "text": "Semi Design 是由抖音前端团队和MED产品设计团队设计、开发并维护的设计系统",
+                    "annotations": [
+                        {
+                            "title": 'Semi Design',
+                            "url": 'https://semi.design/zh-CN/start/getting-started',
+                            "detail": 'Semi Design 快速开始',
+                            "logo": 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png'
+                        },
+                        {
+                            "title": 'Semi Design',
+                            "url": 'https://semi.design/zh-CN/start/getting-started',
+                            "detail": 'Semi Design 快速开始',
+                            "logo": 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png'
+                        },
+                        {
+                            "title": 'Semi Design',
+                            "url": 'https://semi.design/zh-CN/start/getting-started',
+                            "detail": 'Semi Design 快速开始',
+                            "logo": 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png'
+                        },
+                    ]
+                }
+            ]
+        },
+        {
+            "id": "fc_12345xyz",
+            "call_id": "call_12345xyz",
+            "type": "function_call",
+            "name": "get_semi_page",
+            "status": "completed",
+            "arguments": "{\"pageName\":\"AIChatDialogue\"}"
+        },
+    ],
+    // ...
+};
+
+render(ResponseToMessageDemo);
+```
+
+当用户使用 [Response API](https://platform.openai.com/docs/api-reference/responses/create) 接口返回流式数据时,可以通过 `streamingResponseToMessage` 函数将 Response Chunk Object List 转换为 Dialogue Message 消息块格式。
+```jsx live=true noInline=true dir="column"
+import React, { useState, useCallback } from 'react';
+import { AIChatDialogue } from '@douyinfe/semi-ui';
+
+const roleConfig = {
+    user: {
+        name: 'User',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png'
+    },
+    assistant: {
+        name: 'Assistant',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+    },
+    system: {
+        name: 'System',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
+    }
+};
+
+const FIXED_SHUFFLED_INDICES = [
+    0,  // sequence_number: 0
+    1,  // sequence_number: 1
+    2,  // sequence_number: 2
+    3,  // sequence_number: 3
+    4,  // sequence_number: 4
+    6,  // sequence_number: 6 (块5被跳过 / chunk 5 skipped)
+    6,  // sequence_number: 6 (块6重复到达)
+    7,  // sequence_number: 7
+    5,  // sequence_number: 5 (块5延迟到达 / chunk 5 arrives late)
+    8,  // sequence_number: 8
+    9,  // sequence_number: 9
+    10, // sequence_number: 10
+    11, // sequence_number: 11
+    12, // sequence_number: 12 
+    13, // sequence_number: 13 
+    14, // sequence_number: 14
+    15, // sequence_number: 15
+    16, // sequence_number: 16
+];
+
+function StreamingResponseToMessageDemo() {
+    const [messages, setMessage] = useState([]);
+    const [currentState, setCurrentState] = useState(null);
+    const [currentLength, setCurrentLength] = useState(0);
+
+    const onChatsChange = useCallback((chats) => {
+        setMessage(chats);
+    }, []);
+
+    useEffect(() => {
+        if (currentLength > FIXED_SHUFFLED_INDICES.length) {
+            return;
+        }
+
+        const timer = setTimeout(() => {
+            if (currentLength === 0) {
+                setCurrentLength(1);
+                return;
+            }
+
+            const currentIndices = FIXED_SHUFFLED_INDICES.slice(0, currentLength);
+            const currentChunks = currentIndices.map(index => REASONING_CHUNKS[index]);
+
+            const result = streamingResponseToMessage(currentChunks, currentState);
+            
+            if (result) {
+                const { message: responseMessage, nextState } = result;
+                if (responseMessage) {
+                    setMessage([responseMessage]);
+                    // 更新状态供下次使用 / Update state for next iteration
+                    setCurrentState(nextState);
+                }
+            }
+            setCurrentLength(prev => prev + 1);
+        }, 200);
+
+        return () => clearTimeout(timer);
+    }, [currentLength, currentState]);
+  
+    return (
+        <AIChatDialogue 
+            align="leftRight"
+            mode="bubble"
+            chats={messages}
+            roleConfig={roleConfig}
+            onChatsChange={onChatsChange}
+        />
+    );
+};
+
+const REASONING_CHUNKS = [
+    { "type": "response.created", "sequence_number": 0, "response": { "id": "resp_reason_001", "object": "response", "created_at": 1760091777, "status": "in_progress", "background": false, "error": null, "incomplete_details": null, "instructions": null, "max_output_tokens": null, "max_tool_calls": null, "model": "o3-mini-2025-01-31", "output": [], "parallel_tool_calls": true, "previous_response_id": null, "prompt_cache_key": null, "reasoning": { "effort": "medium", "summary": null }, "safety_identifier": null, "service_tier": "auto", "store": true, "temperature": 1.0, "text": { "format": { "type": "text" }, "verbosity": "medium" }, "tool_choice": "auto", "tools": [], "top_logprobs": 0, "top_p": 1.0, "truncation": "disabled", "usage": null, "user": null, "metadata": {} } },
+    { "type": "response.in_progress", "sequence_number": 1, "response": { "id": "resp_reason_001", "object": "response", "created_at": 1760091777, "status": "in_progress", "background": false, "error": null, "incomplete_details": null, "instructions": null, "max_output_tokens": null, "max_tool_calls": null, "model": "o3-mini-2025-01-31", "output": [], "parallel_tool_calls": true, "previous_response_id": null, "prompt_cache_key": null, "reasoning": { "effort": "medium", "summary": null }, "safety_identifier": null, "service_tier": "auto", "store": true, "temperature": 1.0, "text": { "format": { "type": "text" }, "verbosity": "medium" }, "tool_choice": "auto", "tools": [], "top_logprobs": 0, "top_p": 1.0, "truncation": "disabled", "usage": null, "user": null, "metadata": {} } },
+
+    // reasoning item(输出索引 0)
+    { "type": "response.output_item.added", "sequence_number": 2, "output_index": 0, "item": { "id": "rs_reason_001", "type": "reasoning", "summary": [] } },
+    { "type": "response.reasoning_summary_part.added", "sequence_number": 3, "output_index": 0, "summary_index": 0, "part": { "type": "reasoning", "text": "" } },
+    { "type": "response.reasoning_summary_text.delta", "sequence_number": 4, "output_index": 0, "summary_index": 0, "delta": "思" },
+    { "type": "response.reasoning_summary_text.delta", "sequence_number": 5, "output_index": 0, "summary_index": 0, "delta": "考" },
+    { "type": "response.reasoning_summary_text.delta", "sequence_number": 6, "output_index": 0, "summary_index": 0, "delta": "完" },
+    { "type": "response.reasoning_summary_text.delta", "sequence_number": 7, "output_index": 0, "summary_index": 0, "delta": "成" },
+    { "type": "response.reasoning_summary_text.delta", "sequence_number": 8, "output_index": 0, "summary_index": 0, "delta": "!" },
+    { "type": "response.reasoning_summary_text.done", "sequence_number": 9, "output_index": 0, "summary_index": 0, "text": "思考完成!" },
+    { "type": "response.output_item.done", "sequence_number": 10, "output_index": 0, "item": { "id": "rs_reason_001", "type": "reasoning", "summary": [ { "type": "reasoning", "text": "思考完成!" } ] } },
+
+    // assistant message(输出索引 1)
+    { "type": "response.output_item.added", "sequence_number": 11, "output_index": 1, "item": { "id": "msg_reason_001", "type": "message", "status": "in_progress", "content": [], "role": "assistant" } },
+    { "type": "response.content_part.added", "sequence_number": 12, "item_id": "msg_reason_001", "output_index": 1, "content_index": 0, "part": { "type": "output_text", "annotations": [], "text": "" } },
+    { "type": "response.output_text.delta", "sequence_number": 13, "item_id": "msg_reason_001", "output_index": 1, "content_index": 0, "delta": "基于上述思考," },
+    { "type": "response.output_text.delta", "sequence_number": 14, "item_id": "msg_reason_001", "output_index": 1, "content_index": 0, "delta": "结论如下:" },
+    { "type": "response.output_text.done", "sequence_number": 15, "item_id": "msg_reason_001", "output_index": 1, "content_index": 0, "text": "基于上述思考,结论如下:..." },
+
+    { "type": "response.completed", "sequence_number": 16, "response": { "id": "resp_reason_001", "object": "response", "created_at": 1760091777, "status": "completed", "background": false, "error": null, "incomplete_details": null, "instructions": null, "max_output_tokens": null, "max_tool_calls": null, "model": "o3-mini-2025-01-31", "output": [ { "id": "rs_reason_001", "type": "reasoning", "summary": [ { "type": "reasoning", "text": "思考完成!" } ] }, { "id": "msg_reason_001", "type": "message", "status": "completed", "content": [ { "type": "output_text", "annotations": [], "text": "基于上述思考,结论如下:..." } ], "role": "assistant" } ], "parallel_tool_calls": true, "previous_response_id": null, "prompt_cache_key": null, "reasoning": { "effort": "medium", "summary": null }, "safety_identifier": null, "service_tier": "default", "store": true, "temperature": 1.0, "text": { "format": { "type": "text" }, "verbosity": "medium" }, "tool_choice": "auto", "tools": [], "top_logprobs": 0, "top_p": 1.0, "truncation": "disabled", "usage": { "input_tokens": 12, "input_tokens_details": { "cached_tokens": 0 }, "output_tokens": 120, "output_tokens_details": { "reasoning_tokens": 16 }, "total_tokens": 132 }, "user": null, "metadata": {} } }
+];
+
+render(StreamingResponseToMessageDemo);
+
+```
+
+## API 参考
+| 属性 | 说明 | 类型 | 默认值 |
+|---|---|---|---|
+| align | 对话布局方式 | 'leftRight' \| 'leftAlign' | 'leftRight' |
+| chats | 受控对话消息列表 | Message[] | - |
+| className | 自定义类名 | string | - |
+| disabledFileItemClick | 是否禁用文件点击 | boolean | false |
+| hintCls | 提示区最外层样式类名 | string | - |
+| hints | 提示信息 | string[] | - |
+| hintStyle | 提示区最外层样式 | CSSProperties | - |
+| markdownRenderProps | 该参数将透传给对话框渲染所用的 MarkdownRender 组件,详见 [MarkdownRenderProps](/zh-CN/plus/markdownrender#API) | MarkdownRenderProps | - |
+| messageEditRender | 自定义消息编辑渲染 | (props: MessageContent) => React.ReactNode | - |
+| mode | 对话模式 | 'bubble' \| 'noBubble' \| 'userBubble' | 'bubble' |
+| onAnnotationClick | annotation 点击回调 | (annotation?: Annotation) => void | - |
+| onChatsChange | 对话消息列表变更回调 | (chats?: Message[]) => void | - |
+| onFileClick | 附件文件点击回调 | (file?: InputFile) => void | - |
+| onHintClick | 点击提示词回调 | (hint: string) => void | - |
+| onImageClick | 图片点击回调 | (image?: InputImage) => void | - |
+| onMessageBadFeedback | 消息负向反馈回调 | (message?: Message) => void | - |
+| onMessageCopy | 复制消息回调 | (message?: Message) => void | - |
+| onMessageDelete | 删除消息回调 | (message?: Message) => void | - |
+| onMessageEdit | 编辑消息回调 | (message?: Message) => void | - |
+| onMessageGoodFeedback | 消息正向反馈回调 | (message?: Message) => void | - |
+| onMessageReset | 重置消息回调 | (message?: Message) => void | - |
+| onMessageShare | 分享消息回调 | (message?: Message) => void | - |
+| onReferenceClick | 引用按钮点击回调 | (item?: Reference) => void | - |
+| onSelect | 选择项变更回调 | (selectedIds: string[]) => void | - |
+| renderConfig | 自定义各区块渲染 | DialogueRenderConfig | - |
+| renderDialogueContentItem | 按消息类型返回内容渲染映射 | DialogueContentItemRendererMap | - |
+| renderHintBox | 自定义提示项渲染 | (props: { content: string; index: number; onHintClick: () => void }) => React.ReactNode | - |
+| roleConfig | 角色配置(user/assistant/system 等元数据) | [RoleConfig](/zh-CN/ai/aiChatDialogue#RoleConfig) | 必填 |
+| selecting | 是否开启选择模式 | boolean | false |
+| showReset | 是否展示重置操作 | boolean | true |
+| showReference | 是否在文字或者文件消息中展示可被引用图标,仅对用户消息生效 | boolean | false |
+| style | 样式 | CSSProperties | - |
+
+### RoleConfig
+| 属性  | 说明   | 类型   | 默认值 |
+|------|--------|-------|-------|
+| user | 用户信息 | Metadata \| Map<string, Metadata> | - |
+| assistant | 助手信息 | Metadata \| Map<string, Metadata> | - |
+| system | 系统信息 | Metadata \| Map<string, Metadata> | - |
+
+### MetaData
+| 属性  | 说明   | 类型   | 默认值 |
+|------|--------|-------|-------|
+| name | 名称 | string | - |
+| avatar | 头像 | string | - |
+| color | 头像背景色,同 Avatar 组件的 color 参数, 支持 `amber`、 `blue`、 `cyan`、 `green`、 `grey`、 `indigo`、 `light-blue`、 `light-green`、 `lime`、 `orange`、 `pink`、 `purple`、 `red`、 `teal`、 `violet`、 `yellow` | string | `grey` |
+
+### Message
+| 属性  | 说明   | 类型   | 默认值 |
+|------|--------|-------|-------|
+| role | 角色  | string | - |
+| name | 名称  | string | - |
+| id | 唯一标识  | string\| number | - |
+| content | 消息内容 | string\| ContentItem[] | - |
+| createdAt | 创建时间 | number | -|
+| model | 模型名称 | string | -|
+| status | 消息状态,可选值为 `queued` \| `in_progress` \| `incomplete` \| `completed` \| `failed`  \| `cancelled` |string | completed |
+
+### Reference
+| 属性  | 说明   | 类型   | 默认值 |
+|------|--------|-------|-------|
+| id | 唯一标识  | string \| number | - |
+| type | 类型  | string | - |
+| name | 名称  | string | - |
+| url | 地址  | string | - |
+| content | 文本内容  | string | - |
+
+
+### Methods
+| 方法  | 说明   |
+|------|--------|
+| selectAll | 全选所有消息 |
+| deselectAll | 取消全选所有消息 |
+| scrollToBottom(animation: boolean) | 滚动到最底部, animation 为 true,则有动画,反之无动画 |
+
+### ContentItem
+`ContentItem` 支持所有 OpenAI Response [InputItem](https://platform.openai.com/docs/api-reference/responses/create#responses-create-input) 和 [OutputItem](https://platform.openai.com/docs/api-reference/responses/object#responses/object-output) 类型,具体类型定义如下
+
+```ts
+type ContentItem = InputContentItem | OutputContentItem;
+
+type InputContentItem = InputMessage | ItemReference;
+type OutputContentItem = OutputMessage | MCPToolCall | Reasoning FileSearchToolCall | 
+                        WebSearchToolCall | FunctionToolCall | CustomToolCall | ImageGenerationCall| CustomObject;
+
+interface CommonContentItem {
+    id?: string;
+    type?: string;
+    status?: string;
+    role?: string
+}
+
+interface CustomObject {
+    [key: string]: any
+}
+
+// input item
+interface InputMessage extends CommonContentItem {
+    content?: string | (InputText | InputImage | InputFile)[]
+}
+
+interface InputText extends CommonContentItem {
+    text?: string
+}
+
+interface InputImage extends CommonContentItem {
+    detail?: string;
+    file_id?: string;
+    image_url?: string
+}
+
+interface InputFile extends CommonContentItem {
+    file_id?: string;
+    file_data?: string;
+    file_url?: string;
+    filename?: string;
+    size?: string;
+    file_type?: string;
+    fileInstance?: any
+}
+
+interface ItemReference extends CommonContentItem {
+    file_id?: string
+}
+
+
+// output item
+interface OutputMessage extends CommonContentItem {
+    content?: (OutputText | Refusal)[]
+}
+
+interface OutputText {
+    text?: string;
+    type?: string;
+    annotations?: Annotation[]
+}
+
+interface Refusal extends CommonContentItem {
+    refusal?: string;
+    type?: string
+}
+
+type Annotation = URLCitation | CustomObject;
+
+interface URLCitation {
+    end_index?: number;
+    start_index?: number;
+    title?: string;
+    type?: string;
+    url?: string
+}
+
+interface Reasoning extends CommonContentItem {
+    summary?: {
+        text?: string;
+        type?: string
+    }[];
+    content?: {
+        text?: string;
+        type?: string
+    }[]
+}
+
+interface FileSearchToolCallResult {
+    attributes?: Map<string, string>;
+    score?: number;
+    file_id?: string;
+    filename?: string;
+    text?: string
+}
+
+interface FileSearchToolCall extends CommonContentItem {
+    queries?: string[];
+    results?: FileSearchToolCallResult[]
+}
+
+interface WebSearchToolCall extends CommonContentItem {
+    action?: SearchAction | OpenPageAction | FindAction
+}
+
+interface SearchAction {
+    type?: string;
+    query?: string;
+    sources?: { type: string; url: string }[]
+}
+
+interface OpenPageAction {
+    type?: string;
+    url?: string
+}
+
+interface FindAction {
+    action?: string;
+    type?: string;
+    query?: string
+}
+
+interface FunctionToolCall extends CommonContentItem {
+    call_id?: string;
+    name?: string;
+    arguments?: string
+}
+
+interface CustomToolCall extends CommonContentItem {
+    call_id?: string;
+    name?: string;
+    input?: string
+}
+
+interface ImageGenerationCall extends CommonContentItem {
+    result?: string
+}
+
+interface MCPToolCall extends CommonContentItem {
+    arguments?: string;
+    server_label?: string;
+    name?: string;
+    result?: string;
+    output?: string
+}
+
+interface FileUploadToolCall extends CommonContentItem {
+    result?: string
+}
+
+```
+
+## 设计变量
+<DesignToken/>

+ 1516 - 0
content/ai/aiChatInput/index-en-US.md

@@ -0,0 +1,1516 @@
+---
+localeCode: en-US
+order: 99
+category: Ai
+title: AIChatInput
+icon: doc-aiInput
+width: 60%
+brief: Input box used in AI chat scenarios
+showNew: true
+---
+
+## Usage Scenarios
+
+In AI chat scenarios, users can use `AIChatInput` to achieve rich text input, uploading, quoting, suggestions, templates, feature configuration, and rich custom display.
+
+`AIChatInput`'s rich text input is based on `tiptap` (https://tiptap.dev/docs/editor/getting-started/overview), a modern rich text editor development framework that supports mainstream front-end frameworks such as React and Vue, and boasts strong customizability and extensibility. Its componentization capabilities are excellent, performance is high, it has many built-in commonly used extensions, and it supports user-defined nodes, commands, plugins, and menus, enabling flexible adaptation and expansion of rich text input capabilities in complex AI scenarios. Semi's `AIChatInput` component encapsulates tiptap, allowing developers to use it out of the box or extend it as needed according to business requirements.
+
+## Demos
+
+### How to import
+
+```jsx import
+import { AIChatInput } from '@douyinfe/semi-ui';
+```
+
+### Basic Usage
+
+Supports text input and file upload. You can configure the following parameters as needed:
+
+- `uploadProps`: Configure parameters related to file upload. See [UploadProps](/en-US/plus/upload#API)
+- `onUploadChange`: Callback when file upload changes
+- `placeholder`: Placeholder for the input box
+- `defaultContent`: Default content for the input box
+- `onContentChange`: Callback when the content of the input box changes; the parameter is the current content
+
+```jsx live=true dir="column" noInline=true
+import React from 'react';
+import { AIChatInput } from '@douyinfe/semi-ui';
+
+const uploadProps = { action: "https://api.semi.design/upload" };
+const outerStyle = { margin: 12 };
+
+function Basic() {
+    const onContentChange = useCallback((content) => {
+        console.log('onContentChange', content);
+    }, []);
+
+    const onUploadChange = useCallback((fileList) => {
+        console.log('onUploadChange', fileList);
+    }, []);
+  
+    return (
+        <AIChatInput
+            placeholder={'Enter content or upload...'} 
+            uploadProps={uploadProps}
+            onContentChange={onContentChange}
+            onUploadChange={onUploadChange}
+            style={outerStyle} 
+        />
+    );
+};
+
+render(<Basic />);
+```
+
+### Message Sending
+
+When there is content in the input box (including text entry, uploaded content, [reference content](/en-US/plus/aiChatInput#Reference)), sending messages is allowed. Clicking the send message button triggers the `onMessageSend` callback; the argument is the input content, including text, reference content, uploaded files, and configuration area content.
+
+You can manage generating status with `generating`. If `generating` is `true`, AIChatInput will show a stop-generating button instead of the send button and clear the input area as well as uploaded files. References require manual handling.
+
+Clicking the stop button triggers `onStopGenerate`, where you can handle logic such as setting `generating` to `false`.
+
+```jsx live=true dir="column" noInline=true
+import React from 'react';
+import { AIChatInput } from '@douyinfe/semi-ui';
+
+const uploadProps = { 
+    action: "https://api.semi.design/upload",
+    defaultFileList: [
+        {
+            uid: '1',
+            name: 'dy.jpeg',
+            status: 'success',
+            size: '130kb',
+            url: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/dy.png',
+        },
+        {
+            uid: '5',
+            name: 'resso.jpeg',
+            percent: 50,
+            size: '222kb',
+            url: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/Resso.png',
+        }
+    ],
+};
+const outerStyle = { margin: 12 };
+
+const reference = [
+    {
+        id: '1',
+        type: 'text',
+        content: 'Test text: This is a long text repeated many times for demonstration purposes...'
+    }
+];
+
+function SendMessageAndStopGenerate() {
+    const [references, setReferences] = useState(reference);
+    const [generating, setGenerating] = useState(false);
+    const onContentChange = useCallback((content) => {
+        console.log('onContentChange', content);
+    }, []);
+
+    const onUploadChange = useCallback((fileList) => {
+        console.log('onUploadChange', fileList);
+    }, []);
+
+    const toggleGenerate = useCallback((props) => {
+        setGenerating(value => !value);
+    }, []);
+
+    const onMessageSend = useCallback((content) => {
+        toggleGenerate();
+        setReferences([]);
+    }, []);
+
+    const handleReferenceDelete = useCallback((item) => {
+        setReferences((references) => {
+            const newReference = references.filter((ref) => ref.id !== item.id);
+            return newReference;
+        });
+    }, []);
+    
+    return (
+        <AIChatInput
+            defaultContent={"Click Send to see changes in content, uploads, and references."}
+            generating={generating}
+            uploadProps={uploadProps}
+            onContentChange={onContentChange}
+            onUploadChange={onUploadChange}
+            style={outerStyle}
+            onMessageSend={onMessageSend}
+            onStopGenerate={toggleGenerate}
+            onReferenceDelete={handleReferenceDelete}
+            references={references}
+        />
+    );
+};
+
+render(<SendMessageAndStopGenerate />);
+```
+
+### Rich Text Input
+
+AIChatInput uses [tiptap](https://tiptap.dev/docs/editor/getting-started/overview) for its rich text editor. You can enter text, use built-in extensions (including `input-slot`, `select-slot`, `skill-slot`), or extend with your own.
+
+- `input-slot`: Supports text input and placeholder display.
+- `select-slot`: Supports in-box option selection with string options.
+- `skill-slot`: For skill display blocks.
+
+You can set input content with the `setContent` ref method and focus the editor with `focusEditor`.
+
+```jsx live=true dir="column" noInline=true
+import React, { useRef, useCallback } from 'react';
+import { AIChatInput } from '@douyinfe/semi-ui';
+
+const uploadProps = { action: "https://api.semi.design/upload" };
+const outerStyle = { margin: 12 };
+const temp = {
+    'input-slot': 'I am an <input-slot placeholder="[Occupation]">engineer</input-slot>',
+    'select-slot': 'I am a <select-slot value="Front-end Developer" options=\'["Designer","Front-end Developer","Back-end Developer"]\'></select-slot>, please help me complete...',
+    'skill-slot': '<skill-slot data-value="AI Coding"></skill-slot> Please help me complete...'
+};
+
+function RichTextExample() {
+    const [activeIndex, setActiveIndex] = useState(0);
+    const ref = useRef();
+
+    const setTemplate = useCallback((event) => {
+        const index = Number(event.target.dataset.index);
+        setActiveIndex(index);
+        const content = Object.values(temp)[index];
+        if (ref.current) {
+            ref.current.setContent(content);
+            ref.current.focusEditor();
+        }
+    }, [ref]);
+
+    return (<>
+        <div className="aiChatInput-radio">
+            {Object.keys(temp).map((item, index) => (
+                <div 
+                    className={`aiChatInput-radio-item ${index === activeIndex ? 'aiChatInput-radio-item-selected' : ''}`}
+                    key={index} 
+                    data-index={index} 
+                    onClick={setTemplate}
+                >{item}</div>
+            ))}
+        </div>
+        <AIChatInput
+            ref={ref}
+            defaultContent={temp['input-slot']}
+            placeholder={'Enter content or upload'} 
+            uploadProps={uploadProps}
+            style={outerStyle} 
+        />
+    </>);
+};
+
+render(<RichTextExample />);
+```
+
+### Reference
+
+You can pass in references via the `references`, which will display at the top of the input box.
+
+- `renderReference`: Custom renderer for an individual reference.
+- `onReferenceDelete`: Callback for deleting a reference.
+- `onReferenceClick`: Callback for clicking a reference.
+
+```jsx live=true dir="column" noInline=true
+import React from 'react';
+import { AIChatInput } from '@douyinfe/semi-ui';
+
+const uploadProps = { action: "https://api.semi.design/upload" };
+const outerStyle = { margin: 12 };
+const referenceTemp = [
+    { id: '1', type: 'text', content: 'Sample text, repeated to demonstrate a long text.' },
+    { id: '2', name: 'FeishuDoc.docx' },
+    { id: '3', name: 'FeishuDoc.pdf' },
+    { id: '4', name: 'Music.mp4' },
+    { id: '5', name: 'Image.jpeg', url: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/Resso.png' },
+    { id: '6', name: 'code.json' }
+];
+
+function Reference() {
+    const [references, setReferences] = useState(referenceTemp);
+    const handleReferenceDelete = useCallback((item) => {
+        const newReference = references.filter((ref) => ref.id !== item.id);
+        setReferences(newReference);
+    }, [references]);
+
+    const handleReferenceClick = useCallback((item) => {
+        console.log('Clicked reference', item);
+    }, []);
+    
+    return (
+        <AIChatInput
+            placeholder={'Demo for viewing reference content'} 
+            onReferenceDelete={handleReferenceDelete}
+            onReferenceClick={handleReferenceClick}
+            references={references} 
+            uploadProps={uploadProps}
+            style={outerStyle}
+        />
+    );
+};
+
+render(<Reference />);
+```
+
+### Configuration Area
+
+You can configure options such as model parameters, web search, and critical thinking through the configuration area, or display/view MCP tools.
+
+- `renderConfigureArea`: Custom renderer for config area buttons.
+- Use `Configure` components such as `Select`, `Button`, `Mcp`, `RadioButton`, etc.
+
+The `Configure` component manages the state and provides a callback via `onConfigureChange` (make sure to set the unique `field`). For initial values, use `initValue`.
+
+You can also use `getConfigureItem` to adapt your custom components.
+
+```jsx live=true dir="column" noInline=true
+import React from 'react';
+import { AIChatInput } from '@douyinfe/semi-ui';
+import { IconFixedStroked, IconBookOpenStroked, IconFeishuLogo, IconGit, IconFigma } from '@douyinfe/semi-icons';
+
+const { Configure } = AIChatInput;
+const uploadProps = { action: "https://api.semi.design/upload" };
+const outerStyle = { margin: 12 };
+const modelOptions = [
+    { value: 'GPT-5', label: 'GPT-5' },
+    { value: 'GPT-4o', label: 'GPT-4o' },
+    { value: 'Claude 3.5 Sonnet', label: 'Claude 3.5 Sonnet' },
+];
+
+const mcpOptions = [
+    { icon: <IconFeishuLogo />, label: "FeishuDoc", value: "feishu" },
+    { icon: <IconGit />, label: "Github Mcp", value: "github" },
+    { icon: <IconFigma />, label: "IconFigma Mcp", value: "IconFigma" }
+];
+
+const radioButtonProps = [
+    { label: 'Fast', value: 'fast' },
+    { label: 'Think', value: 'think' },
+    { label: 'Super', value: 'super' }
+];
+
+function ConfigureButton() {
+    const onConfigureButtonClick = useCallback(() => {
+        console.log('onConfigureButtonClick');
+    }, []);
+
+    const renderLeftMenu = useCallback(() => (<>
+        <Configure.Select optionList={modelOptions} field="model" initValue="GPT-4o" />
+        <Configure.Button icon={<IconBookOpenStroked />} field="onlineSearch">Web search</Configure.Button>
+        <Configure.Mcp options={mcpOptions} onConfigureButtonClick={onConfigureButtonClick}/>
+        <Configure.RadioButton options={radioButtonProps} field="thinkType" initValue="fast"/>
+    </>), []);
+
+    const onConfigureChange = useCallback((value, changedValue) => {
+        console.log('onConfigureChange', value, changedValue);
+    }, []);
+    
+    return (
+        <AIChatInput
+            placeholder={'Demo for configuration area on the lower left'} 
+            renderConfigureArea={renderLeftMenu} 
+            onConfigureChange={onConfigureChange}
+            uploadProps={uploadProps}
+            style={outerStyle}
+        />
+    );
+};
+
+render(<ConfigureButton />);
+```
+
+You can extend any custom component for configuration using `getConfigureItem`.
+
+```ts
+function getConfigureItem(
+    component: React.ReactElement,
+    opts: {
+        valueKey?: string; 
+        onKeyChangeFnName?: string;
+        valuePath?: string;
+        className?: string;
+        defaultProps?: Record<string, any>
+    }
+)
+```
+
+Demo:
+
+```jsx live=true dir="column" noInline=true
+import React, { useCallback } from 'react';
+import { Cascader, AIChatInput, getConfigureItem } from '@douyinfe/semi-ui';
+
+const uploadProps = { action: "https://api.semi.design/upload" };
+const outerStyle = { margin: 12 };
+const cascaderModalOptions = [
+    { label: 'GPT', value: 'GPT', children: [{ label: 'GPT-4o', value: 'GPT-4o' }, { value: 'GPT-5', label: 'GPT-5' }] },
+    { label: 'Claude', value: 'Claude', children: [{ label: 'Claude 3.5 Sonnet', value: 'Claude 3.5 Sonnet' }] }
+];
+
+const myCascader = (props) => <Cascader {...props} />;
+const CustomCascader = getConfigureItem(myCascader, { 
+    className: 'aiChatInput-cascader-configure'
+});
+
+class CustomConfigure extends React.Component {
+    constructor(props) {
+        super(props);
+        this.renderLeftMenu = this.renderLeftMenu.bind(this);
+        this.onConfigureChange = this.onConfigureChange.bind(this);
+    }
+    renderLeftMenu() {
+        return <CustomCascader field="model" treeData={cascaderModalOptions} initValue={['GPT', 'GPT-4o']} />;
+    }
+    onConfigureChange(value, changedValue) {
+        console.log('onConfigureChange', value, changedValue);
+    }
+    render() {
+        return (<AIChatInput
+            placeholder={'Demo for configuration on the lower left'} 
+            renderConfigureArea={this.renderLeftMenu} 
+            onConfigureChange={this.onConfigureChange}
+            uploadProps={uploadProps}
+            style={outerStyle}
+        />);
+    };
+}
+
+render(<CustomConfigure />);
+```
+
+### Action Area
+
+The lower right corner is the action area. Use `renderActionArea` to customize buttons (e.g. for deleting or other operations).
+
+```jsx live=true dir="column" noInline=true
+import React from 'react';
+import { AIChatInput, Divider, Button } from '@douyinfe/semi-ui';
+import { IconDeleteStroked } from '@douyinfe/semi-icons';
+
+const uploadProps = { action: "https://api.semi.design/upload" };
+const outerStyle = { margin: 12 };
+
+function ActionArea() {
+    const renderActionArea = useCallback((props) => (
+        <div className={props.className}>
+            <div style={{ display: 'flex', alignItems: 'center' }} key="delete">
+                <Button type="tertiary" style={{ borderRadius: '50%' }} icon={<IconDeleteStroked />}/>
+                <Divider layout="vertical" style={{ marginLeft: 8 }}/>
+            </div>
+            {props.menuItem}
+        </div>
+    ), []);
+  
+    return (
+        <AIChatInput
+            renderActionArea={renderActionArea}
+            placeholder={'Enter content or upload...'} 
+            uploadProps={uploadProps}
+            style={outerStyle} 
+        />
+    );
+};
+
+render(<ActionArea />);
+```
+
+### Button Shape
+
+You can use the `round` API to configure the button shape at the bottom. The default is `true` (rounded). Set it to `false` for square buttons.
+
+```jsx live=true dir="column" noInline=true
+import React from 'react';
+import { AIChatInput, RadioGroup, Radio } from '@douyinfe/semi-ui';
+import { IconFixedStroked, IconBookOpenStroked, IconFeishuLogo, IconGit, IconFigma } from '@douyinfe/semi-icons';
+
+const { Configure } = AIChatInput;
+const uploadProps = { action: "https://api.semi.design/upload" };
+const outerStyle = { margin: 12 };
+const modelOptions = [
+    { value: 'GPT-5', label: 'GPT-5' },
+    { value: 'GPT-4o', label: 'GPT-4o' },
+    { value: 'Claude 3.5 Sonnet', label: 'Claude 3.5 Sonnet' },
+];
+
+const mcpOptions = [
+    { icon: <IconFeishuLogo />, label: "FeishuDoc", value: "feishu" },
+    { icon: <IconGit />, label: "Github Mcp", value: "github" },
+    { icon: <IconFigma />, label: "IconFigma Mcp", value: "IconFigma" }
+];
+
+const radioButtonProps = [
+    { label: 'Fast', value: 'fast' },
+    { label: 'Think', value: 'think' },
+    { label: 'Super', value: 'super' }
+];
+
+function Shape() {
+    const [round, setRound] = useState(false);
+    const renderLeftMenu = useCallback(() => <>
+        <Configure.Select optionList={modelOptions} field="model" initValue="GPT-4o" />
+        <Configure.Button icon={<IconBookOpenStroked />} field="onlineSearch">Web search</Configure.Button>
+        <Configure.Mcp options={mcpOptions} />
+        <Configure.RadioButton options={radioButtonProps} initValue="fast"/>
+    </>);
+    const onChange = useCallback((e) => {
+        setRound(e.target.value);
+    }, []);
+    
+    return (<>
+        <RadioGroup onChange={onChange} value={round} aria-label="Radio group demo" name="demo-radio-group">
+            <Radio value={true}>Rounded</Radio>
+            <Radio value={false}>Square</Radio>
+        </RadioGroup>
+        <AIChatInput
+            placeholder={'Square button demo'} 
+            round={round}
+            renderConfigureArea={renderLeftMenu} 
+            uploadProps={uploadProps}
+            style={outerStyle}
+        />
+    </>);
+};
+
+render(<Shape />);
+```
+
+### Suggestions
+
+Configure suggestions with the `suggestion` API. This works similarly to the AutoComplete component. Users can dynamically show suggestions based on input.
+
+Use up/down keys to navigate suggestions. Pressing `ESC` or clicking outside the suggestion/input area will close the suggestions. You can customize rendering using `renderSuggestionItem`.
+
+```jsx live=true dir="column" noInline=true
+import React from 'react';
+import { AIChatInput } from '@douyinfe/semi-ui';
+
+const uploadProps = { action: "https://api.semi.design/upload" };
+const outerStyle = { margin: 12 };
+const suggestionTemplate = [ 'Weather', 'Air Quality', 'Work Progress', 'Schedule' ];
+
+function Suggestion() {
+    const [suggestion, setSuggestion] = useState([]);
+    const onChange = useCallback((content) => {
+        let value;
+        if (content.length && content[0].text) {
+            value = content[0].text;
+        }
+        if (value === undefined) {
+            if (suggestion === undefined || suggestion.length === 0) {
+                return;
+            } else {
+                return setSuggestion([]);
+            }
+        }
+        if (value.length === 0) {
+            setSuggestion([]);
+        } else if (value.length > 0 && value.length < 4) {
+            const su = new Array(suggestionTemplate.length).fill(0).map((item, index) =>
+                `${value}, ${suggestionTemplate[index]}`
+            );
+            setSuggestion(su);
+        } else if (value.length >= 4) {
+            setSuggestion([]);
+        }
+    }, [suggestion]);
+  
+    return (
+        <AIChatInput
+            suggestions={suggestion} 
+            onContentChange={onChange}
+            uploadProps={uploadProps}
+            style={outerStyle}
+            placeholder={'When the length is less than 4, see suggestions. Use up/down to select.'} 
+        />
+    );
+}
+
+render(<Suggestion />);
+```
+
+### Skills & Templates
+
+Configure a skill list with `skills`, and use `skillHotKey` to set the shortcut for skill panel.
+
+- `skills` sample format:
+```ts
+interface Skill {
+    label?: string;
+    value?: string;
+    icon?: React.ReactNode;
+    // If this skill has a template, set hasTemplate to true, affects the display of template display buttons
+    hasTemplate?: boolean;
+}
+```
+
+Because templates can be displayed in a variety of ways, we don't provide a default display method. Users can customize the template display through the `renderTemplate` API. The template panel can be displayed and closed by clicking the template button.
+
+```jsx live=true dir="column" noInline=true
+import React from 'react';
+import { AIChatInput } from '@douyinfe/semi-ui';
+import { IconTemplateStroked, IconSearch } from '@douyinfe/semi-icons';
+
+const { Configure } = AIChatInput;
+const modelOptions = [
+    { value: 'GPT-5', label: 'GPT-5' },
+    { value: 'GPT-4o', label: 'GPT-4o' },
+    { value: 'Claude 3.5 Sonnet', label: 'Claude 3.5 Sonnet' },
+];
+const uploadProps = { action: "https://api.semi.design/upload" };
+const outerStyle = { margin: 12 };
+const skills = [
+    {
+        icon: <IconTemplateStroked />,
+        value: 'writing',
+        label: 'Writing',
+        hasTemplate: true,
+    },
+    {
+        icon: <IconSearch />,
+        value: 'AI coding',
+        label: 'AI coding'
+    },
+];
+
+const template = [
+    {
+        groupKey: 'value',
+        group: 'Work',
+        children: [
+            {
+                bg: 'var(--semi-color-primary)',
+                icon: <IconTemplateStroked />,
+                title: 'Summary report',
+                desc: 'Condensate your work results',
+                content: `My occupation is <input-slot placeholder="[Please enter your occupation]"></input-slot>. Please help me write a summary report on <input-slot placeholder="[Purpose: Project Progress Summary, Team Work Results, or Other]</input-slot>`
+            },
+            {
+                bg: 'var(--semi-color-warning)',
+                icon: <IconTemplateStroked />,
+                title: 'Speech skills',
+                desc: 'Meet the expression needs of different scenarios',
+                content: `I am a <select-slot value="Worker" options='["Worker","Student"]'></select-slot>, please help me write a paragraph for <input-slot placeholder="[input object]">unfamiliar colleagues</input-slot>`
+            }
+        ]
+    },
+    {
+        groupKey: 'marketing',
+        group: 'Marketing',
+        children: [
+            {
+                bg: 'var(--semi-color-primary)',
+                icon: <IconTemplateStroked />,
+                title: 'Promotional copy',
+                desc: 'Write promotional copy for each platform',
+                content: 'Please help me write a promotional copy for <input-slot placeholder="[Enter target group]"></input-slot> professionals about <input-slot placeholder="[Enter product]"></input-slot>. It needs to directly hit the pain points and attract users to click.'
+            },
+            {
+                bg: 'var(--semi-color-warning)',
+                icon: <IconTemplateStroked />,
+                title: 'Program planning',
+                desc: 'Tailor-made solutions',
+                content: 'I am a <input-slot placeholder="[Enter occupation]"></input-slot> professional planner. Please help me write a <input-slot placeholder="[Plan type: such as offline book club activity plan, etc.]"></input-slot> offline book club activity plan, which should include but not be limited to planning goals, detailed plans, required resources and budget, effect evaluation, risk response, etc.'
+            }
+        ]
+    }
+];
+
+const TemplateContent = (props) => {
+    const { onTemplateClick: onTemplateClickProps } = props;
+    const [groupIndex, setGroupIndex] = useState(0);
+
+    const onItemClick = useCallback((e) => {
+        const index = e.target.dataset.index;
+        setGroupIndex(Number(index));
+    }, []);
+
+    const onTemplateClick = useCallback((item) => {
+        const { content } = item;
+        onTemplateClickProps(content);
+    }, [onTemplateClickProps]);
+
+    return (<div className={'aiChatInput-template'} >
+        {/* tabs */}
+        <div className={'template-header'} >
+            {(template ? template : []).map((item, index) => {
+                return (<div
+                    key={index}
+                    data-index={index}
+                    className={`template-header-item ${groupIndex === index ? 'template-header-item-active' : ''}`}
+                    onClick={onItemClick}
+                >
+                    {item.group}
+                </div>);
+            })}
+        </div>
+        {/* content */}
+        <div className='template-content'>
+            {(((template ? template : [])[groupIndex] ? (template ? template : [])[groupIndex] : {}).children ? (template ? template : [])[groupIndex].children : []).map((item, index) => (<div
+                key={index}
+                className='template-content-item'
+                onClick={() => onTemplateClick(item)}
+            >
+                <div className='template-content-item-icon' style={{ background: item.bg }}>{item.icon}</div>
+                <div className='template-content-item-title'>{item.title}</div>
+                <div className='template-content-item-desc'>{item.desc}</div>
+            </div>))}
+        </div>
+    </div>);
+};
+
+function Template() {
+    const ref = useRef();
+
+    const setTemplate = useCallback((content) => {
+        const element = ref.current;
+        if (!element) {
+            return;
+        }
+        element.setContentWhileSaveTool(content);
+        element.focusEditor();
+    }, [ref]);
+
+    const renderTemplate = useCallback((skill = {}, e) => {
+        if (skill.value === 'writing') {
+            return <TemplateContent onTemplateClick={setTemplate}/>;
+        }
+    }, [setTemplate]);
+
+    const renderLeftMenu = useCallback(() => <>
+        <Configure.Select optionList={modelOptions} field="model" initValue="GPT-4o" />
+    </>);
+
+    return (
+        <AIChatInput 
+            placeholder='Input / invoke skills'
+            renderConfigureArea={renderLeftMenu} 
+            ref={ref}
+            uploadProps={uploadProps}
+            skills={skills}
+            skillHotKey='/'
+            renderTemplate={renderTemplate}
+            style={outerStyle}
+        />
+    );
+};
+
+render(<Template />);
+```
+
+### Custom Top Slot
+
+Users can customize the top rendering area using the `renderTopSlot` API, rendering references, uploaded content, and configuration items. This can be combined with the `showReference` and `showUploadFile` APIs to control whether references and uploaded files are displayed. Additionally, the `topSlotPosition` API allows you to configure the relative position of customized rendered content relative to the reference and upload display areas.
+
+```ts
+interface TopSlotProps {
+    references: Reference[];
+    attachments: Attachment[];
+    // User input into the input box
+    content: Content[];
+    handleUploadFileDelete: (attachment: Attachment) => void;
+    handleReferenceDelete: (reference: Reference) => void
+}
+```
+
+Usage examples are as follows:
+
+```jsx live=true dir="column" noInline=true
+import React from 'react';
+import { AIChatInput } from '@douyinfe/semi-ui';
+import { IconClose, IconUpload, IconFile, IconFolder, IconBranch, IconTerminal, IconGlobeStroke, IconConnectionPoint2, IconTemplateStroked, IconSearch, IconGit, IconCode } from '@douyinfe/semi-icons';
+
+const { Configure } = AIChatInput;
+const radioButtonProps = [
+    { label: <IconTemplateStroked />, value: 'fast' },
+    { label: <IconSearch />, value: 'think' }
+];
+const uploadProps = { action: "https://api.semi.design/upload" };
+const outerStyle = { margin: 12 };
+
+const customReferences = [
+    {
+        type: 'file',
+        key: '1',
+        name: 'horizontalScroller.tsx',
+        path: 'packages/semi-ui/AIChatInput/horizontalScroller.tsx',
+    },
+    {
+        type: 'folder',
+        key: '2',
+        name: 'AIChatInput',
+        path: 'packages/semi-ui/AIChatInput',
+    },
+    {
+        type: 'web',
+        key: '3',
+        name: 'web'
+    },
+    {
+        type: 'change',
+        key: '4',
+        name: 'recentChange'
+    },
+    {
+        type: 'branch',
+        key: '5',
+        name: 'Branch',
+        detail: 'Diff with Main Branch',
+        branch: 'feat/aichatinput',
+        targetBranch: 'feat/targetBranch',
+    },
+    {
+        type: 'terminal',
+        key: '6',
+        name: 'From 1-2',
+        from: 1,
+        to: 2,
+    }
+];
+
+function getAttachmentType(item = {}) {
+    const { type, name = '', fileInstance = {} } = item;
+    if (type) {
+        return type;
+    }
+    const suffix = name.split('.').pop();
+    if (suffix) {
+        return suffix;
+    } else if (fileInstance.type && fileInstance.type) {
+        const temp = fileInstance.type.split('/').pop();
+        if (temp) {
+            return temp;
+        }
+    }
+    return 'UNKNOWN';
+}
+
+function isImageType(item = {}) {
+    const PIC_PREFIX = 'image/';
+    const PIC_SUFFIX_ARRAY = ['png', 'jpg', 'jpeg', 'gif', 'bmp', 'webp'];
+    const { name = '', fileInstance = {} } = item;
+    const suffix = name.split('.').pop();
+    let result = false;
+    const { type = '' } = fileInstance;
+    if (type.startsWith(PIC_PREFIX)) {
+        result = true;
+    } else if (PIC_SUFFIX_ARRAY.includes(suffix)) {
+        result = true;
+    }
+    return result;
+}
+
+const refTypeToIconMap = new Map([
+    ['file', <IconFile key={'file'} size="small" />],
+    ['folder', <IconFolder key={'folder'} size="small" />],
+    ['branch', <IconBranch key={'branch'} size="small" />],
+    ['terminal', <IconTerminal key={'terminal'} size="small" /> ],
+    ['web', <IconGlobeStroke key={'globalStroke'} size="small" />],
+    ['change', <IconConnectionPoint2 key={'connectionPoint2'} size="small" />],
+    ['git', <IconGit key="git" size="small" />],
+    ['code', <IconCode key="code" size="small" />],
+]);
+
+function RenderTopSlot() {
+    const ref = useRef();
+    const [reference, setReference] = useState(customReferences);
+
+    const renderLeftMenu = useCallback(() => <>
+        <Configure.RadioButton options={radioButtonProps} initValue="fast" field="mode"/>
+    </>);
+
+    const renderTopSlot = useCallback((props) => {
+        const { attachments = [], references = [] } = props;
+        return <div className="ai-chat-input-topSlot">
+            {references.map((item, index) => {
+                const { type, name, detail, key, ...rest } = item;
+                return (<div className="item" key={key}>
+                    <span className='item-icon'>
+                        {React.cloneElement(refTypeToIconMap.get(type), { className: 'item-left item-icon' })}
+                        <IconClose size="small" className='item-icon-delete' onClick={() => {
+                            const newReferences = [...references];
+                            newReferences.splice(index, 1);
+                            setReference(newReferences);
+                        }}/>
+                    </span>
+                    <span className='item-content'>
+                        {name}
+                        {type === 'branch' && <span className='detail'>{detail}</span>}
+                    </span>
+                </div>);
+            })}
+            {attachments.map((item, index) => {
+                const isImage = isImageType(item);
+                const { uid, name, url, size, percent, status } = item;
+                return (<div className="item" key={uid}>
+                    <span className='item-icon'>
+                        {isImage ? <img className='item-image item-left' src={item.url} alt={item.name} /> : <IconUpload size="small" className='item-left item-icon' />}
+                        <IconClose size="small" className='item-icon-delete' onClick={() => {
+                            ref.current && ref.current.deleteUploadFile(item);
+                        }}/>
+                    </span>
+                    <span className='item-content'>{name}</span>
+                </div>
+                );
+            })}
+        </div>;
+    }, []);
+    
+    return (
+        <AIChatInput
+            className='aiChatInput-customTopSlot'
+            renderTopSlot={renderTopSlot}
+            references={reference}
+            showUploadFile={false}
+            showReference={false}
+            renderConfigureArea={renderLeftMenu} 
+            ref={ref}
+            uploadProps={uploadProps}
+            style={outerStyle}
+            placeholder="Customize the rendering of top content"
+        />
+    );
+}
+
+render(<RenderTopSlot />);
+```
+
+### Custom Extensions
+
+Rich text areas support custom extensions. For implementation details, see [Tiptap Custom Extensions](https://tiptap.dev/docs/editor/extensions/custom-extensions/create-new). Custom extensions can be added to the AIChatInput component using the `extensions` API. If you add a custom extension, you must configure the corresponding transformation rules in `transformer` to ensure that the data returned in `onContentChange` matches your expectations.
+
+```jsx live=true dir="column" noInline=true
+import React from 'react';
+import { Node, mergeAttributes } from '@tiptap/core';
+import { ReactNodeViewRenderer, NodeViewWrapper, posToDOMRect, ReactRenderer } from '@tiptap/react';
+import { computePosition, flip, shift } from '@floating-ui/dom';
+import { IconFile, IconFolder, IconBranch, IconCode, IconGit, IconGlobeStroke, IconChevronRight, IconClose, IconUpload, IconTerminal, IconConnectionPoint2 } from '@douyinfe/semi-icons';
+import { AIChatInput } from '@douyinfe/semi-ui';
+import Mention from '@tiptap/extension-mention';
+
+const uploadProps = { action: "https://api.semi.design/upload" };
+const outerStyle = { margin: 12 };
+
+// Panel options
+const TestAction = {
+    'Files & Folders': [
+        {
+            icon: <IconFile />,
+            key: '1-1',
+            type: 'file',
+            name: 'TagInput.scss',
+            path: 'package/semi-founctaion/TagInput.scss',
+        },
+        {
+            icon: <IconFolder />,
+            key: '1-2',
+            type: 'folder',
+            name: 'package',
+            path: '/package',
+        },
+        {
+            icon: <IconFolder />,
+            key: '1-3',
+            type: 'folder',
+            name: 'semi-ui',
+            path: '/package/semi-ui',
+        },
+    ],
+    Git: [
+        {
+            icon: <IconBranch />,
+            key: '2-1',
+            type: 'branch',
+            name: 'fix/tag',
+        },
+        {
+            icon: <IconCode />,
+            key: '2-2',
+            type: 'code',
+            name: 'v2.86.0',
+            path: '/package',
+        },
+        {
+            icon: <IconGit />,
+            key: '2-3',
+            type: 'git',
+            name: 'chore: publish',
+        },
+    ],
+};
+
+// First level content
+const FirstLevel = Object.keys(TestAction);
+
+// referSlot rendering component
+function ReferSlotComponent(props) {
+    const { node, deleteNode } = props;
+    const value = node.attrs.value ? node.attrs.value : '';
+    const onRemove = (e) => {
+        e.preventDefault();
+        e.stopPropagation();
+        deleteNode && deleteNode();
+    };
+    return (
+        <NodeViewWrapper className="ai-chat-input-refer-slot-wrapper">
+            <span className='ai-chat-input-refer-slot'>
+                {value}
+            </span>
+        </NodeViewWrapper>
+    );
+}
+
+// Creating a ReferSlot Extension
+const ReferSlot = Node.create({
+    name: 'referSlot',
+    inline: true,
+    group: 'inline',
+    atom: true,
+    selectable: false,
+    addAttributes() {
+        return {
+            value: {
+                default: 'Enter content',
+                parseHTML: (element) =>
+                    element.getAttribute('data-value'),
+                renderHTML: (attributes) => ({
+                    'data-value': attributes.value,
+                }),
+            },
+            info: {
+                default: '',
+                parseHTML: (element) =>
+                    element.getAttribute('data-info'),
+                renderHTML: (attributes) => ({
+                    'data-info': attributes.info,
+                }),
+            },
+            type: {
+                default: 'text',
+                parseHTML: (element) =>
+                    element.getAttribute('data-type'),
+                renderHTML: (attributes) => ({
+                    'data-type': attributes.type,
+                }),
+            },
+            uniqueKey: {
+                default: '',
+                parseHTML: (element) =>
+                    element.getAttribute('data-unique-key'),
+                renderHTML: (attributes) => ({
+                    'data-unique-key': attributes.uniqueKey,
+                }),
+            },
+            // !!! Very important, affects the cursor size before and after custom nodes
+            // Please be sure to add this logic to custom nodes
+            isCustomSlot: AIChatInput.getCustomSlotAttribute(),
+        };
+    },
+    parseHTML() {
+        return [{
+            tag: 'refer-slot',
+        }];
+    },
+    renderHTML({ HTMLAttributes }) {
+        // Output custom tags when serializing and keep the value in data-value
+        return ['refer-slot', mergeAttributes(HTMLAttributes)];
+    },
+    addNodeView() {
+        return ReactNodeViewRenderer(ReferSlotComponent);
+    },
+});
+
+// Update position function
+const updatePosition = (editor, element) => {
+    const virtualElement = {
+        getBoundingClientRect: () => posToDOMRect(
+            editor.view,
+            editor.state.selection.from,
+            editor.state.selection.to,
+        ),
+    };
+    computePosition(virtualElement, element, {
+        placement: 'bottom-start',
+        strategy: 'absolute',
+        middleware: [shift()],
+    }).then(({ x, y, strategy }) => {
+        element.style.width = 'max-content';
+        element.style.position = strategy;
+        element.style.left = `${x}px`;
+        element.style.top = `${y}px`;
+    });
+};
+
+const suggestion = {
+    items: () => FirstLevel,
+    command: ({ editor, range, props }) => {
+        const { item } = props;
+        editor.chain().focus().insertContentAt(range, {
+            type: 'referSlot',
+            attrs: {
+                type: item.type,
+                value: item.name || '',
+                info: JSON.stringify({ path: item.path }),
+                uniqueKey: item.key,
+            },
+        }).run();
+    },
+    render: () => {
+        let component;
+        return {
+            onStart: (props) => {
+                component = new ReactRenderer(MentionList, {
+                    props,
+                    editor: props.editor,
+                });
+                if (!props.clientRect) return;
+                component.element.style.position = 'absolute';
+                document.body.appendChild(component.element);
+                updatePosition(props.editor, component.element);
+            },
+            onUpdate(props) {
+                component.updateProps(props);
+                if (!props.clientRect) return;
+                updatePosition(props.editor, component.element);
+            },
+            onKeyDown(props) {
+                function onExit() {
+                    component.destroy();
+                }
+                return component.ref.onKeyDown({ ...props, exitCb: onExit });
+            },
+            onExit() {
+                component.element.remove();
+                component.destroy();
+            },
+            focusEditor(props) {
+                props.editor.commands.focus();
+            },
+        };
+    },
+};
+
+const customReferences = [
+    {
+        type: 'file',
+        key: '1',
+        name: 'horizontalScroller.tsx',
+        path: 'packages/semi-ui/AIChatInput/horizontalScroller.tsx',
+    },
+    {
+        type: 'folder',
+        key: '2',
+        name: 'AIChatInput',
+        path: 'packages/semi-ui/AIChatInput',
+    },
+    {
+        type: 'web',
+        key: '3',
+        name: 'web'
+    },
+    {
+        type: 'change',
+        key: '4',
+        name: 'recentChange'
+    },
+    {
+        type: 'branch',
+        key: '5',
+        name: 'Branch',
+        detail: 'Diff with Main Branch',
+        branch: 'feat/aichatinput',
+        targetBranch: 'feat/targetBranch',
+    },
+    {
+        type: 'terminal',
+        key: '6',
+        name: 'From 1-2',
+        from: 1,
+        to: 2,
+    }
+];
+
+// Rendering Panel for mention list
+class MentionList extends React.Component {
+    constructor(props) {
+        super(props);
+        this.state = {
+            selectedIndex: 0,
+            level: 1,
+            options: FirstLevel,
+            filterOptions: FirstLevel,
+        };
+        this.upHandler = this.upHandler.bind(this);
+        this.downHandler = this.downHandler.bind(this);
+        this.enterHandler = this.enterHandler.bind(this);
+        this.selectItem = this.selectItem.bind(this);
+        this.onKeyDown = this.onKeyDown.bind(this);
+        this.renderItem = this.renderItem.bind(this);
+    }
+    upHandler() {
+        const { selectedIndex, filterOptions } = this.state;
+        this.setState({
+            selectedIndex: (selectedIndex + filterOptions.length - 1) % filterOptions.length,
+        });
+    };
+    downHandler() {
+        const { selectedIndex, filterOptions } = this.state;
+        this.setState({
+            selectedIndex: (selectedIndex + 1) % filterOptions.length,
+        });
+    };
+    enterHandler () {
+        const { selectedIndex, level } = this.state;
+        if (level === 1) {
+            this.setState({
+                level: 2,
+                options: TestAction[FirstLevel[selectedIndex]],
+                selectedIndex: 0,
+            });
+        } else {
+            this.selectItem(selectedIndex);
+        }
+    };
+    selectItem(id) {
+        const { options } = this.state;
+        const item = options[id];
+        if (item) {
+            this.props.command({ item });
+        }
+    };
+    componentDidUpdate(prevProps, prevState) {
+        if (prevProps.items !== this.props.items) {
+            this.setState({ selectedIndex: 0 });
+        }
+        if ( prevState.options !== this.state.options ||
+        prevProps.query !== this.props.query
+        ) {
+            // Manual filter
+            let filter = [];
+            if (this.props.query && this.props.query.length) {
+                filter = (this.state.options ? this.state.options : []).filter((item) => {
+                    let name;
+                    if (typeof item === 'string') {
+                        name = item;
+                    } else {
+                        name = item.name;
+                    }
+                    return name.toLowerCase().includes(this.props.query.toLowerCase());
+                });
+            } else {
+                filter = this.state.options ? this.state.options : [];
+            }
+            this.setState({ 
+                filterOptions: filter,
+                selectedIndex: 0
+            });
+        }
+    }
+    componentDidMount() {
+        if (this.props.innerRef) {
+            this.props.innerRef.current = {
+                onKeyDown: this.onKeyDown,
+            };
+        }
+    }
+    onKeyDown({ event, exitCb }) {
+        if (event.key === 'ArrowUp') {
+            this.upHandler();
+            return true;
+        }
+        if (event.key === 'ArrowDown') {
+            this.downHandler();
+            return true;
+        }
+        if (event.key === 'Enter') {
+            this.enterHandler();
+            return true;
+        }
+        if (event.key === 'Escape') {
+            if (this.state.level === 1) {
+                exitCb && exitCb();
+                return true;
+            } else if (this.state.level === 2) {
+                this.setState({ level: 1, options: FirstLevel });
+                return true;
+            }
+        }
+        return false;
+    };
+
+    renderItem(item) {
+        return (
+            <div className="level2Item">
+                {item.icon}
+                <span className="name">{item.name}</span>
+                <span className="path">{item.path}</span>
+            </div>
+        );
+    };
+    render() {
+        const { level, filterOptions, selectedIndex } = this.state;
+        return (
+            <div className="ai-chat-input-custom-extension-dropdown-menu" style={{ width: level === 1 ? 200 : 300 }}>
+                {filterOptions.length ? (filterOptions.map(
+                    (item, index ) => (
+                        // eslint-disable-next-line jsx-a11y/click-events-have-key-events
+                        <div
+                            key={index}
+                            className={ index === selectedIndex ? 'is-selected optionItem' : 'optionItem '}
+                            onClick={() => {
+                                if (level === 1) {
+                                    if (typeof item === 'string') {
+                                        this.setState({ level: 2, options: TestAction[item] });
+                                        this.props.editor.commands.focus();
+                                    }
+                                } else {
+                                    if (typeof item !== 'string') {
+                                        this.selectItem(index);
+                                    }
+                                }
+                            }}
+                            onMouseEnter={() => {
+                                this.setState({ selectedIndex: index });
+                            }}
+                        >
+                            {typeof item === 'string' ? <span>{item}</span> : this.renderItem(item)}
+                            {level === 1 && <IconChevronRight className='option-item-arrow'/>}
+                        </div>
+                    ),
+                )) : <div className="item">No result</div>}
+            </div>
+        );
+    }
+}
+
+function getAttachmentType(item = {}) {
+    const { type, name = '', fileInstance = {} } = item;
+    if (type) {
+        return type;
+    }
+    const suffix = name.split('.').pop();
+    if (suffix) {
+        return suffix;
+    } else if (fileInstance.type && fileInstance.type) {
+        const temp = fileInstance.type.split('/').pop();
+        if (temp) {
+            return temp;
+        }
+    }
+    return 'UNKNOWN';
+}
+
+function isImageType(item = {}) {
+    const PIC_PREFIX = 'image/';
+    const PIC_SUFFIX_ARRAY = ['png', 'jpg', 'jpeg', 'gif', 'bmp', 'webp'];
+    const { name = '', fileInstance = {} } = item;
+    const suffix = name.split('.').pop();
+    let result = false;
+    const { type = '' } = fileInstance;
+    if (type.startsWith(PIC_PREFIX)) {
+        result = true;
+    } else if (PIC_SUFFIX_ARRAY.includes(suffix)) {
+        result = true;
+    }
+    return result;
+}
+
+const refTypeToIconMap = new Map([
+    ['file', <IconFile key={'file'} size="small" />],
+    ['folder', <IconFolder key={'folder'} size="small" />],
+    ['branch', <IconBranch key={'branch'} size="small" />],
+    ['terminal', <IconTerminal key={'terminal'} size="small" /> ],
+    ['web', <IconGlobeStroke key={'globalStroke'} size="small" />],
+    ['change', <IconConnectionPoint2 key={'connectionPoint2'} size="small" />],
+    ['git', <IconGit key="git" size="small" />],
+    ['code', <IconCode key="code" size="small" />],
+]);
+
+function CustomRichTextExtension() {
+    const ref = useRef();
+    const [reference, setReference] = useState(customReferences);
+    const extensions = useMemo(() => {
+        // Use @ to trigger
+        return [
+            ReferSlot,
+            Mention.configure({
+                HTMLAttributes: {
+                    class: 'mention',
+                },
+                suggestion,
+            }),
+        ];
+    }, []);
+    const renderTopSlot = useCallback((props) => {
+        const { attachments = [], references = [], content = [] } = props;
+        const showContent = content.filter((item) => item.type !== 'text');
+        return <div className="ai-chat-input-topSlot">
+            {/* Order: reference, rich text area content, attachments */}
+            {showContent.map((item, index) => {
+                const { type, value, name, key, detail, ...rest } = item;
+                return (
+                    <div className="item" key={key ? key : index}>
+                        <span className='item-icon'>
+                            {React.cloneElement(refTypeToIconMap.get(type), { className: 'item-left item-icon' })}
+                            <IconClose size="small" className='item-icon-delete' onClick={() => {
+                                if (ref.current && ref.current.deleteContent) {
+                                    ref.current.deleteContent(item);
+                                }
+                            }}/>
+                        </span>
+                        <span className='item-content'>
+                            {name ? name : value}
+                            {type === 'branch' && <span className='detail'>{detail}</span>}
+                        </span>
+                    </div>
+                );
+            })}
+            {references.map((item, index) => {
+                const { type, name, detail, key, ...rest } = item;
+                return (
+                    <div className="item" key={key}>
+                        <span className='item-icon'>
+                            {React.cloneElement(refTypeToIconMap.get(type), { className: 'item-left item-icon' })}
+                            <IconClose size="small" className='item-icon-delete' onClick={() => {
+                                const newReferences = [...references];
+                                newReferences.splice(index, 1);
+                                setReference(newReferences);
+                            }}/>
+                        </span>
+                        <span className='item-content'>
+                            {name}
+                            {type === 'branch' && <span className='detail'>{detail}</span>}
+                        </span>
+                    </div>
+                );
+            })}
+            {attachments.map((item, index) => {
+                const isImage = isImageType(item);
+                const realType = getAttachmentType(item);
+                const { uid, name, url, size, percent, status } = item;
+                return (
+                    <div className="item" key={uid}>
+                        <span className='item-icon'>
+                            {isImage ? <img className='item-image item-left' src={item.url} alt={item.name} /> : <IconUpload size="small" className='item-left item-icon' />}
+                            <IconClose size="small" className='item-icon-delete' onClick={() => {
+                                if (ref.current && ref.current.deleteUploadFile) {
+                                    ref.current.deleteUploadFile(item);
+                                }
+                            }}/>
+                        </span>
+                        <span className='item-content'>{name}</span>
+                    </div>
+                );
+            })}
+        </div>;
+    }, []);
+    const onContentChange = useCallback((content) => {
+        console.log('onContentChange', content);
+    }, []);
+    const transformer = useMemo(() => {
+        return new Map([
+            ['referSlot', (obj) => {
+                const { attrs = {} } = obj;
+                const { value, info, type = 'text', uniqueKey } = attrs;
+                return {
+                    type: type, 
+                    value: value,
+                    uniqueKey: uniqueKey,
+                    ...JSON.parse(info),
+                };
+            }],
+        ]);
+    }, []);
+    return (
+        <>
+            <AIChatInput
+                className='aiChatInput-customTopSlot'
+                renderTopSlot={renderTopSlot}
+                extensions={extensions}
+                references={reference}
+                showUploadFile={false}
+                showReference={false}
+                onContentChange={onContentChange}
+                ref={ref}
+                transformer={transformer}
+                uploadProps={uploadProps}
+                style={outerStyle}
+                placeholder="Use @ to trigger"
+            />
+        </>
+    );
+};
+
+render(<CustomRichTextExtension />);
+```
+
+## API Reference
+
+### AIChatInput
+
+| Prop | Description | Type | Default |
+|------|-------------|------|---------|
+| canSend | Whether sending is allowed. If not set, sending depends on input, uploads, and references | boolean | true |
+| className | Custom class name | string | - |
+| defaultContent | Default input content, supports html string or Tiptap content | TiptapContent | - |
+| dropdownMatchTriggerWidth | Should dropdown width match input? | boolean | true |
+| extensions | Custom editor extensions | Extension[] | - |
+| generating | Is it generating? | boolean | false |
+| onContentChange | Callback when input content changes | (content: <ApiType detail='{ type: string; [key: string]: any }'>OnContentChangeProps</ApiType>) => void | - |
+| onMessageSend | Callback for sending message | (content: <ApiType detail='{references?: Reference[]; attachments?: Attachment[]; inputContents?: Content[]; setup?: Setup}'>OnMessageSendProps</ApiType>) => void | - |
+| onReferenceClick | Callback for clicking a reference | (reference: Reference) => void | - |
+| onReferenceDelete | Callback for deleting a reference | (reference: Reference) => void | - |
+| onSkillChange | Callback for switching skills | (skill: Skill) => void | - |
+| onStopGenerate | Callback for stop generate | () => void | - |
+| onSuggestClick | Callback for clicking a suggestion | (suggestion: Suggestion) => void | - |
+| onTemplateVisibleChange | Callback for template's visibility change | (visible: boolean) => void | - |
+| onUploadChange | Callback for file upload | (props: OnChangeProps) => void | - |
+| popoverProps | Popup configuration | PopoverProps | - |
+| placeholder | Input placeholder | string | - |
+| references | Reference list | Reference[] | - |
+| renderActionArea | Custom bottom-right operation area | () => React.ReactNode | - |
+| renderConfigureArea | Custom configuration area | () => React.ReactNode | - |
+| renderReference | Custom render reference | (reference: Reference) => ReactNode | - |
+| renderSkillItem | Custom skill list item renderer | (props: <ApiType detail='{skill: Skill; onClick: () => void; className: string, onMouseEnter: () => void}'>RenderSkillItemProps</ApiType>) => React.ReactNode | - |
+| renderSuggestionItem | Custom suggestion item renderer | (props: <ApiType detail='{ suggestion: Suggestion; onClick: () => void; className: string, onMouseEnter: () => void}'>RenderSkillItemProps</ApiType>) => React.ReactNode | - |
+| renderTemplate | Custom template renderer | (skill: Skill, onTemplateClick: (content: string) => void) => React.ReactNode | - |
+| renderTopSlot | Custom top slot renderer | () => React.ReactNode | - |
+| round | Whether config/action areas have rounded style | boolean | true |
+| onBlur | Callback when input blurs | (event: React.FocusEvent) => void | - |
+| onConfigureChange | Callback for configuration area changes | (value: LeftMenuChangeProps, changedValue: LeftMenuChangeProps) => void | - |
+| onFocus | Callback when input focused | (event: React.FocusEvent) => void | - |
+| showReference | Show reference area | boolean | true |
+| showTemplateButton | Show template button | boolean | false |
+| showUploadFile | Show upload file area | boolean | true |
+| skillHotKey | Skill panel trigger shortcut | string | - |
+| skills | Skill list | Skill[] | - |
+| style | Custom style | React.CSSProperties | - |
+| suggestions | Suggestions list | Suggestion[] | - |
+| templatesCls| The template's style class name| string | - |
+| templatesStyle| Template style| React.CSSProperties | - |
+| topSlotPosition | Top slot position: relative to reference and uploads | 'top' \| 'bottom' \| 'middle' | - |
+| transformer | Customizing the conversion rules for extensions | Map<string, (obj: any) => any> | |
+| uploadProps | Upload configuration | UploadProps | - |
+| uploadTipProps | Upload tip configuration | UploadTipProps | - |
+
+## Methods
+
+| Method | Description | Type | Default |
+|--------|-------------|------|---------|
+| changeTemplateVisible | Toggle visibility of the template popup | (visible: boolean) => void | - |
+| deleteContent | Delete an item in the rich text. The deletion logic depends on the uniqueKey in the content. | (content: Content) => void | - |
+| deleteUploadFile | Delete an item in the uploaded file | (item: Attachment) => void | - |
+| focusEditor | Focus the input box. By default, the focus is on the end of the input box. | (pos?: string) => void | - |
+| getEditor | Get the current tiptap editor instance | () => Editor | - |
+| setContent | Set input box content | (content: TiptapContent) => void | - |
+| setContentWhileSaveTool | Set the input box content while retaining the skill item | (content: TiptapContent) => void | - |
+
+## Design Tokens
+
+<DesignToken/>

+ 1598 - 0
content/ai/aiChatInput/index.md

@@ -0,0 +1,1598 @@
+---
+localeCode: zh-CN
+order: 99
+category: Ai
+title: AIChatInput 聊天输入框
+icon: doc-aiInput
+width: 60%
+brief: 用于 AI 聊天场景下的输入框
+showNew: true
+---
+
+## 使用场景
+
+在 AI 聊天场景下,用户可通过 `AIChatInput`实现富文本输入、上传、引用、建议、模版、功能配置、及丰富自定义展示等需求。
+
+`AIChatInput` 的富文本输入是基于 [tiptap](https://tiptap.dev/docs/editor/getting-started/overview) 实现,`tiptap` 是一款现代的富文本编辑器开发框架,支持 React、Vue 前端框架,具备极强的可定制性和扩展性。其组件化能力优秀,性能优良,内置多种常用拓展,并支持用户自定义节点、命令、插件与菜单,使复杂 AI 场景下的富文本输入能力能够灵活适配和扩展。Semi 的 `AIChatInput` 组件对 tiptap 进行了封装,开发者可开箱即用或按需按业务扩展。
+
+## 代码演示
+
+### 如何引入
+
+```jsx import
+import { AIChatInput } from '@douyinfe/semi-ui';
+```
+
+### 基本用法
+
+支持文本输入以及文件上传,使用时可按需配置以下参数:
+
+- `uploadProps` 配置文件上传相关的参数,详见 [UploadProps](/zh-CN/plus/upload#API)
+- `onUploadChange` 获取文件上传变化
+- `placeholder` 输入框的占位符
+- `defaultContent` 输入框的默认内容
+- `onContentChange` 输入框内容变化时的回调函数,参数为当前输入框的内容
+
+```jsx live=true dir="column" noInline=true
+import React from 'react';
+import { AIChatInput } from '@douyinfe/semi-ui';
+
+const uploadProps = { action: "https://api.semi.design/upload" };
+const outerStyle = { margin: 12 };
+
+function Basic() {
+    const onContentChange = useCallback((content) => {
+        console.log('onContentChange', content);
+    }, []);
+
+    const onUploadChange = useCallback((fileList) => {
+        console.log('onUploadChange', fileList);
+    }, []);
+  
+    return (
+        <AIChatInput
+            placeholder={'输入内容或者上传内容...'} 
+            uploadProps={uploadProps}
+            onContentChange={onContentChange}
+            onUploadChange={onUploadChange}
+            style={outerStyle} 
+        />
+    );
+};
+
+render(<Basic />);
+```
+
+### 消息发送
+
+当输入框中有内容(包括输入文本,上传内容,[引用内容](/zh-CN/plus/aiChatInput#%E5%BC%95%E7%94%A8)),将允许发送消息。点击消息发送按钮,会触发 `onMessageSend` 回调函数,参数为当前输入框的内容,包括输入区域的文本,引用内容,上传文件,配置区域内容。
+
+用户可在 `onMessageSend` 中根据判断是否设置 `generating` 表示消息正在处理中,如果 `generating` 为 `true`,则 AIChatInput 会在发送按钮位置显示停止生成按钮,并清空输入区的消息,以及上传文件,另外,引用内容需要用户自行清除。
+
+点击停止生成按钮,会触发 `onStopGenerate` 回调函数,用户可在该回调函数中处理停止生成的逻辑, 如将 `generating` 设为 `false`。
+
+```jsx live=true dir="column" noInline=true
+import React from 'react';
+import { AIChatInput } from '@douyinfe/semi-ui';
+
+const uploadProps = { 
+    action: "https://api.semi.design/upload",
+    defaultFileList: [{
+        uid: '1',
+        name: 'dy.jpeg',
+        status: 'success',
+        size: '130kb',
+        url:
+            'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/dy.png',
+    },
+    {
+        uid: '5',
+        name: 'resso.jpeg',
+        percent: 50,
+        size: '222kb',
+        url:
+            'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/Resso.png',
+    }],
+};
+const outerStyle = { margin: 12 };
+
+const reference = [
+    {
+        id: '1',
+        type: 'text',
+        content: '测试文本,这里是一段很长的文字,这里是一段很长的文字,这里是一段很长的文字,这里是一段很长的文字,这里是一段很长的文字,这里是一段很长的文字,这里是一段很长的文字,这里是一段很长的文字,这里是一段很长的文字,这里是一段很长的文字',
+    }
+];
+
+function SendMessageAndStopGenerate() {
+    const [references, setReferences] = useState(reference);
+    const [generating, setGenerating] = useState(false);
+    const onContentChange = useCallback((content) => {
+        console.log('onContentChange', content);
+    }, []);
+
+    const onUploadChange = useCallback((fileList) => {
+        console.log('onUploadChange', fileList);
+    }, []);
+
+    const toggleGenerate = useCallback((props) => {
+        setGenerating(value => !value);
+    }, []);
+
+    const onMessageSend = useCallback((content) => {
+        toggleGenerate();
+        setReferences([]);
+    }, []);
+
+     
+    const handleReferenceDelete = useCallback((item) => {
+        setReferences((references) => {
+            const newReference = references.filter((ref) => ref.id !== item.id);
+            return newReference;
+        });
+    }, []);
+    
+    return (
+        <AIChatInput
+            defaultContent={"点击发送按钮,观察上传内容、引用内容、输入框内容变化"}
+            generating={generating}
+            uploadProps={uploadProps}
+            onContentChange={onContentChange}
+            onUploadChange={onUploadChange}
+            style={outerStyle}
+            onMessageSend={onMessageSend}
+            onStopGenerate={toggleGenerate}
+            onReferenceDelete={handleReferenceDelete}
+            references={references}
+        />
+    );
+};
+
+render(<SendMessageAndStopGenerate />);
+```
+
+### 富文本输入区
+
+AIChatInput 使用 [tiptap](https://tiptap.dev/docs/editor/getting-started/overview) 作为富文本输入框的编辑器,用户可以在输入框中输入文本,使用 AIChatInput 内置的 extensions(包括 `input-slot`,`select-slot`,`skill-slot`)。用户也可以自定义 extensions 来扩展编辑器的功能。
+
+- `input-slot` 支持用户输入文本,并支持 placeholder 占位符。
+- `select-slot` 支持用户进行简单的选择,选项仅支持 string 类型。
+- `skill-slot` 是用于技能展示的块,方便用户理解当前输入框中的技能。
+
+可以通过 ref 方法 `setContent` 来设置输入框的内容,使用 `focusEditor` 方法可以将输入框的焦点设置到编辑器中。
+
+```jsx live=true dir="column" noInline=true
+import React, { useRef, useCallback } from 'react';
+import { AIChatInput } from '@douyinfe/semi-ui';
+
+const uploadProps = { action: "https://api.semi.design/upload" };
+const outerStyle = { margin: 12 };
+const temp = {
+    'input-slot': '我是一个<input-slot placeholder="[职业]">程序员</input-slot>',
+    'select-slot': `我是<select-slot value="前端开发" options='["设计","前端开发","后端开发"]'></select-slot>,帮我完成...`,
+    'skill-slot': `<skill-slot data-label="AI Coding" data-value="AI Coding" data-template=false></skill-slot> 帮我完成...`,
+};
+
+function RichTextExample() {
+    const [activeIndex, setActiveIndex] = useState(0);
+    const ref = useRef();
+
+    const setTemplate = useCallback((event) => {
+        const index = Number(event.target.dataset.index);
+        setActiveIndex(index);
+        const content = Object.values(temp)[index];
+        if (ref.current) {
+            ref.current.setContent(content);
+            ref.current.focusEditor();
+        }
+    }, [ref]);
+
+    return (<>
+        <div className="aiChatInput-radio">
+            {Object.keys(temp).map((item, index) => {
+                return <div 
+                    className={`aiChatInput-radio-item ${index === activeIndex ? 'aiChatInput-radio-item-selected' : ''}` }
+                    key={index} 
+                    data-index={index} 
+                    onClick={setTemplate}
+                >{item}</div>;
+            })}
+        </div>
+        <AIChatInput
+            ref={ref}
+            defaultContent={temp['input-slot']}
+            placeholder={'输入内容或者上传内容'} 
+            uploadProps={uploadProps}
+            style={outerStyle} 
+        />
+    </>);
+};
+
+render(<RichTextExample />);
+```
+
+### 引用
+
+用户可以 `references` 传入引用内容,引用内容会展示在输入框的顶部。
+
+- `renderReference` 自定义单个引用内容的渲染。
+- `onReferenceDelete` 处理引用内容的删除。
+- `onReferenceClick` 处理引用内容的点击。
+
+```jsx live=true dir="column" noInline=true
+import React from 'react';
+import { AIChatInput } from '@douyinfe/semi-ui';
+
+const uploadProps = { action: "https://api.semi.design/upload" };
+const outerStyle = { margin: 12 };
+const referenceTemp = [
+    {
+        id: '1',
+        type: 'text',
+        content: '测试文本,这里是一段很长的文字,这里是一段很长的文字,这里是一段很长的文字,这里是一段很长的文字,这里是一段很长的文字,这里是一段很长的文字,这里是一段很长的文字,这里是一段很长的文字,这里是一段很长的文字,这里是一段很长的文字',
+    },
+    {
+        id: '2',
+        name: '飞书文档.docx',
+    },
+    {
+        id: '3',
+        name: '飞书文档.pdf',
+    },
+    {
+        id: '4',
+        name: 'Music.mp4',
+    },
+    {
+        id: '5',
+        name: 'Image.jpeg',
+        url: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/Resso.png'
+    },
+    {
+        id: '6',
+        name: 'code.json',
+    }
+];
+
+function Reference() {
+    const [references, setReferences] = useState(referenceTemp);
+    const handleReferenceDelete = useCallback((item) => {
+        const newReference = references.filter((ref) => ref.id !== item.id);
+        setReferences(newReference);
+    }, [references]);
+
+    const handleReferenceClick = useCallback((item) => {
+        console.log('点击了引用', item);
+    }, []);
+    
+    return (
+        <AIChatInput
+            placeholder={'用于查看引用内容的用例'} 
+            onReferenceDelete={handleReferenceDelete}
+            onReferenceClick={handleReferenceClick}
+            references={references} 
+            uploadProps={uploadProps}
+            style={outerStyle}
+        />
+    );
+};
+
+render(<Reference />);
+```
+
+### 配置区域
+
+用户可以通过配置区域设置使用模型参数、联网搜索、深度思考等配置项,展示或者查看 MCP 工具。
+
+可通过 `renderConfigureArea` API 自定义输入框的操作按钮。
+
+使用 `Configure` 中的 `Select`、`Button`、`Mcp`、`RadioButton` 等组件可以自定义配置项。
+
+`Configure` 将管理配置项的状态,用户可以通过 `onConfigureChange` API 监听配置项的变化。一定要配置 `field` 属性,用于标识配置项的唯一标识。如需设置初始值,可通过 `initValue` 属性设置。
+
+如果用户有其他形式的配置需求,可以通过 `getConfigureItem` 将自定义组件扩展成 `Configure` 类型组件。
+
+```jsx live=true dir="column" noInline=true
+import React from 'react';
+import { AIChatInput } from '@douyinfe/semi-ui';
+import { IconFixedStroked, IconBookOpenStroked, IconFeishuLogo, IconGit, IconFigma } from '@douyinfe/semi-icons';
+
+const { Configure } = AIChatInput;
+const uploadProps = { action: "https://api.semi.design/upload" };
+const outerStyle = { margin: 12 };
+
+const modelOptions = [
+    { value: 'GPT-5', label: 'GPT-5' },
+    { value: 'GPT-4o', label: 'GPT-4o' },
+    { value: 'Claude 3.5 Sonnet', label: 'Claude 3.5 Sonnet' },
+];
+
+const mcpOptions = [
+    { icon: <IconFeishuLogo />, label: "飞书文档", value: "feishu" },
+    { icon: <IconGit />, label: "Github Mcp", value: "github" },
+    { icon: <IconFigma />, label: "IconFigma Mcp", value: "IconFigma" }
+];
+
+const radioButtonProps = [
+    { label: '极速', value: 'fast' },
+    { label: '思考', value: 'think' },
+    { label: '超能', value: 'super' }
+];
+
+
+function ConfigureButton() {
+    const onConfigureButtonClick = useCallback(() => {
+        console.log('onConfigureButtonClick');
+    }, []);
+
+    const renderLeftMenu = useCallback(() => (<>
+        <Configure.Select optionList={modelOptions} field="model" initValue="GPT-4o" />
+        <Configure.Button icon={<IconBookOpenStroked />} field="onlineSearch">联网搜索</Configure.Button>
+        <Configure.Mcp options={mcpOptions} onConfigureButtonClick={onConfigureButtonClick}/>
+        <Configure.RadioButton options={radioButtonProps} field="thinkType" initValue="fast"/>
+    </>), []);
+
+    const onConfigureChange = useCallback((value, changedValue) => {
+        console.log('onConfigureChange', value, changedValue);
+    }, []);
+    
+    return (
+        <AIChatInput
+            placeholder={'用于查看左下方配置项的用例'} 
+            renderConfigureArea={renderLeftMenu} 
+            onConfigureChange={onConfigureChange}
+            uploadProps={uploadProps}
+            style={outerStyle}
+        />
+    );
+};
+
+render(<ConfigureButton />);
+
+```
+
+使用 `getConfigureItem` 扩展自定义组件为 `Configure` 类型组件。
+
+```ts
+function getConfigureItem(
+    component: React.ReactElement,
+    opts: {
+        // 指定需要接管的组件的 value 对应的 key,默认是 value
+        valueKey?: string; 
+        // 指定需要接管的组件的值变化对应的函数名,默认是 onChange
+        onKeyChangeFnName?: string;
+        // 指定需要接管的组件的值变化函数参数中 value 对应的路径,默认是 ''
+        valuePath?: string;
+        className?: string;
+        defaultProps?: Record<string, any>
+    }
+)
+```
+
+使用示例如下:
+
+```jsx live=true dir="column" noInline=true
+import React, { useCallback } from 'react';
+import { Cascader, AIChatInput, getConfigureItem } from '@douyinfe/semi-ui';
+
+const uploadProps = { action: "https://api.semi.design/upload" };
+const outerStyle = { margin: 12 };
+const cascaderModalOptions = [
+    {
+        label: 'GPT',
+        value: 'GPT',
+        children: [
+            { label: 'GPT-4o', value: 'GPT-4o' },
+            { value: 'GPT-5', label: 'GPT-5' }
+        ],
+    },
+    {
+        label: 'Claude',
+        value: 'Claude',
+        children: [
+            { label: 'Claude 3.5 Sonnet', value: 'Claude 3.5 Sonnet' }
+        ],
+    }
+];
+
+const myCascader = (props) => {
+    return <Cascader {...props} />;
+};
+
+const CustomCascader = getConfigureItem(myCascader, { 
+    className: 'aiChatInput-cascader-configure'
+});
+
+class CustomConfigure extends React.Component {
+
+    constructor(props) {
+        super(props);
+        // Bind methods to the class instance
+        this.renderLeftMenu = this.renderLeftMenu.bind(this);
+        this.onConfigureChange = this.onConfigureChange.bind(this);
+    }
+
+    // Define methods without using arrow function syntax
+    renderLeftMenu() {
+        return <CustomCascader field="model" treeData={cascaderModalOptions} initValue={['GPT', 'GPT-4o']} />;
+    }
+
+    onConfigureChange(value, changedValue) {
+        console.log('onConfigureChange', value, changedValue);
+    }
+
+    render() {
+        return (<AIChatInput
+            placeholder={'用于查看左下方配置项的用例'} 
+            renderConfigureArea={this.renderLeftMenu} 
+            onConfigureChange={this.onConfigureChange}
+            uploadProps={uploadProps}
+            style={outerStyle}
+        />);
+    };
+}
+
+render(<CustomConfigure />);
+```
+
+### 操作区域
+
+输入框右下角为操作区域,用户可以通过 `renderActionArea` API 自定义操作区域,展示自定义的操作按钮。
+
+```ts
+interface ActionAreaProps {
+    menuItem: ReactNode[];
+    className: string
+}
+```
+
+使用示例如下:
+
+```jsx live=true dir="column" noInline=true
+import React from 'react';
+import { AIChatInput, Divider, Button } from '@douyinfe/semi-ui';
+import { IconDeleteStroked } from '@douyinfe/semi-icons';
+
+const uploadProps = { action: "https://api.semi.design/upload" };
+const outerStyle = { margin: 12 };
+
+function ActionArea() {
+    const renderActionArea = useCallback((props) => {
+        return (
+            <div className={props.className}>
+                <div style={{ display: 'flex', alignItems: 'center' }} key="delete">
+                    <Button type="tertiary" style={{ borderRadius: '50%' }} icon={<IconDeleteStroked />}/>
+                    <Divider layout="vertical" style={{ marginLeft: 8 }}/>
+                </div>
+                {props.menuItem}
+            </div>
+        );
+    }, []);
+  
+    return (
+        <AIChatInput
+            renderActionArea={renderActionArea}
+            placeholder={'输入内容或者上传内容...'} 
+            uploadProps={uploadProps}
+            style={outerStyle} 
+        />
+    );
+};
+
+render(<ActionArea />);
+```
+
+### 底部按钮形状
+
+用户可以通过 `round` API 配置底部按钮的形状,默认是 `true`,是圆角按钮, 可以设置为 `false` 来配置为方形按钮。
+
+```jsx live=true dir="column" noInline=true
+import React from 'react';
+import { AIChatInput, RadioGroup, Radio } from '@douyinfe/semi-ui';
+import { IconFixedStroked, IconBookOpenStroked, IconFeishuLogo, IconGit, IconFigma } from '@douyinfe/semi-icons';
+
+const { Configure } = AIChatInput;
+const uploadProps = { action: "https://api.semi.design/upload" };
+const outerStyle = { margin: 12 };
+const modelOptions = [
+    { value: 'GPT-5', label: 'GPT-5' },
+    { value: 'GPT-4o', label: 'GPT-4o' },
+    { value: 'Claude 3.5 Sonnet', label: 'Claude 3.5 Sonnet' },
+];
+
+const mcpOptions = [
+    { icon: <IconFeishuLogo />, label: "飞书文档", value: "feishu" },
+    { icon: <IconGit />, label: "Github Mcp", value: "github" },
+    { icon: <IconFigma />, label: "IconFigma Mcp", value: "IconFigma" }
+];
+
+const radioButtonProps = [
+    { label: '极速', value: 'fast' },
+    { label: '思考', value: 'think' },
+    { label: '超能', value: 'super' }
+];
+
+function Shape() {
+    const [round, setRound] = useState(false);
+    const renderLeftMenu = useCallback(() => <>
+        <Configure.Select optionList={modelOptions} field="model" initValue="GPT-4o" />
+        <Configure.Button icon={<IconBookOpenStroked />} field="onlineSearch">联网搜索</Configure.Button>
+        <Configure.Mcp options={mcpOptions} />
+        <Configure.RadioButton options={radioButtonProps} initValue="fast"/>
+    </>);
+
+    const onChange = useCallback((e) => {
+        setRound(e.target.value);
+    }, []);
+    
+    return (<>
+        <RadioGroup onChange={onChange} value={round} aria-label="单选组合示例" name="demo-radio-group">
+            <Radio value={true}>圆形</Radio>
+            <Radio value={false}>方形</Radio>
+        </RadioGroup>
+        <AIChatInput
+            placeholder={'下方按钮为方形的用例'} 
+            round={round}
+            renderConfigureArea={renderLeftMenu} 
+            uploadProps={uploadProps}
+            style={outerStyle}
+        />
+    </>);
+};
+
+render(<Shape />);
+```
+
+### 建议
+
+用户可通过 `suggestion` API 配置建议列表,功能类似于 AutoComplete 组件,用户可以根据输入的内容实现根据输入的内容动态展示建议列表。
+
+使用鼠标上下按键切换建议列表的选项。按下 `ESC` 或者点击非建议列表,输入框区域,建议列表将关闭。
+
+还可通过 `renderSuggestionItem` API 自定义建议列表的展示。
+
+```jsx live=true dir="column" noInline=true
+import React from 'react';
+import { AIChatInput } from '@douyinfe/semi-ui';
+
+const uploadProps = { action: "https://api.semi.design/upload" };
+const outerStyle = { margin: 12 };
+const suggestionTemplate = [ '天气如何', '空气质量', '工作进程', '日程安排'];
+
+
+function Suggestion() {
+    const [suggestion, setSuggestion] = useState([]);
+    const onChange = useCallback((content) => {
+        let value;
+        if (content.length && content[0].text) {
+            value = content[0].text;
+        }
+        if (value === undefined || value.includes('\n')) {
+            if (suggestion === undefined || suggestion.length === 0) {
+                return;
+            } else {
+                return setSuggestion([]);
+            }
+        }
+        if (value.length === 0) {
+            setSuggestion([]);
+        } else if (value.length > 0 && value.length < 4) {
+            const su = new Array(suggestionTemplate.length).fill(0).map((item, index) => {
+                return `${value},${suggestionTemplate[index]}`;
+            });
+            setSuggestion(su);
+        } else if (value.length >= 4) {
+            setSuggestion([]);
+        }
+    }, [suggestion]);
+  
+    return (
+        <AIChatInput
+            suggestions={suggestion} 
+            onContentChange={onChange}
+            uploadProps={uploadProps}
+            style={outerStyle}
+            placeholder={'输入内容,当内容长度小于 4个字符可以看到建议,使用上下按键可切换侯选项'} 
+        />
+    );
+}
+
+render(<Suggestion />);
+```
+
+### 技能及模版
+
+用户可以通过 `skills` API 配置技能列表,使用 `skillHotKey` 配置技能的触发键。
+
+`skills` 的格式如下
+
+```ts
+interface Skill {
+    label?: string;
+    value?: string;
+    icon?: React.ReactNode;
+    // 技能是否有模版,有模版的技能被选中后,将在输入框的底部展示模版按钮
+    hasTemplate?: boolean;
+}
+```
+
+由于模版的展示形式丰富,因此我们不提供默认的展示形式,用户可以通过 `renderTemplate`API 自定义模版的展示。模版面板的展示和关闭可通过点击模版按钮实现。
+
+```ts
+renderTemplate?: (
+    skill: Skill, 
+    // 模版点击回调,点击模版后,将模版的内容插入到输入框中
+    onTemplateClick: (content: string) => void
+) => ReactNode;
+```
+
+使用示例如下:
+
+```jsx live=true dir="column" noInline=true
+import React from 'react';
+import { AIChatInput } from '@douyinfe/semi-ui';
+import { IconTemplateStroked, IconSearch } from '@douyinfe/semi-icons';
+
+const { Configure } = AIChatInput;
+const modelOptions = [
+    { value: 'GPT-5', label: 'GPT-5' },
+    { value: 'GPT-4o', label: 'GPT-4o' },
+    { value: 'Claude 3.5 Sonnet', label: 'Claude 3.5 Sonnet' },
+];
+const uploadProps = { action: "https://api.semi.design/upload" };
+const outerStyle = { margin: 12 };
+const skills = [
+    {
+        icon: <IconTemplateStroked />,
+        value: 'writing',
+        label: '帮我写作',
+        hasTemplate: true,
+    },
+    {
+        icon: <IconSearch />,
+        value: 'AI 编程',
+        label: 'AI coding'
+    },
+];
+
+const template = [
+    {
+        groupKey: 'value',
+        group: '工作',
+        children: [
+            {
+                bg: 'var(--semi-color-primary)',
+                icon: <IconTemplateStroked />,
+                title: '总结汇报',
+                desc: '凝练你的工作成效',
+                content: `我的职业是<input-slot placeholder="[请输入职业]"></input-slot>,帮我写一份关于<input-slot placeholder="[输入目的:项目进展总结、团队工作成果或其他]</input-slot>的总结汇报`
+            },
+            {
+                bg: 'var(--semi-color-warning)',
+                icon: <IconTemplateStroked />,
+                title: '话术',
+                desc: '满足不同场景表达需求',
+                content: `我是一名<select-slot value="打工人" options='["打工人","学生"]'></select-slot> ,帮我写一段面向<input-slot placeholder="[输入对象]">陌生同事</input-slot>的话术内容`
+            }
+        ]
+    },
+    {
+        groupKey: 'marketing',
+        group: '商业营销',
+        children: [
+            {
+                bg: 'var(--semi-color-primary)',
+                icon: <IconTemplateStroked />,
+                title: '宣传文案',
+                desc: '撰写各平台的推广文案',
+                content: '帮我写一篇面向<input-slot placeholder="[输入目标人群]"></input-slot>职场人士,关于<input-slot placeholder="[输入产品]"></input-slot>的宣传文案,需要直击痛点,吸引用户点击。'
+            },
+            {
+                bg: 'var(--semi-color-warning)',
+                icon: <IconTemplateStroked />,
+                title: '方案策划',
+                desc: '量身定制各种方案',
+                content: '我是一名<input-slot placeholder="[输入职业]"></input-slot>职业策划人 ,帮我写一个<input-slot placeholder="[方案类型:如线下读书会活动方案等]"></input-slot>线下读书会活动 的方案,需要包含但不限于策划目标、详细计划、所需资源和预算、效果评估、风险应对等。'
+            }
+        ]
+    }
+];
+
+const TemplateContent = (props) => {
+    const { onTemplateClick: onTemplateClickProps } = props;
+    const [groupIndex, setGroupIndex] = useState(0);
+
+    const onItemClick = useCallback((e) => {
+        const index = e.target.dataset.index;
+        setGroupIndex(Number(index));
+    }, []);
+
+    const onTemplateClick = useCallback((item) => {
+        const { content } = item;
+        onTemplateClickProps(content);
+    }, [onTemplateClickProps]);
+
+    return (<div className={'aiChatInput-template'} >
+        {/* tabs */}
+        <div className={'template-header'} >
+            {(template ? template : []).map((item, index) => {
+                return (<div
+                    key={index}
+                    data-index={index}
+                    className={`template-header-item ${groupIndex === index ? 'template-header-item-active' : ''}`}
+                    onClick={onItemClick}
+                >
+                    {item.group}
+                </div>);
+            })}
+        </div>
+        {/* content */}
+        <div className='template-content'>
+            {(((template ? template : [])[groupIndex] ? (template ? template : [])[groupIndex] : {}).children ? (template ? template : [])[groupIndex].children : []).map((item, index) => (<div
+                key={index}
+                className='template-content-item'
+                onClick={() => onTemplateClick(item)}
+            >
+                <div className='template-content-item-icon' style={{ background: item.bg }}>{item.icon}</div>
+                <div className='template-content-item-title'>{item.title}</div>
+                <div className='template-content-item-desc'>{item.desc}</div>
+            </div>))}
+        </div>
+    </div>);
+};
+
+function Template() {
+    const ref = useRef();
+
+    const setTemplate = useCallback((content) => {
+        const element = ref.current;
+        if (!element) {
+            return;
+        }
+        element.setContentWhileSaveTool(content);
+        element.focusEditor();
+    }, [ref]);
+
+    const renderTemplate = useCallback((skill = {}, e) => {
+        if (skill.value === 'writing') {
+            return <TemplateContent onTemplateClick={setTemplate}/>;
+        }
+    }, [setTemplate]);
+
+    const renderLeftMenu = useCallback(() => <>
+        <Configure.Select optionList={modelOptions} field="model" initValue="GPT-4o" />
+    </>);
+
+    return (
+        <AIChatInput 
+            placeholder='输入 / 唤起技能,选择技能后,点击模版按钮可查看模版,可通过鼠标上下按键切换侯选项'
+            renderConfigureArea={renderLeftMenu} 
+            ref={ref}
+            uploadProps={uploadProps}
+            skills={skills}
+            skillHotKey='/'
+            renderTemplate={renderTemplate}
+            style={outerStyle}
+        />
+    );
+};
+
+render(<Template />);
+```
+
+### 自定义渲染顶部区域
+
+用户可以通过 `renderTopSlot` API 自定义渲染顶部区域,可自行渲染引用,上传内容以及配置项。可结合 `showReference` 和 `showUploadFile` API 控制是否展示引用和上传文件。另外,可通过 `topSlotPosition` API 配置自定义渲染内容相对于引用区域,上传展示区域的相对位置。
+
+```ts
+interface TopSlotProps {
+    // 引用
+    references: Reference[];
+    // 上传内容
+    attachments: Attachment[];
+    // 输入框消息
+    content: Content[];
+    handleUploadFileDelete: (attachment: Attachment) => void;
+    handleReferenceDelete: (reference: Reference) => void
+}
+```
+
+使用用例如下:
+
+```jsx live=true dir="column" noInline=true
+import React from 'react';
+import { AIChatInput } from '@douyinfe/semi-ui';
+import { IconClose, IconUpload, IconFile, IconFolder, IconBranch, IconTerminal, IconGlobeStroke, IconConnectionPoint2, IconTemplateStroked, IconSearch, IconGit, IconCode } from '@douyinfe/semi-icons';
+
+const { Configure } = AIChatInput;
+const radioButtonProps = [
+    { label: <IconTemplateStroked />, value: 'fast' },
+    { label: <IconSearch />, value: 'think' }
+];
+const uploadProps = { action: "https://api.semi.design/upload" };
+const outerStyle = { margin: 12 };
+
+const customReferences = [
+    {
+        type: 'file',
+        key: '1',
+        name: 'horizontalScroller.tsx',
+        path: 'packages/semi-ui/AIChatInput/horizontalScroller.tsx',
+    },
+    {
+        type: 'folder',
+        key: '2',
+        name: 'AIChatInput',
+        path: 'packages/semi-ui/AIChatInput',
+    },
+    {
+        type: 'web',
+        key: '3',
+        name: 'web'
+    },
+    {
+        type: 'change',
+        key: '4',
+        name: 'recentChange'
+    },
+    {
+        type: 'branch',
+        key: '5',
+        name: 'Branch',
+        detail: 'Diff with Main Branch',
+        branch: 'feat/aichatinput',
+        targetBranch: 'feat/targetBranch',
+    },
+    {
+        type: 'terminal',
+        key: '6',
+        name: 'From 1-2',
+        from: 1,
+        to: 2,
+    }
+];
+
+function getAttachmentType(item = {}) {
+    const { type, name = '', fileInstance = {} } = item;
+    if (type) {
+        return type;
+    }
+    const suffix = name.split('.').pop();
+    if (suffix) {
+        return suffix;
+    } else if (fileInstance.type && fileInstance.type) {
+        const temp = fileInstance.type.split('/').pop();
+        if (temp) {
+            return temp;
+        }
+    }
+    return 'UNKNOWN';
+}
+
+function isImageType(item = {}) {
+    const PIC_PREFIX = 'image/';
+    const PIC_SUFFIX_ARRAY = ['png', 'jpg', 'jpeg', 'gif', 'bmp', 'webp'];
+    const { name = '', fileInstance = {} } = item;
+    const suffix = name.split('.').pop();
+    let result = false;
+    const { type = '' } = fileInstance;
+    if (type.startsWith(PIC_PREFIX)) {
+        result = true;
+    } else if (PIC_SUFFIX_ARRAY.includes(suffix)) {
+        result = true;
+    }
+    return result;
+}
+
+const refTypeToIconMap = new Map([
+    ['file', <IconFile key={'file'} size="small" />],
+    ['folder', <IconFolder key={'folder'} size="small" />],
+    ['branch', <IconBranch key={'branch'} size="small" />],
+    ['terminal', <IconTerminal key={'terminal'} size="small" /> ],
+    ['web', <IconGlobeStroke key={'globalStroke'} size="small" />],
+    ['change', <IconConnectionPoint2 key={'connectionPoint2'} size="small" />],
+    ['git', <IconGit key="git" size="small" />],
+    ['code', <IconCode key="code" size="small" />],
+]);
+
+function RenderTopSlot() {
+    const ref = useRef();
+    const [reference, setReference] = useState(customReferences);
+
+    const renderLeftMenu = useCallback(() => <>
+        <Configure.RadioButton options={radioButtonProps} initValue="fast" field="mode"/>
+    </>);
+
+    const renderTopSlot = useCallback((props) => {
+        const { attachments = [], references = [] } = props;
+        return <div className="ai-chat-input-topSlot">
+            {references.map((item, index) => {
+                const { type, name, detail, key, ...rest } = item;
+                return (<div className="item" key={key}>
+                    <span className='item-icon'>
+                        {React.cloneElement(refTypeToIconMap.get(type), { className: 'item-left item-icon' })}
+                        <IconClose size="small" className='item-icon-delete' onClick={() => {
+                            const newReferences = [...references];
+                            newReferences.splice(index, 1);
+                            setReference(newReferences);
+                        }}/>
+                    </span>
+                    <span className='item-content'>
+                        {name}
+                        {type === 'branch' && <span className='detail'>{detail}</span>}
+                    </span>
+                </div>);
+            })}
+            {attachments.map((item, index) => {
+                const isImage = isImageType(item);
+                const { uid, name, url, size, percent, status } = item;
+                return (<div className="item" key={uid}>
+                    <span className='item-icon'>
+                        {isImage ? <img className='item-image item-left' src={item.url} alt={item.name} /> : <IconUpload size="small" className='item-left item-icon' />}
+                        <IconClose size="small" className='item-icon-delete' onClick={() => {
+                            ref.current && ref.current.deleteUploadFile(item);
+                        }}/>
+                    </span>
+                    <span className='item-content'>{name}</span>
+                </div>
+                );
+            })}
+        </div>;
+    }, []);
+    
+    return (
+        <AIChatInput
+            className='aiChatInput-customTopSlot'
+            renderTopSlot={renderTopSlot}
+            references={reference}
+            showUploadFile={false}
+            showReference={false}
+            renderConfigureArea={renderLeftMenu} 
+            ref={ref}
+            uploadProps={uploadProps}
+            style={outerStyle}
+            placeholder="自定义渲染顶部内容,可用于渲染上传内容、引用内容"
+        />
+    );
+}
+
+render(<RenderTopSlot />);
+```
+
+### 自定义扩展
+
+富文本区域可以自定义扩展,自定义扩展的实现可参考 [Tiptap 自定义扩展](https://tiptap.dev/docs/editor/extensions/custom-extensions/create-new)。通过 `extensions` API 可将自定义扩展添加到 `AIChatInput` 组件中。如果添加了自定义扩展,需要在 `transformer` 中添加对应的转换规则, 以保证在 `onContentChange` 中得到的该节点数据符合用户预期。
+
+```jsx live=true dir="column" noInline=true
+import React from 'react';
+import { Node, mergeAttributes } from '@tiptap/core';
+import { ReactNodeViewRenderer, NodeViewWrapper, posToDOMRect, ReactRenderer } from '@tiptap/react';
+import { computePosition, flip, shift } from '@floating-ui/dom';
+import { IconFile, IconFolder, IconBranch, IconCode, IconGit, IconGlobeStroke, IconChevronRight, IconClose, IconUpload, IconTerminal, IconConnectionPoint2 } from '@douyinfe/semi-icons';
+import { AIChatInput } from '@douyinfe/semi-ui';
+import Mention from '@tiptap/extension-mention';
+
+const uploadProps = { action: "https://api.semi.design/upload" };
+const outerStyle = { margin: 12 };
+
+// 面板选项
+const TestAction = {
+    'Files & Folders': [
+        {
+            icon: <IconFile />,
+            key: '1-1',
+            type: 'file',
+            name: 'TagInput.scss',
+            path: 'package/semi-founctaion/TagInput.scss',
+        },
+        {
+            icon: <IconFolder />,
+            key: '1-2',
+            type: 'folder',
+            name: 'package',
+            path: '/package',
+        },
+        {
+            icon: <IconFolder />,
+            key: '1-3',
+            type: 'folder',
+            name: 'semi-ui',
+            path: '/package/semi-ui',
+        },
+    ],
+    Git: [
+        {
+            icon: <IconBranch />,
+            key: '2-1',
+            type: 'branch',
+            name: 'fix/tag',
+        },
+        {
+            icon: <IconCode />,
+            key: '2-2',
+            type: 'code',
+            name: 'v2.86.0',
+            path: '/package',
+        },
+        {
+            icon: <IconGit />,
+            key: '2-3',
+            type: 'git',
+            name: 'chore: publish',
+        },
+    ],
+};
+
+// 第一级内容
+const FirstLevel = Object.keys(TestAction);
+
+// referSlot 的渲染组件
+function ReferSlotComponent(props) {
+    const { node, deleteNode } = props;
+    const value = node.attrs.value ? node.attrs.value : '';
+    const onRemove = (e) => {
+        e.preventDefault();
+        e.stopPropagation();
+        deleteNode && deleteNode();
+    };
+    return (
+        <NodeViewWrapper className="ai-chat-input-refer-slot-wrapper">
+            <span className='ai-chat-input-refer-slot'>
+                {value}
+            </span>
+        </NodeViewWrapper>
+    );
+}
+
+// 创建 ReferSlot 扩展
+const ReferSlot = Node.create({
+    name: 'referSlot',
+    inline: true,
+    group: 'inline',
+    atom: true,
+    selectable: false,
+    addAttributes() {
+        return {
+            value: {
+                default: '输入内容',
+                parseHTML: (element) =>
+                    element.getAttribute('data-value'),
+                renderHTML: (attributes) => ({
+                    'data-value': attributes.value,
+                }),
+            },
+            info: {
+                default: '',
+                parseHTML: (element) =>
+                    element.getAttribute('data-info'),
+                renderHTML: (attributes) => ({
+                    'data-info': attributes.info,
+                }),
+            },
+            type: {
+                default: 'text',
+                parseHTML: (element) =>
+                    element.getAttribute('data-type'),
+                renderHTML: (attributes) => ({
+                    'data-type': attributes.type,
+                }),
+            },
+            uniqueKey: {
+                default: '',
+                parseHTML: (element) =>
+                    element.getAttribute('data-unique-key'),
+                renderHTML: (attributes) => ({
+                    'data-unique-key': attributes.uniqueKey,
+                }),
+            },
+            // !!! Very important, affects the cursor size before and after custom nodes
+            // Please be sure to add this logic to custom nodes
+            isCustomSlot: AIChatInput.getCustomSlotAttribute(),
+        };
+    },
+    parseHTML() {
+        return [{
+            tag: 'refer-slot',
+        }];
+    },
+    renderHTML({ HTMLAttributes }) {
+        // 序列化时输出自定义标签,保留值到 data-value
+        return ['refer-slot', mergeAttributes(HTMLAttributes)];
+    },
+    addNodeView() {
+        return ReactNodeViewRenderer(ReferSlotComponent);
+    },
+});
+
+// 更新位置用函数
+const updatePosition = (editor, element) => {
+    const virtualElement = {
+        getBoundingClientRect: () => posToDOMRect(
+            editor.view,
+            editor.state.selection.from,
+            editor.state.selection.to,
+        ),
+    };
+    computePosition(virtualElement, element, {
+        placement: 'bottom-start',
+        strategy: 'absolute',
+        middleware: [shift()],
+    }).then(({ x, y, strategy }) => {
+        element.style.width = 'max-content';
+        element.style.position = strategy;
+        element.style.left = `${x}px`;
+        element.style.top = `${y}px`;
+    });
+};
+
+// 建议
+const suggestion = {
+    items: () => FirstLevel,
+    command: ({ editor, range, props }) => {
+        const { item } = props;
+        editor.chain().focus().insertContentAt(range, {
+            type: 'referSlot',
+            attrs: {
+                type: item.type,
+                value: item.name || '',
+                info: JSON.stringify({ path: item.path }),
+                uniqueKey: item.key,
+            },
+        }).run();
+    },
+    render: () => {
+        let component;
+        return {
+            onStart: (props) => {
+                component = new ReactRenderer(MentionList, {
+                    props,
+                    editor: props.editor,
+                });
+                if (!props.clientRect) return;
+                component.element.style.position = 'absolute';
+                document.body.appendChild(component.element);
+                updatePosition(props.editor, component.element);
+            },
+            onUpdate(props) {
+                component.updateProps(props);
+                if (!props.clientRect) return;
+                updatePosition(props.editor, component.element);
+            },
+            onKeyDown(props) {
+                function onExit() {
+                    component.destroy();
+                }
+                return component.ref.onKeyDown({ ...props, exitCb: onExit });
+            },
+            onExit() {
+                component.element.remove();
+                component.destroy();
+            },
+            focusEditor(props) {
+                props.editor.commands.focus();
+            },
+        };
+    },
+};
+
+const customReferences = [
+    {
+        type: 'file',
+        key: '1',
+        name: 'horizontalScroller.tsx',
+        path: 'packages/semi-ui/AIChatInput/horizontalScroller.tsx',
+    },
+    {
+        type: 'folder',
+        key: '2',
+        name: 'AIChatInput',
+        path: 'packages/semi-ui/AIChatInput',
+    },
+    {
+        type: 'web',
+        key: '3',
+        name: 'web'
+    },
+    {
+        type: 'change',
+        key: '4',
+        name: 'recentChange'
+    },
+    {
+        type: 'branch',
+        key: '5',
+        name: 'Branch',
+        detail: 'Diff with Main Branch',
+        branch: 'feat/aichatinput',
+        targetBranch: 'feat/targetBranch',
+    },
+    {
+        type: 'terminal',
+        key: '6',
+        name: 'From 1-2',
+        from: 1,
+        to: 2,
+    }
+];
+
+class MentionList extends React.Component {
+    constructor(props) {
+        super(props);
+        this.state = {
+            selectedIndex: 0,
+            level: 1,
+            options: FirstLevel,
+            filterOptions: FirstLevel,
+        };
+        this.upHandler = this.upHandler.bind(this);
+        this.downHandler = this.downHandler.bind(this);
+        this.enterHandler = this.enterHandler.bind(this);
+        this.selectItem = this.selectItem.bind(this);
+        this.onKeyDown = this.onKeyDown.bind(this);
+        this.renderItem = this.renderItem.bind(this);
+    }
+    upHandler() {
+        const { selectedIndex, filterOptions } = this.state;
+        this.setState({
+            selectedIndex: (selectedIndex + filterOptions.length - 1) % filterOptions.length,
+        });
+    };
+    downHandler() {
+        const { selectedIndex, filterOptions } = this.state;
+        this.setState({
+            selectedIndex: (selectedIndex + 1) % filterOptions.length,
+        });
+    };
+    enterHandler () {
+        const { selectedIndex, level } = this.state;
+        if (level === 1) {
+            this.setState({
+                level: 2,
+                options: TestAction[FirstLevel[selectedIndex]],
+                selectedIndex: 0,
+            });
+        } else {
+            this.selectItem(selectedIndex);
+        }
+    };
+    selectItem(id) {
+        const { options } = this.state;
+        const item = options[id];
+        if (item) {
+            this.props.command({ item });
+        }
+    };
+    componentDidUpdate(prevProps, prevState) {
+        if (prevProps.items !== this.props.items) {
+            this.setState({ selectedIndex: 0 });
+        }
+        if ( prevState.options !== this.state.options ||
+        prevProps.query !== this.props.query
+        ) {
+            // 手动 filter
+            let filter = [];
+            if (this.props.query && this.props.query.length) {
+                filter = (this.state.options ? this.state.options : []).filter((item) => {
+                    let name;
+                    if (typeof item === 'string') {
+                        name = item;
+                    } else {
+                        name = item.name;
+                    }
+                    return name.toLowerCase().includes(this.props.query.toLowerCase());
+                });
+            } else {
+                filter = this.state.options ? this.state.options : [];
+            }
+            this.setState({ 
+                filterOptions: filter, 
+                selectedIndex: 0
+            });
+        }
+    }
+    componentDidMount() {
+        if (this.props.innerRef) {
+            this.props.innerRef.current = {
+                onKeyDown: this.onKeyDown,
+            };
+        }
+    }
+    onKeyDown({ event, exitCb }) {
+        if (event.key === 'ArrowUp') {
+            this.upHandler();
+            return true;
+        }
+        if (event.key === 'ArrowDown') {
+            this.downHandler();
+            return true;
+        }
+        if (event.key === 'Enter') {
+            this.enterHandler();
+            return true;
+        }
+        if (event.key === 'Escape') {
+            if (this.state.level === 1) {
+                exitCb && exitCb();
+                return true;
+            } else if (this.state.level === 2) {
+                this.setState({ level: 1, options: FirstLevel });
+                return true;
+            }
+        }
+        return false;
+    };
+
+    // 明确参数类型
+    renderItem(item) {
+        return (
+            <div className="level2Item">
+                {item.icon}
+                <span className="name">{item.name}</span>
+                <span className="path">{item.path}</span>
+            </div>
+        );
+    };
+    render() {
+        const { level, filterOptions, selectedIndex } = this.state;
+        return (
+            <div className="ai-chat-input-custom-extension-dropdown-menu" style={{ width: level === 1 ? 200 : 300 }}>
+                {filterOptions.length ? (filterOptions.map(
+                    (item, index ) => (
+                        // eslint-disable-next-line jsx-a11y/click-events-have-key-events
+                        <div
+                            key={index}
+                            className={ index === selectedIndex ? 'is-selected optionItem' : 'optionItem '}
+                            onClick={() => {
+                                if (level === 1) {
+                                    if (typeof item === 'string') {
+                                        this.setState({ level: 2, options: TestAction[item] });
+                                        this.props.editor.commands.focus();
+                                    }
+                                } else {
+                                    if (typeof item !== 'string') {
+                                        this.selectItem(index);
+                                    }
+                                }
+                            }}
+                            onMouseEnter={() => {
+                                this.setState({ selectedIndex: index });
+                            }}
+                        >
+                            {typeof item === 'string' ? <span>{item}</span> : this.renderItem(item)}
+                            {level === 1 && <IconChevronRight className='option-item-arrow'/>}
+                        </div>
+                    ),
+                )) : <div className="item">No result</div>}
+            </div>
+        );
+    }
+}
+
+function getAttachmentType(item = {}) {
+    const { type, name = '', fileInstance = {} } = item;
+    if (type) {
+        return type;
+    }
+    const suffix = name.split('.').pop();
+    if (suffix) {
+        return suffix;
+    } else if (fileInstance.type && fileInstance.type) {
+        const temp = fileInstance.type.split('/').pop();
+        if (temp) {
+            return temp;
+        }
+    }
+    return 'UNKNOWN';
+}
+
+function isImageType(item = {}) {
+    const PIC_PREFIX = 'image/';
+    const PIC_SUFFIX_ARRAY = ['png', 'jpg', 'jpeg', 'gif', 'bmp', 'webp'];
+    const { name = '', fileInstance = {} } = item;
+    const suffix = name.split('.').pop();
+    let result = false;
+    const { type = '' } = fileInstance;
+    if (type.startsWith(PIC_PREFIX)) {
+        result = true;
+    } else if (PIC_SUFFIX_ARRAY.includes(suffix)) {
+        result = true;
+    }
+    return result;
+}
+
+const refTypeToIconMap = new Map([
+    ['file', <IconFile key={'file'} size="small" />],
+    ['folder', <IconFolder key={'folder'} size="small" />],
+    ['branch', <IconBranch key={'branch'} size="small" />],
+    ['terminal', <IconTerminal key={'terminal'} size="small" /> ],
+    ['web', <IconGlobeStroke key={'globalStroke'} size="small" />],
+    ['change', <IconConnectionPoint2 key={'connectionPoint2'} size="small" />],
+    ['git', <IconGit key="git" size="small" />],
+    ['code', <IconCode key="code" size="small" />],
+]);
+
+function CustomRichTextExtension() {
+    const ref = useRef();
+    const [reference, setReference] = useState(customReferences);
+    const extensions = useMemo(() => {
+        // 使用 @ 触发
+        return [
+            ReferSlot,
+            Mention.configure({
+                HTMLAttributes: {
+                    class: 'mention',
+                },
+                suggestion,
+            }),
+        ];
+    }, []);
+    const renderTopSlot = useCallback((props) => {
+        const { attachments = [], references = [], content = [] } = props;
+        const showContent = content.filter((item) => item.type !== 'text');
+        return <div className="ai-chat-input-topSlot">
+            {/* order: reference, rich text area content, attachments */}
+            {showContent.map((item, index) => {
+                const { type, value, name, key, detail, ...rest } = item;
+                return (
+                    <div className="item" key={key ? key : index}>
+                        <span className='item-icon'>
+                            {React.cloneElement(refTypeToIconMap.get(type), { className: 'item-left item-icon' })}
+                            <IconClose size="small" className='item-icon-delete' onClick={() => {
+                                if (ref.current && ref.current.deleteContent) {
+                                    ref.current.deleteContent(item);
+                                }
+                            }}/>
+                        </span>
+                        <span className='item-content'>
+                            {name ? name : value}
+                            {type === 'branch' && <span className='detail'>{detail}</span>}
+                        </span>
+                    </div>
+                );
+            })}
+            {references.map((item, index) => {
+                const { type, name, detail, key, ...rest } = item;
+                return (
+                    <div className="item" key={key}>
+                        <span className='item-icon'>
+                            {React.cloneElement(refTypeToIconMap.get(type), { className: 'item-left item-icon' })}
+                            <IconClose size="small" className='item-icon-delete' onClick={() => {
+                                const newReferences = [...references];
+                                newReferences.splice(index, 1);
+                                setReference(newReferences);
+                            }}/>
+                        </span>
+                        <span className='item-content'>
+                            {name}
+                            {type === 'branch' && <span className='detail'>{detail}</span>}
+                        </span>
+                    </div>
+                );
+            })}
+            {attachments.map((item, index) => {
+                const isImage = isImageType(item);
+                const realType = getAttachmentType(item);
+                const { uid, name, url, size, percent, status } = item;
+                return (
+                    <div className="item" key={uid}>
+                        <span className='item-icon'>
+                            {isImage ? <img className='item-image item-left' src={item.url} alt={item.name} /> : <IconUpload size="small" className='item-left item-icon' />}
+                            <IconClose size="small" className='item-icon-delete' onClick={() => {
+                                if (ref.current && ref.current.deleteUploadFile) {
+                                    ref.current.deleteUploadFile(item);
+                                }
+                            }}/>
+                        </span>
+                        <span className='item-content'>{name}</span>
+                    </div>
+                );
+            })}
+        </div>;
+    }, []);
+    const onContentChange = useCallback((content) => {
+        console.log('onContentChange', content);
+    }, []);
+    const transformer = useMemo(() => {
+        return new Map([
+            ['referSlot', (obj) => {
+                const { attrs = {} } = obj;
+                const { value, info, type = 'text', uniqueKey } = attrs;
+                return {
+                    type: type, 
+                    value: value,
+                    uniqueKey: uniqueKey,
+                    ...JSON.parse(info),
+                };
+            }],
+        ]);
+    }, []);
+    return (
+        <>
+            <AIChatInput
+                className='aiChatInput-customTopSlot'
+                renderTopSlot={renderTopSlot}
+                extensions={extensions}
+                references={reference}
+                showUploadFile={false}
+                showReference={false}
+                onContentChange={onContentChange}
+                ref={ref}
+                transformer={transformer}
+                uploadProps={uploadProps}
+                style={outerStyle}
+                placeholder="使用 @ 触发"
+            />
+        </>
+    );
+};
+
+render(<CustomRichTextExtension />);
+```
+
+## API 参考
+
+### AIChatInput
+
+| 属性 | 说明 | 类型 | 默认值 |
+|------|----|------|-------|
+| canSend | 是否可以发送,未设置时,根据输入框内容,上传内容,引用内容决定是否可发送 | boolean | true |
+| className | 自定义类名 | string | - |
+| defaultContent | 输入框默认内容,支持 html string 以及 json 格式,同 Tiptap 的 Content | TiptapContent | - |
+| dropdownMatchTriggerWidth | 下拉弹出层是否是否与输入框宽度一致 | boolean | true |
+| extensions | 自定义扩展,类型同 tiptap 的 Extension 类型相同 | Extension[] | - |
+| generating | 是否正在生成中 | boolean | false |
+| onContentChange | 输入框内容变化时候的回调 | (content: <ApiType detail='{ type: string; [key: string]: any }'>OnContentChangeProps</ApiType>) => void | - |
+| onMessageSend | 发送消息回调 | (content: <ApiType detail='{references?: Reference[]; attachments?: Attachment[]; inputContents?: Content[]; setup?: Setup}'>OnMessageSendProps</ApiType>) => void | - |
+| onReferenceClick | 引用点击回调 | (reference: Reference) => void | - |
+| onReferenceDelete | 引用删除回调 | (reference: Reference) => void | - |
+| onSkillChange | 技能切换回调 | (skill: Skill) => void | - |
+| onStopGenerate | 停止生成回调 | () => void | - |
+| onSuggestClick | 建议点击回调 | (suggestion: Suggestion) => void | - |
+| onTemplateVisibleChange | 模板弹出层可见性变化回调 | (visible: boolean) => void | - |
+| onUploadChange | 上传文件相关回调 | (props: OnChangeProps) => void | - |
+| popoverProps | 下拉弹出层的配置参数 | PopoverProps | - |
+| placeholder | 输入框占位符 | string | - |
+| references | 输入框引用列表 | Reference[] | - |
+| renderActionArea | 自定义底部的操作区域 | () => React.ReactNode | - |
+| renderConfigureArea | 自定义底部的配置区域 | () => React.ReactNode | - |
+| renderReference | 自定义渲染引用 | (reference: Reference) => ReactNode | - |
+| renderSkillItem | 自定义技能列表的 item 渲染 | (props: <ApiType detail='{skill: Skill; onClick: () => void; className: string, onMouseEnter: () => void}'>RenderSkillItemProps</ApiType>) => React.ReactNode | - |
+| renderSuggestionItem | 自定义建议列表的 item 渲染 | (props: <ApiType detail='{ suggestion: Suggestion; onClick: () => void; className: string, onMouseEnter: () => void}'>RenderSkillItemProps</ApiType>) => React.ReactNode | - |
+| renderTemplate | 自定义模板渲染 | (skill: Skill, onTemplateClick: (content: string) => void) => React.ReactNode | - |
+| renderTopSlot | 自定义顶部 slot | () => React.ReactNode | - |
+| round | 底部的配置区域和操作区域是否形状是否为全圆角 | boolean | true |
+| onBlur | 富文本输入框失焦的回调 | (event: React.FocusEvent) => void | - |
+| onConfigureChange | 配置区域发生变化的回调 | (value: LeftMenuChangeProps, changedValue: LeftMenuChangeProps) => void | - |
+| onFocus | 富文本输入框聚焦的回调 | (event: React.FocusEvent) => void | - |
+| showReference | 是否展示引用区域,用于配合 renderTopSlot 使用 | boolean | true |
+| showTemplateButton | 是否展示模板按钮,未设置时,将根据当前选中技能中的 hasTemplate 决定是否展示模版按钮 | boolean | false |
+| showUploadFile | 是否展示上传文件区域,用于配合 renderTopSlot 使用 | boolean | true |
+| skillHotKey | 输入框中触发技能的热键 | string | - |
+| skills | 技能列表 | Skill[] | - |
+| style | 自定义样式 | React.CSSProperties | - |
+| suggestions | 建议列表 | Suggestion[] | - |
+| templatesCls| 模版的样式类名称| string | - |
+| templatesStyle| 模版的样式| React.CSSProperties | - |
+| topSlotPosition | 顶部 slot 位置,相对于引用内容,上传内容 | 'top' \| 'bottom' \| 'middle' | - |
+| transformer | 自定义扩展的转换规则 | Map<string, (obj: any) => any> | |
+| uploadProps | 上传文件相关配置 | UploadProps | - |
+| uploadTipProps | 上传文件相关提示配置 | UploadTipProps | - |
+
+## Methods
+
+| 属性 | 说明 | 类型 | 默认值 |
+|------|----|------|-------|
+| changeTemplateVisible | 切换模板弹出层的可见性 | (visible: boolean) => void | - |
+| deleteContent | 删除富文本中的某一项,删除逻辑依赖的是 content 中的 uniqueKey | (content: Content) => void | - |
+| deleteUploadFile | 删除上传文件中的某一项 | (item: Attachment) => void | - |
+| focusEditor | 聚焦输入框,默认聚焦到输入框的末尾 | (pos?: string) => void | - |
+| getEditor | 获取当前的 tiptap 的 editor 实例 | () => Editor | - |
+| setContent | 设置输入框内容 | (content: TiptapContent) => void | - |
+| setContentWhileSaveTool | 保留技能项的同时设置输入框内容 | (content: TiptapContent) => void | - |
+
+
+
+## 设计变量
+<DesignToken/>
+
+

+ 554 - 0
content/ai/aiComponent/index-en-US.md

@@ -0,0 +1,554 @@
+---
+localeCode: en-US
+order: 98
+category: Ai
+title: AI Ability Introduction
+icon: doc-aiComponent
+width: 60%
+brief: Introducing components related to AI application scenarios
+showNew: true
+---
+
+Semi AI Components is an innovative component library designed specifically for AI application scenarios. In an era where AI is becoming a key player in products, traditional design systems are struggling to support increasingly complex intelligent interactions. Semi AI Components, with "human-machine intelligent collaboration" as its core concept, aims to make user collaboration with AI systems more efficient, controllable, perceptible, and reliable. The Semi AI Components library includes the following: AI Token, basic AI components, and AI Chat components, used to serve scenarios such as intelligent question answering and assistants, multimodal input, and multi-turn dialogue.
+
+- `AI Token`: Added 20 basic tokens in 20 colors for AI scenarios.
+
+- `AI Basic Components`: Added 25 icons for AI scenarios, and added AI styles to `Button/Tag/FloatButton`.
+
+- `AI Chat Components`: Added `AIChatInput`, which supports rich text input, quoting, uploading, function configuration, and rich custom display; and `AIChatDialogue`, which supports conversation display, selection, editing, prompts, rich custom rendering, and message transformation. The chat component supports the OpenAI community's [Response](https://platform.openai.com/docs/api-reference/responses/create) / [Chat Completion](https://platform.openai.com/docs/api-reference/chat/create) format standards by default, supporting GPT-5 and GPT-4o. All models in the series support out-of-the-box response; see [Message Data Conversion](/en-US/ai/aiChatDialogue#%E6%B6%88%E6%81%AF%E6%95%B0%E6%8D%AE%E8%BD%AC%E6%8D%A2) for details. (For information on how to select the `Chat` and `AI Chat` components, see [FAQ](/en-US/ai/aiComponent#FAQ)).
+
+In the future, we will support more AI Chat components, such as the integrated component `AIChatBox` combining `AIChatInput` and `AIChatDialogue`, and the multi-functional sidebar component `SideBar` with capabilities for product editing, product viewing, and displaying cited materials, to meet the information and result management needs in complex AI application scenarios.
+
+### AI Basic Components
+
+The AI ​​basic components include `AI Icon` and AI-style `Button`, `Tag`, and `FloatButton`. The AI ​​style of the basic AI components is implemented based on `AI Token`.
+
+For `AI Token`, we have built a brand color palette with a purple-blue gradient as its core. Two new hues, AI purple and AI general, have been added to the base colors, resulting in a color wheel of 20 colors.
+
+For `AI Icon`, single-color, dual-color, and multi-color icons are supported, totaling 25 icons.
+
+For AI-style `Button`, `Tag`, and `FloatButton`, the `Colorful` property of the component can be enabled.
+
+Below are some examples of basic AI components. For more examples and use cases, please see [AI Token](/en-US/basic/tokens), [AI Icon](en-US/basic/icon), [AI Button](/en-US/basic/button#AI%20%E9%A3%8E%E6%A0%BC%20-%20%E5%A4%9A%E5%BD%A9%E6%8C%89%E9%92%AE), [AI Tag](/en-US/show/tag#AI%20%E9%A3%8E%E6%A0%BC%20-%20%E5%A4%9A%E5%BD%A9%E6%A0%87%E7%AD%BE), [AI FloatButton](/en-US/basic/floatbutton#AI%20%E9%A3%8E%E6%A0%BC%20-%20%E5%A4%9A%E5%BD%A9%E6%82%AC%E6%B5%AE%E6%8C%89%E9%92%AE).
+
+```jsx live=true dir="column"
+import React from 'react';
+import { Typography, Button, Tag, FloatButton } from '@douyinfe/semi-ui';
+import { IconAIBellLevel1, IconAIEditLevel2, IconAIFileLevel3, IconAIFilledLevel3, IconAIImageLevel3, IconAISearchLevel3, IconAIStrokedLevel3, IconAIWandLevel3, IconAILoading, IconAIFilledLevel1, IconAIEditLevel1 } from '@douyinfe/semi-icons';
+
+() => {
+    return (<div style={{ display: 'flex', flexDirection: 'column', rowGap: 20 }}>
+        <div key="AIToken" style={{ display: 'flex', flexDirection: 'column', rowGap: 10 }}>
+            <Typography.Title heading={5}>AI Token</Typography.Title>
+            <div style={{ display: 'flex', alignItems: 'center', columnGap: 10 }}>
+                <span>Purple</span>
+                <div style={{ display: 'inline-flex', columnGap: 4 }}>
+                    {(new Array(10).fill(1).map((i, index) => (
+                        <div key={index} style={{ width: 40, height: 40, backgroundColor: `rgba(var(--semi-ai-purple-${index}), 1)`, borderRadius: '50%' }} />
+                    )))}
+                </div>
+            </div>
+            <div style={{ display: 'flex', alignItems: 'center', columnGap: 10 }}>
+                <span>General</span>
+                <div style={{ display: 'inline-flex', columnGap: 4, }}>
+                    {(new Array(10).fill(1).map((i, index) => (
+                        <div key={index} style={{ width: 40, height: 40, background: `var(--semi-ai-general-${index})`, borderRadius: '50%' }} />
+                    )))}
+                </div>
+            </div>
+        </div>
+        <div key="AIIcon" style={{ display: 'flex', flexDirection: 'column', rowGap: 10 }}>
+            <Typography.Title heading={5} >AI Icon</Typography.Title>
+            <div style={{ display: 'flex', columnGap: 10 }}>
+                <IconAIBellLevel1 size="extra-large"/>
+                <IconAIEditLevel2 size="extra-large"/>
+                <IconAIFileLevel3 size="extra-large" />
+                <IconAIFilledLevel3 size="extra-large" />
+                <IconAIImageLevel3 size="extra-large" />
+                <IconAISearchLevel3 size="extra-large" />
+                <IconAIStrokedLevel3 size="extra-large" />
+                <IconAIWandLevel3 fill={['var(--semi-color-danger)', 'var(--semi-color-success)', 'var(--semi-color-primary)', 'var(--semi-color-warning)']} size="extra-large"/>
+                <IconAILoading size="extra-large"/>
+            </div>
+        </div>
+        <div style={{ display: 'flex', flexDirection: 'column', rowGap: 10 }}>
+            <Typography.Title heading={5}>AI Button</Typography.Title>
+            <div style={{ display: 'flex', rowGap: 16, flexDirection: 'column' }}>
+                <div style={{ display: 'flex', columnGap: 16 }}>
+                    <Button colorful theme="solid" type="primary" icon={<IconAIFilledLevel1 />}>Colorful</Button>
+                    <Button colorful theme="solid" type="primary" loading >Colorful</Button>
+                    <Button colorful theme="solid" type="primary" icon={<IconAIFilledLevel1 />} disabled >Colorful</Button>
+                </div>
+                <div style={{ display: 'flex', columnGap: 16 }}>
+                    <Button colorful theme="solid" type="tertiary" icon={<IconAIFilledLevel3 />}>Colorful</Button>
+                    <Button colorful theme="solid" type="tertiary" loading >Colorful</Button>
+                    <Button colorful theme="solid" type="tertiary" icon={<IconAIFilledLevel3 />} disabled >Colorful</Button>
+                </div>
+                <div style={{ display: 'flex', columnGap: 16 }}>
+                    <Button colorful theme="solid" type="primary" icon={<IconAIFilledLevel1 />} />
+                    <Button colorful theme="solid" type="primary" loading />
+                    <Button colorful theme="solid" type="primary" icon={<IconAIFilledLevel1 />} disabled />
+                    <Button colorful theme="solid" type="tertiary" icon={<IconAIFilledLevel3 />} />
+                    <Button colorful theme="solid" type="tertiary" loading />
+                    <Button colorful theme="solid" type="tertiary" icon={<IconAIFilledLevel3 />} />
+                </div>
+            </div>
+        </div>
+        <div style={{ display: 'flex', flexDirection: 'column', rowGap: 10 }}>
+            <Typography.Title heading={5} style={{ marginTop: 10 }}>AI Tag</Typography.Title>
+            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3,1fr)', gridGap: '10px', width: 'fit-content' }}>
+                <Tag colorful prefixIcon={<IconAIFilledLevel1 size="small"/>} type="solid" shape='circle' gradient>AI</Tag>
+                <Tag colorful prefixIcon={<IconAIFilledLevel3 size="small" />} type="light" shape='circle' gradient>AI</Tag>
+                <Tag colorful prefixIcon={<IconAIFilledLevel3 size="small"/>} type="ghost" shape='circle' gradient >AI</Tag>
+                <Tag colorful prefixIcon={<IconAIFilledLevel1 size="small"/>} type="solid" shape='circle' >AI</Tag>
+                <Tag colorful prefixIcon={<IconAIFilledLevel1 size="small" />} type="light" shape='circle'>AI</Tag>
+                <Tag colorful prefixIcon={<IconAIFilledLevel1 size="small"/>} type="ghost" shape='circle'>AI</Tag>
+            </div>
+        </div>
+        <div style={{ display: 'flex', flexDirection: 'column', rowGap: 10 }}>
+            <Typography.Title heading={5} style={{ marginTop: 10 }}>AI FloatButton</Typography.Title>
+            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3,1fr)', gridGap: '10px', width: 'fit-content' }}>
+                <FloatButton 
+                    icon={<IconAIEditLevel1 />}
+                    colorful
+                    size="large"
+                    badge={{ count: 'VIP', type: "danger" }}
+                    style={{ position: 'static' }} 
+                />
+            </div>
+        </div>
+    </div>);
+};
+```
+
+### Building a Conversation with the AI ​​Chat Component
+
+In this example, we'll combine the AIChatInput and AIChatDialogue components to build a conversational use case suitable for a Multiple Agent scenario.
+For more examples and usage scenarios, see [AIChatInput](/en-US/ai/aiChatInput) and [AIChatDialogue](/en-US/ai/aiChatDialogue). For examples of front-end and back-end combined use cases, please refer to [semi-ai-chat-demo](https://github.com/YannLynn/semi-ai-chat-demo).
+
+```jsx live=true dir="column" noInline=true
+import React, { useState, useCallback } from 'react';
+import { AIChatDialogue, AIChatInput, chatInputToMessage, Typography, Button } from '@douyinfe/semi-ui';
+import { IconFixedStroked, IconFeishuLogo, IconBookOpenStroked, IconGit, IconFigma, IconWord, IconClose, IconTemplateStroked, IconSearch } from '@douyinfe/semi-icons';
+
+const { Configure } = AIChatInput;
+
+const simpleIsEqual = (a, b) => {
+    if (a === b) {
+        return true;
+    }
+    if (Number.isNaN(a) && Number.isNaN(b)) {
+        return true;
+    }
+    if (typeof a !== 'object' || a === null || typeof b !== 'object' || b === null) {
+        return false;
+    }
+    const isArrayA = Array.isArray(a);
+    const isArrayB = Array.isArray(b);
+    if (isArrayA !== isArrayB) {
+        return false; 
+    }
+    const keysA = Object.keys(a);
+    const keysB = Object.keys(b);
+    if (keysA.length !== keysB.length) {
+        return false;
+    }
+    for (const key of keysA) {
+        if (!Object.prototype.hasOwnProperty.call(b, key)) {
+            return false;
+        }
+        if (!simpleIsEqual(a[key], b[key])) {
+            return false;
+        }
+    }
+    return true;
+};
+
+
+function AIChatInputWithDialogue() {
+    const inputOuterStyle = { margin: '12px', minHeight: 150, maxHeight: 300, flexShrink: 0 };
+    const editingInputOuterStyle = { margin: '12px 0px', maxHeight: 300, flexShrink: 0 };
+    const dialogueOuterStyle = { flex: 1, overflow: 'auto' };
+    const [sideBarVisible, setSideBarVisible] = useState(false);
+    const [messages, setMessages] = useState(defaultMessages); 
+    const [generating, setGenerating] = useState(false);
+    const [references, setReferences] = useState([]); 
+    const [sideBarContent, setSideBarContent] = useState({});
+
+    const renderLeftMenu = useCallback(() => (<>
+        <Configure.Select optionList={modelOptions} field="model" initValue="GPT-4o" />
+        <Configure.Button icon={<IconBookOpenStroked />} field="onlineSearch">Online search</Configure.Button>
+        <Configure.Mcp options={mcpOptions} />
+        <Configure.RadioButton options={radioButtonProps} field="thinkType" initValue="think"/>
+    </>), []);
+
+    const onChatsChange = useCallback((chats) => {
+        console.log('onChatsChange', chats);
+        setMessages(chats);
+    }, []);
+
+    const onContentChange = useCallback((content) => {
+        // console.log('onContentChange', content);
+    }, []);
+
+
+    const onReferenceClick = useCallback((item) => {
+        setReferences((references) => [...references, { ...item, id: `reference-${Date.now()}` }]);
+    }, []);
+
+    const handleReferenceDelete = useCallback((item) => {
+        const newReference = references.filter((ref) => ref.id !== item.id);
+        setReferences(newReference);
+    }, [references]);
+
+    const onMessageSend = useCallback((props) => {
+        setGenerating(true);
+        // 模拟发送请求
+        setMessages((messages) => [...messages, {
+            id: `message-${Date.now()}`,
+            ...chatInputToMessage(props),
+        }]);
+        setReferences([]);
+        setTimeout(() => {
+            setGenerating(false);
+        }, 100);
+        setTimeout(() => {
+            // 模拟接口返回
+            setMessages((messages) => {
+                return [...messages, {
+                    id: `message-${Date.now()}`,
+                    role: 'assistant',
+                    name: 'FE',
+                    content: "This is a mock reply message.",
+                }];
+            });
+        }, 1000);
+    }, []);
+
+    const onEditMessageSend = useCallback((props) => {
+        const index = messages.findIndex((message) => message.editing);
+        const newMessages = [...messages.slice(0, index), {
+            id: `message-${Date.now()}`,
+            ...chatInputToMessage(props),
+        }];
+        setMessages(newMessages);
+    }, [messages]);
+
+    const handleEditingReferenceDelete = useCallback((item) => {
+        const newMessages = messages.map((message) => {
+            if (message.editing) {
+                message.references = message.references.filter((ref) => ref.id !== item.id);
+            }
+            return message;
+        });
+        setMessages(newMessages);
+    }, [messages]);
+
+    const messageEditRender = useCallback((props) => {
+        return (
+            <AIChatInput 
+                style={editingInputOuterStyle}
+                generating={false}
+                references={props.references}
+                uploadProps={{ ...uploadProps, defaultFileList: props.attachments }}
+                defaultContent={props.inputContents[0].text}
+                renderConfigureArea={renderLeftMenu} 
+                // onContentChange={onContentChange}
+                onMessageSend={onEditMessageSend}
+                onReferenceDelete={handleEditingReferenceDelete}
+            />
+        );
+    }, [messages, handleEditingReferenceDelete]);
+
+    const changeSideBarContent = useCallback((content) => {
+        setSideBarContent((oldContent) => {
+            if (!simpleIsEqual(content, oldContent)) {
+                setSideBarVisible(true);
+            } else {
+                setSideBarVisible(v => !v);
+            }
+            return content;
+        });
+    });
+
+    const onAnnotationClick = useCallback((annotations) => {
+        changeSideBarContent({
+            type: 'annotation',
+            value: annotations
+        });
+    }, [changeSideBarContent]);
+
+    const toggleSideBar = useCallback(() => {
+        setSideBarVisible(v => !v);
+    }, []);
+
+    const renderSideBarTitle = useCallback((content) => {
+        const { type, value } = content;
+        return <div style={{ display: 'flex', alignItems: 'center ', justifyContent: 'space-between', padding: 12, color: 'var(--semi-color-text)' }}>
+            {type === 'annotation' && <div style={{ fontSize: '16px', lineHeight: '22px', fontWeight: 600 }}>References</div>}
+            {type === 'resource' && <div style={{ fontSize: '16px', lineHeight: '22px', fontWeight: 600 }}>Product List</div>}
+            <Button onClick={toggleSideBar} theme="borderless" type="tertiary" icon={<IconClose />} style={{ padding: '0px', width: 24, height: 24 }} />
+        </div>;
+    }, [toggleSideBar]);
+
+    const renderSideBarBody = useCallback((content) => {
+        const { type, value = {} } = content;
+        if (type === 'annotation') {
+            return <div style={{ display: 'flex', flexDirection: 'column', rowGap: '12px', padding: '12px' }} >
+                {value.map((item, index) => (<div key={index} style={{ display: 'flex', flexDirection: 'column', rowGap: '8px' }} >
+                    <span style={{ display: 'flex', alignItems: 'center ', columnGap: 4 }}>
+                        <img style={{ width: 20, height: 20, borderRadius: '50%' }} src={item.logo}/>
+                        <span style={{ fontSize: '14px', lineHeight: '20px', fontWeight: 600, color: 'var(--semi-color-text-0)' }}>{item.title}</span>
+                    </span>
+                    <Typography.Paragraph ellipsis={{ rows: 3 }} style={{ fontSize: '12px', lineHeight: '16px', color: 'var(--semi-color-text-1)' }} >{item.detail}</Typography.Paragraph>
+                </div>))}
+            </div>;
+        } else if (type === 'resource') {
+            return <div style={{ display: 'flex', flexDirection: 'column', rowGap: '12px', padding: '12px' }} >
+                <div style={{ display: 'flex', gap: 12, alignItems: 'center', }}>
+                    <IconWord style={{ color: 'var(--semi-color-primary)' }} size='extra-large' /> {value.name}
+                </div>
+            </div>;
+        }
+        return <div>
+
+        </div>;
+    }, []);
+
+    const customRender = {
+        "resource": (item, message) => {
+            return <div 
+                style={{ 
+                    display: 'flex', 
+                    gap: 8, 
+                    backgroundColor: 'var(--semi-color-fill-0)', 
+                    padding: '12px 16px',
+                    justifyContent: 'center',
+                    alignItems: 'center',
+                    borderRadius: '12px',
+                    cursor: 'pointer'
+                }}
+                onClick={() => {
+                    changeSideBarContent({
+                        type: 'resource',
+                        value: item
+                    });
+                }}
+            >
+                <IconWord style={{ color: 'var(--semi-color-primary)' }} />
+                {item.name}
+            </div>;
+        },
+    };
+
+    return (
+        <div style={{ display: 'flex', columnGap: 10 }}>
+            <div style={{ display: 'flex', flexDirection: 'column', height: 'calc(100vh - 32px)', overflow: 'hidden', flexGrow: 1 }}>
+                <AIChatDialogue 
+                    style={dialogueOuterStyle}
+                    roleConfig={roleConfig}
+                    showReference={true}
+                    align="leftRight"
+                    mode="bubble"
+                    chats={messages}
+                    onChatsChange={onChatsChange}
+                    onReferenceClick={onReferenceClick}
+                    messageEditRender={messageEditRender}
+                    onAnnotationClick={onAnnotationClick}
+                    renderDialogueContentItem={customRender}
+                />
+                <AIChatInput 
+                    style={inputOuterStyle}
+                    placeholder={'Enter content or upload content'} 
+                    defaultContent={'I am a <input-slot placeholder="[Profession]">programmer</input-slot>,Please help me implement<input-slot placeholder="[Requirement Description]">a chat application in a Multi-Agent scenario</input-slot>'}
+                    generating={generating}
+                    references={references}
+                    uploadProps={uploadProps}
+                    renderConfigureArea={renderLeftMenu} 
+                    onContentChange={onContentChange}
+                    onMessageSend={onMessageSend}
+                    onStopGenerate={() => setGenerating(false)}
+                    onReferenceDelete={handleReferenceDelete}
+                />
+            </div>
+            {sideBarVisible && <div 
+                style={{ flexShrink: 0, width: 300, height: 'calc(100vh - 32px)', borderRadius: '12px', border: '1px solid var(--semi-color-border)', flexShrink: 0 }}
+            >
+                {renderSideBarTitle(sideBarContent)}
+                {renderSideBarBody(sideBarContent)}
+            </div>}
+        </div>
+    );
+}
+
+
+const defaultMessages = [{
+    id: '1',
+    role: 'user',
+    content: 'I want to develop a chat application for a multi-agent scenario. Can you help me design it?',
+    status: 'completed',
+}, {
+    id: '2',
+    role: 'assistant',
+    name: 'PM',
+    content: [{
+        type: 'message',
+        content: [{
+            type: 'input_text',
+            text: 'Received. To ensure the feasibility of the solution, I will first clarify the goals and scope:\n\n- Goal: Support multi-agent collaborative replies, where users can choose an agent or the system can automatically assign one.\n- MVP Features:\n 1) Basic conversation (text/image/file)\n 2) Agent identification and avatar\n 3) Input in progress and streaming output\n 4) Display of cited sources and tool results\n- Constraints: Focus on single-session implementation first, without cloud persistence; prioritize mobile adaptation.\n\nNext, I will organize the PRD key points and share them with the design and front-end teams.',
+            annotations: [
+                {
+                    title: 'Semi Design',
+                    url: 'https://semi.design/en-US/start/getting-started',
+                    detail: 'Semi Design is a design system designed, developed, and maintained by the Douyin front-end team and the MED product design team. As a comprehensive, user-friendly, and high-quality modern application UI solution, Semi Design is derived from the complex scenarios across ByteDance various business lines. It currently supports nearly a thousand platform products and serves over 100,000 internal and external users.',
+                    logo: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/card-meta-avatar-docs-demo.jpg'
+                },
+                {
+                    title: 'Semi DSM',
+                    url: 'https://semi.design/en-US/start/getting-started',
+                    detail: 'Semi DSM supports global and component-level style customization and maintains synchronization between Figma and online code. Using DSM, Semi Design can be adapted to Any Design.',
+                    logo: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/card-meta-avatar-docs-demo.jpg'
+                },
+                {
+                    title: 'Semi D2C',
+                    url: 'https://semi.design/en-US/start/getting-started',
+                    detail: 'Semi D2C offers out-of-the-box design-to-code conversion: it supports one-click recognition of layer layouts and design system components in Figma pages, reproducing design drafts pixel-perfectly and translating them into React JSX and CSS code. Furthermore, it provides rich extensibility, allowing teams to quickly create their own custom design and development collaboration tools based on a custom plugin system.',
+                    logo: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/card-meta-avatar-docs-demo.jpg'
+                }
+            ],
+        }],
+    }],
+}, {
+    id: '3',
+    role: 'assistant',
+    name: 'PM',
+    content: [{
+        type: 'message',
+        content: [{
+            type: 'input_text',
+            text: 'The generated PRD is as follows. The designer will first use this summary to create the information architecture and key pages.',
+        }, {
+            type: 'resource',
+            name: 'PRD.doc',
+            size: '100KB',
+        }]
+    }],
+}, {
+    id: '4',
+    role: 'assistant',
+    name: 'UI',
+    content: [{
+        id: "rs_02175871288540800000000000000000000ffffac1598778c9aa5",
+        type: "reasoning",
+        summary: [
+            {
+                "type": "summary_text",
+                "text": "\nBased on the PRD provided by the product manager, I need to draw the key pages."
+            }
+        ],
+        status: "completed"
+    }, {
+        type: 'function_call',
+        name: 'paint_key_pages',
+        arguments: "{\"file\":\"PRD\"}",
+        status: 'completed',
+    }, {
+        type: 'message',
+        content: [{
+            "type": "output_text",
+            "text": `The initial design draft is as follows:\n\n- Information Architecture: Dialogue Page (History List | Message Flow | Tool Card Area)\n- Visuals: The left side displays Agent avatars and name tags, with color blocks distinguishing roles\n- Interaction:\n- Input area supports quick switching and suggestion prompts using @Agent\n- During streaming output, a typing bubble and progress placeholder are displayed\n- Tool results are inserted in the form of cards/step bars, which can be expanded for details and copied\n\nI'll start with a low-fidelity wireframe; high-fidelity and animation details will be added later.`,
+        }],
+        status: "completed"
+    }],
+    status: 'completed',
+}, {
+    id: '5',
+    role: 'assistant',
+    name: 'FE',
+    content: `Technical Solution Suggestions:\n\n- Technology Stack: React + Semi UI, backend using WebSocket or SSE to support streaming responses\n- Data Model: Messages include fields such as id, role, name, content, status, and references\n- Component Splitting: AIChatInput + AIChatDialogue; content rendered using Markdown, supporting image and file clicks\n- Performance: Virtual list and scroll-to-bottom; long text chunked rendering; lazy loading of images\n- Observability: Message tracking latency, error rate, and tool call time\n\nIf confirmed, I can first build the page skeleton and integrate mock data for integration testing.`,
+}];
+
+const roleConfig = {
+    user: {
+        name: 'User',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/22606991eh7uhfups/img/user.png'
+    },
+    assistant: new Map([
+        ['PM', {
+            name: 'Product Manager',
+            avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/22606991eh7uhfups/PM.png'
+        }],
+        ['UI', {
+            name: 'Designer',
+            avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/22606991eh7uhfups/UI.png'
+        }],
+        ['FE', {
+            name: 'Front-end programmer',
+            avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/22606991eh7uhfups/FE.png'
+        }],
+    ]),
+};
+
+const uploadProps = {
+    action: "https://api.semi.design/upload"
+};
+
+const modelOptions = [
+    {
+        value: 'GPT-5',
+        label: 'GPT-5',
+        type: 'gpt',
+    },
+    {
+        value: 'GPT-4o',
+        label: 'GPT-4o',
+        type: 'gpt',
+    },
+    {
+        value: 'Claude 3.5 Sonnet',
+        label: 'Claude 3.5 Sonnet',
+        type: 'claude',
+    },
+];
+
+const mcpOptions = [
+    {
+        icon: <IconFeishuLogo />,
+        label: "Lark Doc",
+        value: "feishu",
+    },
+    {
+        icon: <IconGit />,
+        label: "Github Mcp",
+        value: "github",
+    },
+    {
+        icon: <IconFigma />,
+        label: "IconFigma Mcp",
+        value: "IconFigma",
+    }
+];
+
+const radioButtonProps = [
+    { label: <IconTemplateStroked />, value: 'fast' },
+    { label: <IconSearch />, value: 'think' }
+];
+
+render(AIChatInputWithDialogue);
+```
+
+### FAQ
+- **How should you choose between Chat components and AI Chat series components?**
+   - If the scenario is relatively simple, requiring only plain text conversations and basic document/image displays, the Chat component is recommended.
+        - [Chat](/en-US/plus/chat) component integrates input and message display by default. Its advantage is that it is easy to understand and can be quickly learned. Its disadvantage is that it is relatively difficult to customize complex input boxes or message display requirements, and the workload is large.
+   - If the scenario is relatively complex, it is recommended to use the AIChatInput and AIChatDialogue components together, with the following advantages:
+        - [AIChatInput](/en-US/ai/aiChatInput) supports more complex style customization
+            1. Users can easily customize the [configuration area](/en-US/ai/aiChatInput#%E9%85%8D%E7%BD%AE%E5%8C%BA%E5%9F%9F) in the lower left corner and the [operation area](/en-US/ai/aiChatInput#%E6%93%8D%E4%BD%9C%E5%8C%BA%E5%9F%9F) in the lower right corner.
+            2. Provides a [rich text input area](/en-US/ai/aiChatInput#%E5%AF%8C%E6%96%87%E6%9C%AC%E8%BE%93%E5%85%A5%E5%8C%BA)to display input templates;
+            3. By default, it supports displaying [reference](/en-US/ai/aiChatInput#%E5%BC%95%E7%94%A8).
+            4. Supports hotkey-activated [skill templates](/en-US/ai/aiChatInput#%E6%8A%80%E8%83%BD%E5%8F%8A%E6%A8%A1%E7%89%88);
+            5. It supports custom [Input Extension](/en-US/ai/aiChatInput#%E8%87%AA%E5%AE%9A%E4%B9%89%E6%89%A9%E5%B1%95) and [TopSlot](/en-US/ai/aiChatInput#%E8%87%AA%E5%AE%9A%E4%B9%89%E6%B8%B2%E6%9F%93%E9%A1%B6%E9%83%A8%E5%8C%BA%E5%9F%9F), making complex displays easy to achieve.
+         - [AIChatDialogue](/en-US/ai/aiChatDialogue) message display is more flexible。
+            1. The component supports OpenAI's [Response](https://platform.openai.com/docs/api-reference/responses/create) / [Chat Completion](https://platform.openai.com/docs/api-reference/chat/create) Object format standard by default. Calling the [internal message conversion function](/en-US/ai/aiChatDialogue#%E6%B6%88%E6%81%AF%E6%95%B0%E6%8D%AE%E8%BD%AC%E6%8D%A2) can easily convert the results returned by OpenAI into the data structure required by the component.
+            2. It provides an API for [customized display based on message type](/en-US/ai/aiChatDialogue#%E8%87%AA%E5%AE%9A%E4%B9%89%E6%B8%B2%E6%9F%93%E6%B6%88%E6%81%AF%E5%86%85%E5%AE%B9) to facilitate quick and easy message display.
+            3. By default, message [reference](/en-US/ai/aiChatDialogue#%E5%BC%95%E7%94%A8) and [select](/en-US/ai/aiChatDialogue#%E9%80%89%E6%8B%A9) operations are supported.

+ 555 - 0
content/ai/aiComponent/index.md

@@ -0,0 +1,555 @@
+---
+localeCode: zh-CN
+order: 98
+category: Ai
+title: AIComponent 能力介绍
+icon: doc-aiComponent
+width: 60%
+brief: 整体介绍 AI 应用场景下的组件能力
+showNew: true
+---
+
+Semi AI 组件是一套专为 AI 应用场景设计的创新组件库。面对 AI 正在成为产品主角的时代,传统的设计体系已难以支撑日益复杂的智能交互,Semi AI 组件以「人机智能协同」为核心理念,致力于让用户与 AI 系统协作更高效、可控、可感知、可信赖。Semi AI 组件库包含以下内容:AI Token、AI 基础组件以及 AI Chat 组件,用于服务智能问答与助手、多模态输入与多轮对话等场景。
+
+- `AI Token`, 新增加 AI 场景下的基础 20 个颜色的基础 token
+- `AI 基础组件`, 新增加 AI 场景下的 25 个 icon,以及对 `Button/Tag/FloatButton` 新增 AI 风格
+- `AI Chat 组件`,新增加支持富文本输入、引用,上传、功能配置、及丰富自定义展示的 `AIChatInput`;以及会话展示、选择、编辑、提示、丰富自定义渲染、消息转换的 `AIChatDialogue`,对话组件默认支持 OpenAI 社区 [Response](https://platform.openai.com/docs/api-reference/responses/create) / [Chat Completion](https://platform.openai.com/docs/api-reference/chat/create) 格式标准,对 GPT-5、GPT-4o 系列模型的响应均支持开箱即用,详见[消息数据转换](/zh-CN/ai/aiChatDialogue#%E6%B6%88%E6%81%AF%E6%95%B0%E6%8D%AE%E8%BD%AC%E6%8D%A2)(关于 `Chat` 组件和 `AI Chat` 组件如何选型见 [FAQ](/zh-CN/ai/aiComponent#FAQ))
+
+在未来,我们将支持更多 AI Chat 组件,比如结合 `AIChatInput` 和 `AIChatDialogue` 的一体化组件 `AIChatBox`,以及具备产物编辑、产物查看、引用资料展示等能力的多功能侧边栏组件 `SideBar`,用于满足复杂 AI 应用场景下的信息与结果管理需求。
+
+
+### AI 基础组件
+
+AI 基础组件包括 `AI Icon`、AI 风格的 `Button` / `Tag` / `FloatButton`, AI 基础组件的 AI 风格是在 `AI Token` 的基础上实现。
+
+对于 `AI Token`,我们构建了一套以紫蓝渐变系为核心的品牌色板,在基础色中,新增加了 AI purple 和 AI general 两个色相,20 个颜色的色盘。
+
+对于 `AI Icon`,支持 Icon 场景下的单色、双色、及多色 Icon,共 25 个图标。
+
+对于 AI 风格的 `Button / Tag / FloatButton`,可通过组件的 `Colorful` 属性开启。
+
+以下是 AI 基础组件的一些示例,更多示例及使用场景详见 [AI Token](/zh-CN/basic/tokens)、[AI Icon](zh-CN/basic/icon)、[AI Button](/zh-CN/basic/button#AI%20%E9%A3%8E%E6%A0%BC%20-%20%E5%A4%9A%E5%BD%A9%E6%8C%89%E9%92%AE)、[AI Tag](/zh-CN/show/tag#AI%20%E9%A3%8E%E6%A0%BC%20-%20%E5%A4%9A%E5%BD%A9%E6%A0%87%E7%AD%BE)、[AI FloatButton](/zh-CN/basic/floatbutton#AI%20%E9%A3%8E%E6%A0%BC%20-%20%E5%A4%9A%E5%BD%A9%E6%82%AC%E6%B5%AE%E6%8C%89%E9%92%AE)。
+ 
+
+```jsx live=true dir="column"
+import React from 'react';
+import { Typography, Button, Tag, FloatButton } from '@douyinfe/semi-ui';
+import { IconAIBellLevel1, IconAIEditLevel2, IconAIFileLevel3, IconAIFilledLevel3, IconAIImageLevel3, IconAISearchLevel3, IconAIStrokedLevel3, IconAIWandLevel3, IconAILoading, IconAIFilledLevel1, IconAIEditLevel1 } from '@douyinfe/semi-icons';
+
+() => {
+    return (<div style={{ display: 'flex', flexDirection: 'column', rowGap: 20 }}>
+        <div key="AIToken" style={{ display: 'flex', flexDirection: 'column', rowGap: 10 }}>
+            <Typography.Title heading={5}>AI Token</Typography.Title>
+            <div style={{ display: 'flex', alignItems: 'center', columnGap: 10 }}>
+                <span>Purple</span>
+                <div style={{ display: 'inline-flex', columnGap: 4 }}>
+                    {(new Array(10).fill(1).map((i, index) => (
+                        <div key={index} style={{ width: 40, height: 40, backgroundColor: `rgba(var(--semi-ai-purple-${index}), 1)`, borderRadius: '50%' }} />
+                    )))}
+                </div>
+            </div>
+            <div style={{ display: 'flex', alignItems: 'center', columnGap: 10 }}>
+                <span>General</span>
+                <div style={{ display: 'inline-flex', columnGap: 4, }}>
+                    {(new Array(10).fill(1).map((i, index) => (
+                        <div key={index} style={{ width: 40, height: 40, background: `var(--semi-ai-general-${index})`, borderRadius: '50%' }} />
+                    )))}
+                </div>
+            </div>
+        </div>
+        <div key="AIIcon" style={{ display: 'flex', flexDirection: 'column', rowGap: 10 }}>
+            <Typography.Title heading={5} >AI Icon</Typography.Title>
+            <div style={{ display: 'flex', columnGap: 10 }}>
+                <IconAIBellLevel1 size="extra-large"/>
+                <IconAIEditLevel2 size="extra-large"/>
+                <IconAIFileLevel3 size="extra-large" />
+                <IconAIFilledLevel3 size="extra-large" />
+                <IconAIImageLevel3 size="extra-large" />
+                <IconAISearchLevel3 size="extra-large" />
+                <IconAIStrokedLevel3 size="extra-large" />
+                <IconAIWandLevel3 fill={['var(--semi-color-danger)', 'var(--semi-color-success)', 'var(--semi-color-primary)', 'var(--semi-color-warning)']} size="extra-large"/>
+                <IconAILoading size="extra-large"/>
+            </div>
+        </div>
+        <div style={{ display: 'flex', flexDirection: 'column', rowGap: 10 }}>
+            <Typography.Title heading={5}>AI Button</Typography.Title>
+            <div style={{ display: 'flex', rowGap: 16, flexDirection: 'column' }}>
+                <div style={{ display: 'flex', columnGap: 16 }}>
+                    <Button colorful theme="solid" type="primary" icon={<IconAIFilledLevel1 />}>Colorful</Button>
+                    <Button colorful theme="solid" type="primary" loading >Colorful</Button>
+                    <Button colorful theme="solid" type="primary" icon={<IconAIFilledLevel1 />} disabled >Colorful</Button>
+                </div>
+                <div style={{ display: 'flex', columnGap: 16 }}>
+                    <Button colorful theme="solid" type="tertiary" icon={<IconAIFilledLevel3 />}>Colorful</Button>
+                    <Button colorful theme="solid" type="tertiary" loading >Colorful</Button>
+                    <Button colorful theme="solid" type="tertiary" icon={<IconAIFilledLevel3 />} disabled >Colorful</Button>
+                </div>
+                <div style={{ display: 'flex', columnGap: 16 }}>
+                    <Button colorful theme="solid" type="primary" icon={<IconAIFilledLevel1 />} />
+                    <Button colorful theme="solid" type="primary" loading />
+                    <Button colorful theme="solid" type="primary" icon={<IconAIFilledLevel1 />} disabled />
+                    <Button colorful theme="solid" type="tertiary" icon={<IconAIFilledLevel3 />} />
+                    <Button colorful theme="solid" type="tertiary" loading />
+                    <Button colorful theme="solid" type="tertiary" icon={<IconAIFilledLevel3 />} />
+                </div>
+            </div>
+        </div>
+        <div style={{ display: 'flex', flexDirection: 'column', rowGap: 10 }}>
+            <Typography.Title heading={5} style={{ marginTop: 10 }}>AI Tag</Typography.Title>
+            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3,1fr)', gridGap: '10px', width: 'fit-content' }}>
+                <Tag colorful prefixIcon={<IconAIFilledLevel1 size="small"/>} type="solid" shape='circle' gradient>AI</Tag>
+                <Tag colorful prefixIcon={<IconAIFilledLevel3 size="small" />} type="light" shape='circle' gradient>AI</Tag>
+                <Tag colorful prefixIcon={<IconAIFilledLevel3 size="small"/>} type="ghost" shape='circle' gradient >AI</Tag>
+                <Tag colorful prefixIcon={<IconAIFilledLevel1 size="small"/>} type="solid" shape='circle' >AI</Tag>
+                <Tag colorful prefixIcon={<IconAIFilledLevel1 size="small" />} type="light" shape='circle'>AI</Tag>
+                <Tag colorful prefixIcon={<IconAIFilledLevel1 size="small"/>} type="ghost" shape='circle'>AI</Tag>
+            </div>
+        </div>
+        <div style={{ display: 'flex', flexDirection: 'column', rowGap: 10 }}>
+            <Typography.Title heading={5} style={{ marginTop: 10 }}>AI FloatButton</Typography.Title>
+            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3,1fr)', gridGap: '10px', width: 'fit-content' }}>
+                <FloatButton 
+                    icon={<IconAIEditLevel1 />}
+                    colorful
+                    size="large"
+                    badge={{ count: 'VIP', type: "danger" }}
+                    style={{ position: 'static' }} 
+                />
+            </div>
+        </div>
+    </div>);
+};
+```
+
+### AI Chat 组件构建对话
+
+本例中我们将联合使用 `AIChatInput` 和 `AIChatDialogue` 组件,构建一个适用于 `Multiple Agent` 场景的对话用例。
+更多示例及使用场景详见 [AIChatInput](/zh-CN/ai/aiChatInput)、[AIChatDialogue](/zh-CN/ai/aiChatDialogue)。前后端组合使用用例可参考[semi-ai-chat-demo](https://github.com/YannLynn/semi-ai-chat-demo)
+
+```jsx live=true dir="column" noInline=true
+import React, { useState, useCallback } from 'react';
+import { AIChatDialogue, AIChatInput, chatInputToMessage, Typography, Button } from '@douyinfe/semi-ui';
+import { IconFixedStroked, IconFeishuLogo, IconBookOpenStroked, IconGit, IconFigma, IconWord, IconClose, IconTemplateStroked, IconSearch } from '@douyinfe/semi-icons';
+
+const { Configure } = AIChatInput;
+
+const simpleIsEqual = (a, b) => {
+    if (a === b) {
+        return true;
+    }
+    if (Number.isNaN(a) && Number.isNaN(b)) {
+        return true;
+    }
+    if (typeof a !== 'object' || a === null || typeof b !== 'object' || b === null) {
+        return false;
+    }
+    const isArrayA = Array.isArray(a);
+    const isArrayB = Array.isArray(b);
+    if (isArrayA !== isArrayB) {
+        return false; 
+    }
+    const keysA = Object.keys(a);
+    const keysB = Object.keys(b);
+    if (keysA.length !== keysB.length) {
+        return false;
+    }
+    for (const key of keysA) {
+        if (!Object.prototype.hasOwnProperty.call(b, key)) {
+            return false;
+        }
+        if (!simpleIsEqual(a[key], b[key])) {
+            return false;
+        }
+    }
+    return true;
+};
+
+
+function AIChatInputWithDialogue() {
+    const inputOuterStyle = { margin: '12px', minHeight: 150, maxHeight: 300, flexShrink: 0 };
+    const editingInputOuterStyle = { margin: '12px 0px', maxHeight: 300, flexShrink: 0 };
+    const dialogueOuterStyle = { flex: 1, overflow: 'auto' };
+    const [sideBarVisible, setSideBarVisible] = useState(false);
+    const [messages, setMessages] = useState(defaultMessages); 
+    const [generating, setGenerating] = useState(false);
+    const [references, setReferences] = useState([]); 
+    const [sideBarContent, setSideBarContent] = useState({});
+
+    const renderLeftMenu = useCallback(() => (<>
+        <Configure.Select optionList={modelOptions} field="model" initValue="GPT-4o" />
+        <Configure.Button icon={<IconBookOpenStroked />} field="onlineSearch">联网搜索</Configure.Button>
+        <Configure.Mcp options={mcpOptions} />
+        <Configure.RadioButton options={radioButtonProps} field="thinkType" initValue="think"/>
+    </>), []);
+
+    const onChatsChange = useCallback((chats) => {
+        console.log('onChatsChange', chats);
+        setMessages(chats);
+    }, []);
+
+    const onContentChange = useCallback((content) => {
+        // console.log('onContentChange', content);
+    }, []);
+
+
+    const onReferenceClick = useCallback((item) => {
+        setReferences((references) => [...references, { ...item, id: `reference-${Date.now()}` }]);
+    }, []);
+
+    const handleReferenceDelete = useCallback((item) => {
+        const newReference = references.filter((ref) => ref.id !== item.id);
+        setReferences(newReference);
+    }, [references]);
+
+    const onMessageSend = useCallback((props) => {
+        setGenerating(true);
+        // 模拟发送请求
+        setMessages((messages) => [...messages, {
+            id: `message-${Date.now()}`,
+            ...chatInputToMessage(props),
+        }]);
+        setReferences([]);
+        setTimeout(() => {
+            setGenerating(false);
+        }, 100);
+        setTimeout(() => {
+            // 模拟接口返回
+            setMessages((messages) => {
+                return [...messages, {
+                    id: `message-${Date.now()}`,
+                    role: 'assistant',
+                    name: 'FE',
+                    content: "这是一条 mock 回复信息",
+                }];
+            });
+        }, 1000);
+    }, []);
+
+    const onEditMessageSend = useCallback((props) => {
+        const index = messages.findIndex((message) => message.editing);
+        const newMessages = [...messages.slice(0, index), {
+            id: `message-${Date.now()}`,
+            ...chatInputToMessage(props),
+        }];
+        setMessages(newMessages);
+    }, [messages]);
+
+    const handleEditingReferenceDelete = useCallback((item) => {
+        const newMessages = messages.map((message) => {
+            if (message.editing) {
+                message.references = message.references.filter((ref) => ref.id !== item.id);
+            }
+            return message;
+        });
+        setMessages(newMessages);
+    }, [messages]);
+
+    const messageEditRender = useCallback((props) => {
+        return (
+            <AIChatInput 
+                style={editingInputOuterStyle}
+                generating={false}
+                references={props.references}
+                uploadProps={{ ...uploadProps, defaultFileList: props.attachments }}
+                defaultContent={props.inputContents[0].text}
+                renderConfigureArea={renderLeftMenu} 
+                // onContentChange={onContentChange}
+                onMessageSend={onEditMessageSend}
+                onReferenceDelete={handleEditingReferenceDelete}
+            />
+        );
+    }, [messages, handleEditingReferenceDelete]);
+
+    const changeSideBarContent = useCallback((content) => {
+        setSideBarContent((oldContent) => {
+            if (!simpleIsEqual(content, oldContent)) {
+                setSideBarVisible(true);
+            } else {
+                setSideBarVisible(v => !v);
+            }
+            return content;
+        });
+    });
+
+    const onAnnotationClick = useCallback((annotations) => {
+        changeSideBarContent({
+            type: 'annotation',
+            value: annotations
+        });
+    }, [changeSideBarContent]);
+
+    const toggleSideBar = useCallback(() => {
+        setSideBarVisible(v => !v);
+    }, []);
+
+    const renderSideBarTitle = useCallback((content) => {
+        const { type, value } = content;
+        return <div style={{ display: 'flex', alignItems: 'center ', justifyContent: 'space-between', padding: 12, color: 'var(--semi-color-text)' }}>
+            {type === 'annotation' && <div style={{ fontSize: '16px', lineHeight: '22px', fontWeight: 600 }}>参考资料</div>}
+            {type === 'resource' && <div style={{ fontSize: '16px', lineHeight: '22px', fontWeight: 600 }}>产物列表</div>}
+            <Button onClick={toggleSideBar} theme="borderless" type="tertiary" icon={<IconClose />} style={{ padding: '0px', width: 24, height: 24 }} />
+        </div>;
+    }, [toggleSideBar]);
+
+    const renderSideBarBody = useCallback((content) => {
+        const { type, value = {} } = content;
+        if (type === 'annotation') {
+            return <div style={{ display: 'flex', flexDirection: 'column', rowGap: '12px', padding: '12px' }} >
+                {value.map((item, index) => (<div key={index} style={{ display: 'flex', flexDirection: 'column', rowGap: '8px' }} >
+                    <span style={{ display: 'flex', alignItems: 'center ', columnGap: 4 }}>
+                        <img style={{ width: 20, height: 20, borderRadius: '50%' }} src={item.logo}/>
+                        <span style={{ fontSize: '14px', lineHeight: '20px', fontWeight: 600, color: 'var(--semi-color-text-0)' }}>{item.title}</span>
+                    </span>
+                    <Typography.Paragraph ellipsis={{ rows: 3 }} style={{ fontSize: '12px', lineHeight: '16px', color: 'var(--semi-color-text-1)' }} >{item.detail}</Typography.Paragraph>
+                </div>))}
+            </div>;
+        } else if (type === 'resource') {
+            return <div style={{ display: 'flex', flexDirection: 'column', rowGap: '12px', padding: '12px' }} >
+                <div style={{ display: 'flex', gap: 12, alignItems: 'center', }}>
+                    <IconWord style={{ color: 'var(--semi-color-primary)' }} size='extra-large' /> {value.name}
+                </div>
+            </div>;
+        }
+        return <div>
+
+        </div>;
+    }, []);
+
+    const customRender = {
+        "resource": (item, message) => {
+            return <div 
+                style={{ 
+                    display: 'flex', 
+                    gap: 8, 
+                    backgroundColor: 'var(--semi-color-fill-0)', 
+                    padding: '12px 16px',
+                    justifyContent: 'center',
+                    alignItems: 'center',
+                    borderRadius: '12px',
+                    cursor: 'pointer'
+                }}
+                onClick={() => {
+                    changeSideBarContent({
+                        type: 'resource',
+                        value: item
+                    });
+                }}
+            >
+                <IconWord style={{ color: 'var(--semi-color-primary)' }} />
+                {item.name}
+            </div>;
+        },
+    };
+
+    return (
+        <div style={{ display: 'flex', columnGap: 10 }}>
+            <div style={{ display: 'flex', flexDirection: 'column', height: 'calc(100vh - 32px)', overflow: 'hidden', flexGrow: 1 }}>
+                <AIChatDialogue 
+                    style={dialogueOuterStyle}
+                    roleConfig={roleConfig}
+                    showReference={true}
+                    align="leftRight"
+                    mode="bubble"
+                    chats={messages}
+                    onChatsChange={onChatsChange}
+                    onReferenceClick={onReferenceClick}
+                    messageEditRender={messageEditRender}
+                    onAnnotationClick={onAnnotationClick}
+                    renderDialogueContentItem={customRender}
+                />
+                <AIChatInput 
+                    style={inputOuterStyle}
+                    placeholder={'输入内容或者上传内容'} 
+                    defaultContent={'我是一名<input-slot placeholder="[职业]">程序员</input-slot>,帮我实现<input-slot placeholder="[需求描述]">Multi Agent 场景下的聊天应用</input-slot>需求'}
+                    generating={generating}
+                    references={references}
+                    uploadProps={uploadProps}
+                    renderConfigureArea={renderLeftMenu} 
+                    onContentChange={onContentChange}
+                    onMessageSend={onMessageSend}
+                    onStopGenerate={() => setGenerating(false)}
+                    onReferenceDelete={handleReferenceDelete}
+                />
+            </div>
+            {sideBarVisible && <div 
+                style={{ flexShrink: 0, width: 300, height: 'calc(100vh - 32px)', borderRadius: '12px', border: '1px solid var(--semi-color-border)', flexShrink: 0 }}
+            >
+                {renderSideBarTitle(sideBarContent)}
+                {renderSideBarBody(sideBarContent)}
+            </div>}
+        </div>
+    );
+}
+
+
+const defaultMessages = [{
+    id: '1',
+    role: 'user',
+    content: '我想开发一个 Multi Agent 场景下的聊天应用,你能帮我设计一下吗?',
+    status: 'completed',
+}, {
+    id: '2',
+    role: 'assistant',
+    name: 'PM',
+    content: [{
+        type: 'message',
+        content: [{
+            type: 'input_text',
+            text: '收到。为保证方案可落地,我先明确目标与范围:\n\n- 目标:支持多 Agent 协同回复,用户可选择 Agent 或由系统自动分配\n- MVP 功能:\n  1) 基础对话(文本/图片/文件)\n  2) Agent 身份标识与头像\n  3) 正在输入与流式输出\n  4) 引用来源与工具结果展示\n- 约束:先做单会话,不做云端持久化;优先移动端适配\n\n接下来我会整理 PRD 要点并同步给设计与前端。',
+            annotations: [
+                {
+                    title: 'Semi Design',
+                    url: 'https://semi.design/zh-CN/start/getting-started',
+                    detail: 'Semi Design 是由抖音前端团队和MED产品设计团队设计、开发并维护的设计系统。作为一个全面、易用、优质的现代应用UI解决方案,Semi Design从字节跳动各业务线的复杂场景中提炼而来,目前已经支撑了近千个平台产品,服务了内外部超过10万用户',
+                    logo: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/card-meta-avatar-docs-demo.jpg'
+                },
+                {
+                    title: 'Semi DSM',
+                    url: 'https://semi.design/zh-CN/start/getting-started',
+                    detail: 'Semi DSM 支持全局、组件级别的样式定制,并在 Figma 和线上代码之间保持同步。使用 DSM,将 Semi Design 适配为 Any Design',
+                    logo: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/card-meta-avatar-docs-demo.jpg'
+                },
+                {
+                    title: 'Semi D2C',
+                    url: 'https://semi.design/zh-CN/start/getting-started',
+                    detail: 'Semi D2C 提供开箱即用的设计稿转代码:支持一键识别 Figma 页面中图层布局 + 设计系统组件,像素级还原设计稿,转译为 React JSX 和 CSS 代码。此外还提供了丰富的扩展能力,基于自定义插件系统快速打造团队专属的设计研发协作工具。',
+                    logo: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/card-meta-avatar-docs-demo.jpg'
+                }
+            ],
+        }],
+    }],
+}, {
+    id: '3',
+    role: 'assistant',
+    name: 'PM',
+    content: [{
+        type: 'message',
+        content: [{
+            type: 'input_text',
+            text: '生成的PRD如下,设计师会先根据此摘要出信息架构与关键页面',
+        }, {
+            type: 'resource',
+            name: 'PRD.doc',
+            size: '100KB',
+        }]
+    }],
+}, {
+    id: '4',
+    role: 'assistant',
+    name: 'UI',
+    content: [{
+        id: "rs_02175871288540800000000000000000000ffffac1598778c9aa5",
+        type: "reasoning",
+        summary: [
+            {
+                "type": "summary_text",
+                "text": "\n根据产品经理给的 PRD 绘制关键页面,我需要...."
+            }
+        ],
+        status: "completed"
+    }, {
+        type: 'function_call',
+        name: 'paint_key_pages',
+        arguments: "{\"file\":\"PRD\"}",
+        status: 'completed',
+    }, {
+        type: 'message',
+        content: [{
+            "type": "output_text",
+            "text": `设计初稿如下:\n\n- 信息架构:对话页(历史列表 | 消息流 | 工具卡片区)\n- 视觉:左侧展示 Agent 头像与名称标签,色块区分角色\n- 交互:\n  - 输入区支持 @Agent 快速切换与建议提示\n  - 流式输出时展示打字气泡与进度占位\n  - 工具结果以卡片/步骤条形式插入,可展开详情与复制\n\n我先出低保真线框,稍后补高保真与动效说明。`,
+        }],
+        status: "completed"
+    }],
+    status: 'completed',
+}, {
+    id: '5',
+    role: 'assistant',
+    name: 'FE',
+    content: `技术方案建议:\n\n- 技术栈:React + Semi UI,后端采用 WebSocket 或 SSE 支持流式响应\n- 数据模型:消息包含 id、role、name、content、status、references 等字段\n- 组件拆分:AIChatInput + AIChatDialogue;内容采用 Markdown 渲染,支持图片与文件点击\n- 性能:虚拟列表与滚动置底;长文本分块渲染;图片懒加载\n- 可观测性:埋点消息延迟、出错率、工具调用耗时\n\n若确认,我可先搭建页面骨架并接入 mock 数据进行联调。`,
+}];
+
+const roleConfig = {
+    user: {
+        name: 'User',
+        avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/22606991eh7uhfups/img/user.png'
+    },
+    assistant: new Map([
+        ['PM', {
+            name: '产品经理',
+            avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/22606991eh7uhfups/PM.png'
+        }],
+        ['UI', {
+            name: '设计师',
+            avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/22606991eh7uhfups/UI.png'
+        }],
+        ['FE', {
+            name: '前端开发',
+            avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/22606991eh7uhfups/FE.png'
+        }],
+    ]),
+};
+
+const uploadProps = {
+    action: "https://api.semi.design/upload"
+};
+
+const modelOptions = [
+    {
+        value: 'GPT-5',
+        label: 'GPT-5',
+        type: 'gpt',
+    },
+    {
+        value: 'GPT-4o',
+        label: 'GPT-4o',
+        type: 'gpt',
+    },
+    {
+        value: 'Claude 3.5 Sonnet',
+        label: 'Claude 3.5 Sonnet',
+        type: 'claude',
+    },
+];
+
+const mcpOptions = [
+    {
+        icon: <IconFeishuLogo />,
+        label: "飞书文档",
+        value: "feishu",
+    },
+    {
+        icon: <IconGit />,
+        label: "Github Mcp",
+        value: "github",
+    },
+    {
+        icon: <IconFigma />,
+        label: "IconFigma Mcp",
+        value: "IconFigma",
+    }
+];
+
+const radioButtonProps = [
+    { label: <IconTemplateStroked />, value: 'fast' },
+    { label: <IconSearch />, value: 'think' }
+];
+
+render(AIChatInputWithDialogue);
+```
+
+### FAQ 
+- **Chat 组件和 AI Chat 系列组件应该如何选型?**
+   - 如果场景比较简单,仅需要普通文字对话和简单文件图片展示,推荐 Chat 组件。
+        - [Chat](/zh-CN/plus/chat) 组件默认集成 input 输入和消息展示部分,优势是理解简单,能够快速上手;缺点是复杂的输入框或者消息展示需求定制相对困难,工作量大。
+   - 如果场景相对复杂,推荐将 AIChatInput 和 AIChatDialogue 组件搭配使用,优势如下:
+        - [AIChatInput](/zh-CN/ai/aiChatInput) 支持更复杂的样式定制。
+            1. 用户可以非常方便地定制左下角的[配置区域](/zh-CN/ai/aiChatInput#%E9%85%8D%E7%BD%AE%E5%8C%BA%E5%9F%9F)和右下角的[操作区域](/zh-CN/ai/aiChatInput#%E6%93%8D%E4%BD%9C%E5%8C%BA%E5%9F%9F);
+            2. 提供[富文本输入区](/zh-CN/ai/aiChatInput#%E5%AF%8C%E6%96%87%E6%9C%AC%E8%BE%93%E5%85%A5%E5%8C%BA)展示输入模版;
+            3. 默认支持[引用](/zh-CN/ai/aiChatInput#%E5%BC%95%E7%94%A8)展示;
+            4. 支持热键唤起的[技能模版](/zh-CN/ai/aiChatInput#%E6%8A%80%E8%83%BD%E5%8F%8A%E6%A8%A1%E7%89%88);
+            5. 支持自定义[ Input 扩展](/zh-CN/ai/aiChatInput#%E8%87%AA%E5%AE%9A%E4%B9%89%E6%89%A9%E5%B1%95)和[ TopSlot](/zh-CN/ai/aiChatInput#%E8%87%AA%E5%AE%9A%E4%B9%89%E6%B8%B2%E6%9F%93%E9%A1%B6%E9%83%A8%E5%8C%BA%E5%9F%9F),复杂展示也能轻松实现。
+        - [AIChatDialogue](/zh-CN/ai/aiChatDialogue) 消息展示的灵活性更高。
+            1. 组件默认支持 OpenAI 的 [Response](https://platform.openai.com/docs/api-reference/responses/create) / [Chat Completion](https://platform.openai.com/docs/api-reference/chat/create) Object 格式标准,调用[内部消息转换函数](/zh-CN/ai/aiChatDialogue#%E6%B6%88%E6%81%AF%E6%95%B0%E6%8D%AE%E8%BD%AC%E6%8D%A2)可轻松进行将 OpenAI 返回的结果转换为组件需要的数据结构。
+            2. 提供[根据消息类型的定制展示](/zh-CN/ai/aiChatDialogue#%E8%87%AA%E5%AE%9A%E4%B9%89%E6%B8%B2%E6%9F%93%E6%B6%88%E6%81%AF%E5%86%85%E5%AE%B9)的 API,方便快速实现消息展示。
+            3. 默认支持消息[引用](/zh-CN/ai/aiChatDialogue#%E5%BC%95%E7%94%A8)和[选择](/zh-CN/ai/aiChatDialogue#%E9%80%89%E6%8B%A9)操作。
+

+ 53 - 1
content/basic/button/index-en-US.md

@@ -52,7 +52,7 @@ function ButtonDemo() {
 
 -   `var(--semi-color-primary)`: main
 -   `var(--semi-color-secondary)`: secondary
--   `var(--semi-color-colored)`: third
+-   `var(--semi-color-tertiary)`: third
 -   `var(--semi-color-warning)`: warning
 -   `var(--semi-color-danger)`: danger
 
@@ -380,6 +380,56 @@ function ButtonDemo() {
 }
 ```
 
+### AI style - Colorful buttons
+
+Set `colorful` to get colorful buttons. Colorful buttons support all `theme`, and `type` only supports `primary` and `tertiary`.
+
+```jsx live=true dir="column"
+import React, { useState } from 'react';
+import { Button } from '@douyinfe/semi-ui';
+import { IconAIFilledLevel1, IconAIFilledLevel2, IconAIFilledLevel3 } from '@douyinfe/semi-icons';
+
+function ButtonDemo() {
+    return (['Colorful', undefined].map(content => (<div 
+        key={content}
+        style={{ display: 'flex', rowGap: 16, marginTop: 20, marginLeft: 10, flexDirection: 'column' }}
+    >
+        <div style={{ display: 'flex', columnGap: 16 }}>
+            <Button colorful theme="solid" type="primary" icon={<IconAIFilledLevel1 />}>{content}</Button>
+            <Button colorful theme="solid" type="primary" loading >{content}</Button>
+            <Button colorful theme="solid" type="primary" icon={<IconAIFilledLevel1 />} disabled >{content}</Button>
+            <Button colorful theme="solid" type="tertiary" icon={<IconAIFilledLevel3 />}>{content}</Button>
+            <Button colorful theme="solid" type="tertiary" loading >{content}</Button>
+            <Button colorful theme="solid" type="tertiary" icon={<IconAIFilledLevel3 />} disabled >{content}</Button>
+        </div>
+        <div style={{ display: 'flex', columnGap: 16 }}>
+            <Button colorful theme="light" type="primary" icon={<IconAIFilledLevel3 />}>{content}</Button>
+            <Button colorful theme="light" type="primary" loading >{content}</Button>
+            <Button colorful theme="light" type="primary" icon={<IconAIFilledLevel3 />} disabled >{content}</Button>
+            <Button colorful theme="light" type="tertiary" icon={<IconAIFilledLevel2 />}>{content}</Button>
+            <Button colorful theme="light" type="tertiary" loading >{content}</Button>
+            <Button colorful theme="light" type="tertiary" icon={<IconAIFilledLevel2 />} disabled >{content}</Button>
+        </div>
+        <div style={{ display: 'flex', columnGap: 16 }}>
+            <Button colorful theme="outline" type="primary" icon={<IconAIFilledLevel1 />}>{content}</Button>
+            <Button colorful theme="outline" type="primary" loading >{content}</Button>
+            <Button colorful theme="outline" type="primary" icon={<IconAIFilledLevel1 />} disabled >{content}</Button>
+            <Button colorful theme="outline" type="tertiary" icon={<IconAIFilledLevel2 />}>{content}</Button>
+            <Button colorful theme="outline" type="tertiary" loading >{content}</Button>
+            <Button colorful theme="outline" type="tertiary" icon={<IconAIFilledLevel2 />} disabled >{content}</Button>
+        </div>
+        <div style={{ display: 'flex', columnGap: 16 }}>
+            <Button colorful theme="borderless" type="primary" icon={<IconAIFilledLevel3 />}>{content}</Button>
+            <Button colorful theme="borderless" type="primary" loading >{content}</Button>
+            <Button colorful theme="borderless" type="primary" icon={<IconAIFilledLevel3 />} disabled >{content}</Button>
+            <Button colorful theme="borderless" type="tertiary" icon={<IconAIFilledLevel2 />}>{content}</Button>
+            <Button colorful theme="borderless" type="tertiary" loading >{content}</Button>
+            <Button colorful theme="borderless" type="tertiary" icon={<IconAIFilledLevel2 />} disabled >{content}</Button>
+        </div>
+    </div>)));
+}
+```
+
 ### Button Combination
 
 You can put multiple buttons in `ButtonGroup` In the container, by setting `size`, `disabled`, `type` You can uniformly set the button size in the button combination, whether disabled and type.
@@ -528,6 +578,7 @@ function SplitButtonDemo(){
 | block               | Set the button to the block level button                                                                                                                                                  | boolean                          | false     |
 | className           | Class name                                                                                                                                                                                | string                           |           |
 | contentClassName | content className                                                                                                                                                                         |  string | -         |
+| colorful | Colorful buttons, supported since version 2.86.0 |  boolean | false |
 | disabled            | Prohibited status                                                                                                                                                                         | boolean                          | false     |
 | htmlType           | Set the `button` native `type` value, optional values: `"button"`, `"reset"`, `"submit"`                                                                                                  | string                           | "button"  |
 | icon                | Icon                                                                                                                                                                                      | ReactNode              |           |
@@ -549,6 +600,7 @@ function SplitButtonDemo(){
 | ---------- |--------------------------------------------------------------------------------------------------------------------------------------------------| ------- | --------- |---------|
 | aria-label | Label of the button group                                                                                                                        | string  | - | |
 | className  | Custom class name                                                                                                                                | string   | - | |
+| colorful | Colorful buttons |  boolean | false | 2.86.0 |
 | disabled   | Disabled status                                                                                                                                  | boolean | false | |
 | size       | Button size, optional value: `"large"`,`"default"`,`"small"`                                                                                     | string  | "default" |
 | style      | Custom style                                                                                                                                     | CSSProperties   | - | 2.20.0 |

+ 52 - 0
content/basic/button/index.md

@@ -328,6 +328,56 @@ function ButtonDemo() {
 }
 ```
 
+### AI 风格 - 多彩按钮
+
+设置 `colorful` 即可获得多彩按钮,多彩按钮支持所有的 `theme` , `type` 仅支持 `primary` 及 `tertiary`。
+
+```jsx live=true dir="column"
+import React, { useState } from 'react';
+import { Button } from '@douyinfe/semi-ui';
+import { IconAIFilledLevel1, IconAIFilledLevel2, IconAIFilledLevel3 } from '@douyinfe/semi-icons';
+
+function ButtonDemo() {
+    return (['Colorful', undefined].map(content => (<div 
+        key={content}
+        style={{ display: 'flex', rowGap: 16, marginTop: 20, marginLeft: 10, flexDirection: 'column' }}
+    >
+        <div style={{ display: 'flex', columnGap: 16 }}>
+            <Button colorful theme="solid" type="primary" icon={<IconAIFilledLevel1 />}>{content}</Button>
+            <Button colorful theme="solid" type="primary" loading >{content}</Button>
+            <Button colorful theme="solid" type="primary" icon={<IconAIFilledLevel1 />} disabled >{content}</Button>
+            <Button colorful theme="solid" type="tertiary" icon={<IconAIFilledLevel3 />}>{content}</Button>
+            <Button colorful theme="solid" type="tertiary" loading >{content}</Button>
+            <Button colorful theme="solid" type="tertiary" icon={<IconAIFilledLevel3 />} disabled >{content}</Button>
+        </div>
+        <div style={{ display: 'flex', columnGap: 16 }}>
+            <Button colorful theme="light" type="primary" icon={<IconAIFilledLevel3 />}>{content}</Button>
+            <Button colorful theme="light" type="primary" loading >{content}</Button>
+            <Button colorful theme="light" type="primary" icon={<IconAIFilledLevel3 />} disabled >{content}</Button>
+            <Button colorful theme="light" type="tertiary" icon={<IconAIFilledLevel2 />}>{content}</Button>
+            <Button colorful theme="light" type="tertiary" loading >{content}</Button>
+            <Button colorful theme="light" type="tertiary" icon={<IconAIFilledLevel2 />} disabled >{content}</Button>
+        </div>
+        <div style={{ display: 'flex', columnGap: 16 }}>
+            <Button colorful theme="outline" type="primary" icon={<IconAIFilledLevel1 />}>{content}</Button>
+            <Button colorful theme="outline" type="primary" loading >{content}</Button>
+            <Button colorful theme="outline" type="primary" icon={<IconAIFilledLevel1 />} disabled >{content}</Button>
+            <Button colorful theme="outline" type="tertiary" icon={<IconAIFilledLevel2 />}>{content}</Button>
+            <Button colorful theme="outline" type="tertiary" loading >{content}</Button>
+            <Button colorful theme="outline" type="tertiary" icon={<IconAIFilledLevel2 />} disabled >{content}</Button>
+        </div>
+        <div style={{ display: 'flex', columnGap: 16 }}>
+            <Button colorful theme="borderless" type="primary" icon={<IconAIFilledLevel3 />}>{content}</Button>
+            <Button colorful theme="borderless" type="primary" loading >{content}</Button>
+            <Button colorful theme="borderless" type="primary" icon={<IconAIFilledLevel3 />} disabled >{content}</Button>
+            <Button colorful theme="borderless" type="tertiary" icon={<IconAIFilledLevel2 />}>{content}</Button>
+            <Button colorful theme="borderless" type="tertiary" loading >{content}</Button>
+            <Button colorful theme="borderless" type="tertiary" icon={<IconAIFilledLevel2 />} disabled >{content}</Button>
+        </div>
+    </div>)));
+}
+```
+
 ### 按钮组合
 
 可以将多个按钮放入`ButtonGroup`的容器中,通过设置`size`,`disabled`,`type`可统一设置按钮组合中的按钮尺寸,是否禁用和类型。
@@ -476,6 +526,7 @@ function SplitButtonDemo(){
 | block               | 将按钮设置为块级按钮                                                                                                  | bool                            | false     |
 | className           | 类名                                                                                                          | string                          |           |
 | contentClassName | 内容区域 className |  string | 无 |
+| colorful | 多彩按钮,自 2.86.0 版本开始支持 |  boolean | false |
 | disabled            | 禁用状态                                                                                                        | boolean                         | false     |
 | htmlType           | 设置 `button` 原生的 `type` 值,可选值:`button`、`reset`、`submit`                                                      | string                          | "button"  |
 | icon                | 图标                                                                                                          | ReactNode               |           |
@@ -497,6 +548,7 @@ function SplitButtonDemo(){
 | -------- | -------------| ------- | --------- |---- |
 | aria-label | 按钮组的标签 | string  | - | |
 | className  | 自定义类名   | string  | - | |
+| colorful | 多彩按钮,自 2.86.0 版本开始支持 |  boolean | false |
 | disabled   | 禁用状态     | boolean | false | |
 | size       | 按钮大小,可选值:`large`、`default`、`small` | string  | "default" | |
 | style      | 自定义样式   | CSSProperties   | - | 2.20.0 |

+ 1 - 1
content/basic/divider/index-en-US.md

@@ -1,6 +1,6 @@
 ---
 localeCode: en-US
-order: 22
+order: 23
 category: Basic
 title:  Divider
 icon: doc-divider

+ 1 - 1
content/basic/divider/index.md

@@ -1,6 +1,6 @@
 ---
 localeCode: zh-CN
-order: 22
+order: 23
 category: 基础 
 title:  Divider 分割线 
 icon: doc-divider 

+ 240 - 0
content/basic/floatbutton/index-en-US.md

@@ -0,0 +1,240 @@
+---
+localeCode: en-US
+order: 21
+category: Basic
+title:  FloatButton
+icon: doc-floatButton
+brief: A floating button is an actionable button that can float on the page
+showNew: true
+---
+
+## Demos
+
+### How to import
+
+FloatButton is supported since 2.85.0.
+
+```jsx import
+import { FloatButton } from '@douyinfe/semi-ui';
+```
+
+### Basic usage
+
+```jsx live=true
+import React from 'react';
+import { FloatButton } from '@douyinfe/semi-ui';
+import { IconAIEditLevel1 } from '@douyinfe/semi-icons';
+
+() => {
+    const onClick = () => {
+        console.log('float button clicked');
+    };
+
+    return (<>
+        <span>Basic usage: Row one, third column at the bottom right of the page </span>
+        <FloatButton icon={<IconAIEditLevel1 />} style={{ bottom: '270px' }} onClick={onClick}/>
+    </>
+    );
+};
+```
+
+### Size
+
+Three sizes are supported: default, small, large.
+
+```jsx live=true
+import React from 'react';
+import { FloatButton } from '@douyinfe/semi-ui';
+import { IconAIEditLevel1 } from '@douyinfe/semi-icons';
+
+() => {
+    const onClick = () => {
+        console.log('float button clicked');
+    };
+    return (<>
+        <span>Large size: Row two, third column at the bottom right of the page </span>
+        <FloatButton size="large" icon={<IconAIEditLevel1 />} style={{ bottom: '200px' }} onClick={onClick}/>
+    </>);
+};
+```
+
+### Shape
+
+Two shapes are defined by default: square (default) and circle.
+
+```jsx live=true
+import React from 'react';
+import { FloatButton } from '@douyinfe/semi-ui';
+import { IconAIEditLevel1 } from '@douyinfe/semi-icons';
+
+() => {
+    const onClick = () => {
+        console.log('float button clicked');
+    };
+    return (<>
+        <span>Square: Row three, third column at the bottom right of the page </span>
+        <FloatButton shape="square" icon={<IconAIEditLevel1 />} style={{ bottom: '150px' }} onClick={onClick}/>
+    </>);
+};
+```
+
+### Click to jump
+
+You can set the jump address through `href`, and `target` specifies the window or frame in which the target web page should be opened.
+
+```jsx live=true
+import React from 'react';
+import { FloatButton } from '@douyinfe/semi-ui';
+import { IconAIEditLevel1 } from '@douyinfe/semi-icons';
+
+() => {
+    const onClick = () => {
+        console.log('float button clicked');
+    };
+    return (<>
+        <span>Click to jump: Row four, third column at the bottom right of the page</span>
+        <FloatButton
+            icon={<IconAIEditLevel1 />} 
+            style={{ bottom: '100px' }} 
+            href={'https://semi.design'}
+            target={'_blank'}
+        />
+    </>);
+};
+```
+
+### AI style - Colorful floating buttons
+
+You can set `colorful` to true to display colorful floating buttons.
+
+```jsx live=true
+import React from 'react';
+import { FloatButton } from '@douyinfe/semi-ui';
+import { IconAIEditLevel1 } from '@douyinfe/semi-icons';
+
+() => {
+    const onClick = () => {
+        console.log('float button clicked');
+    };
+    return (<>
+        <span>Colorful buttons: The first column at the bottom right of the page</span>
+        <FloatButton
+            colorful
+            icon={<IconAIEditLevel1 />} 
+            style={{ bottom: '110px', insetInlineEnd: '150px' }} 
+            href={'https://semi.design'}
+            target={'_blank'}
+        />
+    </>);
+};
+```
+
+### Badge
+
+```jsx live=true
+import React from 'react';
+import { FloatButton } from '@douyinfe/semi-ui';
+import { IconAIEditLevel1 } from '@douyinfe/semi-icons';
+
+() => {
+    return (<>
+        <span>With badge: second column from the bottom right of the page</span>
+        <FloatButton
+            disabled
+            icon={<IconAIEditLevel1 />}  
+            badge={{ dot: true, type: 'danger' }} 
+            style={{ bottom: 270, insetInlineEnd: '100px' }} 
+        />
+        <FloatButton
+            badge={{ count: 1000, overflowCount: 999 }} 
+            size={"large"}
+            icon={<IconAIEditLevel1 />}  
+            style={{ bottom: 210, insetInlineEnd: 100 }} 
+        />
+        <FloatButton 
+            icon={<IconAIEditLevel1 />}  
+            badge={{ dot: true }} 
+            colorful 
+            style={{ bottom: 170, insetInlineEnd: 100 }} 
+        />
+        <FloatButton 
+            icon={<IconAIEditLevel1 />}  
+            colorful
+            size="large"
+            badge={{ count: 'VIP', type: "danger" }}
+            style={{ bottom: 110, insetInlineEnd: 100 }} 
+        />
+    </>);
+};
+```
+
+### Floating button Group
+
+Subitems can be passed in via `items`.
+
+```jsx live=true
+import React from 'react';
+import { FloatButtonGroup } from '@douyinfe/semi-ui';
+import { IconAIEditLevel1, IconAIStrokedLevel3, IconSearchStroked, IconHelpCircleStroked } from '@douyinfe/semi-icons';
+
+() => {
+    return (<>
+        <span>页面右下方最后一行</span>
+        <FloatButtonGroup 
+            style={{
+                insetInlineEnd: 24,
+                bottom: 50,
+            }}
+            items={[
+                {
+                    icon: <IconAIStrokedLevel3 />,
+                    content: "Edit"
+                },
+                {
+                    icon: <IconSearchStroked />,
+                    content: "Search"
+                },
+                {
+                    icon: <IconHelpCircleStroked />,
+                    content: "Help"
+                }
+            ]}
+        />
+    </>);
+};
+```
+
+## API Reference
+
+### FloatButton
+
+| Properties | Instructions | Type | Default |
+|-----|-----|------|-------|
+| badge | Badge parameters | [BadgeProps](/en-US/show/badge#API%E5%8F%82%E8%80%83) | - |
+| colorful | Use colorful floating buttons | boolean | false |
+| className | Style class name |  string | - |
+| disabled | Disabled state | boolean | false|
+| href | Click the jump link, the same as [href](https://developer.mozilla.org/zh-CN/docs/Web/API/Location/href) | string | - |
+| icon | Icon | ReactNode | - |
+| onClick | Click callback function | string | - |
+| shape | Shape, supports round, square | string | round |
+| size | Size, supports default, small, large | string | default|
+| style | Style | CSSProperties  | - |
+| target | Specifies where to display the URL of the link, same as [target](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Reference/Elements/a#target) | string | - |
+
+### FloatButtonGroupItem
+
+Add the following parameters based on FloatButtonProps
+
+| Properties | Instructions | Type | Default |
+|-----|-----|------|-------|
+| content | Text content | String | - |
+
+### FloatButtonGroup
+
+| Properties | Instructions | Type | Default |
+|-----|-----|------|-------|
+| className | Style class name |  string | - |
+| disabled | Disabled state | boolean | false|
+| items | Information about a single child | FloatButtonGroupItem | - |
+| style | style | CSSProperties  | - |

+ 240 - 0
content/basic/floatbutton/index.md

@@ -0,0 +1,240 @@
+---
+localeCode: zh-CN
+order: 21
+category: 基础 
+title: FloatButton 悬浮按钮
+icon: doc-floatButton
+brief: 悬浮按钮是可以悬浮在页面上的可操作按钮
+showNew: true
+---
+
+## 代码演示
+
+### 如何引入
+
+FloatButton 自 2.85.0 支持。
+
+```jsx import
+import { FloatButton } from '@douyinfe/semi-ui';
+```
+
+### 基本用法
+
+```jsx live=true
+import React from 'react';
+import { FloatButton } from '@douyinfe/semi-ui';
+import { IconAIEditLevel1 } from '@douyinfe/semi-icons';
+
+() => {
+    const onClick = () => {
+        console.log('float button clicked');
+    };
+
+    return (<>
+        <span>基本使用:页面右下第三列 1 </span>
+        <FloatButton icon={<IconAIEditLevel1 />} style={{ bottom: '270px' }} onClick={onClick}/>
+    </>
+    );
+};
+```
+
+### 尺寸
+
+支持三种尺寸:默认,小,大。
+
+```jsx live=true
+import React from 'react';
+import { FloatButton } from '@douyinfe/semi-ui';
+import { IconAIEditLevel1 } from '@douyinfe/semi-icons';
+
+() => {
+    const onClick = () => {
+        console.log('float button clicked');
+    };
+    return (<>
+        <span>大尺寸:页面右下第三列 2</span>
+        <FloatButton size="large" icon={<IconAIEditLevel1 />} style={{ bottom: '200px' }} onClick={onClick}/>
+    </>);
+};
+```
+
+### 形状
+
+默认定义了两种形状:square(默认)、circle。
+
+```jsx live=true
+import React from 'react';
+import { FloatButton } from '@douyinfe/semi-ui';
+import { IconAIEditLevel1 } from '@douyinfe/semi-icons';
+
+() => {
+    const onClick = () => {
+        console.log('float button clicked');
+    };
+    return (<>
+        <span>方形:页面右下第三列 3</span>
+        <FloatButton shape="square" icon={<IconAIEditLevel1 />} style={{ bottom: '150px' }} onClick={onClick}/>
+    </>);
+};
+```
+
+### 点击跳转
+
+可通过 `href` 设置跳转地址, `target` 指定目标网页应该在哪个窗口或框架中打开。
+
+```jsx live=true
+import React from 'react';
+import { FloatButton } from '@douyinfe/semi-ui';
+import { IconAIEditLevel1 } from '@douyinfe/semi-icons';
+
+() => {
+    const onClick = () => {
+        console.log('float button clicked');
+    };
+    return (<>
+        <span>点击跳转:页面右下第三列 4</span>
+        <FloatButton
+            icon={<IconAIEditLevel1 />} 
+            style={{ bottom: '100px' }} 
+            href={'https://semi.design'}
+            target={'_blank'}
+        />
+    </>);
+};
+```
+
+### AI 风格 - 多彩悬浮按钮
+
+可设置 `colorful` 为 true,展示多彩的悬浮按钮。
+
+```jsx live=true
+import React from 'react';
+import { FloatButton } from '@douyinfe/semi-ui';
+import { IconAIEditLevel1 } from '@douyinfe/semi-icons';
+
+() => {
+    const onClick = () => {
+        console.log('float button clicked');
+    };
+    return (<>
+        <span>多彩按钮:页面右下第一列</span>
+        <FloatButton
+            colorful
+            icon={<IconAIEditLevel1 />} 
+            style={{ bottom: '110px', insetInlineEnd: '150px' }} 
+            href={'https://semi.design'}
+            target={'_blank'}
+        />
+    </>);
+};
+```
+
+### 带徽章的
+
+```jsx live=true
+import React from 'react';
+import { FloatButton } from '@douyinfe/semi-ui';
+import { IconAIEditLevel1 } from '@douyinfe/semi-icons';
+
+() => {
+    return (<>
+        <span>带徽章:页面右下第二列</span>
+        <FloatButton
+            disabled
+            icon={<IconAIEditLevel1 />}  
+            badge={{ dot: true, type: 'danger' }} 
+            style={{ bottom: 270, insetInlineEnd: '100px' }} 
+        />
+        <FloatButton
+            badge={{ count: 1000, overflowCount: 999 }} 
+            size={"large"}
+            icon={<IconAIEditLevel1 />}  
+            style={{ bottom: 210, insetInlineEnd: 100 }} 
+        />
+        <FloatButton 
+            icon={<IconAIEditLevel1 />}  
+            badge={{ dot: true }} 
+            colorful 
+            style={{ bottom: 170, insetInlineEnd: 100 }} 
+        />
+        <FloatButton 
+            icon={<IconAIEditLevel1 />}  
+            colorful
+            size="large"
+            badge={{ count: 'VIP', type: "danger" }}
+            style={{ bottom: 110, insetInlineEnd: 100 }} 
+        />
+    </>);
+};
+```
+
+### 悬浮按钮组
+
+可通过  `items` 传入子项
+
+```jsx live=true
+import React from 'react';
+import { FloatButtonGroup } from '@douyinfe/semi-ui';
+import { IconAIEditLevel1, IconAIStrokedLevel3, IconSearchStroked, IconHelpCircleStroked } from '@douyinfe/semi-icons';
+
+() => {
+    return (<>
+        <span>The last row at the bottom right of the page</span>
+        <FloatButtonGroup 
+            style={{
+                insetInlineEnd: 24,
+                bottom: 50,
+            }}
+            items={[
+                {
+                    icon: <IconAIStrokedLevel3 />,
+                    content: "编辑"
+                },
+                {
+                    icon: <IconSearchStroked />,
+                    content: "搜索"
+                },
+                {
+                    icon: <IconHelpCircleStroked />,
+                    content: "帮助"
+                }
+            ]}
+        />
+    </>);
+};
+```
+
+## API参考
+
+### FloatButton
+
+| 属性 | 说明 | 类型 | 默认值 |
+|-----|-----|------|-------|
+| badge | 徽章参数 | [BadgeProps](/zh-CN/show/badge#API%E5%8F%82%E8%80%83) | - |
+| colorful | 多彩悬浮按钮 | boolean | false |
+| className | 样式类名 |  string | - |
+| disabled | 禁用状态 | boolean | false|
+| href | 点击跳转的链接, 同 [href](https://developer.mozilla.org/zh-CN/docs/Web/API/Location/href) | string | - |
+| icon | 显示图标 | ReactNode | - |
+| onClick | 点击回调函数 | string | - |
+| shape | 样式,支持 round、 square | string | round |
+| size | 尺寸,支持 default、small、large | string | default |
+| style | 样式 | CSSProperties  | - |
+| target | 指定在何处显示链接的 URL, 同 [target](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Reference/Elements/a#target) | string | - |
+
+### FloatButtonGroupItem
+
+在 FloatButtonProps 基础上增加以下参数
+
+| 属性 | 说明 | 类型 | 默认值 |
+|-----|-----|------|-------|
+| content | 文本内容 | String | - |
+
+### FloatButtonGroup
+
+| 属性 | 说明 | 类型 | 默认值 |
+|-----|-----|------|-------|
+| className | 样式类名 |  string | - |
+| disabled | 禁用状态 | boolean | false|
+| items | 单个子项的信息 | FloatButtonGroupItem | - |
+| style | 样式 | CSSProperties  | - |

+ 87 - 1
content/basic/icon/index-en-US.md

@@ -1,6 +1,6 @@
 ---
 localeCode: en-US
-order: 23
+order: 24
 category: Basic
 title: Icon
 subTitle: Icon
@@ -9,7 +9,12 @@ brief: Semantic vector graphics.
 ---
 
 ## Icon List
+The default icon set `@douyinfe/semi-icons` includes three sets of icons: surface, linear, and AI. Surface icons, linear icons, and monochrome icons in AI icons have no color by default, and the color can be changed through the css color attribute.
+Dual-color and multi-color icons in AI icons have default colors, which can be changed via fill.
 
+AI icons are available since v2.86.0.
+
+`@douyinfe/semi-icons-lab` is a color icon set, which needs to be installed separately and cannot be changed. The lab icon set is provided after v2.48
 
 <div style={{display: "none"}}>
 @douyinfe/semi-icons icon list:
@@ -17,6 +22,7 @@ brief: Semantic vector graphics.
 IconAbsoluteStroked
 IconActivity
 IconAlarm
+IconAlarmStroked
 IconAlertCircle
 IconAlertTriangle
 IconAlignBottom
@@ -57,6 +63,7 @@ IconBell
 IconBellStroked
 IconBold
 IconBolt
+IconBook
 IconBookH5Stroked
 IconBookOpenStroked
 IconBookStroked
@@ -71,18 +78,22 @@ IconBrackets
 IconBranch
 IconBriefStroked
 IconBriefcase
+IconBriefcaseStroked
 IconBulb
 IconButtonStroked
 IconBytedanceLogo
 IconCalendar
 IconCalendarClock
+IconCalendarClockStroked
 IconCalendarStroked
 IconCamera
+IconCameraStroked
 IconCandlestickChartStroked
 IconCaretdown
 IconCaretup
 IconCarouselStroked
 IconCart
+IconCartStroked
 IconCaseSensitive
 IconCenterLeftStroked
 IconCenterRightStroked
@@ -102,12 +113,14 @@ IconChevronUp
 IconChevronUpDown
 IconClear
 IconClock
+IconClockStroked
 IconClose
 IconCloud
 IconCloudStroked
 IconCloudUploadStroked
 IconCode
 IconCodeStroked
+IconCoinMoney
 IconCoinMoneyStroked
 IconColorPalette
 IconColumnsStroked
@@ -126,10 +139,12 @@ IconCopyAdd
 IconCopyStroked
 IconCornerRadiusStroked
 IconCreditCard
+IconCreditCardStroked
 IconCrop
 IconCrossCircleStroked
 IconCrossStroked
 IconCrown
+IconCrownStroked
 IconCustomerSupport
 IconCustomerSupportStroked
 IconCustomize
@@ -144,11 +159,13 @@ IconDivide
 IconDongchediLogo
 IconDoubleChevronLeft
 IconDoubleChevronRight
+IconDownCircle
 IconDownCircleStroked
 IconDownload
 IconDownloadStroked
 IconDuration
 IconEdit
+IconEdit2
 IconEdit2Stroked
 IconEditStroked
 IconElementStroked
@@ -160,7 +177,10 @@ IconExternalOpen
 IconExternalOpenStroked
 IconEyeClosed
 IconEyeClosedSolid
+IconEyeClosedSolidStroked
+IconEyeClosedStroked
 IconEyeOpened
+IconEyeOpenedStroked
 IconEyedropper
 IconFacebook
 IconFaceuLogo
@@ -176,13 +196,16 @@ IconFilledArrowDown
 IconFilledArrowUp
 IconFilpVertical
 IconFilter
+IconFilterStroked
 IconFingerLeftStroked
 IconFixedStroked
 IconFlag
+IconFlagStroked
 IconFlipHorizontal
 IconFlowChartStroked
 IconFolder
 IconFolderOpen
+IconFolderOpenStroked
 IconFolderStroked
 IconFollowStroked
 IconFont
@@ -198,6 +221,8 @@ IconGithubLogo
 IconGitlabLogo
 IconGlobe
 IconGlobeStroke
+IconGlobeStrokeStroked
+IconGlobeStroked
 IconGridRectangle
 IconGridSquare
 IconGridStroked
@@ -224,9 +249,11 @@ IconHn
 IconHome
 IconHomeStroked
 IconHorn
+IconHornStroked
 IconHourglass
 IconHourglassStroked
 IconIdCard
+IconIdCardStroked
 IconIdentity
 IconImage
 IconImageStroked
@@ -251,6 +278,7 @@ IconKey
 IconKeyStroked
 IconLanguage
 IconLayers
+IconLeftCircle
 IconLeftCircleStroked
 IconLightningStroked
 IconLikeHeart
@@ -279,6 +307,9 @@ IconMember
 IconMenu
 IconMicrophone
 IconMicrophoneOff
+IconMicrophoneOffStroked
+IconMicrophoneStroked
+IconMiniPlayer
 IconMinimize
 IconMinus
 IconMinusCircle
@@ -288,21 +319,26 @@ IconModalStroked
 IconMoneyExchangeStroked
 IconMonitorStroked
 IconMoon
+IconMoonStroked
 IconMore
 IconMoreStroked
 IconMusic
 IconMusicNoteStroked
 IconMute
+IconMuteStroked
 IconNineGridStroked
+IconNoteMoney
 IconNoteMoneyStroked
 IconOption
 IconOrderedList
 IconOrderedListStroked
 IconPaperclip
+IconPaperclipStroked
 IconPause
 IconPercentage
 IconPhone
 IconPhoneStroke
+IconPhoneStroked
 IconPieChart2Stroked
 IconPieChartStroked
 IconPiechartH5Stroked
@@ -315,6 +351,7 @@ IconPlusCircleStroked
 IconPlusStroked
 IconPriceTag
 IconPrint
+IconPrize
 IconPrizeStroked
 IconPulse
 IconPuzzle
@@ -324,6 +361,7 @@ IconQuit
 IconQuote
 IconRadio
 IconRankingCardStroked
+IconRealSize
 IconRealSizeStroked
 IconRedo
 IconRedoStroked
@@ -340,10 +378,12 @@ IconRotationStroked
 IconRoute
 IconRowsStroked
 IconSafe
+IconSafeStroked
 IconSave
 IconSaveStroked
 IconScan
 IconScissors
+IconScissorsStroked
 IconSearch
 IconSearchStroked
 IconSectionStroked
@@ -355,12 +395,14 @@ IconServer
 IconServerStroked
 IconSetting
 IconSettingStroked
+IconShare
 IconShareMoneyStroked
 IconShareStroked
 IconShield
 IconShieldStroked
 IconShift
 IconShoppingBag
+IconShoppingBagStroked
 IconShrink
 IconShrinkScreenStroked
 IconSidebar
@@ -386,6 +428,7 @@ IconStopwatchStroked
 IconStoryStroked
 IconStrikeThrough
 IconSun
+IconSunStroked
 IconSync
 IconTabArrowStroked
 IconTabsStroked
@@ -393,6 +436,7 @@ IconTaskMoneyStroked
 IconTemplate
 IconTemplateStroked
 IconTerminal
+IconTestScore
 IconTestScoreStroked
 IconText
 IconTextRectangle
@@ -400,6 +444,7 @@ IconTextStroked
 IconThumbUpStroked
 IconTick
 IconTickCircle
+IconTicketCode
 IconTicketCodeExchangeStroked
 IconTicketCodeStroked
 IconTiktokLogo
@@ -432,9 +477,11 @@ IconUser
 IconUserAdd
 IconUserCardPhone
 IconUserCardVideo
+IconUserCardVideoStroked
 IconUserCircle
 IconUserCircleStroked
 IconUserGroup
+IconUserList
 IconUserListStroked
 IconUserSetting
 IconUserStroked
@@ -448,8 +495,11 @@ IconVideoStroked
 IconVideoUrlStroked
 IconVigoLogo
 IconVolume1
+IconVolume1Stroked
 IconVolume2
+IconVolume2Stroked
 IconVolumnSilent
+IconVolumeSilentStroked
 IconVoteStroked
 IconVoteVideoStroked
 IconWeibo
@@ -457,6 +507,7 @@ IconWholeWord
 IconWifi
 IconWindowAdaptionStroked
 IconWrench
+IconWrenchStroked
 IconXiguaLogo
 IconYoutube
 
@@ -637,7 +688,41 @@ import { IconLikeHeart, IconFlag, IconLock, IconUnlock } from '@douyinfe/semi-ic
 );
 ```
 
+### Bicolor icon
+
+The color of the two-color icon can be set through the `fill` attribute, which supports string and string[].
+
+```jsx live=true
+import React from 'react';
+import { IconAIWandLevel2, IconAIFilledLevel2 } from '@douyinfe/semi-icons';
+
+() => (
+    <div>
+        <IconAIWandLevel2 fill={['var(--semi-color-danger)', 'var(--semi-color-success)']} style={{ marginRight: 10 }} size="extra-large"/>
+        <IconAIFilledLevel2 fill={'var(--semi-color-success)'} size="extra-large"/>
+    </div>
+);
+```
+
+### Multicolor buttons
+
+Multi-color icon, the current multi-color button can pass in four colors. The color can be set through the `fill` attribute, which supports string and string[].
+
+```jsx live=true
+import React from 'react';
+import { IconAIBellLevel3, IconAIWandLevel3, IconAIFilledLevel3 } from '@douyinfe/semi-icons';
+
+() => (
+    <div>
+        <IconAIBellLevel3 style={{ marginRight: 10 }} size="extra-large"/>
+        <IconAIWandLevel3 fill={['var(--semi-color-danger)', 'var(--semi-color-success)', 'var(--semi-color-primary)', 'var(--semi-color-warning)']} style={{ marginRight: 10 }} size="extra-large"/>
+        <IconAIFilledLevel3 fill={['var(--semi-color-primary)', 'var(--semi-color-success)']} size="extra-large"/>
+    </div>
+);
+```
+
 ### Custom icon
+
 You can use custom icons to pass in Icon components
 Icon component supports size, rotate, spin and other attributes
 
@@ -691,6 +776,7 @@ import StarIcon from './star.svg';
 | Properties  | Illustrate        | Type            | Default |
 |-------|-------------|-----------------|--------|
 | className | class name | string | none |
+| fill | Fill color for bicolor, multicolor icons | string \| string[] | None |
 | onClick | Callback event of clicking the icon | (e: Event) => void | None |
 | onMouseDown | The callback event of mouse button press >=v1.21 | (e: Event) => void | None |
 | onMouseEnter | Callback event of entering icon | (e: Event) => void | None |

+ 114 - 6
content/basic/icon/index.md

@@ -1,6 +1,6 @@
 ---
 localeCode: zh-CN
-order: 23
+order: 24
 category: 基础
 title:  Icon 图标
 icon: doc-icons
@@ -9,7 +9,10 @@ brief: 语义化的矢量图形。
 
 ## 图标列表
 
-默认的图标集 `@douyinfe/semi-icons` 包含面性、线性两套图标,默认不带颜色,可通过 css color属性更改颜色。
+默认的图标集 `@douyinfe/semi-icons` 包含面性、线性、AI 三套图标。面性图标、线性图标,以及 AI 图标中的单色图标默认不带颜色,可通过 css color 属性更改颜色。
+AI 图标中的双色,多色图标有默认颜色,可以通过 fill 更改颜色。
+
+AI 图标自 v2.86.0 提供。
 
 `@douyinfe/semi-icons-lab` 为彩色图标集,需单独安装,不可改色, lab 图标集于 v2.48 后提供
 
@@ -19,6 +22,7 @@ brief: 语义化的矢量图形。
 IconAbsoluteStroked
 IconActivity
 IconAlarm
+IconAlarmStroked
 IconAlertCircle
 IconAlertTriangle
 IconAlignBottom
@@ -59,6 +63,7 @@ IconBell
 IconBellStroked
 IconBold
 IconBolt
+IconBook
 IconBookH5Stroked
 IconBookOpenStroked
 IconBookStroked
@@ -73,18 +78,22 @@ IconBrackets
 IconBranch
 IconBriefStroked
 IconBriefcase
+IconBriefcaseStroked
 IconBulb
 IconButtonStroked
 IconBytedanceLogo
 IconCalendar
 IconCalendarClock
+IconCalendarClockStroked
 IconCalendarStroked
 IconCamera
+IconCameraStroked
 IconCandlestickChartStroked
 IconCaretdown
 IconCaretup
 IconCarouselStroked
 IconCart
+IconCartStroked
 IconCaseSensitive
 IconCenterLeftStroked
 IconCenterRightStroked
@@ -104,12 +113,14 @@ IconChevronUp
 IconChevronUpDown
 IconClear
 IconClock
+IconClockStroked
 IconClose
 IconCloud
 IconCloudStroked
 IconCloudUploadStroked
 IconCode
 IconCodeStroked
+IconCoinMoney
 IconCoinMoneyStroked
 IconColorPalette
 IconColumnsStroked
@@ -128,10 +139,12 @@ IconCopyAdd
 IconCopyStroked
 IconCornerRadiusStroked
 IconCreditCard
+IconCreditCardStroked
 IconCrop
 IconCrossCircleStroked
 IconCrossStroked
 IconCrown
+IconCrownStroked
 IconCustomerSupport
 IconCustomerSupportStroked
 IconCustomize
@@ -146,11 +159,13 @@ IconDivide
 IconDongchediLogo
 IconDoubleChevronLeft
 IconDoubleChevronRight
+IconDownCircle
 IconDownCircleStroked
 IconDownload
 IconDownloadStroked
 IconDuration
 IconEdit
+IconEdit2
 IconEdit2Stroked
 IconEditStroked
 IconElementStroked
@@ -162,7 +177,10 @@ IconExternalOpen
 IconExternalOpenStroked
 IconEyeClosed
 IconEyeClosedSolid
+IconEyeClosedSolidStroked
+IconEyeClosedStroked
 IconEyeOpened
+IconEyeOpenedStroked
 IconEyedropper
 IconFacebook
 IconFaceuLogo
@@ -178,13 +196,16 @@ IconFilledArrowDown
 IconFilledArrowUp
 IconFilpVertical
 IconFilter
+IconFilterStroked
 IconFingerLeftStroked
 IconFixedStroked
 IconFlag
+IconFlagStroked
 IconFlipHorizontal
 IconFlowChartStroked
 IconFolder
 IconFolderOpen
+IconFolderOpenStroked
 IconFolderStroked
 IconFollowStroked
 IconFont
@@ -200,6 +221,8 @@ IconGithubLogo
 IconGitlabLogo
 IconGlobe
 IconGlobeStroke
+IconGlobeStrokeStroked
+IconGlobeStroked
 IconGridRectangle
 IconGridSquare
 IconGridStroked
@@ -226,9 +249,11 @@ IconHn
 IconHome
 IconHomeStroked
 IconHorn
+IconHornStroked
 IconHourglass
 IconHourglassStroked
 IconIdCard
+IconIdCardStroked
 IconIdentity
 IconImage
 IconImageStroked
@@ -253,6 +278,7 @@ IconKey
 IconKeyStroked
 IconLanguage
 IconLayers
+IconLeftCircle
 IconLeftCircleStroked
 IconLightningStroked
 IconLikeHeart
@@ -281,6 +307,9 @@ IconMember
 IconMenu
 IconMicrophone
 IconMicrophoneOff
+IconMicrophoneOffStroked
+IconMicrophoneStroked
+IconMiniPlayer
 IconMinimize
 IconMinus
 IconMinusCircle
@@ -290,21 +319,26 @@ IconModalStroked
 IconMoneyExchangeStroked
 IconMonitorStroked
 IconMoon
+IconMoonStroked
 IconMore
 IconMoreStroked
 IconMusic
 IconMusicNoteStroked
 IconMute
+IconMuteStroked
 IconNineGridStroked
+IconNoteMoney
 IconNoteMoneyStroked
 IconOption
 IconOrderedList
 IconOrderedListStroked
 IconPaperclip
+IconPaperclipStroked
 IconPause
 IconPercentage
 IconPhone
 IconPhoneStroke
+IconPhoneStroked
 IconPieChart2Stroked
 IconPieChartStroked
 IconPiechartH5Stroked
@@ -317,6 +351,7 @@ IconPlusCircleStroked
 IconPlusStroked
 IconPriceTag
 IconPrint
+IconPrize
 IconPrizeStroked
 IconPulse
 IconPuzzle
@@ -326,6 +361,7 @@ IconQuit
 IconQuote
 IconRadio
 IconRankingCardStroked
+IconRealSize
 IconRealSizeStroked
 IconRedo
 IconRedoStroked
@@ -342,10 +378,12 @@ IconRotationStroked
 IconRoute
 IconRowsStroked
 IconSafe
+IconSafeStroked
 IconSave
 IconSaveStroked
 IconScan
 IconScissors
+IconScissorsStroked
 IconSearch
 IconSearchStroked
 IconSectionStroked
@@ -357,12 +395,14 @@ IconServer
 IconServerStroked
 IconSetting
 IconSettingStroked
+IconShare
 IconShareMoneyStroked
 IconShareStroked
 IconShield
 IconShieldStroked
 IconShift
 IconShoppingBag
+IconShoppingBagStroked
 IconShrink
 IconShrinkScreenStroked
 IconSidebar
@@ -388,6 +428,7 @@ IconStopwatchStroked
 IconStoryStroked
 IconStrikeThrough
 IconSun
+IconSunStroked
 IconSync
 IconTabArrowStroked
 IconTabsStroked
@@ -395,6 +436,7 @@ IconTaskMoneyStroked
 IconTemplate
 IconTemplateStroked
 IconTerminal
+IconTestScore
 IconTestScoreStroked
 IconText
 IconTextRectangle
@@ -402,6 +444,7 @@ IconTextStroked
 IconThumbUpStroked
 IconTick
 IconTickCircle
+IconTicketCode
 IconTicketCodeExchangeStroked
 IconTicketCodeStroked
 IconTiktokLogo
@@ -434,9 +477,11 @@ IconUser
 IconUserAdd
 IconUserCardPhone
 IconUserCardVideo
+IconUserCardVideoStroked
 IconUserCircle
 IconUserCircleStroked
 IconUserGroup
+IconUserList
 IconUserListStroked
 IconUserSetting
 IconUserStroked
@@ -450,8 +495,11 @@ IconVideoStroked
 IconVideoUrlStroked
 IconVigoLogo
 IconVolume1
+IconVolume1Stroked
 IconVolume2
+IconVolume2Stroked
 IconVolumnSilent
+IconVolumeSilentStroked
 IconVoteStroked
 IconVoteVideoStroked
 IconWeibo
@@ -459,9 +507,34 @@ IconWholeWord
 IconWifi
 IconWindowAdaptionStroked
 IconWrench
+IconWrenchStroked
 IconXiguaLogo
 IconYoutube
-
+IconAIBellLevel1
+IconAIBellLevel2
+IconAIBellLevel3
+IconAIEditLevel1
+IconAIEditLevel2
+IconAIEditLevel3
+IconAIFileLevel1
+IconAIFileLevel2
+IconAIFileLevel3
+IconAIFiledLevel1
+IconAIFiledLevel2
+IconAIFiledLevel3
+IconAIImageLevel1
+IconAIImageLevel2
+IconAIImageLevel3
+IconAISearchLevel1
+IconAISearchLevel2
+IconAISearchLevel3
+IconAIStrokeLevel1
+IconAIStrokeLevel2
+IconAIStrokeLevel3
+IconAIWandLevel1
+IconAIWandLevel2
+IconAIWandLevel3
+IconAILoading
 
 
 @douyinfe/semi-icons-lab icon list:
@@ -620,7 +693,7 @@ import { IconSearch, IconHelpCircle, IconAlertCircle, IconMinusCircle, IconPlusC
 ```
 
 ### 颜色
-图标会自动继承外部容器 CSS 的 `color` 属性
+单色图标会自动继承外部容器 CSS 的 `color` 属性
 你还可以通过给 Icon 设置 style props 来修改图标的颜色。
 
 ```jsx live=true
@@ -642,9 +715,43 @@ import { IconLikeHeart, IconFlag, IconLock, IconUnlock } from '@douyinfe/semi-ic
 );
 ```
 
+### 双色图标
+
+双色图标可以通过 `fill` 属性设置颜色,支持 string 以及 string[]。
+
+```jsx live=true
+import React from 'react';
+import { IconAIWandLevel2, IconAIFilledLevel2 } from '@douyinfe/semi-icons';
+
+() => (
+    <div>
+        <IconAIWandLevel2 fill={['var(--semi-color-danger)', 'var(--semi-color-success)']} style={{ marginRight: 10 }} size="extra-large"/>
+        <IconAIFilledLevel2 fill={'var(--semi-color-success)'} size="extra-large"/>
+    </div>
+);
+```
+
+### 多色按钮
+
+多色图标,当前的多色按钮可传入四个颜色。可以通过 `fill` 属性设置颜色,支持 string 以及 string[]。
+
+```jsx live=true
+import React from 'react';
+import { IconAIBellLevel3, IconAIWandLevel3, IconAIFilledLevel3 } from '@douyinfe/semi-icons';
+
+() => (
+    <div>
+        <IconAIBellLevel3 style={{ marginRight: 10 }} size="extra-large"/>
+        <IconAIWandLevel3 fill={['var(--semi-color-danger)', 'var(--semi-color-success)', 'var(--semi-color-primary)', 'var(--semi-color-warning)']} style={{ marginRight: 10 }} size="extra-large"/>
+        <IconAIFilledLevel3 fill={['var(--semi-color-primary)', 'var(--semi-color-success)']} size="extra-large"/>
+    </div>
+);
+```
+
+
 ### 自定义图标
-可以使用自定义图标传入Icon组件
-Icon组件支持size、rotate、spin等属性
+
+可以使用自定义图标传入Icon组件。Icon组件支持 size、rotate、spin 等属性
 
 ```jsx live=true
 import React from 'react';
@@ -696,6 +803,7 @@ import StarIcon from './star.svg';
 | 属性  | 说明        | 类型            | 默认值 |
 |-------|-------------|-----------------|--------|
 | className | 类名 | string | 无    |
+| fill | 双色,多色图标的填充颜色 | string \| string[] | 无 |
 | onClick | 单击图标的回调事件 | (e: Event) => void | 无    |
 | onMouseDown | 鼠标按钮按下的回调事件 >=v1.21 | (e: Event) => void | 无    |
 | onMouseEnter | 进入图标的回调事件 | (e: Event) => void | 无    |

+ 0 - 1
content/basic/resizable/index-en-US.md

@@ -5,7 +5,6 @@ category: Basic
 title: Resizable
 icon: doc-steps
 dir: column
-showNew: true
 brief: The component size is adjusted based on the user's mouse drag, supporting both resizing of a single component and combined resizing.
 ---
 

+ 0 - 1
content/basic/resizable/index.md

@@ -5,7 +5,6 @@ category: 基础
 title: Resizable 伸缩框
 icon: doc-steps
 brief: 根据用户的鼠标拖拽,改变组件的大小,支持单个组件伸缩与组合伸缩
-showNew: true
 ---
 
 ## 代码演示

+ 1 - 1
content/basic/space/index-en-US.md

@@ -1,6 +1,6 @@
 ---
 localeCode: en-US
-order: 24
+order: 25
 category: basic
 title:  Space
 icon: doc-space

+ 1 - 1
content/basic/space/index.md

@@ -1,6 +1,6 @@
 ---
 localeCode: zh-CN
-order: 24
+order: 25
 category: 基础
 title:  Space 间距
 icon: doc-space

+ 4 - 0
content/basic/tokens/index-en-US.md

@@ -21,6 +21,10 @@ In particular, for platforms with dark mode requirements, Semi Design's color va
 Based on the dynamic generation of brand color, including 160 colors, 16 different hue gradient color disk. In general, we use the color in the base color to further define the function color. You can use your brand color in the theme store to dynamically generate a new basic color disk.
 <FullPalette/>
 
+<Notice title='Attention'>
+The colors of the AI general series are gradient colors implemented using linear-gradient(). They cannot be used as background-color values and need to be used as background-image or background values to be effective.
+</Notice>
+
 ### Color conversion
 
 <ColorConverter/>

+ 25 - 0
content/basic/tokens/index.md

@@ -27,6 +27,10 @@ Design Token 设计变量实际上是将设计中的基础元素与具体的样
 
 <FullPalette/>
 
+<Notice title='注意'>
+    AI general 系列的颜色为使用 linear-gradient() 实现的渐变色,作为 background-color 的值无法生效,需要作为 background-image 或者 background 的值才能生效
+</Notice>
+
 ### 颜色转换
 <ColorConverter/>
 
@@ -76,6 +80,24 @@ Design Token 设计变量实际上是将设计中的基础元素与具体的样
 
 <DesignToken componentName='global' reg={/color-danger/}/>
 
+### AI - general
+
+用于 AI 场景的背景色,字体颜色
+
+<DesignToken componentName='global' reg={/color-ai-general/}/>
+
+### AI - purple
+
+用于 AI 相关的次要场景的背景色,字体颜色
+
+<DesignToken componentName='global' reg={/color-ai-purple/}/>
+
+### AI - background
+
+用于 AI 场景的背景色
+
+<DesignToken componentName='global' reg={/color-ai-background/}/>
+
 ### 文本与图标颜色 - text
 
 四个不同层级的文本/图标颜色,依次代表产品界面中最主要、次主要、稍次要和最次要的内容
@@ -106,6 +128,9 @@ Design Token 设计变量实际上是将设计中的基础元素与具体的样
 
 <DesignToken componentName='global' reg={/color-border/}/>
 
+### AI 状态色
+
+
 ### 禁用态 - disabled
 
 用于界面中各类表达禁用的元素填充,如背景、文本、描边、填充等

+ 1 - 1
content/basic/typography/index-en-US.md

@@ -1,6 +1,6 @@
 ---
 localeCode: en-US
-order: 21
+order: 22
 category: Basic
 title:  Typography
 subTitle: Typography

+ 1 - 1
content/basic/typography/index.md

@@ -1,6 +1,6 @@
 ---
 localeCode: zh-CN
-order: 21
+order: 22
 category: 基础
 title:  Typography 版式
 icon: doc-typography

+ 1 - 1
content/feedback/banner/index-en-US.md

@@ -1,6 +1,6 @@
 ---
 localeCode: en-US
-order: 84
+order: 85
 category: Feedback
 title:  Banner
 subTitle: Banner

+ 1 - 1
content/feedback/banner/index.md

@@ -1,6 +1,6 @@
 ---
 localeCode: zh-CN
-order: 84
+order: 85
 category: 反馈类
 title:  Banner 通知横幅
 icon: doc-banner

+ 358 - 0
content/feedback/feedback/index-en-US.md

@@ -0,0 +1,358 @@
+---
+localeCode: en-US
+order: 87
+category: Basic
+title:  Feedback
+icon: doc-feedback
+brief: Quick feedback component
+showNew: true
+---
+
+## Demos
+
+### How to import
+
+Feedback Supported since 2.85.0.
+
+```jsx import
+import { Feedback } from '@douyinfe/semi-ui';
+```
+
+### Basic usage
+
+Use `visible` to set whether to display or not. The default feedback display content is in emoji form. The currently selected content can be obtained through `onValueChange`.
+
+```jsx live=true
+import React, { useState, useCallback } from 'react';
+import { Feedback, Button } from '@douyinfe/semi-ui';
+
+() => {
+    const [visible, setVisible] = useState(false);
+    const handleOk = useCallback(() => setVisible(false), []);
+    const handleCancel = useCallback(() => setVisible(false), []);
+    const onValueChange = useCallback((value) => {
+        console.log('emoji value', value);
+    });
+
+    return (<>
+        <Button onClick={() => setVisible(!visible)} >
+            Show feedback: Popup, emoji
+        </Button>
+        <Feedback
+            title="What is your rating of this product?"
+            visible={visible}
+            onOk={handleOk}
+            onCancel={handleCancel}
+            onValueChange={onValueChange}
+        />
+    </>);
+};
+```
+
+### Text type
+
+Set `type` to `text` to get feedback in the form of a multi-line input box, and set the parameters of the multi-line input box through `textAreaProps`.
+
+```jsx live=true
+import React, { useState, useCallback } from 'react';
+import { Feedback, Button } from '@douyinfe/semi-ui';
+
+() => {
+    const [visible, setVisible] = useState(false);
+    const handleOk = useCallback(() => setVisible(false), []);
+    const handleCancel = useCallback(() => setVisible(false), []);
+
+    return (<>
+        <Button onClick={() => setVisible(!visible)} >
+            Show feedback: Popup, text
+        </Button>
+        <Feedback
+            type="text"
+            textAreaProps={{ maxCount: 200 }}
+            title="What is your suggestion of this product?"
+            visible={visible}
+            onOk={handleOk}
+            onCancel={handleCancel}
+        />
+    </>);
+};
+```
+
+### Single choice feedback
+
+Set `type` to `radio` to get feedback in the form of a single selection, and set the parameters of the radio selection through `radioGroupProps`.
+
+```jsx live=true
+import React, { useState, useCallback } from 'react';
+import { Feedback, Button } from '@douyinfe/semi-ui';
+
+() => {
+    const [visible, setVisible] = useState(false);
+    const handleOk = useCallback(() => setVisible(false), []);
+    const handleCancel = useCallback(() => setVisible(false), []);
+
+    return (<>
+        <Button onClick={() => setVisible(!visible)} >
+            Show feedback: Popup, radio
+        </Button>
+        <Feedback
+            type="radio"
+            radioGroupProps={{
+                options: ['Guest', 'Developer', 'Maintainer'],
+            }}
+            title="What is your role?"
+            visible={visible}
+            onOk={handleOk}
+            onCancel={handleCancel}
+        />
+    </>);
+};
+```
+
+### Multiple choice feedback
+
+Set `type` to `checkbox` to obtain feedback in the form of multiple selections, and set the parameters of the multi selection through `checkboxGroupProps`.
+
+```jsx live=true
+import React, { useState, useCallback } from 'react';
+import { Feedback, Button } from '@douyinfe/semi-ui';
+
+() => {
+    const [visible, setVisible] = useState(false);
+    const handleOk = useCallback(() => setVisible(false), []);
+    const handleCancel = useCallback(() => setVisible(false), []);
+
+    return (<>
+        <Button onClick={() => setVisible(!visible)} >
+            Show feedback: Popup, checkbox
+        </Button>
+        <Feedback
+            type="checkbox"
+            checkboxGroupProps={{
+                options: ['Douyin', ' Huoshan', 'doubao']
+            }}
+            title="Which products you choose?"
+            visible={visible}
+            onOk={handleOk}
+            onCancel={handleCancel}
+        />
+    </>);
+};
+```
+
+### Customized feedback content
+
+Set `type` to `custom` to obtain feedback in the form of multiple selections, and set the feedback content through `renderContent`. When using custom feedback, you need to control whether the submit button is disabled or not. Users can set it through `okButtonProps`.
+
+```jsx live=true
+import React, { useState, useCallback } from 'react';
+import { Feedback, Button, TextArea } from '@douyinfe/semi-ui';
+
+() => {
+    const [visible, setVisible] = useState(false);
+    const [value, setValue] = useState(value);
+    const handleOk = useCallback(() => setVisible(false), []);
+    const handleCancel = useCallback(() => setVisible(false), []);
+    const onTextAreaChange = useCallback((value) => {
+        setValue(value);
+    }, []);
+    const renderContent = useCallback(() => {
+        return <>
+            <span>This is a custom content</span>
+            <TextArea
+                value={value}
+                onChange={onTextAreaChange}
+            />
+        </>;
+    }, [onTextAreaChange]);
+
+    return (<>
+        <Button onClick={() => setVisible(!visible)} >
+            Show Feedback: Popup, custom
+        </Button>
+        <Feedback
+            type="custom"
+            title="What is your suggestion?"
+            okButtonProps={{ disabled: !Boolean(value) }}
+            visible={visible}
+            onOk={handleOk}
+            onCancel={handleCancel}
+            renderContent={renderContent}
+        />
+    </>);
+};
+```
+
+### Modal
+
+The form of feedback can be passed through `mode`, the default is `popup`, set to `modal` to get the display in the form of modal dialog box.
+
+```jsx live=true
+import React, { useState, useCallback } from 'react';
+import { Feedback, Button } from '@douyinfe/semi-ui';
+
+() => {
+    const [visible, setVisible] = useState(false);
+    const handleOk = useCallback(() => setVisible(false), []);
+    const handleCancel = useCallback(() => setVisible(false), []);
+    const onValueChange = useCallback((value) => {
+        console.log('emoji value', value);
+    });
+
+    return (<>
+        <Button onClick={() => setVisible(!visible)} >
+            Show: Modal, emoji
+        </Button>
+        <Feedback
+            mode="modal"
+            title="Why did you choose this rating?"
+            visible={visible}
+            onOk={handleOk}
+            onCancel={handleCancel}
+            onValueChange={onValueChange}
+        />
+    </>);
+};
+```
+
+### Feedback completion tips
+
+After the feedback is completed, you can switch to display information to remind the user that the feedback has been completed.
+
+```jsx live=true
+import React, { useState, useCallback, useMemo } from 'react';
+import { Feedback, Button, Empty, TextArea } from '@douyinfe/semi-ui';
+import { IllustrationSuccess, IllustrationSuccessDark } from '@douyinfe/semi-illustrations';
+
+() => {
+    const [visible1, setVisible1] = useState(false);
+    const [value1, setValue1] = useState('');
+    const [showThanks1, setShowThanks1] = useState(false);
+
+    const [visible2, setVisible2] = useState(false);
+    const [value2, setValue2] = useState('');
+    const [showThanks2, setShowThanks2] = useState(false);
+
+    const handleOk1 = useCallback(() => {
+        setShowThanks1(true);
+        setTimeout(() => {
+            setVisible1(false);
+            setTimeout(() => {
+                setShowThanks1(false);
+            }, 200);
+        }, 1500); 
+    }, []);
+
+    const hideFeedback1 = useCallback(() => {
+        setVisible1(false);
+    }, []);
+
+    const onTextAreaChange1 = useCallback((value) => {
+        setValue1(value);
+    }, []);
+
+    const handleOk2 = useCallback(() => {
+        setShowThanks2(true);
+        setTimeout(() => {
+            setVisible2(false);
+            setTimeout(() => {
+                setShowThanks2(false);
+            }, 200);
+        }, 1500); 
+    }, []);
+
+    const hideFeedback2 = useCallback(() => {
+        setVisible2(false);
+    }, []);
+
+    const onTextAreaChange2 = useCallback((value) => {
+        setValue2(value);
+    }, []);
+
+    const showThankProps = useMemo(() => ({ title: ' ', footer: null }), []);
+
+    return <div>
+        <Button onClick={() => setVisible1(!visible1)} >
+            Open Feedback: Popup, Custom
+        </Button>
+        <Feedback
+            visible={visible1}
+            onOk={handleOk1}
+            onCancel={hideFeedback1}
+            okButtonProps={{
+                disabled: !Boolean(value1),
+            }}
+            title="What is your feedback on this product?"
+            type='custom'
+            {...(showThanks1 ? showThankProps : {})}
+            renderContent={() => {
+                return showThanks1 ? <>
+                    <Empty
+                        image={<IllustrationSuccess style={{ width: 150, height: 150 }} />}
+                        darkModeImage={<IllustrationSuccessDark style={{ width: 150, height: 150 }} />}
+                        description={'Thanks for your feedback'}
+                        style={{ padding: 30 }}
+                    />
+                </> : <>
+                    <span>This is a custom content</span>
+                    <TextArea
+                        onChange={onTextAreaChange1}
+                    />
+                </>;
+            }}
+        />
+        <br /><br />
+        <Button onClick={() => setVisible2(!visible2)} >
+            Open Feedback: Modal, Custom
+        </Button>
+        <Feedback
+            visible={visible2}
+            onOk={handleOk2}
+            onCancel={hideFeedback2}
+            okButtonProps={{
+                disabled: !Boolean(value2),
+            }}
+            title="What is your feedback on this product?"
+            type='custom'
+            mode='modal'
+            {...(showThanks2 ? showThankProps : {})}
+            renderContent={() => {
+                return showThanks2 ? <>
+                    <Empty
+                        image={<IllustrationSuccess style={{ width: 150, height: 150 }} />}
+                        darkModeImage={<IllustrationSuccessDark style={{ width: 150, height: 150 }} />}
+                        description={'Thanks for your feedback'}
+                        style={{ padding: 30 }}
+                    />
+                </> : <>
+                    <span>This is a custom content</span>
+                    <TextArea
+                        onChange={onTextAreaChange2}
+                    />
+                </>;
+            }}
+        />
+    </div>;
+};
+```
+
+## API reference
+
+In addition to the parameters listed below, when `mode` is `modal`, FeedbackProps also supports the parameters in [ModalProps](/zh-CN/show/modal#Modal).
+When `mode` is `popup`, FeedbackProps also supports the parameters in [SideSheetProps](/zh-CN/show/sidesheet#API%20%E5%8F%82%E8%80%83)
+
+| Properties | Instructions | type | Default |
+|-----|-----|------|-------|
+| cancelButtonProps | Set the parameters for the cancel button | [ButtonProps](/zh-CN/basic/button#Button) | - |
+| checkboxGroupProps | Set parameters for multiple selections | [CheckBoxGroupProps](/en-US/input/checkbox#Checkbox%20Group) | - |
+| radioGroupProps | Set radio parameters | [RadioGroupProps](/en-US/input/radio#RadioGroup) | - |
+| renderContent | Customized feedback content display | (content: ReactNode) => ReactNode | - |
+| ModalProps | When mode is modal, it is used to set modal parameters. | ModalProps | - |
+| mode | Display mode, supports popup and modal | boolean | popup |
+| okButtonProps | Set the parameters of the submit button. For example, when customizing content, set disabled in okButtonProps to disable submission | [ButtonProps](/zh-CN/input/input#Button) | - |
+| onCancel | Cancel callback, the parameter is the shutdown function, and it will automatically close after the promise is resolved. | (e: any) => void \| Promise<any\> | - |
+| onOk | Click OK callback, the parameter is the closing function, and it will automatically close after the promise is resolved. | (e: any) => void \| Promise<any\> | - |
+| onValueChange | Callback when feedback content changes |function  | (value: string \| string[] \| Object) |
+| SideSheetProps | When modal is popup, it is used to set the parameters of the internal SideSheet | SideSheetProps | - |
+| type | Type of feedback content, supports text, emoji, radio, checkbox, custom | boolean | emoji |
+| textAreaProps | Set parameters of multi-line input box | [TextAreaProps](/en-US/input/input#TextArea) | - |

+ 358 - 0
content/feedback/feedback/index.md

@@ -0,0 +1,358 @@
+---
+localeCode: zh-CN
+order: 87
+category: 基础 
+title: Feedback 反馈
+icon: doc-feedback
+brief: 快速定义各类型反馈
+showNew: true
+---
+
+## 代码演示
+
+### 如何引入
+
+Feedback 自 2.85.0 支持。
+
+```jsx import
+import { Feedback } from '@douyinfe/semi-ui';
+```
+
+### 基本使用
+
+通过 `visible` 设置是否显示。默认反馈展示内容是 emoji 形式。 可通过 `onValueChange` 获取当前选择的内容。
+
+```jsx live=true
+import React, { useState, useCallback } from 'react';
+import { Feedback, Button } from '@douyinfe/semi-ui';
+
+() => {
+    const [visible, setVisible] = useState(false);
+    const handleOk = useCallback(() => setVisible(false), []);
+    const handleCancel = useCallback(() => setVisible(false), []);
+    const onValueChange = useCallback((value) => {
+        console.log('emoji value', value);
+    });
+
+    return (<>
+        <Button onClick={() => setVisible(!visible)} >
+            展示反馈: Popup, emoji
+        </Button>
+        <Feedback
+            title="您对本产品的评分是?"
+            visible={visible}
+            onOk={handleOk}
+            onCancel={handleCancel}
+            onValueChange={onValueChange}
+        />
+    </>);
+};
+```
+
+### 文字类型
+
+设置 `type` 为 `text` 可获得多行输入框形式的 feedback,可通过 `textAreaProps` 设置多行输入框的参数。
+
+```jsx live=true
+import React, { useState, useCallback } from 'react';
+import { Feedback, Button } from '@douyinfe/semi-ui';
+
+() => {
+    const [visible, setVisible] = useState(false);
+    const handleOk = useCallback(() => setVisible(false), []);
+    const handleCancel = useCallback(() => setVisible(false), []);
+
+    return (<>
+        <Button onClick={() => setVisible(!visible)} >
+            展示反馈: Popup, text
+        </Button>
+        <Feedback
+            type="text"
+            textAreaProps={{ maxCount: 200 }}
+            title="您对本产品的建议是?"
+            visible={visible}
+            onOk={handleOk}
+            onCancel={handleCancel}
+        />
+    </>);
+};
+```
+
+### 单选反馈
+
+设置 `type` 为 `radio` 可获得单选形式的 feedback,可通过 `radioGroupProps` 设置单选的参数。
+
+```jsx live=true
+import React, { useState, useCallback } from 'react';
+import { Feedback, Button } from '@douyinfe/semi-ui';
+
+() => {
+    const [visible, setVisible] = useState(false);
+    const handleOk = useCallback(() => setVisible(false), []);
+    const handleCancel = useCallback(() => setVisible(false), []);
+
+    return (<>
+        <Button onClick={() => setVisible(!visible)} >
+            展示反馈: Popup, radio
+        </Button>
+        <Feedback
+            type="radio"
+            radioGroupProps={{
+                options: ['访客', '开发者', '维护者'],
+            }}
+            title="您的身份是"
+            visible={visible}
+            onOk={handleOk}
+            onCancel={handleCancel}
+        />
+    </>);
+};
+```
+
+### 多选反馈
+
+设置 `type` 为 `checkbox` 可获得多选形式的 feedback,可通过 `checkboxGroupProps` 设置多选的参数。
+
+```jsx live=true
+import React, { useState, useCallback } from 'react';
+import { Feedback, Button } from '@douyinfe/semi-ui';
+
+() => {
+    const [visible, setVisible] = useState(false);
+    const handleOk = useCallback(() => setVisible(false), []);
+    const handleCancel = useCallback(() => setVisible(false), []);
+
+    return (<>
+        <Button onClick={() => setVisible(!visible)} >
+            展示反馈: Popup, checkbox
+        </Button>
+        <Feedback
+            type="checkbox"
+            checkboxGroupProps={{
+                options: ['抖音', '火山', '豆包']
+            }}
+            title="您最常使用以下哪些产品?"
+            visible={visible}
+            onOk={handleOk}
+            onCancel={handleCancel}
+        />
+    </>);
+};
+```
+
+### 自定义反馈内容
+
+设置 `type` 为 `custom` 可获得多选形式的 feedback,可通过 `renderContent` 设置反馈的内容。使用自定义反馈时候,需自行控制提交按钮的禁用与否状态,用户可通过 `okButtonProps` 设置。
+
+```jsx live=true
+import React, { useState, useCallback } from 'react';
+import { Feedback, Button, TextArea } from '@douyinfe/semi-ui';
+
+() => {
+    const [visible, setVisible] = useState(false);
+    const [value, setValue] = useState(value);
+    const handleOk = useCallback(() => setVisible(false), []);
+    const handleCancel = useCallback(() => setVisible(false), []);
+    const onTextAreaChange = useCallback((value) => {
+        setValue(value);
+    }, []);
+
+    const renderContent = useCallback(() => {
+        return <>
+            <span>这是一段自定义的内容</span>
+            <TextArea
+                onChange={onTextAreaChange}
+            />
+        </>;
+    }, [onTextAreaChange]);
+
+    return (<>
+        <Button onClick={() => setVisible(!visible)} >
+            展示反馈: Popup, custom
+        </Button>
+        <Feedback
+            type="custom"
+            okButtonProps={{ disabled: !Boolean(value) }}
+            title="您对本产品的建议是?"
+            visible={visible}
+            onOk={handleOk}
+            onCancel={handleCancel}
+            renderContent={renderContent}
+        />
+    </>);
+};
+```
+
+### 模态对话框形式
+
+可通过 `mode` 反馈的形式,默认是 `popup`, 设置为 `modal` 可获得模态对话框形式的展示。
+
+```jsx live=true
+import React, { useState, useCallback } from 'react';
+import { Feedback, Button } from '@douyinfe/semi-ui';
+
+() => {
+    const [visible, setVisible] = useState(false);
+    const handleOk = useCallback(() => setVisible(false), []);
+    const handleCancel = useCallback(() => setVisible(false), []);
+    const onValueChange = useCallback((value) => {
+        console.log('emoji value', value);
+    });
+
+    return (<>
+        <Button onClick={() => setVisible(!visible)} >
+            展示反馈: Modal, emoji
+        </Button>
+        <Feedback
+            mode="modal"
+            title="Why did you choose this rating?"
+            visible={visible}
+            onOk={handleOk}
+            onCancel={handleCancel}
+            onValueChange={onValueChange}
+        />
+    </>);
+};
+```
+
+### 反馈完成提示
+
+反馈完成后,可以切换展示信息提示用户本次反馈已经完成。
+
+```jsx live=true
+import React, { useState, useCallback, useMemo } from 'react';
+import { Feedback, Button, Empty, TextArea } from '@douyinfe/semi-ui';
+import { IllustrationSuccess, IllustrationSuccessDark } from '@douyinfe/semi-illustrations';
+
+() => {
+    const [visible1, setVisible1] = useState(false);
+    const [value1, setValue1] = useState('');
+    const [showThanks1, setShowThanks1] = useState(false);
+
+    const [visible2, setVisible2] = useState(false);
+    const [value2, setValue2] = useState('');
+    const [showThanks2, setShowThanks2] = useState(false);
+
+    const handleOk1 = useCallback(() => {
+        setShowThanks1(true);
+        setTimeout(() => {
+            setVisible1(false);
+            setTimeout(() => {
+                setShowThanks1(false);
+            }, 200);
+        }, 1500); 
+    }, []);
+
+    const hideFeedback1 = useCallback(() => {
+        setVisible1(false);
+    }, []);
+
+    const onTextAreaChange1 = useCallback((value) => {
+        setValue1(value);
+    }, []);
+
+    const handleOk2 = useCallback(() => {
+        setShowThanks2(true);
+        setTimeout(() => {
+            setVisible2(false);
+            setTimeout(() => {
+                setShowThanks2(false);
+            }, 200);
+        }, 1500); 
+    }, []);
+
+    const hideFeedback2 = useCallback(() => {
+        setVisible2(false);
+    }, []);
+
+    const onTextAreaChange2 = useCallback((value) => {
+        setValue2(value);
+    }, []);
+
+    const showThankProps = useMemo(() => ({ title: ' ', footer: null }), []);
+
+    return <div>
+        <Button onClick={() => setVisible1(!visible1)} >
+            Open Feedback: Popup, Custom
+        </Button>
+        <Feedback
+            visible={visible1}
+            onOk={handleOk1}
+            onCancel={hideFeedback1}
+            okButtonProps={{
+                disabled: !Boolean(value1),
+            }}
+            title="What is your feedback on this product?"
+            type='custom'
+            {...(showThanks1 ? showThankProps : {})}
+            renderContent={() => {
+                return showThanks1 ? <>
+                    <Empty
+                        image={<IllustrationSuccess style={{ width: 150, height: 150 }} />}
+                        darkModeImage={<IllustrationSuccessDark style={{ width: 150, height: 150 }} />}
+                        description={'感谢您的反馈'}
+                        style={{ padding: 30 }}
+                    />
+                </> : <>
+                    <span>这是一段自定义的内容</span>
+                    <TextArea
+                        onChange={onTextAreaChange1}
+                    />
+                </>;
+            }}
+        />
+        <br /><br />
+        <Button onClick={() => setVisible2(!visible2)} >
+            Open Feedback: Modal, Custom
+        </Button>
+        <Feedback
+            visible={visible2}
+            onOk={handleOk2}
+            onCancel={hideFeedback2}
+            okButtonProps={{
+                disabled: !Boolean(value2),
+            }}
+            title="What is your feedback on this product?"
+            type='custom'
+            mode='modal'
+            {...(showThanks2 ? showThankProps : {})}
+            renderContent={() => {
+                return showThanks2 ? <>
+                    <Empty
+                        image={<IllustrationSuccess style={{ width: 150, height: 150 }} />}
+                        darkModeImage={<IllustrationSuccessDark style={{ width: 150, height: 150 }} />}
+                        description={'感谢您的反馈'}
+                        style={{ padding: 30 }}
+                    />
+                </> : <>
+                    <span>这是一段自定义的内容</span>
+                    <TextArea
+                        onChange={onTextAreaChange2}
+                    />
+                </>;
+            }}
+        />
+    </div>;
+};
+```
+
+## API 参考
+
+### FeedbackProps
+
+除去下面参数列表所列参数外,当 `mode` 为 `modal` 时, FeedbackProps 还支持 [ModalProps](/zh-CN/show/modal#Modal) 中的参数,
+当 `mode` 为 `popup` 时, FeedbackProps 还支持 [SideSheetProps](/zh-CN/show/sidesheet#API%20%E5%8F%82%E8%80%83) 中的参数
+
+| 属性 | 说明 | 类型 | 默认值 |
+|-----|-----|------|-------|
+| cancelButtonProps | 设置取消按钮的参数 | [ButtonProps](/zh-CN/basic/button#Button) | - |
+| checkboxGroupProps | 设置多选的参数 | [CheckBoxGroupProps](/zh-CN/input/checkbox#Checkbox%20Group) | - |
+| radioGroupProps | 设置单选的参数 | [RadioGroupProps](/zh-CN/input/radio#RadioGroup) | - |
+| renderContent | 自定义反馈内容展示 | (content: ReactNode) => ReactNode | - |
+| mode | 展示模式,支持 popup、modal | boolean | popup |
+| okButtonProps | 设置提交按钮的参数,比如当设置 type 为 custom,用户自定义反馈内容时,通过设置 okButtonProps 中的 disabled 设置是否禁用提交 | [ButtonProps](/zh-CN/input/input#Button) | - |
+| onCancel | 取消回调,参数为关闭函数,返回 promise 时 resolve 后自动关闭 | (e: any) => void \| Promise<any\> | 无 |
+| onOk | 点击确定回调,参数为关闭函数,返回 promise 时 resolve 后自动关闭 | (e: any) => void \| Promise<any\> | 无 |
+| onValueChange | 在反馈内容变化时候的回调|function  | (value: string \| string[] \| Object) |
+| type | 反馈内容的类型,支持 text、emoji、radio,checkbox,custom| boolean | emoji |
+| textAreaProps | 设置多行输入框的参数 | [TextAreaProps](/zh-CN/input/input#TextArea) | - |

+ 1 - 1
content/feedback/notification/index-en-US.md

@@ -1,6 +1,6 @@
 ---
 localeCode: en-US
-order: 85
+order: 86
 category: Feedback
 title:  Notification
 subTitle: Notification

+ 1 - 1
content/feedback/notification/index.md

@@ -1,6 +1,6 @@
 ---
 localeCode: zh-CN
-order: 85
+order: 86
 category: 反馈类
 title: Notification 通知
 icon: doc-notification

+ 1 - 1
content/feedback/popconfirm/index-en-US.md

@@ -1,6 +1,6 @@
 ---
 localeCode: en-US
-order: 86
+order: 88
 category: Feedback
 title:  Popconfirm
 subTitle: Popconfirm

+ 1 - 1
content/feedback/popconfirm/index.md

@@ -1,6 +1,6 @@
 ---
 localeCode: zh-CN
-order: 86
+order: 88
 category: 反馈类
 title:  Popconfirm 气泡确认框
 icon: doc-popconfirm

+ 1 - 1
content/feedback/progress/index-en-US.md

@@ -1,6 +1,6 @@
 ---
 localeCode: en-US
-order: 87
+order: 89
 category: Feedback
 title: Progress
 subTitle: Progress

+ 1 - 1
content/feedback/progress/index.md

@@ -1,6 +1,6 @@
 ---
 localeCode: zh-CN
-order: 87
+order: 89
 category: 反馈类
 title: Progress 进度条
 icon: doc-progress

+ 1 - 1
content/feedback/skeleton/index-en-US.md

@@ -1,6 +1,6 @@
 ---
 localeCode: en-US
-order: 88
+order: 90
 category: Feedback
 title: Skeleton
 subTitle: Skeleton

+ 1 - 1
content/feedback/skeleton/index.md

@@ -1,6 +1,6 @@
 ---
 localeCode: zh-CN
-order: 88
+order: 90
 category: 反馈类
 title: Skeleton 骨架屏
 icon: doc-skeleton

+ 1 - 1
content/feedback/spin/index-en-US.md

@@ -1,6 +1,6 @@
 ---
 localeCode: en-US
-order: 89
+order: 91
 category: Feedback
 title: Spin
 subTitle: Spin

+ 1 - 1
content/feedback/spin/index.md

@@ -1,6 +1,6 @@
 ---
 localeCode: zh-CN
-order: 89
+order: 91
 category: 反馈类
 title: Spin 加载器
 icon: doc-spin

+ 1 - 1
content/feedback/toast/index-en-US.md

@@ -1,6 +1,6 @@
 ---
 localeCode: en-US
-order: 90
+order: 92
 category: Feedback
 title: Toast
 subTitle: Toast

+ 1 - 1
content/feedback/toast/index.md

@@ -1,6 +1,6 @@
 ---
 localeCode: zh-CN
-order: 90
+order: 92
 category: 反馈类
 title: Toast 提示
 icon: doc-toast

+ 1 - 1
content/input/autocomplete/index-en-US.md

@@ -1,6 +1,6 @@
 ---
 localeCode: en-US
-order: 32
+order: 33
 category: Input
 title: AutoComplete
 icon: doc-autocomplete

+ 1 - 1
content/input/autocomplete/index.md

@@ -1,6 +1,6 @@
 ---
 localeCode: zh-CN
-order: 32
+order: 33
 category: 输入类
 title: AutoComplete 自动完成
 icon: doc-autocomplete

+ 1 - 1
content/input/cascader/index-en-US.md

@@ -1,6 +1,6 @@
 ---
 localeCode: en-US
-order: 33
+order: 34
 category: Input
 title:  Cascader
 subTitle: Cascade

+ 1 - 1
content/input/cascader/index.md

@@ -1,6 +1,6 @@
 ---
 localeCode: zh-CN
-order: 33
+order: 34
 category: 输入类
 title:  Cascader 级联选择
 icon: doc-cascader

+ 1 - 1
content/input/checkbox/index-en-US.md

@@ -1,6 +1,6 @@
 ---
 localeCode: en-US
-order: 34
+order: 35
 category: Input
 title:  Checkbox
 subTitle: Checkbox

+ 1 - 1
content/input/checkbox/index.md

@@ -1,6 +1,6 @@
 ---
 localeCode: zh-CN
-order: 34
+order: 35
 category: 输入类
 title: Checkbox 复选框
 icon: doc-checkbox

+ 1 - 1
content/input/colorpicker/index-en-US.md

@@ -1,6 +1,6 @@
 ---
 localeCode: en-US
-order: 35
+order: 36
 category: Input
 title: ColorPicker
 icon: doc-colorPlatteNew

+ 1 - 1
content/input/colorpicker/index.md

@@ -1,6 +1,6 @@
 ---
 localeCode: zh-CN
-order: 35
+order: 36
 category: 输入类
 title: ColorPicker 颜色选择器
 icon: doc-colorPlatteNew

+ 1 - 1
content/input/datepicker/index-en-US.md

@@ -1,6 +1,6 @@
 ---
 localeCode: en-US
-order: 36
+order: 37
 category: Input
 title: DatePicker
 subTitle: Date Selector

+ 1 - 1
content/input/datepicker/index.md

@@ -1,6 +1,6 @@
 ---
 localeCode: zh-CN
-order: 36
+order: 37
 category: 输入类
 title: DatePicker 日期选择器
 icon: doc-datepicker

+ 1 - 1
content/input/form/index-en-US.md

@@ -1,6 +1,6 @@
 ---
 localeCode: en-US
-order: 37
+order: 38
 category: Input
 title:  Form
 subTitle: Form

+ 1 - 1
content/input/form/index.md

@@ -1,6 +1,6 @@
 ---
 localeCode: zh-CN
-order: 37
+order: 38
 category: 输入类
 title:  Form 表单
 icon: doc-form

+ 1 - 1
content/input/input/index-en-US.md

@@ -1,6 +1,6 @@
 ---
 localeCode: en-US
-order: 38
+order: 39
 category: Input
 title:  Input
 subTitle: Input

+ 1 - 1
content/input/input/index.md

@@ -1,6 +1,6 @@
 ---
 localeCode: zh-CN
-order: 38
+order: 39
 category: 输入类
 title:  Input 输入框
 icon: doc-input

+ 1 - 1
content/input/inputnumber/index-en-US.md

@@ -1,6 +1,6 @@
 ---
 localeCode: en-US
-order: 39
+order: 40
 category: Input
 title:  InputNumber
 subTitle: InputNumber

+ 1 - 1
content/input/inputnumber/index.md

@@ -1,6 +1,6 @@
 ---
 localeCode: zh-CN
-order: 39
+order: 40
 category: 输入类
 title: InputNumber 数字输入框
 icon: doc-inputnumber

+ 1 - 2
content/input/pincode/index-en-US.md

@@ -1,12 +1,11 @@
 ---
 localeCode: en-US
-order: 40
+order: 41
 category: Input
 title: PinCode
 icon: doc-pincode
 width: 60%
 brief: For easy and intuitive verification code entry
-showNew: true
 ---
 
 ## Code demonstration

+ 1 - 2
content/input/pincode/index.md

@@ -1,12 +1,11 @@
 ---
 localeCode: zh-CN
-order: 40
+order: 41
 category: 输入类
 title: PinCode 验证码输入
 icon: doc-pincode
 width: 60%
 brief: 用于便捷直观地输入验证码
-showNew: true
 ---
 
 ## 代码演示

+ 1 - 1
content/input/radio/index-en-US.md

@@ -1,6 +1,6 @@
 ---
 localeCode: en-US
-order: 41
+order: 42
 category: Input
 title: Radio
 subTitle: Radio

+ 1 - 1
content/input/radio/index.md

@@ -1,6 +1,6 @@
 ---
 localeCode: zh-CN
-order: 41
+order: 42
 category: 输入类
 title: Radio 单选框
 icon: doc-radio

+ 1 - 1
content/input/rating/index-en-US.md

@@ -1,6 +1,6 @@
 ---
 localeCode: en-US
-order: 42
+order: 43
 category: Input
 title: Rating
 subTitle: Rating

+ 1 - 1
content/input/rating/index.md

@@ -1,6 +1,6 @@
 ---
 localeCode: zh-CN
-order: 42
+order: 43
 category: 输入类
 title:  Rating 评分
 icon: doc-rating

+ 1 - 1
content/input/select/index-en-US.md

@@ -1,6 +1,6 @@
 ---
 localeCode: en-US
-order: 43
+order: 44
 category: Input
 title: Select
 subTitle: Select

+ 1 - 1
content/input/select/index.md

@@ -1,6 +1,6 @@
 ---
 localeCode: zh-CN
-order: 43
+order: 44
 category: 输入类
 title: Select 选择器
 icon: doc-select

+ 1 - 1
content/input/slider/index-en-US.md

@@ -1,6 +1,6 @@
 ---
 localeCode: en-US
-order: 44
+order: 45
 category: Input
 title:  Slider
 subTitle: Slider

+ 1 - 1
content/input/slider/index.md

@@ -1,6 +1,6 @@
 ---
 localeCode: zh-CN
-order: 44
+order: 45
 category: 输入类
 title:  Slider 滑动选择器
 icon: doc-slider

+ 1 - 1
content/input/switch/index-en-US.md

@@ -1,6 +1,6 @@
 ---
 localeCode: en-US
-order: 45
+order: 46
 category: Input
 title: Switch
 subTitle: Switch

+ 1 - 1
content/input/switch/index.md

@@ -1,6 +1,6 @@
 ---
 localeCode: zh-CN
-order: 45
+order: 46
 category: 输入类
 title: Switch 开关
 icon: doc-switch

+ 1 - 1
content/input/taginput/index-en-US.md

@@ -1,6 +1,6 @@
 ---
 localeCode: en-US
-order: 46
+order: 47
 category: Input
 title: TagInput
 subTitle: TagInput

+ 1 - 1
content/input/taginput/index.md

@@ -1,6 +1,6 @@
 ---
 localeCode: zh-CN
-order: 46
+order: 47
 category: 输入类
 title: TagInput 标签输入框
 icon: doc-tagInput

+ 1 - 1
content/input/timepicker/index-en-US.md

@@ -1,6 +1,6 @@
 ---
 localeCode: en-US
-order: 47
+order: 48
 category: Input
 title: TimePicker
 subTitle: TimePicker

+ 1 - 1
content/input/timepicker/index.md

@@ -1,6 +1,6 @@
 ---
 localeCode: zh-CN
-order: 47
+order: 48
 category: 输入类
 title: TimePicker 时间选择器
 icon: doc-timepicker

+ 1 - 1
content/input/transfer/index-en-US.md

@@ -1,6 +1,6 @@
 ---
 localeCode: en-US
-order: 48
+order: 49
 category: Input
 title: Transfer
 icon: doc-transfer

+ 1 - 1
content/input/transfer/index.md

@@ -1,6 +1,6 @@
 ---
 localeCode: zh-CN
-order: 48
+order: 49
 category: 输入类
 title: Transfer 穿梭框
 icon: doc-transfer

+ 1 - 1
content/input/treeselect/index-en-US.md

@@ -1,6 +1,6 @@
 ---
 localeCode: en-US
-order: 49
+order: 50
 category: Input
 title:  TreeSelect
 subTitle: TreeSelect

+ 1 - 1
content/input/treeselect/index.md

@@ -1,6 +1,6 @@
 ---
 localeCode: zh-CN
-order: 49
+order: 50
 category: 输入类
 title: TreeSelect 树选择器
 icon: doc-treeselect

+ 1 - 1
content/input/upload/index-en-US.md

@@ -1,6 +1,6 @@
 ---
 localeCode: en-US
-order: 50
+order: 51
 category: Input
 title: Upload
 icon: doc-upload

+ 1 - 1
content/input/upload/index.md

@@ -1,6 +1,6 @@
 ---
 localeCode: zh-CN
-order: 50
+order: 51
 category: 输入类
 title: Upload 上传
 icon: doc-upload

+ 1 - 1
content/navigation/anchor/index-en-US.md

@@ -1,6 +1,6 @@
 ---
 localeCode: en-US
-order: 51
+order: 52
 category: Navigation
 title:  Anchor
 subTitle: Anchor

+ 1 - 1
content/navigation/anchor/index.md

@@ -1,6 +1,6 @@
 ---
 localeCode: zh-CN
-order: 51
+order: 52
 category: 导航类
 title:  Anchor 锚点
 icon: doc-anchor

+ 1 - 1
content/navigation/backtop/index-en-US.md

@@ -1,6 +1,6 @@
 ---
 localeCode: en-US
-order: 52
+order: 53
 category: Navigation
 title: BackTop
 subTitle: BackTop

+ 1 - 1
content/navigation/backtop/index.md

@@ -1,6 +1,6 @@
 ---
 localeCode: zh-CN
-order: 52
+order: 53
 category: 导航类
 title: BackTop 回到顶部
 icon: doc-backtop

+ 1 - 1
content/navigation/breadcrumb/index-en-US.md

@@ -1,6 +1,6 @@
 ---
 localeCode: en-US
-order: 53
+order: 54
 category: Navigation
 title:  Breadcrumb
 subTitle: Breadcrumb

+ 1 - 1
content/navigation/breadcrumb/index.md

@@ -1,6 +1,6 @@
 ---
 localeCode: zh-CN
-order: 53
+order: 54
 category: 导航类
 title:  Breadcrumb 面包屑
 icon: doc-breadcrumb

+ 1 - 1
content/navigation/navigation/index-en-US.md

@@ -1,6 +1,6 @@
 ---
 localeCode: en-US
-order: 54
+order: 55
 category: Navigation
 title:  Navigation
 subTitle: Navigation

+ 1 - 1
content/navigation/navigation/index.md

@@ -1,6 +1,6 @@
 ---
 localeCode: zh-CN
-order: 54
+order: 55
 category: 导航类
 title:  Navigation 导航
 icon: doc-navigation

+ 1 - 1
content/navigation/pagination/index-en-US.md

@@ -1,6 +1,6 @@
 ---
 localeCode: en-US
-order: 55
+order: 56
 category: Navigation
 title:  Pagination
 subTitle: Pagination

+ 1 - 1
content/navigation/pagination/index.md

@@ -1,6 +1,6 @@
 ---
 localeCode: zh-CN
-order: 55
+order: 56
 category: 导航类
 title:  Pagination 翻页器
 icon: doc-pagination

+ 1 - 1
content/navigation/steps/index-en-US.md

@@ -1,6 +1,6 @@
 ---
 localeCode: en-US
-order: 56
+order: 57
 category: Navigation
 title: Steps
 subTitle: Steps

+ 1 - 1
content/navigation/steps/index.md

@@ -1,6 +1,6 @@
 ---
 localeCode: zh-CN
-order: 56
+order: 57
 category: 导航类
 title:  Steps 步骤
 icon: doc-steps

+ 1 - 1
content/navigation/tabs/index-en-US.md

@@ -1,6 +1,6 @@
 ---
 localeCode: en-US
-order: 57
+order: 58
 category: Navigation
 title: Tabs
 subTitle: Tabs

+ 1 - 1
content/navigation/tabs/index.md

@@ -1,6 +1,6 @@
 ---
 localeCode: zh-CN
-order: 57
+order: 58
 category: 导航类
 title: Tabs 标签栏
 icon: doc-tabs

+ 1 - 1
content/navigation/tree/index-en-US.md

@@ -1,6 +1,6 @@
 ---
 localeCode: en-US
-order: 58
+order: 59
 category: Navigation
 title:  Tree
 subTitle: Tree

+ 1 - 1
content/navigation/tree/index.md

@@ -1,6 +1,6 @@
 ---
 localeCode: zh-CN
-order: 58
+order: 59
 category: 导航类
 title:  Tree 树形控件
 icon: doc-tree

+ 5 - 0
content/order.js

@@ -19,6 +19,7 @@ const order = [
     'grid',
     'resizable',
     'button',
+    'floatbutton',
     'typography',
     'divider',
     'icon',
@@ -84,6 +85,7 @@ const order = [
     'chart',
     'banner',
     'notification',
+    'feedback',
     'popconfirm',
     'progress',
     'skeleton',
@@ -94,6 +96,9 @@ const order = [
     'jsonviewer',
     'audioPlayer',
     'videoPlayer',
+    'aiComponent',
+    'aiChatInput',
+    'aiChatDialogue',
 ];
 let { exec } = require('child_process');
 let fs = require('fs');

+ 1 - 1
content/other/configprovider/index-en-US.md

@@ -1,6 +1,6 @@
 ---
 localeCode: en-US
-order: 91
+order: 93
 category: Other
 title: ConfigProvider
 icon: doc-configprovider

+ 1 - 1
content/other/configprovider/index.md

@@ -1,6 +1,6 @@
 ---
 localeCode: zh-CN
-order: 91
+order: 93
 category: 其他
 title:  ConfigProvider 全局配置
 icon: doc-configprovider

+ 108 - 2
content/other/locale/index-en-US.md

@@ -1,6 +1,6 @@
 ---
 localeCode: en-US
-order: 92
+order: 94
 category: Other
 title: LocaleProvider
 subTitle: LocaleProvider
@@ -24,6 +24,7 @@ brief: Internationalized components to provide multilingual support for Semi com
 | v2.15.0     | Italian: it、French:fr、German:de   |
 | v2.21.0     | Romanian: ro   |
 | v2.29.0     | Swedish: sv_SE、 Polish: pl_PL、Dutch: nl_NL |
+| v2.88.0 | Azerbaijani: az, Bulgarian: bg, Catalan: ca, Czech: cs_CZ, Cebu: ceb_PH, Danish: da, Greek: el_GR, Spanish (Latin America): es_419, Estonian: et, Persian: fa_IR, Filipino: fil_PH, Finnish: fi_FI, French (Canada): fr_CA, Irish: ga, Hebrew: he_IL, Hindi: hi_IN, Croatian: hr, Hungarian: hu_HU, Icelandic: is, Javanese: jv_ID, Kazakh: kk, Khmer: km_KH, Lithuanian: lt, Latvian: lv, Burmese: my_MM, Norwegian: nb, Portuguese: pt, Slovak: sk, Slovenian: sl, Albanian: sq, Swahili: sw, Ukrainian: uk_UA, Urdu: ur, Uzbek: uz |
 
 
 ## Components supported
@@ -200,6 +201,41 @@ import it from '@douyinfe/semi-ui/lib/es/locale/source/it';
 import de from '@douyinfe/semi-ui/lib/es/locale/source/de';
 import fr from '@douyinfe/semi-ui/lib/es/locale/source/fr';
 import ro from '@douyinfe/semi-ui/lib/es/locale/source/ro';
+import az from '@douyinfe/semi-ui/locale/source/az';
+import bg from '@douyinfe/semi-ui/locale/source/bg';
+import bn_IN from '@douyinfe/semi-ui/locale/source/bn_IN';  
+import ca from '@douyinfe/semi-ui/locale/source/ca';
+import cs_CZ from '@douyinfe/semi-ui/locale/source/cs_CZ';
+import ceb_PH from '@douyinfe/semi-ui/locale/source/ceb_PH';
+import da from '@douyinfe/semi-ui/locale/source/da';
+import el_GR from '@douyinfe/semi-ui/locale/source/el_GR';
+import es_419 from '@douyinfe/semi-ui/locale/source/es_419';
+import et from '@douyinfe/semi-ui/locale/source/et';
+import fa_IR from '@douyinfe/semi-ui/locale/source/fa_IR';
+import fil_PH from '@douyinfe/semi-ui/locale/source/fil_PH';
+import fi_FI from '@douyinfe/semi-ui/locale/source/fi_FI';
+import fr_CA from '@douyinfe/semi-ui/locale/source/fr_CA';
+import ga from '@douyinfe/semi-ui/locale/source/ga';
+import he_IL from '@douyinfe/semi-ui/locale/source/he_IL';
+import hi_IN from '@douyinfe/semi-ui/locale/source/hi_IN';
+import hr from '@douyinfe/semi-ui/locale/source/hr';
+import hu_HU from '@douyinfe/semi-ui/locale/source/hu_HU';
+import is from '@douyinfe/semi-ui/locale/source/is';
+import jv_ID from '@douyinfe/semi-ui/locale/source/jv_ID';
+import kk from '@douyinfe/semi-ui/locale/source/kk';
+import km_KH from '@douyinfe/semi-ui/locale/source/km_KH';
+import lt from '@douyinfe/semi-ui/locale/source/lt';
+import lv from '@douyinfe/semi-ui/locale/source/lv';
+import my_MM from '@douyinfe/semi-ui/locale/source/my_MM';
+import nb from '@douyinfe/semi-ui/locale/source/nb';
+import pt from '@douyinfe/semi-ui/locale/source/pt';
+import sk from '@douyinfe/semi-ui/locale/source/sk';
+import sl from '@douyinfe/semi-ui/locale/source/sl';
+import sq from '@douyinfe/semi-ui/locale/source/sq';
+import sw from '@douyinfe/semi-ui/locale/source/sw';
+import uk_UA from '@douyinfe/semi-ui/locale/source/uk_UA';
+import ur from '@douyinfe/semi-ui/locale/source/ur';
+import uz from '@douyinfe/semi-ui/locale/source/uz';
 import { LocaleProvider, ConfigProvider, Pagination, Modal, Button, Select, Cascader, DatePicker, TreeSelect, Table, TimePicker, List, Calendar, Typography, Transfer, ImagePreview, Image, Form, Nav } from '@douyinfe/semi-ui';
 import { IconUser, IconSemiLogo, IconStar } from '@douyinfe/semi-icons';
 
@@ -233,7 +269,42 @@ class I18nDemo extends React.Component {
             de,
             it,
             fr,
-            ro
+            ro,
+            'bn_IN': bn_IN,
+            az,
+            bg,
+            ca,
+            'cs_CZ': cs_CZ,
+            'ceb_PH': ceb_PH,
+            da,
+            'el_GR': el_GR,
+            'es_419': es_419,
+            et,
+            'fa_IR': fa_IR,
+            'fil_PH': fil_PH,
+            'fi_FI': fi_FI,
+            'fr_CA': fr_CA,
+            ga,
+            'he_IL': he_IL,
+            'hi_IN': hi_IN,
+            hr,
+            'hu_HU': hu_HU,
+            is,
+            'jv_ID': jv_ID,
+            kk,
+            'km_KH': km_KH,
+            lt,
+            lv,
+            'my_MM': my_MM,
+            nb,
+            pt,
+            sk,
+            sl,
+            sq,
+            sw,
+            'uk_UA': uk_UA,
+            ur,
+            uz,
         };
         this.setState({ locale: language[code], localeCode: code });
     }
@@ -438,6 +509,41 @@ class I18nDemo extends React.Component {
                         <Select.Option value='sv_SE'>Swedish</Select.Option>
                         <Select.Option value='pl_PL'>Polish</Select.Option>
                         <Select.Option value='nl_NL'>Dutch</Select.Option>
+                        <Select.Option value="az">Azerbaijani</Select.Option>
+                        <Select.Option value="bn_IN">Bengali</Select.Option>
+                        <Select.Option value="bg">Bulgarian</Select.Option>
+                        <Select.Option value="ca">Catalan</Select.Option>
+                        <Select.Option value="cs_CZ">Czech</Select.Option>
+                        <Select.Option value="ceb_PH">Cebuano</Select.Option>
+                        <Select.Option value="da">Danish</Select.Option>
+                        <Select.Option value="el_GR">Greek</Select.Option>
+                        <Select.Option value="es_419">Spanish (Latin America)</Select.Option>
+                        <Select.Option value="et">Estonian</Select.Option>
+                        <Select.Option value="fa_IR">Persian</Select.Option>
+                        <Select.Option value="fil_PH">Filipino</Select.Option>
+                        <Select.Option value="fi_FI">Finnish</Select.Option>
+                        <Select.Option value="fr_CA">French (Canada)</Select.Option>
+                        <Select.Option value="ga">Irish</Select.Option>
+                        <Select.Option value="he_IL">Hebrew</Select.Option>
+                        <Select.Option value="hi_IN">Hindi</Select.Option>
+                        <Select.Option value="hr">Croatian</Select.Option>
+                        <Select.Option value="hu_HU">Hungarian</Select.Option>
+                        <Select.Option value="is">Icelandic</Select.Option>
+                        <Select.Option value="jv_ID">Javanese</Select.Option>
+                        <Select.Option value="kk">Kazakh</Select.Option>
+                        <Select.Option value="km_KH">Khmer</Select.Option>
+                        <Select.Option value="lt">Lithuanian</Select.Option>
+                        <Select.Option value="lv">Latvian</Select.Option>
+                        <Select.Option value="my_MM">Burmese</Select.Option>
+                        <Select.Option value="nb">Norwegian</Select.Option>
+                        <Select.Option value="pt">Portuguese</Select.Option>
+                        <Select.Option value="sk">Slovak</Select.Option>
+                        <Select.Option value="sl">Slovenian</Select.Option>
+                        <Select.Option value="sq">Albanian</Select.Option>
+                        <Select.Option value="sw">Swahili</Select.Option>
+                        <Select.Option value="uk_UA">Ukrainian</Select.Option>
+                        <Select.Option value="ur">Urdu</Select.Option>
+                        <Select.Option value="uz">Uzbek</Select.Option>
                     </Select>
                 </div>
                 <LocaleProvider locale={locale}>

+ 109 - 3
content/other/locale/index.md

@@ -1,6 +1,6 @@
 ---
 localeCode: zh-CN
-order: 92
+order: 94
 category: 其他
 title:  LocaleProvider 多语言
 icon: doc-i18n
@@ -22,7 +22,8 @@ brief: 国际化组件,为 Semi 组件提供多语言支持
 | v2.2.0     | 西班牙语: es       |
 | v2.15.0     | 意大利语: it、法语:fr、德语:de   |
 | v2.21.0     | 罗马尼亚语: ro   |
-| v2.29.0     | 瑞典语: sv_SE、波兰语: pl_PL 、荷兰语: nl_NL |
+| v2.29.0     | 瑞典语: sv_SE、波兰语: pl_PL、荷兰语: nl_NL |
+| v2.88.0     | 阿塞拜疆语:az、保加利亚语:bg、加泰罗尼亚语:ca、捷克语:cs_CZ、宿务语:ceb_PH、丹麦语: da、希腊语:el_GR、西班牙语(拉美):es_419、爱沙尼亚语:et、波斯语:fa_IR、菲律宾语:fil_PH、芬兰语: fi_FI、法语(加):fr_CA、爱尔兰语:ga、希伯来语:he_IL、印地语:hi_IN、克罗地亚语:hr、匈牙利语:hu_HU、冰岛语:is、爪哇语:jv_ID、哈萨克语:kk、高棉语:km_KH、立陶宛语:lt、拉脱维亚语:lv、缅甸语:my_MM、挪威语: nb、葡萄牙语:pt、斯洛伐克语:sk、斯洛文尼亚语:sl、阿尔巴尼亚语:sq、斯瓦希里语:sw、乌克兰语:uk_UA、乌尔都语:ur、乌兹别克语:uz |
 
 ## 已支持组件  
 目前有以下组件存在内置默认文本,均已实现国际化多语言适配  
@@ -203,6 +204,41 @@ import it from '@douyinfe/semi-ui/lib/es/locale/source/it';
 import de from '@douyinfe/semi-ui/lib/es/locale/source/de';
 import fr from '@douyinfe/semi-ui/lib/es/locale/source/fr';
 import ro from '@douyinfe/semi-ui/lib/es/locale/source/ro';
+import az from '@douyinfe/semi-ui/lib/es/locale/source/az';
+import bg from '@douyinfe/semi-ui/lib/es/locale/source/bg';
+import bn_IN from '@douyinfe/semi-ui/lib/es/locale/source/bn_IN';  
+import ca from '@douyinfe/semi-ui/lib/es/locale/source/ca';
+import cs_CZ from '@douyinfe/semi-ui/lib/es/locale/source/cs_CZ';
+import ceb_PH from '@douyinfe/semi-ui/lib/es/locale/source/ceb_PH';
+import da from '@douyinfe/semi-ui/lib/es/locale/source/da';
+import el_GR from '@douyinfe/semi-ui/lib/es/locale/source/el_GR';
+import es_419 from '@douyinfe/semi-ui/lib/es/locale/source/es_419';
+import et from '@douyinfe/semi-ui/lib/es/locale/source/et';
+import fa_IR from '@douyinfe/semi-ui/lib/es/locale/source/fa_IR';
+import fil_PH from '@douyinfe/semi-ui/lib/es/locale/source/fil_PH';
+import fi_FI from '@douyinfe/semi-ui/lib/es/locale/source/fi_FI';
+import fr_CA from '@douyinfe/semi-ui/lib/es/locale/source/fr_CA';
+import ga from '@douyinfe/semi-ui/lib/es/locale/source/ga';
+import he_IL from '@douyinfe/semi-ui/lib/es/locale/source/he_IL';
+import hi_IN from '@douyinfe/semi-ui/lib/es/locale/source/hi_IN';
+import hr from '@douyinfe/semi-ui/lib/es/locale/source/hr';
+import hu_HU from '@douyinfe/semi-ui/lib/es/locale/source/hu_HU';
+import is from '@douyinfe/semi-ui/lib/es/locale/source/is';
+import jv_ID from '@douyinfe/semi-ui/lib/es/locale/source/jv_ID';
+import kk from '@douyinfe/semi-ui/lib/es/locale/source/kk';
+import km_KH from '@douyinfe/semi-ui/lib/es/locale/source/km_KH';
+import lt from '@douyinfe/semi-ui/lib/es/locale/source/lt';
+import lv from '@douyinfe/semi-ui/lib/es/locale/source/lv';
+import my_MM from '@douyinfe/semi-ui/lib/es/locale/source/my_MM';
+import nb from '@douyinfe/semi-ui/lib/es/locale/source/nb';
+import pt from '@douyinfe/semi-ui/lib/es/locale/source/pt';
+import sk from '@douyinfe/semi-ui/lib/es/locale/source/sk';
+import sl from '@douyinfe/semi-ui/lib/es/locale/source/sl';
+import sq from '@douyinfe/semi-ui/lib/es/locale/source/sq';
+import sw from '@douyinfe/semi-ui/lib/es/locale/source/sw';
+import uk_UA from '@douyinfe/semi-ui/lib/es/locale/source/uk_UA';
+import ur from '@douyinfe/semi-ui/lib/es/locale/source/ur';
+import uz from '@douyinfe/semi-ui/lib/es/locale/source/uz';
 import { LocaleProvider, ConfigProvider, Pagination, Modal, Button, Select, Cascader, DatePicker, TreeSelect, Table, TimePicker, List, Calendar, Typography, Transfer, ImagePreview, Image, Form, Nav } from '@douyinfe/semi-ui';
 import { IconUser, IconSemiLogo, IconStar } from '@douyinfe/semi-icons';
 
@@ -239,7 +275,42 @@ class I18nDemo extends React.Component {
             de,
             it,
             fr,
-            ro
+            ro,
+            'bn_IN': bn_IN,
+            az,
+            bg,
+            ca,
+            'cs_CZ': cs_CZ,
+            'ceb_PH': ceb_PH,
+            da,
+            'el_GR': el_GR,
+            'es_419': es_419,
+            et,
+            'fa_IR': fa_IR,
+            'fil_PH': fil_PH,
+            'fi_FI': fi_FI,
+            'fr_CA': fr_CA,
+            ga,
+            'he_IL': he_IL,
+            'hi_IN': hi_IN,
+            hr,
+            'hu_HU': hu_HU,
+            is,
+            'jv_ID': jv_ID,
+            kk,
+            'km_KH': km_KH,
+            lt,
+            lv,
+            'my_MM': my_MM,
+            nb,
+            pt,
+            sk,
+            sl,
+            sq,
+            sw,
+            'uk_UA': uk_UA,
+            ur,
+            uz,
         };
         this.setState({ locale: language[code], localeCode: code });
     }
@@ -447,6 +518,41 @@ class I18nDemo extends React.Component {
                         <Select.Option value='sv_SE'>瑞典语</Select.Option>
                         <Select.Option value='pl_PL'>波兰语</Select.Option>
                         <Select.Option value='nl_NL'>荷兰语</Select.Option>
+                        <Select.Option value="az">阿塞拜疆语</Select.Option>
+                        <Select.Option value="bn_IN">孟加拉语</Select.Option>
+                        <Select.Option value="bg">保加利亚语</Select.Option>
+                        <Select.Option value="ca">加泰罗尼亚语</Select.Option>
+                        <Select.Option value="cs_CZ">捷克语</Select.Option>
+                        <Select.Option value="ceb_PH">宿务语</Select.Option>
+                        <Select.Option value="da">丹麦语</Select.Option>
+                        <Select.Option value="el_GR">希腊语</Select.Option>
+                        <Select.Option value="es_419">西班牙语(拉美)</Select.Option>
+                        <Select.Option value="et">爱沙尼亚语</Select.Option>
+                        <Select.Option value="fa_IR">波斯语</Select.Option>
+                        <Select.Option value="fil_PH">菲律宾语</Select.Option>
+                        <Select.Option value="fi_FI">芬兰语</Select.Option>
+                        <Select.Option value="fr_CA">法语(加)</Select.Option>
+                        <Select.Option value="ga">爱尔兰语</Select.Option>
+                        <Select.Option value="he_IL">希伯来语</Select.Option>
+                        <Select.Option value="hi_IN">印地语</Select.Option>
+                        <Select.Option value="hr">克罗地亚语</Select.Option>
+                        <Select.Option value="hu_HU">匈牙利语</Select.Option>
+                        <Select.Option value="is">冰岛语</Select.Option>
+                        <Select.Option value="jv_ID">爪哇语</Select.Option>
+                        <Select.Option value="kk">哈萨克语</Select.Option>
+                        <Select.Option value="km_KH">高棉语</Select.Option>
+                        <Select.Option value="lt">立陶宛语</Select.Option>
+                        <Select.Option value="lv">拉脱维亚语</Select.Option>
+                        <Select.Option value="my_MM">缅甸语</Select.Option>
+                        <Select.Option value="nb">挪威语</Select.Option>
+                        <Select.Option value="pt">葡萄牙语</Select.Option>
+                        <Select.Option value="sk">斯洛伐克语</Select.Option>
+                        <Select.Option value="sl">斯洛文尼亚语</Select.Option>
+                        <Select.Option value="sq">阿尔巴尼亚语</Select.Option>
+                        <Select.Option value="sw">斯瓦希里语</Select.Option>
+                        <Select.Option value="uk_UA">乌克兰语</Select.Option>
+                        <Select.Option value="ur">乌尔都语</Select.Option>
+                        <Select.Option value="uz">乌兹别克语</Select.Option>
                     </Select>
                 </div>
                 <LocaleProvider locale={locale}>

+ 1 - 2
content/plus/audioPlayer/index-en-US.md

@@ -1,12 +1,11 @@
 ---
 localeCode: en-US
-order: 94
+order: 96
 category: Plus
 title: AudioPlayer
 icon: doc-audioplayer
 width: 60%
 brief: Used to play audio
-showNew: true
 ---
 
 ## Demos

+ 1 - 2
content/plus/audioPlayer/index.md

@@ -1,12 +1,11 @@
 ---
 localeCode: zh-CN
-order: 94
+order: 96
 category: Plus
 title: AudioPlayer 音频播放器
 icon: doc-audioplayer
 width: 60%
 brief: 用于播放音频
-showNew: true
 ---
 
 ## 代码演示

+ 1 - 2
content/plus/chat/index-en-US.md

@@ -1,12 +1,11 @@
 ---
 localeCode: en-US
-order: 25
+order: 26
 category: Plus
 title:  Chat
 icon: doc-chat
 dir: column
 brief: Used to quickly build conversation content
-showNew: true
 ---
 
 ## When to use

Some files were not shown because too many files changed in this diff