Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Proposal: Support for Custom Components in Chatkit #53

Open
@MatthieuBonnardot

Description

@MatthieuBonnardot

Hi team,

First off, I really appreciate the amazing work you’re doing with Chatkit — it’s been great to build on top of it.

I currently have a branch ready across chatkit, chatkit-python, and chatkit-react that enables support for custom components. The core idea is to introduce a new widget called CustomWidget, which accepts the necessary props and JSON configuration. On the frontend, these would then be hydrated with user-defined custom components.

In theory, everything looks good with my current changes. I’ve also implemented a hook to list available custom components and automatically hydrate them in chat. However, since the Chatkit CDN code is minified, I don’t have a straightforward way to fully test this end-to-end.

Would it still be useful for me to open these PRs so the team can review the approach and direction? Or is this not aligned with OpenAI’s current vision for widgets?

I genuinely believe that enabling custom components could significantly improve flexibility, enhance customization, and drive greater adoption of Chatkit.

Thanks for your time and the great work you’re doing!

==============================

Proposed Implementation

I have a working implementation across all three repos that I'm happy to contribute.

1. Core Widget Type (@openai/chatkit)

// packages/chatkit/types/widgets.d.tsexporttypeWidgetComponent=|TextComponent|Title|Caption// ... existing types|CustomComponent;// New typeexporttypeCustomComponent={type:'Custom';key?:string;id?:string;componentType:string;// Identifier for the React componentprops?:Record<string,unknown>;// Props to pass to the component}&BlockProps;

2. Widget Options Extension

// packages/chatkit/types/index.d.tsexporttypeWidgetsOption={onAction?:(...)=>Promise<void>;// New callback for custom component renderingonRenderCustom?:(component:Widgets.CustomComponent,container:HTMLElement,)=>void|Promise<void>;};

3. React Hook (@openai/chatkit-react)

// packages/chatkit-react/src/useCustomWidgets.tsxexporttypeCustomComponentRegistry=Record<string,React.ComponentType<any>>;exportfunctionuseCustomWidgets(components:CustomComponentRegistry){constrootsRef=React.useRef<Map<HTMLElement,ReactDOM.Root>>(newMap());constonRenderCustom=React.useCallback((component:Widgets.CustomComponent,container:HTMLElement)=>{constComponent=components[component.componentType];if(!Component){console.warn(`Custom component "${component.componentType}" not found in registry.`);return;}// Clean up existing root if it existsconstexistingRoot=rootsRef.current.get(container);if(existingRoot){existingRoot.unmount();}// Create new root and renderconstroot=ReactDOM.createRoot(container);rootsRef.current.set(container,root);root.render(<React.StrictMode><Component{...(component.props||{})}/></React.StrictMode>);},[components]);// Cleanup on unmountReact.useEffect(()=>{constroots=rootsRef.current;return()=>{for(constrootofroots.values()){root.unmount();}roots.clear();};},[]);return{widgets:{ onRenderCustom}};}

Usage Example

Frontend

import{useChatKit,useCustomWidgets,ChatKit}from'@openai/chatkit-react';// Define custom componentfunctionProductCard({ name, price, imageUrl}:ProductCardProps){return(<divclassName="product-card"><imgsrc={imageUrl}alt={name}/><h3>{name}</h3><p>${price.toFixed(2)}</p><button>Add to Cart</button></div>);}functionApp(){// Register custom componentsconstcustomWidgets=useCustomWidgets({'product-card':ProductCard,'user-profile':UserProfile,'chart':ChartWidget,});constchatKit=useChatKit({api:{url:'/api/chatkit',domainKey:'key'},widgets:customWidgets.widgets,});return<ChatKitcontrol={chatKit.control}/>;}

Backend (Python SDK)

fromchatkitimportCardfromchatkit.widgetsimportCustomComponentwidget=Card(children=[CustomComponent(component_type="product-card",props={"name":"Wireless Headphones","price":149.99,"imageUrl":"https://example.com/image.jpg"            }        )    ])

Backend (JSON)

{"type":"Card","children": [    {"type":"Custom","componentType":"product-card","props": {"name":"Wireless Headphones","price":149.99,"imageUrl":"https://example.com/image.jpg"      }    }  ]}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions


      [8]ページ先頭

      ©2009-2025 Movatter.jp