diff --git a/widget/.npmignore b/widget/.npmignore new file mode 100644 index 00000000..46ce5535 --- /dev/null +++ b/widget/.npmignore @@ -0,0 +1,17 @@ +src +node_modules +build +public +tests +Dockerfile +.dockerignore +.eslintrc.json +index.html +package.json +tsconfig.app.json +tsconfig.json +tsconfig.node.json +vite.config.ts +dist/index.html +dist/shadow.html +vite.svg diff --git a/widget/README.md b/widget/README.md index bb512674..64f272ba 100644 --- a/widget/README.md +++ b/widget/README.md @@ -1,6 +1,8 @@ # Hexabot Live Chat Widget The [Hexabot](https://hexabot.ai/) Live Chat Widget is a React-based embeddable widget that allows users to integrate real-time chat functionality into their websites. It connects to the Hexabot API and facilitates seamless interaction between end-users and chatbots across multiple channels. +[Hexabot](https://hexabot.ai/) is an open-source chatbot / agent solution that allows users to create and manage AI-powered, multi-channel, and multilingual chatbots with ease. If you would like to learn more, please visit the [official github repo](https://github.com/Hexastack/Hexabot/). + ## Key Features - **Real-Time Chat:** Engage in real-time conversations with users directly through your website. - **Customizable:** Easily customize the widget's appearance and behavior to fit your brand and website. @@ -68,6 +70,40 @@ Once the widget is built, you can easily embed it into any webpage. Here's an ex ``` Replace the values in apiUrl and token with your configuration details. +To prevent the website css from conflicting with the chat widget css, we can leverage the shadow dom: +```js + + + + +
+ +``` + ## Customization You can customize the look and feel of the chat widget by modifying the widget’s scss styles or behavior. The widget allows you to: diff --git a/widget/package.json b/widget/package.json index 85a07b2e..4d7a3b03 100644 --- a/widget/package.json +++ b/widget/package.json @@ -1,11 +1,12 @@ { - "name": "hexabot-widget", - "private": true, - "version": "2.0.0", + "name": "hexabot-live-chat-widget", + "version": "2.0.0-rc.2", "description": "Hexabot is a solution for creating and managing chatbots across multiple channels, leveraging AI for advanced conversational capabilities. It provides a user-friendly interface for building, training, and deploying chatbots with integrated support for various messaging platforms.", "author": "Hexastack", "license": "AGPL-3.0-only", "type": "module", + "main": "dist/hexabot-widget.umd.js", + "style": "dist/style.css", "scripts": { "dev": "vite", "build": "tsc && vite build", @@ -38,5 +39,9 @@ "typescript": "^5.2.2", "vite": "^5.3.4", "vite-plugin-dts": "^4.0.2" + }, + "optionalDependencies": { + "@rollup/rollup-darwin-arm64": "^4.24.0", + "@esbuild/darwin-arm64": "^0.24.0" } } diff --git a/widget/public/index.html b/widget/public/index.html index 6904e828..08131b04 100644 --- a/widget/public/index.html +++ b/widget/public/index.html @@ -18,15 +18,26 @@
diff --git a/widget/src/components/UserInput.scss b/widget/src/components/UserInput.scss index 5ea10e54..60152fd7 100644 --- a/widget/src/components/UserInput.scss +++ b/widget/src/components/UserInput.scss @@ -8,7 +8,7 @@ border-bottom-left-radius: 10px; border-bottom-right-radius: 10px; transition: background-color 0.2s ease, box-shadow 0.2s ease; - border-top: 1px solid #eaeaea; + border: 1px solid #eaeaea; } .sc-user-input--text { diff --git a/widget/src/components/UserInput.tsx b/widget/src/components/UserInput.tsx index ba9f4625..12f4055c 100644 --- a/widget/src/components/UserInput.tsx +++ b/widget/src/components/UserInput.tsx @@ -137,10 +137,7 @@ const UserInput: React.FC = () => { const uploading = outgoingMessageState === OutgoingMessageState.uploading; return ( -
+
{suggestions.length > 0 && } {(file || uploading) && ( diff --git a/widget/src/components/buttons/EmojiButton.scss b/widget/src/components/buttons/EmojiButton.scss index 62492033..d740605a 100644 --- a/widget/src/components/buttons/EmojiButton.scss +++ b/widget/src/components/buttons/EmojiButton.scss @@ -5,6 +5,7 @@ padding: 0px; margin: 0px; outline: none; + opacity: .5; } .sc-user-input--emoji-icon-wrapper:focus { @@ -12,18 +13,14 @@ } .sc-user-input--emoji-icon { - width: 18px; - height: 18px; + width: 20px; + height: 20px; cursor: pointer; align-self: center; vertical-align: middle; } - .sc-user-input--emoji-icon-wrapper:focus .sc-user-input--emoji-icon path, - .sc-user-input--emoji-icon-wrapper:focus .sc-user-input--emoji-icon circle, - .sc-user-input--emoji-icon.active path, - .sc-user-input--emoji-icon.active circle, - .sc-user-input--emoji-icon:hover path, - .sc-user-input--emoji-icon:hover circle { - filter: contrast(15%); + .sc-user-input--emoji-icon-wrapper:focus, + .sc-user-input--emoji-icon-wrapper:hover { + opacity: 1; } \ No newline at end of file diff --git a/widget/src/components/buttons/FileButton.scss b/widget/src/components/buttons/FileButton.scss index 5c072a0e..3405d15d 100644 --- a/widget/src/components/buttons/FileButton.scss +++ b/widget/src/components/buttons/FileButton.scss @@ -1,6 +1,12 @@ .sc-user-input--file-wrapper { + background: none; + border: none; + padding: 0px; + margin: 0px; + outline: none; position: relative; cursor: pointer; + opacity: .5; } .sc-user-input--file-icon-wrapper { background: none; @@ -8,7 +14,7 @@ padding: 0px; margin: 0px; outline: none; - cursor: pointer; + cursor: pointer !important; } .sc-user-input--file-icon { @@ -19,6 +25,6 @@ vertical-align: middle; } -.sc-user-input--file-icon:hover path { - filter: contrast(15%); +.sc-user-input--file-wrapper:hover { + opacity: 1 } diff --git a/widget/src/components/buttons/LocationButton.scss b/widget/src/components/buttons/LocationButton.scss index b1420adc..a80a8c68 100644 --- a/widget/src/components/buttons/LocationButton.scss +++ b/widget/src/components/buttons/LocationButton.scss @@ -4,6 +4,7 @@ padding: 0px; margin: 0px; outline: none; + opacity: .5; } .sc-user-input--location-icon-wrapper:focus { @@ -11,20 +12,13 @@ } .sc-user-input--location-icon { - width: 16px; - height: 16px; + width: 20px; + height: 20px; cursor: pointer; align-self: center; vertical-align: middle; } -.sc-user-input--location-icon-wrapper:focus .sc-user-input--location-icon path, -.sc-user-input--location-icon-wrapper:focus - .sc-user-input--location-icon - circle, -.sc-user-input--location-icon.active path, -.sc-user-input--location-icon.active circle, -.sc-user-input--location-icon:hover path, -.sc-user-input--location-icon:hover circle { - filter: contrast(15%); +.sc-user-input--location-icon-wrapper:hover { + opacity: 1; } diff --git a/widget/src/components/icons/EmojiIcon.tsx b/widget/src/components/icons/EmojiIcon.tsx index 936896b6..65855b68 100644 --- a/widget/src/components/icons/EmojiIcon.tsx +++ b/widget/src/components/icons/EmojiIcon.tsx @@ -12,7 +12,7 @@ const EmojiIcon: FC> = ({ x = '0', y = '0', className = 'sc-user-input--emoji-icon', - viewBox = '0 0 37 37', + viewBox = '0 0 24 24', ...rest }) => { return ( @@ -24,10 +24,11 @@ const EmojiIcon: FC> = ({ viewBox={viewBox} {...rest} > - - - - + + + + + ); }; diff --git a/widget/src/components/icons/FileInputIcon.tsx b/widget/src/components/icons/FileInputIcon.tsx index 6b3b042d..24b311ed 100644 --- a/widget/src/components/icons/FileInputIcon.tsx +++ b/widget/src/components/icons/FileInputIcon.tsx @@ -12,7 +12,7 @@ const FileInputIcon: FC> = ({ x = '0', y = '0', className = 'sc-user-input--file-icon', - viewBox = '0 0 32 32', + viewBox = '0 0 24 24', ...rest }) => { return ( @@ -24,10 +24,7 @@ const FileInputIcon: FC> = ({ viewBox={viewBox} {...rest} > - + {' '} ); }; diff --git a/widget/src/components/icons/LocationIcon.tsx b/widget/src/components/icons/LocationIcon.tsx index 05f26692..14d8ed39 100644 --- a/widget/src/components/icons/LocationIcon.tsx +++ b/widget/src/components/icons/LocationIcon.tsx @@ -13,7 +13,7 @@ const LocationIcon: FC> = ({ y = '0', className = 'sc-user-input--location-icon', version = '1.1', - viewBox = '0 0 32 32', + viewBox = '0 0 24 24', ...rest }) => { return ( @@ -26,8 +26,7 @@ const LocationIcon: FC> = ({ viewBox={viewBox} {...rest} > - - + ); }; diff --git a/widget/src/components/messages/ButtonMessage.scss b/widget/src/components/messages/ButtonMessage.scss index 78b978af..c36c953a 100644 --- a/widget/src/components/messages/ButtonMessage.scss +++ b/widget/src/components/messages/ButtonMessage.scss @@ -18,7 +18,7 @@ margin: 2px; cursor: pointer; outline: 0; - font-size: 1rem; + font-size: .75rem; } } diff --git a/widget/src/constants/colors.ts b/widget/src/constants/colors.ts index d1b5553a..186574db 100644 --- a/widget/src/constants/colors.ts +++ b/widget/src/constants/colors.ts @@ -11,34 +11,34 @@ import { ColorState } from '../types/colors.types'; const colors: Record = { orange: { header: { - bg: '#E6A23D', + bg: '#FF851B', text: '#fff', }, launcher: { - bg: '#E6A23D', + bg: '#FF851B', }, messageList: { bg: '#fff', }, sent: { - bg: '#E6A23D', + bg: '#FF851B', text: '#fff', }, received: { bg: '#eaeaea', - text: '#222222', + text: '#000', }, userInput: { - bg: '#fff', - text: '#212121', + bg: '#fbfbfb', + text: '#000', }, button: { bg: '#ffffff', - text: '#E6A23D', - border: '#E6A23D', + text: '#FF851B', + border: '#FF851B', }, messageStatus: { - bg: '#E6A23D', + bg: '#FF851B', }, messageTime: { text: '#9C9C9C', @@ -46,139 +46,139 @@ const colors: Record = { }, red: { header: { - bg: '#AB1251', + bg: '#FF4136', text: '#fff', }, launcher: { - bg: '#AB1251', + bg: '#FF4136', }, messageList: { bg: '#fff', }, sent: { - bg: '#AB1251', + bg: '#FF4136', text: '#fff', }, received: { bg: '#eaeaea', - text: '#222222', + text: '#000', }, userInput: { - bg: '#fff', - text: '#212121', + bg: '#fbfbfb', + text: '#000', }, button: { bg: '#ffffff', - text: '#AB1251', - border: '#AB1251', + text: '#FF4136', + border: '#FF4136', }, messageStatus: { - bg: '#AB1251', + bg: '#FF4136', }, messageTime: { - text: '#9C9C9C', + text: '#FF4136', }, }, green: { header: { - bg: '#ABBD49', + bg: '#2ECC40', text: '#fff', }, launcher: { - bg: '#ABBD49', + bg: '#2ECC40', }, messageList: { bg: '#fff', }, sent: { - bg: '#4CAF50', + bg: '#2ECC40', text: '#fff', }, received: { bg: '#eaeaea', - text: '#222222', + text: '#000', }, userInput: { - bg: '#fff', - text: '#212121', + bg: '#fbfbfb', + text: '#000', }, button: { bg: '#ffffff', - text: '#ABBD49', - border: '#ABBD49', + text: '#2ECC40', + border: '#2ECC40', }, messageStatus: { - bg: '#ABBD49', + bg: '#2ECC40', }, messageTime: { - text: '#9C9C9C', + text: '#2ECC40', }, }, blue: { header: { - bg: '#108AA8', - text: '#ffffff', + bg: '#0074D9', + text: '#fff', }, launcher: { - bg: '#108AA8', + bg: '#0074D9', }, messageList: { - bg: '#ffffff', + bg: '#fff', }, sent: { - bg: '#108AA8', - text: '#ffffff', + bg: '#0074D9', + text: '#fff', }, received: { bg: '#eaeaea', - text: '#222222', + text: '#000', }, userInput: { - bg: '#f4f7f9', - text: '#565867', + bg: '#fbfbfb', + text: '#000', }, button: { bg: '#ffffff', - text: '#108AA8', - border: '#108AA8', + text: '#0074D9', + border: '#0074D9', }, messageStatus: { - bg: '#108AA8', + bg: '#0074D9', }, messageTime: { - text: '#9C9C9C', + text: '#0074D9', }, }, teal: { header: { - bg: '#279084', - text: '#ffffff', + bg: '#1BA089', + text: '#fff', }, launcher: { - bg: '#279084', + bg: '#1BA089', }, messageList: { - bg: '#ffffff', + bg: '#fff', }, sent: { - bg: '#279084', - text: '#ffffff', + bg: '#1BA089', + text: '#fff', }, received: { bg: '#eaeaea', - text: '#222222', + text: '#000', }, userInput: { - bg: '#f4f7f9', - text: '#565867', + bg: '#fbfbfb', + text: '#000', }, button: { bg: '#ffffff', - text: '#279084', - border: '#279084', + text: '#1BA089', + border: '#1BA089', }, messageStatus: { - bg: '#279084', + bg: '#1BA089', }, messageTime: { text: '#9C9C9C', @@ -186,26 +186,26 @@ const colors: Record = { }, dark: { header: { - bg: '#34495e', + bg: '#000', text: '#ecf0f1', }, launcher: { - bg: '#34495e', + bg: '#000', }, messageList: { - bg: '#2c3e50', + bg: '#FFF', }, sent: { - bg: '#7f8c8d', - text: '#ecf0f1', + bg: '#000', + text: '#FFF', }, received: { - bg: '#95a5a6', - text: '#ecf0f1', + bg: '#F0F0F0', + text: '#000', }, userInput: { - bg: '#34495e', - text: '#ecf0f1', + bg: '#FFF', + text: '#000', }, button: { bg: '#2c3e50',