From f0d9000ac21f2ff7324ddcf8d79836cbc14c355f Mon Sep 17 00:00:00 2001 From: Quan Date: Mon, 10 Nov 2025 19:08:18 +0800 Subject: [PATCH 1/3] feat: add artifact component and its sub components --- packages/elements/src/artifact/Artifact.vue | 23 +++++++ .../elements/src/artifact/ArtifactAction.vue | 61 +++++++++++++++++++ .../elements/src/artifact/ArtifactActions.vue | 20 ++++++ .../elements/src/artifact/ArtifactClose.vue | 32 ++++++++++ .../elements/src/artifact/ArtifactContent.vue | 22 +++++++ .../src/artifact/ArtifactDescription.vue | 20 ++++++ .../elements/src/artifact/ArtifactHeader.vue | 24 ++++++++ .../elements/src/artifact/ArtifactTitle.vue | 20 ++++++ packages/elements/src/artifact/index.tsx | 19 ++++++ packages/elements/src/artifact/props.ts | 17 ++++++ 10 files changed, 258 insertions(+) create mode 100644 packages/elements/src/artifact/Artifact.vue create mode 100644 packages/elements/src/artifact/ArtifactAction.vue create mode 100644 packages/elements/src/artifact/ArtifactActions.vue create mode 100644 packages/elements/src/artifact/ArtifactClose.vue create mode 100644 packages/elements/src/artifact/ArtifactContent.vue create mode 100644 packages/elements/src/artifact/ArtifactDescription.vue create mode 100644 packages/elements/src/artifact/ArtifactHeader.vue create mode 100644 packages/elements/src/artifact/ArtifactTitle.vue create mode 100644 packages/elements/src/artifact/index.tsx create mode 100644 packages/elements/src/artifact/props.ts diff --git a/packages/elements/src/artifact/Artifact.vue b/packages/elements/src/artifact/Artifact.vue new file mode 100644 index 0000000..bd199b7 --- /dev/null +++ b/packages/elements/src/artifact/Artifact.vue @@ -0,0 +1,23 @@ + + + diff --git a/packages/elements/src/artifact/ArtifactAction.vue b/packages/elements/src/artifact/ArtifactAction.vue new file mode 100644 index 0000000..44cde40 --- /dev/null +++ b/packages/elements/src/artifact/ArtifactAction.vue @@ -0,0 +1,61 @@ + + + diff --git a/packages/elements/src/artifact/ArtifactActions.vue b/packages/elements/src/artifact/ArtifactActions.vue new file mode 100644 index 0000000..9f79e19 --- /dev/null +++ b/packages/elements/src/artifact/ArtifactActions.vue @@ -0,0 +1,20 @@ + + + diff --git a/packages/elements/src/artifact/ArtifactClose.vue b/packages/elements/src/artifact/ArtifactClose.vue new file mode 100644 index 0000000..094e593 --- /dev/null +++ b/packages/elements/src/artifact/ArtifactClose.vue @@ -0,0 +1,32 @@ + + + diff --git a/packages/elements/src/artifact/ArtifactContent.vue b/packages/elements/src/artifact/ArtifactContent.vue new file mode 100644 index 0000000..a48db86 --- /dev/null +++ b/packages/elements/src/artifact/ArtifactContent.vue @@ -0,0 +1,22 @@ + + + diff --git a/packages/elements/src/artifact/ArtifactDescription.vue b/packages/elements/src/artifact/ArtifactDescription.vue new file mode 100644 index 0000000..3b4318a --- /dev/null +++ b/packages/elements/src/artifact/ArtifactDescription.vue @@ -0,0 +1,20 @@ + + + diff --git a/packages/elements/src/artifact/ArtifactHeader.vue b/packages/elements/src/artifact/ArtifactHeader.vue new file mode 100644 index 0000000..f1a7d43 --- /dev/null +++ b/packages/elements/src/artifact/ArtifactHeader.vue @@ -0,0 +1,24 @@ + + + diff --git a/packages/elements/src/artifact/ArtifactTitle.vue b/packages/elements/src/artifact/ArtifactTitle.vue new file mode 100644 index 0000000..15433df --- /dev/null +++ b/packages/elements/src/artifact/ArtifactTitle.vue @@ -0,0 +1,20 @@ + + + diff --git a/packages/elements/src/artifact/index.tsx b/packages/elements/src/artifact/index.tsx new file mode 100644 index 0000000..bff50bb --- /dev/null +++ b/packages/elements/src/artifact/index.tsx @@ -0,0 +1,19 @@ +export { default as Artifact } from './Artifact.vue' +export { default as ArtifactAction } from './ArtifactAction.vue' +export { default as ArtifactActions } from './ArtifactActions.vue' +export { default as ArtifactClose } from './ArtifactClose.vue' +export { default as ArtifactContent } from './ArtifactContent.vue' +export { default as ArtifactDescription } from './ArtifactDescription.vue' +export { default as ArtifactHeader } from './ArtifactHeader.vue' +export { default as ArtifactTitle } from './ArtifactTitle.vue' + +export type { + ArtifactActionProps, + ArtifactActionsProps, + ArtifactCloseProps, + ArtifactContentProps, + ArtifactDescriptionProps, + ArtifactHeaderProps, + ArtifactProps, + ArtifactTitleProps, +} from './props' diff --git a/packages/elements/src/artifact/props.ts b/packages/elements/src/artifact/props.ts new file mode 100644 index 0000000..8515230 --- /dev/null +++ b/packages/elements/src/artifact/props.ts @@ -0,0 +1,17 @@ +import type Button from '@repo/shadcn-vue/components/ui/button/Button.vue' +import type { LucideIcon } from 'lucide-vue-next' +import type { HTMLAttributes } from 'vue' + +export type ArtifactProps = HTMLAttributes +export type ArtifactHeaderProps = HTMLAttributes +export type ArtifactCloseProps = InstanceType +export type ArtifactTitleProps = HTMLAttributes +export type ArtifactDescriptionProps = HTMLAttributes +export type ArtifactActionsProps = HTMLAttributes +export type ArtifactActionProps = InstanceType & { + tooltip?: string + label?: string + icon?: LucideIcon +} + +export type ArtifactContentProps = HTMLAttributes From ddeceae7a3b242fb5da4b7bb8ae8f9e57187433e Mon Sep 17 00:00:00 2001 From: Quan Date: Mon, 10 Nov 2025 19:21:22 +0800 Subject: [PATCH 2/3] chore: create artifact example component with actions --- .../src/artifact/{index.tsx => index.ts} | 11 +- packages/elements/src/artifact/props.ts | 6 +- packages/examples/src/artifact.vue | 124 ++++++++++++++++++ packages/examples/src/index.ts | 1 + 4 files changed, 130 insertions(+), 12 deletions(-) rename packages/elements/src/artifact/{index.tsx => index.ts} (70%) create mode 100644 packages/examples/src/artifact.vue diff --git a/packages/elements/src/artifact/index.tsx b/packages/elements/src/artifact/index.ts similarity index 70% rename from packages/elements/src/artifact/index.tsx rename to packages/elements/src/artifact/index.ts index bff50bb..bf343c4 100644 --- a/packages/elements/src/artifact/index.tsx +++ b/packages/elements/src/artifact/index.ts @@ -7,13 +7,4 @@ export { default as ArtifactDescription } from './ArtifactDescription.vue' export { default as ArtifactHeader } from './ArtifactHeader.vue' export { default as ArtifactTitle } from './ArtifactTitle.vue' -export type { - ArtifactActionProps, - ArtifactActionsProps, - ArtifactCloseProps, - ArtifactContentProps, - ArtifactDescriptionProps, - ArtifactHeaderProps, - ArtifactProps, - ArtifactTitleProps, -} from './props' +export * from './props' diff --git a/packages/elements/src/artifact/props.ts b/packages/elements/src/artifact/props.ts index 8515230..80844ba 100644 --- a/packages/elements/src/artifact/props.ts +++ b/packages/elements/src/artifact/props.ts @@ -2,13 +2,15 @@ import type Button from '@repo/shadcn-vue/components/ui/button/Button.vue' import type { LucideIcon } from 'lucide-vue-next' import type { HTMLAttributes } from 'vue' +type ButtonProps = InstanceType['$props'] + export type ArtifactProps = HTMLAttributes export type ArtifactHeaderProps = HTMLAttributes -export type ArtifactCloseProps = InstanceType +export type ArtifactCloseProps = ButtonProps export type ArtifactTitleProps = HTMLAttributes export type ArtifactDescriptionProps = HTMLAttributes export type ArtifactActionsProps = HTMLAttributes -export type ArtifactActionProps = InstanceType & { +export type ArtifactActionProps = ButtonProps & { tooltip?: string label?: string icon?: LucideIcon diff --git a/packages/examples/src/artifact.vue b/packages/examples/src/artifact.vue new file mode 100644 index 0000000..f5899da --- /dev/null +++ b/packages/examples/src/artifact.vue @@ -0,0 +1,124 @@ + + + diff --git a/packages/examples/src/index.ts b/packages/examples/src/index.ts index fd38924..104d2a7 100644 --- a/packages/examples/src/index.ts +++ b/packages/examples/src/index.ts @@ -1,5 +1,6 @@ export { default as ActionsHover } from './actions-hover.vue' export { default as Actions } from './actions.vue' +export { default as Artifact } from './artifact.vue' export { default as Branch } from './branch.vue' export { default as ChainOfThought } from './chain-of-thought.vue' export { default as CodeBlockDark } from './code-block-dark.vue' From 0dc8c1de1a74e9aa97c88d2c46090a6d8efde5ec Mon Sep 17 00:00:00 2001 From: Quan Date: Mon, 10 Nov 2025 22:25:00 +0800 Subject: [PATCH 3/3] feat: implement Artifact component with subcomponents and update installation instructions --- apps/www/content/2.components/artifact.md | 402 ++++++++++++++++++ apps/www/plugins/ai-elements.ts | 2 + packages/elements/src/artifact/Artifact.vue | 15 +- .../elements/src/artifact/ArtifactAction.vue | 12 +- .../elements/src/artifact/ArtifactActions.vue | 16 +- .../elements/src/artifact/ArtifactClose.vue | 8 +- .../elements/src/artifact/ArtifactContent.vue | 9 +- .../src/artifact/ArtifactDescription.vue | 15 +- .../elements/src/artifact/ArtifactHeader.vue | 14 +- .../elements/src/artifact/ArtifactTitle.vue | 15 +- packages/elements/src/artifact/index.ts | 2 - packages/elements/src/artifact/props.ts | 19 - packages/elements/src/index.ts | 1 + 13 files changed, 466 insertions(+), 64 deletions(-) create mode 100644 apps/www/content/2.components/artifact.md delete mode 100644 packages/elements/src/artifact/props.ts diff --git a/apps/www/content/2.components/artifact.md b/apps/www/content/2.components/artifact.md new file mode 100644 index 0000000..13d505e --- /dev/null +++ b/apps/www/content/2.components/artifact.md @@ -0,0 +1,402 @@ +--- +title: Artifact +description: A container component for displaying generated content like code, documents, or other outputs with built-in actions. +icon: lucide:file-text +--- + +The `Artifact` component provides a structured container for displaying generated content like code, documents, or other outputs with built-in header actions. + +## Install using CLI + +:::tabs{variant="card"} + ::div{label="ai-elements-vue"} + ```sh + npx ai-elements-vue@latest add artifact + ``` + :: + ::div{label="shadcn-vue"} + + ```sh + npx shadcn-vue@latest add https://registry.ai-elements-vue.com/artifact.json + ``` + :: +::: + +## Install Manually + +Copy and paste the following code in the same folder. + +:::code-group + ```vue [Artifact.vue] + + + + ``` + + ```vue [ArtifactAction.vue] + + + + ``` + + ```vue [ArtifactActions.vue] + + + + ``` + + ```vue [ArtifactClose.vue] + + + + ``` + + ```vue [ArtifactContent.vue] + + + + ``` + + ```vue [ArtifactDescription.vue] + + + + ``` + + ```vue [ArtifactHeader.vue] + + + + ``` + + ```vue [ArtifactTitle.vue] + + + + ``` + + ```ts [index.ts] + export { default as Artifact } from './Artifact.vue' + export { default as ArtifactAction } from './ArtifactAction.vue' + export { default as ArtifactActions } from './ArtifactActions.vue' + export { default as ArtifactClose } from './ArtifactClose.vue' + export { default as ArtifactContent } from './ArtifactContent.vue' + export { default as ArtifactDescription } from './ArtifactDescription.vue' + export { default as ArtifactHeader } from './ArtifactHeader.vue' + export { default as ArtifactTitle } from './ArtifactTitle.vue' + ``` + +::: + +## Features + +- Structured container with header and content areas +- Built-in header with title and description support +- Flexible action buttons with tooltips +- Customizable styling for all subcomponents +- Support for close buttons and action groups +- Clean, modern design with border and shadow +- Responsive layout that adapts to content +- TypeScript support with proper type definitions +- Composable architecture for maximum flexibility + +## Examples + +### With Code Display + +:::ComponentLoader{label="Artifact" componentName="Artifact"} +::: + +## Props + +### `` + +:::field-group + ::field{name="[...props]" type="HTMLAttributes"} + Additional props forwarded to the root `
` element. + :: +::: + +### `` + +:::field-group + ::field{name="[...props]" type="HTMLAttributes"} + Additional props forwarded to the header `
` element. + :: +::: + +### `` + +:::field-group + ::field{name="[...props]" type="HTMLAttributes"} + Additional props forwarded to the title `

` element. + :: +::: + +### `` + +:::field-group + ::field{name="[...props]" type="HTMLAttributes"} + Additional props forwarded to the description `

` element. + :: +::: + +### `` + +:::field-group + ::field{name="[...props]" type="HTMLAttributes"} + Additional props forwarded to the actions `

` element. + :: +::: + +### `` + +:::field-group + ::field{name="tooltip" type="string"} + Tooltip text shown when hovering the action button. + :: + + ::field{name="label" type="string"} + Screen reader label used for accessible button text. + :: + + ::field{name="icon" type="LucideIcon"} + Lucide icon component rendered inside the action button. + :: + + ::field{name="[...props]" type="ButtonProps"} + Additional props forwarded to the underlying shadcn-vue `Button`. + :: +::: + +### `` + +:::field-group + ::field{name="[...props]" type="ButtonProps"} + Additional props forwarded to the underlying shadcn-vue `Button`. + :: +::: + +### `` + +:::field-group + ::field{name="[...props]" type="HTMLAttributes"} + Additional props forwarded to the content `
` element. + :: +::: diff --git a/apps/www/plugins/ai-elements.ts b/apps/www/plugins/ai-elements.ts index afe782c..82f4990 100644 --- a/apps/www/plugins/ai-elements.ts +++ b/apps/www/plugins/ai-elements.ts @@ -1,6 +1,7 @@ import { Actions, ActionsHover, + Artifact, Branch, ChainOfThought, CodeBlock, @@ -39,6 +40,7 @@ export default defineNuxtPlugin((nuxtApp) => { vueApp.component('ComponentLoader', ComponentLoader) vueApp.component('ComponentViewer', ComponentViewer) + vueApp.component('Artifact', Artifact) vueApp.component('Actions', Actions) vueApp.component('ActionsHover', ActionsHover) vueApp.component('Branch', Branch) diff --git a/packages/elements/src/artifact/Artifact.vue b/packages/elements/src/artifact/Artifact.vue index bd199b7..6375401 100644 --- a/packages/elements/src/artifact/Artifact.vue +++ b/packages/elements/src/artifact/Artifact.vue @@ -1,22 +1,23 @@