2
0

docs: 📝 Explain how to pass parent URL

This commit is contained in:
Baptiste Arnaud
2022-05-31 09:59:34 +02:00
parent 797ff1892d
commit 61e4ca1313
7 changed files with 229 additions and 102 deletions

View File

@ -14,10 +14,11 @@ import {
NumberDecrementStepper, NumberDecrementStepper,
Switch, Switch,
Text, Text,
Tag, Image,
} from '@chakra-ui/react' } from '@chakra-ui/react'
import { ColorPicker } from 'components/theme/GeneralSettings/ColorPicker' import { ColorPicker } from 'components/theme/GeneralSettings/ColorPicker'
import { useTypebot } from 'contexts/TypebotContext' import { useTypebot } from 'contexts/TypebotContext'
import { useUser } from 'contexts/UserContext'
import { useState, useEffect } from 'react' import { useState, useEffect } from 'react'
import { BubbleParams } from 'typebot-js' import { BubbleParams } from 'typebot-js'
@ -30,30 +31,41 @@ export const ChatEmbedSettings = ({
onUpdateSettings, onUpdateSettings,
...props ...props
}: ChatEmbedSettingsProps & StackProps) => { }: ChatEmbedSettingsProps & StackProps) => {
const { user } = useUser()
const { typebot } = useTypebot() const { typebot } = useTypebot()
const [proactiveMessageChecked, setProactiveMessageChecked] = useState(false) const [proactiveMessageChecked, setProactiveMessageChecked] = useState(false)
const [isCustomIconChecked, setIsCustomIconChecked] = useState(false)
const [rememberProMessageChecked] = useState(true) const [rememberProMessageChecked] = useState(true)
const [customIconInputValue, setCustomIconInputValue] = useState('') const [customIconInputValue, setCustomIconInputValue] = useState('')
const [inputValues, setInputValues] = useState({ const [inputValues, setInputValues] = useState({
messageDelay: '0', messageDelay: '0',
messageContent: 'I have a question for you!', messageContent: 'I have a question for you!',
avatarUrl: typebot?.theme.chat.hostAvatar?.url ?? user?.image ?? '',
}) })
const [bubbleColor, setBubbleColor] = useState( const [bubbleColor, setBubbleColor] = useState(
typebot?.theme.chat.buttons.backgroundColor ?? '#0042DA' typebot?.theme.chat.buttons.backgroundColor ?? '#0042DA'
) )
const [bubbleIconColor, setIconBubbleColor] = useState(
typebot?.theme.chat.buttons.color ?? '#FFFFFF'
)
useEffect(() => { useEffect(() => {
if (proactiveMessageChecked) { if (proactiveMessageChecked) {
onUpdateSettings({ onUpdateSettings({
button: { button: {
color: bubbleColor, color: bubbleColor,
iconUrl: customIconInputValue, iconUrl: isCustomIconChecked ? customIconInputValue : undefined,
iconColor:
bubbleIconColor === '#FFFFFF' ? undefined : bubbleIconColor,
}, },
proactiveMessage: { proactiveMessage: {
delay: parseInt(inputValues.messageDelay) * 1000, delay: parseInt(inputValues.messageDelay) * 1000,
textContent: inputValues.messageContent, textContent: inputValues.messageContent,
avatarUrl: inputValues.avatarUrl,
rememberClose: rememberProMessageChecked, rememberClose: rememberProMessageChecked,
}, },
}) })
@ -61,43 +73,66 @@ export const ChatEmbedSettings = ({
onUpdateSettings({ onUpdateSettings({
button: { button: {
color: bubbleColor, color: bubbleColor,
iconUrl: customIconInputValue, iconUrl: isCustomIconChecked ? customIconInputValue : undefined,
iconColor:
bubbleIconColor === '#FFFFFF' ? undefined : bubbleIconColor,
}, },
proactiveMessage: undefined, proactiveMessage: undefined,
}) })
} }
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [ }, [
inputValues, inputValues,
bubbleColor, bubbleColor,
rememberProMessageChecked, rememberProMessageChecked,
customIconInputValue, customIconInputValue,
bubbleIconColor,
proactiveMessageChecked, proactiveMessageChecked,
isCustomIconChecked,
]) ])
return ( return (
<Stack {...props}> <Stack {...props} spacing="4">
<Heading fontSize="md" fontWeight="semibold"> <Heading fontSize="md" fontWeight="semibold">
Chat bubble settings Chat bubble settings
</Heading> </Heading>
<Flex justify="space-between" align="center" mb="4"> <Flex justify="space-between" align="center">
<Text>Button color</Text> <Text>Button color</Text>
<ColorPicker <ColorPicker
initialColor={bubbleColor} initialColor={bubbleColor}
onColorChange={setBubbleColor} onColorChange={setBubbleColor}
/> />
</Flex> </Flex>
<HStack> <HStack justify="space-between">
<Text flexShrink={0}> <Text>Icon color</Text>
Custom button icon <Tag>Optional</Tag> <ColorPicker
</Text> initialColor={bubbleIconColor}
<Input onColorChange={setIconBubbleColor}
placeholder={'Paste image link (.png, .svg)'}
value={customIconInputValue}
onChange={(e) => setCustomIconInputValue(e.target.value)}
/> />
</HStack> </HStack>
<HStack justifyContent="space-between">
<FormLabel htmlFor="custom-icon" mb="1" flexShrink={0}>
Custom button icon?
</FormLabel>
<Switch
id="custom-icon"
onChange={() => setIsCustomIconChecked(!isCustomIconChecked)}
isChecked={isCustomIconChecked}
/>
</HStack>
{isCustomIconChecked && (
<>
<HStack pl="4">
<Text>Url:</Text>
<Input
placeholder={'Paste image link (.png, .svg)'}
value={customIconInputValue}
onChange={(e) => setCustomIconInputValue(e.target.value)}
minW="0"
/>
</HStack>
</>
)}
<Flex alignItems="center"> <Flex alignItems="center">
<FormControl <FormControl
display="flex" display="flex"
@ -120,7 +155,23 @@ export const ChatEmbedSettings = ({
</Flex> </Flex>
{proactiveMessageChecked && ( {proactiveMessageChecked && (
<> <>
<Flex justify="space-between" align="center" pl="4" mb="2"> <Flex pl="4">
<HStack
bgColor="white"
shadow="md"
rounded="md"
p="3"
maxW="280px"
spacing={4}
>
{inputValues.avatarUrl && (
// eslint-disable-next-line jsx-a11y/alt-text
<Image src={inputValues.avatarUrl} w="40px" rounded="full" />
)}
<Text>{inputValues.messageContent}</Text>
</HStack>
</Flex>
<Flex justify="space-between" align="center" pl="4">
<Text>Appearance delay</Text> <Text>Appearance delay</Text>
<NumberInput <NumberInput
onChange={(messageDelay) => onChange={(messageDelay) =>
@ -139,7 +190,21 @@ export const ChatEmbedSettings = ({
</NumberInputStepper> </NumberInputStepper>
</NumberInput> </NumberInput>
</Flex> </Flex>
<Flex justify="space-between" align="center" pl="4" mb="2"> <Flex justify="space-between" align="center" pl="4">
<Text>Avatar URL</Text>
<Input
type="text"
onChange={(e) =>
setInputValues({
...inputValues,
avatarUrl: e.target.value,
})
}
value={inputValues.avatarUrl}
placeholder={'Paste image link (.png, .jpg)'}
/>
</Flex>
<Flex justify="space-between" align="center" pl="4">
<Text>Message content</Text> <Text>Message content</Text>
<Input <Input
type="text" type="text"

View File

@ -33,22 +33,19 @@ const parseButton = (button?: ButtonParams): string => {
if (!button) return '' if (!button) return ''
const iconUrlString = parseStringParam('iconUrl', button.iconUrl) const iconUrlString = parseStringParam('iconUrl', button.iconUrl)
const buttonColorstring = parseStringParam('color', button.color) const buttonColorstring = parseStringParam('color', button.color)
return `button: {${iconUrlString}${buttonColorstring}},` const buttonIconColorString = parseStringParam('iconColor', button.iconColor)
return `button: {${iconUrlString}${buttonColorstring}${buttonIconColorString}},`
} }
const parseProactiveMessage = ( const parseProactiveMessage = (
proactiveMessage?: ProactiveMessageParams proactiveMessage?: ProactiveMessageParams
): string => { ): string => {
if (!proactiveMessage) return `` if (!proactiveMessage) return ``
const { avatarUrl, textContent, delay, rememberClose } = proactiveMessage const { avatarUrl, textContent, delay } = proactiveMessage
const avatarUrlString = parseStringParam('avatarUrl', avatarUrl) const avatarUrlString = parseStringParam('avatarUrl', avatarUrl)
const textContentString = parseStringParam('textContent', textContent) const textContentString = parseStringParam('textContent', textContent)
const rememberCloseString = parseNonStringParam(
'rememberClose',
rememberClose
)
const delayString = parseNonStringParam('delay', delay) const delayString = parseNonStringParam('delay', delay)
return `proactiveMessage: {${avatarUrlString}${textContentString}${rememberCloseString}${delayString}},` return `proactiveMessage: {${avatarUrlString}${textContentString}${delayString}},`
} }
const parseIframeParams = ({ const parseIframeParams = ({

View File

@ -42,12 +42,8 @@ A popular request also is to set a variable to the current URL. Here is the valu
window.location.href window.location.href
``` ```
It will not give you the parent URL if you embed the bot on your site. A more bullet proof value would then be: :::caution
It will not give you the parent URL if you embed the bot on your site.
```js A more bullet proof option is to pass the URL as a hidden variable in the embed code options. You can find an example [here](../../embed/html-javascript#additional-configuration).
window.location != window.parent.location :::
? document.referrer
: document.location.href
```
It checks whether or not the bot is embedded and return the appropriate URL.

View File

@ -0,0 +1,127 @@
---
sidebar_position: 4
---
# HTML & Javascript
## Standard
You can get the standard HTML and Javascript code by clicking on the "HTML & Javascript" button in the "Share" tab of your typebot.
There, you can change the container dimensions. Here is a code example:
```html
<script src="https://unpkg.com/typebot-js@2.2"></script>
<div id="typebot-container" style="width: 100%; height: 600px;"></div>
<script>
Typebot.initContainer('typebot-container', {
url: 'https://viewer.typebot.io/my-typebot',
})
</script>
```
This code is creating a container with a 100% width (will match parent width) and 600px height.
## Popup
You can get the popup HTML and Javascript code by clicking on the "HTML & Javascript" button in the "Share" tab of your typebot.
Here is an example:
```html
<script src="https://unpkg.com/typebot-js@2.2"></script>
<script>
var typebotCommands = Typebot.initPopup({
url: 'https://viewer.typebot.io/my-typebot',
delay: 3000,
})
</script>
```
This code will automatically trigger the popup window after 3 seconds.
### Open or Close a popup
You can use these commands:
```js
Typebot.getPopupActions().open()
```
```js
Typebot.getPopupActions().close()
```
You can bind these commands on a button element, for example:
```html
<button onclick="Typebot.getPopupActions().open()">Open the popup</button>
```
## Bubble
You can get the bubble HTML and Javascript code by clicking on the "HTML & Javascript" button in the "Share" tab of your typebot.
Here is an example:
```html
<script src="https://unpkg.com/typebot-js@2.2"></script>
<script>
var typebotCommands = Typebot.initPopup({
url: 'https://viewer.typebot.io/my-typebot',
delay: 3000,
})
</script>
```
This code will automatically trigger the popup window after 3 seconds.
### Open or close the proactive message
You can use this command:
```js
Typebot.getBubbleActions().openProactiveMessage()
```
You can bind this command on a button element, for example:
```html
<button onclick="Typebot.getBubbleActions().openProactiveMessage()">
Open proactive message
</button>
```
### Open or close the typebot
You can use these commands:
```js
Typebot.getBubbleActions().open()
```
```js
Typebot.getBubbleActions().close()
```
You can bind these commands on a button element, for example:
```html
<button onclick="Typebot.getBubbleActions().open()">Open the chat</button>
```
## Additional configuration
You can add hidden variable values in your embed code by adding the `hiddenVariables` option. Here is an example:
```js
Typebot.initContainer('typebot-container', {
url: 'https://viewer.typebot.io/my-typebot',
hiddenVariables: {
'Current URL': window.location.href,
'User name': 'John Doe',
},
})
```
It will populate the `Current URL` variable with the parent URL and the `User name` variable with "John Doe".

View File

@ -1,65 +0,0 @@
---
sidebar_position: 4
---
# Javascript library
Typebot Javascript library is open-source ([check out the repository](https://github.com/baptisteArno/typebot.io/tree/main/packages/typebot-js)). Feel free to contribute if you're a developer and wish to improve its features.
Whenever a typebot is embedded on your website, you have access to commands to automatically trigger actions on your embedding depending on its type.
## Popup
### Open or Close a popup
You can use these commands:
```js
Typebot.getPopupActions().open()
```
```js
Typebot.getPopupActions().close()
```
You can bind these commands on a button element, for example:
```html
<button onclick="Typebot.getPopupActions().open()">Open the popup</button>
```
## Bubble
### Open or close the proactive message
You can use this command:
```js
Typebot.getBubbleActions().openProactiveMessage()
```
You can bind this command on a button element, for example:
```html
<button onclick="Typebot.getBubbleActions().openProactiveMessage()">
Open proactive message
</button>
```
### Open or close the typebot
You can use these commands:
```js
Typebot.getBubbleActions().open()
```
```js
Typebot.getBubbleActions().close()
```
You can bind these commands on a button element, for example:
```html
<button onclick="Typebot.getBubbleActions().open()">Open the chat</button>
```

View File

@ -4,16 +4,21 @@ export const createButton = (params?: ButtonParams): HTMLButtonElement => {
const button = document.createElement('button') const button = document.createElement('button')
button.id = 'typebot-bubble-button' button.id = 'typebot-bubble-button'
button.style.backgroundColor = params?.color ?? '#0042DA' button.style.backgroundColor = params?.color ?? '#0042DA'
button.appendChild(createButtonIcon(params?.iconUrl, params?.iconStyle)) button.appendChild(
button.appendChild(createCloseIcon(params?.closeIconColor)) createButtonIcon(params?.iconUrl, params?.iconColor, params?.iconStyle)
)
button.appendChild(
createCloseIcon(params?.iconColor ?? params?.closeIconColor)
)
return button return button
} }
const createButtonIcon = ( const createButtonIcon = (
src?: string, src?: string,
iconColor?: string,
style?: string style?: string
): SVGElement | HTMLElement => { ): SVGElement | HTMLElement => {
if (!src) return createDefaultIcon() if (!src) return createDefaultIcon(iconColor)
const icon = document.createElement('img') const icon = document.createElement('img')
icon.classList.add('icon') icon.classList.add('icon')
icon.src = src icon.src = src
@ -21,20 +26,21 @@ const createButtonIcon = (
return icon return icon
} }
const createDefaultIcon = (): SVGElement => { const createDefaultIcon = (iconColor?: string): SVGElement => {
const icon = document.createElementNS('http://www.w3.org/2000/svg', 'svg') const icon = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
icon.setAttribute('viewBox', '0 0 24 24') icon.setAttribute('viewBox', '0 0 24 24')
icon.innerHTML = typebotLogoSvgTextContent() icon.innerHTML = typebotLogoSvgTextContent()
icon.classList.add('icon') icon.classList.add('icon')
icon.style.stroke = iconColor ?? '#ffffff'
return icon return icon
} }
const createCloseIcon = (closeIconColor?: string): SVGElement => { const createCloseIcon = (iconColor?: string): SVGElement => {
const icon = document.createElementNS('http://www.w3.org/2000/svg', 'svg') const icon = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
icon.setAttribute('viewBox', '0 0 24 24') icon.setAttribute('viewBox', '0 0 24 24')
icon.innerHTML = closeSvgPath icon.innerHTML = closeSvgPath
icon.classList.add('close-icon') icon.classList.add('close-icon')
icon.style.stroke = closeIconColor ?? '#ffffff' icon.style.stroke = iconColor ?? '#ffffff'
return icon return icon
} }

View File

@ -30,6 +30,7 @@ export type ButtonParams = {
color?: string color?: string
iconUrl?: string iconUrl?: string
iconStyle?: string iconStyle?: string
iconColor?: string
closeIconColor?: string closeIconColor?: string
} }