tencent cloud

Tencent Cloud Agent Development Platform

ADP-Widget SDK

PDF
Focus Mode
Font Size
Last updated: 2026-04-09 15:21:27

What is ADP-Widget?

ADP-Widget is a cross-framework UI component SDK developed based on the Web Components standard, supporting dynamic rendering of complete user interfaces through JSON configuration. If users do not use the ADP page but wish to display the Widget in their own product systems, they can achieve this by leveraging the ADP-Widget SDK.
Download link: ADP-Widget SDK.

Core Features

Cross-framework compatibility: Supports React, Vue, and vanilla HTML.
JSON-driven: Renders complete UI through configuration objects.
Zero CSS import: Styles are fully inlined into the Shadow DOM.
On-demand loading: Markdown and Chart components are dynamically loaded.
Internationalization support: Built-in Chinese/English switching is supported.
Type safety: Complete TypeScript type definitions.

Scenarios

Dynamic form rendering.
Conversational UI cards.
Data visualization dashboard (based on Recharts).
Configuration-based page generation.
Rendering of ChatKit Widget JSON protocol.

Preparing the Environment

1. Browser requirements

Browser
Minimum version
Chrome
67+
Firefox
63+
Safari
12.1+
Edge
79+
Note:
Does not support Internet Explorer.

2. Tech stack requirements

Native HTML project.
No special requirements, only requires support for ES Module.
React project
React 16.8+ (React 18+ recommended).
TypeScript 4.0+ (optional).
Vue project
Vue 2.x / Vue 3.x (both supported).
TypeScript 4.0+ (optional).
Note:
ADP-Widget is based on the Web Components standard, independent of framework versions, and supports all mainstream frameworks in theory.

3. SDK introduction method

Download the SDK package

Obtain the complete SDK file package from the release channel. After decompression, it contains:
lib/
├── adp-widget.js (366KB) - main package [required]
├── adp-widget-vendor.js (342KB) - dependency package [required]
├── adp-widget-markdown.js (600KB) - Markdown component [on-demand loading]
└── adp-widget-chart.js (790KB) - chart component [on-demand loading]

Method 1: CDN deployment

Step 1: Obtain the CDN link
After decompression, deploy all js files in the lib folder to the same CDN address, for example:
https://cdn.example.com/adp-widget/v1.2.1/adp-widget.js
https://cdn.example.com/adp-widget/v1.2.1/adp-widget-vendor.js
https://cdn.example.com/adp-widget/v1.2.1/adp-widget-markdown.js
https://cdn.example.com/adp-widget/v1.2.1/adp-widget-chart.js
Step 2: Import in HTML
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>ADP-Widget Example</title>

<!-- Import local SDK files -->
<script type="module" src="/widget/adp-widget.js"></script>
</head>
<body>
<adp-widget id="my-widget"></adp-widget>

<script type="module">
const widget = document.getElementById("my-widget");

widget.setAttribute(
"widget-json",
JSON.stringify({
type: "Card",
children: [
{ type: "Title", value: "Welcome to ADP-Widget" },
{ type: "Text", value: "This is a dynamically rendered card" },
],
})
);
</script>
</body>
</html>

Option 2: Local deployment

Step 1: Deploy to the project
Place all js files in the lib folder after decompression into the static resources directory of the project, for example:
Project root directory/
├── public/
│ └── widget/
│ ├── adp-widget.js
│ ├── adp-widget-vendor.js
│ ├── adp-widget-markdown.js
│ └── adp-widget-chart.js
└── index.html
Step 2: Import in HTML
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>ADP-Widget Example</title>

<!-- Import local SDK files -->
<script type="module" src="/widget/adp-widget.js"></script>
</head>
<body>
<adp-widget id="my-widget"></adp-widget>

<script type="module">
const widget = document.getElementById("my-widget");

widget.setAttribute(
"widget-json",
JSON.stringify({
type: "Card",
children: [
{ type: "Title", value: "Welcome to ADP-Widget" },
{ type: "Text", value: "This is a dynamically rendered card" },
],
})
);
</script>
</body>
</html>


4. Use in the frontend framework

Whether using CDN or local deployment, ADP-Widget can be used in any frontend framework. The following are integration methods for common frameworks.

4.1 React Project Integration

Step 1: Import the SDK in index.html.
<!doctype html>
<html lang="zh-CN">
<head>
<!-- Method 1: Use CDN -->
<script
type="module"
src="https://cdn.example.com/adp-widget/v1.0.0/adp-widget.js"
></script>

<!-- Method 2: Use local files -->
<!-- <script type="module" src="/widget/adp-widget.js"></script> -->
</head>
<body>
<div id="root"></div>
</body>
</html>
Step 2: Add TypeScript type declarations (optional).
Applicable scenarios:
The project is developed using TypeScript.
Code hints and type checking are required in the editor.
Pure JavaScript projects can skip this step.
If using TypeScript, create src/vite-env.d.ts:
/// <reference types="vite/client" />

declare namespace JSX {
interface IntrinsicElements {
"adp-widget": React.DetailedHTMLProps<
React.HTMLAttributes<HTMLElement> & {
"widget-json"?: string;
disable?: boolean;
locale?: string;
ref?: React.Ref<HTMLElement>;
},
HTMLElement
>;
}
}
Step 3: Use in components.
import { useEffect, useRef, useState } from "react";

function WidgetDemo() {
const widgetRef = useRef<HTMLElement>(null);
const [config, setConfig] = useState({
type: "Card",
children: [
{ type: "Title", value: "React Integration Example" },
{
type: "Button",
label: "click me",
onClickAction: { type: "button.click" },
},
],
});

useEffect(() => {
const widget = widgetRef.current;
if (!widget) return;

const handleAction = (e: Event) => {
const customEvent = e as CustomEvent;
console.log("Action:", customEvent.detail.action);
};

widget.addEventListener("widget-action", handleAction);
return () => {
widget.removeEventListener("widget-action", handleAction);
};
}, []);

return (
<adp-widget
ref={widgetRef}
widget-json={JSON.stringify(config)}
locale="zh-CN"
/>
);
}

export default WidgetDemo;

4.2 Vue Implementation Integration

Step 1: Import the SDK in index.html.
<!doctype html>
<html lang="zh-CN">
<head>
<!-- Method 1: Use CDN -->
<script
type="module"
src="https://cdn.example.com/adp-widget/v1.0.0/adp-widget.js"
></script>

<!-- Method 2: Use local files -->
<!-- <script type="module" src="/widget/adp-widget.js"></script> -->
</head>
<body>
<div id="app"></div>
</body>
</html>
Step 2: Add TypeScript type declarations (optional).
Applicable scenarios:
The project is developed using TypeScript.
Code hints and type checking are required in the editor.
Pure JavaScript projects can skip this step.
If using TypeScript, create src/vite-env.d.ts:
/// <reference types="vite/client" />

declare module "vue" {
export interface GlobalComponents {
"adp-widget": {
"widget-json"?: string;
disable?: boolean;
locale?: string;
};
}
}

Step 3: Use in components.
<template>
<div class="widget-container">
<adp-widget
ref="widgetRef"
:widget-json="JSON.stringify(config)"
:locale="locale"
:disable="isDisabled"
@widget-action="handleAction"
@widget-rendered="handleRendered"
/>
</div>
</template>

<script setup lang="ts">
import { ref } from "vue";

const widgetRef = ref<HTMLElement>();
const locale = ref<"zh-CN" | "en-US">("zh-CN");
const isDisabled = ref(false);

const config = ref({
type: "Card",
children: [
{ type: "Title", value: "Vue Integration Example" },
{
type: "Button",
label: "Click me",
onClickAction: { type: "button.click" },
},
],
});

const handleAction = (e: Event) => {
const customEvent = e as CustomEvent;
console.log("Action:", customEvent.detail.action);
};

const handleRendered = (e: Event) => {
const customEvent = e as CustomEvent;
console.log("Rendered:", customEvent.detail);
};
</script>

Core API

HTML Attributes (Attributes)

widget-json (required)
Type: string
Description: A configuration object in JSON string format.
Example:
<adp-widget widget-json='{"type":"Button","label":"button"}'></adp-widget>
Dynamically set in JavaScript:
const config = { type: "Button", label: "button" };
widget.setAttribute("widget-json", JSON.stringify(config));
disable (optional)
Type: boolean
Default: false
Description: Globally disable all form inputs and buttons (except those with alwaysEnabled: true set).
Example:
<!-- Disable -->
<adp-widget widget-json="..." disable></adp-widget>

<!-- enable -->
<adp-widget widget-json="..."></adp-widget>
Dynamic control:
// Disable
widget.setAttribute("disable", "");

// enable
widget.removeAttribute("disable");
locale (optional)
Type: string
Default: 'zh-CN'
Supported values:
Chinese: 'zh-CN','zh','chinese'
English: 'en-US','en','english'
Description: Set the interface language.
Example:
<!-- Chinese -->
<adp-widget widget-json="..." locale="zh-CN"></adp-widget>

<!-- English -->
<adp-widget widget-json="..." locale="en-US"></adp-widget>

event handling

widget-action event

Event details:
interface WidgetActionEvent extends CustomEvent {
detail: {
action: {
type: string; // Action type
payload?: Record<string, unknown>; // Action data
};
};
}
Native HTML JavaScript:
<!doctype html>
<html>
<head>
<script type="module" src="/widget/adp-widget.js"></script>
</head>
<body>
<adp-widget id="demo"></adp-widget>

<script type="module">
const widget = document.getElementById("demo");

// Listen for widget-action events
widget.addEventListener("widget-action", (e) => {
console.log("widget-action event:", e.detail.action);
});

// Listen for widget-rendered events
widget.addEventListener("widget-rendered", (e) => {
console.log("widget-rendered event:", e.detail);
});
</script>
</body>
</html>
React project:
import { useEffect, useRef } from "react";

function WidgetWrapper() {
const widgetRef = useRef<HTMLElement>(null);

useEffect(() => {
const widget = widgetRef.current;
if (!widget) return;

const handleAction = (e: Event) => {
const customEvent = e as CustomEvent;
console.log("widget-action event:", customEvent.detail.action);
};

const handleRendered = (e: Event) => {
const customEvent = e as CustomEvent;
console.log("widget-rendered event:", customEvent.detail);
};

widget.addEventListener("widget-action", handleAction);
widget.addEventListener("widget-rendered", handleRendered);

return () => {
widget.removeEventListener("widget-action", handleAction);
widget.removeEventListener("widget-rendered", handleRendered);
};
}, []);

return <adp-widget ref={widgetRef} widget-json={JSON.stringify(config)} />;
}
Vue 3 project:
<template>
<adp-widget
:widget-json="JSON.stringify(config)"
@widget-action="handleAction"
@widget-rendered="handleRendered"
/>
</template>


<script setup lang="ts">
import { ref } from "vue";


const config = ref({ type: "Button", label: "Click me" });


const handleAction = (e: Event) => {
const customEvent = e as CustomEvent;
console.log("widget-action event:", customEvent.detail.action);
};


const handleRendered = (e: Event) => {
const customEvent = e as CustomEvent;
console.log("widget-rendered event:", customEvent.detail);
};
</script>

Advanced Features

Globally disabled feature

Basic usage:
<!-- Disable the entire form -->
<adp-widget widget-json="..." disable></adp-widget>
Dynamic switching:
const widget = document.querySelector("adp-widget");

// Disable
widget.setAttribute("disable", "true");
// Or
widget.disable = true;

// enable
widget.removeAttribute("disable");
// Or
widget.disable = false;
The alwaysEnabled feature: Certain buttons can be clicked even when the form is disabled.
{
"type": "Button",
"label": "View Help",
"onClickAction": {
"type": "help.show",
"alwaysEnabled": true // 🔥 ignore global disable
}
}
Applicable scenarios:
Help button
Cancel button
Navigation button

Internationalization feature

Switch language

<!-- Chinese -->
<adp-widget widget-json="..." locale="zh-CN"></adp-widget>

<!-- English -->
<adp-widget widget-json="..." locale="en-US"></adp-widget>
Dynamic switching:
const widget = document.querySelector("adp-widget");

// Switch to English
widget.setAttribute("locale", "en-US");

// Switch to Chinese
widget.setAttribute("locale", "zh-CN");
Supported language aliases:
Language
standard value
Alias
Chinese
zh-CN
zh, chinese
English
en-US
en, english

Common error handling

Configuration error

Error example 1: JSON format error
// Error: Single quotes are not valid JSON
widget.setAttribute("widget-json", "{'type':'Button'}");

// Correct: Use JSON.stringify
widget.setAttribute("widget-json", JSON.stringify({ type: "Button" }));
Error example 2: Missing required field
// Error: Input must have a name field
{
"type": "Input",
"placeholder": "Please enter"
}

// Correct:
{
"type": "Input",
"name": "username",
"placeholder": "Please enter"
}
Error example 3: Listening for rendering errors
widget.addEventListener("widget-rendered", (e) => {
if (!e.detail.success) {
const error = e.detail.error;
console.error("Rendering failed:", error.message);

// Display a friendly prompt
alert(`Configuration error: ${error.message}`);
}
});

Event listening error

Error example 1: ref is null
// Error: Accessing ref before component mount
const widgetRef = useRef<HTMLElement>(null);
widgetRef.current.addEventListener("widget-action", handler); // Error!

// Correct: Listen in useEffect
useEffect(() => {
const widget = widgetRef.current;
if (!widget) return;

widget.addEventListener("widget-action", handler);
return () => widget.removeEventListener("widget-action", handler);
}, []);
Error example 2: Forgot to remove the listener
// Error: Memory leak
function setupWidget() {
widget.addEventListener("widget-action", (e) => {
console.log(e.detail);
});
}


// Correct: Save the reference and remove it during cleanup
function setupWidget() {
const handler = (e) => console.log(e.detail);
widget.addEventListener("widget-action", handler);


return () => {
widget.removeEventListener("widget-action", handler);
};
}

Property passing error

Common Errors in Vue
<!-- Error: disable is a boolean attribute, requires v-bind -->
<adp-widget disable="false"></adp-widget>

<!-- Correct -->
<adp-widget :disable="false"></adp-widget>

<!-- Error: widget-json should be a string -->
<adp-widget :widget-json="config"></adp-widget>

<!-- Correct -->
<adp-widget :widget-json="JSON.stringify(config)"></adp-widget>

Loading error

Error: adp-widget tag not found.
<!-- Error: Used before SDK is loaded -->
<script>
const widget = document.querySelector("adp-widget"); // null!
</script>
<script type="module" src="/widget/adp-widget.js"></script>

<!-- Correct: Ensure the SDK is loaded first -->
<script type="module" src="/widget/adp-widget.js"></script>
<script type="module">
// Wait for the DOM to be ready
document.addEventListener("DOMContentLoaded", () => {
const widget = document.querySelector("adp-widget");
});
</script>

Appendix: Complete Example Project

React Example
# Clone the example project
git clone https://github.com/example/adp-widget-examples.git
cd adp-widget-examples/react-example

# Install dependencies.
npm install

# Start the development server
npm run dev
Vue Example
cd adp-widget-examples/vue-example
npm install
npm run dev
Clone the sample project.
git clone https://github.com/example/adp-widget-examples.git
cd adp-widget-examples/react-example
Install dependencies.
npm install
Start the development server.
npm run dev





Help and Support

Was this page helpful?

Help us improve! Rate your documentation experience in 5 mins.

Feedback