diff --git a/app/javascript/react-components/src/components/VueWebComponentWrapper.jsx b/app/javascript/react-components/src/components/VueWebComponentWrapper.jsx
new file mode 100644
index 000000000..43a4d1fb8
--- /dev/null
+++ b/app/javascript/react-components/src/components/VueWebComponentWrapper.jsx
@@ -0,0 +1,106 @@
+import React, { useEffect, useRef, useState } from 'react';
+import { registerVueWebComponents } from '../vue-components/registerWebComponents';
+
+export const VueWebComponentWrapper = ({
+ initialCount = 0,
+ title = 'Hello from Vue in React!',
+ color = '#42b883',
+ ...otherProps
+}) => {
+ const elementRef = useRef();
+ const [isReady, setIsReady] = useState(false);
+ const [currentCount, setCurrentCount] = useState(initialCount);
+
+ // Register Web Components on mount
+ useEffect(() => {
+ registerVueWebComponents();
+ setIsReady(true);
+
+ // Listen for custom events from Vue component
+ const handleCountChange = event => {
+ setCurrentCount(event.detail.count);
+ console.log('Vue component count changed:', event.detail.count);
+ };
+
+ document.addEventListener('vue-counter-changed', handleCountChange);
+
+ return () => {
+ document.removeEventListener('vue-counter-changed', handleCountChange);
+ };
+ }, []);
+
+ // Update Web Component properties when React props change
+ useEffect(() => {
+ if (!isReady || !elementRef.current) return;
+
+ const element = elementRef.current;
+
+ // Set properties on the Web Component
+ // Vue converts camelCase props to kebab-case attributes
+ element.setAttribute('initial-count', initialCount);
+ element.setAttribute('title', title);
+ element.setAttribute('color', color);
+
+ console.log('Updated Vue Web Component props:', {
+ initialCount,
+ title,
+ color,
+ });
+ }, [isReady, initialCount, title, color]);
+
+ if (!isReady) {
+ return (
+
+ Loading Vue Web Component...
+
+ );
+ }
+
+ return (
+
+
+ React Wrapper Info: Current count tracked by React:{' '}
+ {currentCount}
+
+
+ {/* This is the Vue Web Component rendered inside React */}
+
+
+
+ ✅ This Vue component is running as a Web Component inside React!
+
+
+ );
+};
diff --git a/app/javascript/react-components/src/index.jsx b/app/javascript/react-components/src/index.jsx
index 45893072f..c2f0dcd63 100644
--- a/app/javascript/react-components/src/index.jsx
+++ b/app/javascript/react-components/src/index.jsx
@@ -1,2 +1,3 @@
// Export all React components for the Chatwoot React Components library
-export { HelloWorld } from './components/HelloWorld';
\ No newline at end of file
+export { HelloWorld } from './components/HelloWorld';
+export { VueWebComponentWrapper } from './components/VueWebComponentWrapper';
\ No newline at end of file
diff --git a/app/javascript/react-components/src/vue-components/VueHelloWorld.vue b/app/javascript/react-components/src/vue-components/VueHelloWorld.vue
new file mode 100644
index 000000000..aba34307d
--- /dev/null
+++ b/app/javascript/react-components/src/vue-components/VueHelloWorld.vue
@@ -0,0 +1,134 @@
+
+
+
+
+
{{ title }}
+
{{ labels.currentCount }} {{ count }}
+
+
+
+
+
+
{{ labels.info }}
+
+
+
+
diff --git a/app/javascript/react-components/src/vue-components/registerWebComponents.js b/app/javascript/react-components/src/vue-components/registerWebComponents.js
new file mode 100644
index 000000000..7d6837966
--- /dev/null
+++ b/app/javascript/react-components/src/vue-components/registerWebComponents.js
@@ -0,0 +1,18 @@
+import { defineCustomElement } from 'vue';
+import VueHelloWorld from './VueHelloWorld.vue';
+
+// Convert Vue component to Web Component
+const VueHelloWorldElement = defineCustomElement(VueHelloWorld);
+
+// Register Web Components
+export const registerVueWebComponents = () => {
+ // Check if already registered to prevent errors
+ if (!customElements.get('vue-hello-world')) {
+ customElements.define('vue-hello-world', VueHelloWorldElement);
+ // eslint-disable-next-line no-console
+ console.log('✅ Registered vue-hello-world Web Component');
+ }
+};
+
+// Export for manual registration if needed
+export { VueHelloWorldElement };