Skip to content

Commit

Permalink
⚡ (js) Add placement option for bubble embed
Browse files Browse the repository at this point in the history
Allows you to place the bubble embed on the bottom left corner
of your site
  • Loading branch information
baptisteArno committed May 31, 2023
1 parent b2ea8fc commit 57f3e5c
Show file tree
Hide file tree
Showing 9 changed files with 74 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,24 @@ import {
AccordionIcon,
AccordionItem,
AccordionPanel,
Button,
HStack,
Menu,
MenuButton,
MenuItem,
MenuList,
Stack,
Text,
} from '@chakra-ui/react'
import { BubbleProps } from '@typebot.io/js'
import {
BubbleTheme,
ButtonTheme,
PreviewMessageTheme,
} from '@typebot.io/js/dist/features/bubble/types'
import { ButtonThemeSettings } from './ButtonThemeSettings'
import { PreviewMessageThemeSettings } from './PreviewMessageThemeSettings'
import { ChevronDownIcon } from '@/components/icons'

type Props = {
isPreviewMessageEnabled: boolean
Expand All @@ -41,6 +48,13 @@ export const ThemeSettings = ({
})
}

const updatePlacement = (placement: BubbleTheme['placement']) => {
onChange({
...theme,
placement,
})
}

return (
<Accordion allowMultiple>
<AccordionItem>
Expand All @@ -51,6 +65,22 @@ export const ThemeSettings = ({
<AccordionIcon />
</AccordionButton>
<AccordionPanel as={Stack} pb={4} spacing={4} px="0">
<HStack justify="space-between">
<Text>Placement</Text>
<Menu>
<MenuButton as={Button} size="sm" rightIcon={<ChevronDownIcon />}>
{theme?.placement ?? 'right'}
</MenuButton>
<MenuList>
<MenuItem onClick={() => updatePlacement('right')}>
right
</MenuItem>
<MenuItem onClick={() => updatePlacement('left')}>
left
</MenuItem>
</MenuList>
</Menu>
</HStack>
<ButtonThemeSettings
buttonTheme={theme?.button}
onChange={updateButtonTheme}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ const parseBubbleTheme = (theme: BubbleProps['theme']): string => {
const buttonThemeLine = parseButtonTheme(button)
const previewMessageThemeLine = parsePreviewMessageTheme(previewMessage)
const chatWindowThemeLine = parseChatWindowTheme(theme.chatWindow)
const line = `theme: {${buttonThemeLine}${previewMessageThemeLine}${chatWindowThemeLine}},`
const placementLine = parseStringParam('placement', theme.placement, 'right')
const line = `theme: {${placementLine}${buttonThemeLine}${previewMessageThemeLine}${chatWindowThemeLine}},`
if (line === 'theme: {},') return ''
return line
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,15 @@ import { Typebot } from '@typebot.io/schemas'
import { isCloudProdInstance } from '@/helpers/isCloudProdInstance'
import packageJson from '../../../../../../../../packages/embeds/js/package.json'

export const parseStringParam = (fieldName: string, fieldValue?: string) =>
fieldValue ? `${fieldName}: "${fieldValue}",` : ``
export const parseStringParam = (
fieldName: string,
fieldValue?: string,
defaultValue?: string
) => {
if (!fieldValue) return ''
if (isDefined(defaultValue) && fieldValue === defaultValue) return ''
return `${fieldName}: "${fieldValue}",`
}

export const parseNumberOrBoolParam = (
fieldName: string,
Expand Down
2 changes: 1 addition & 1 deletion packages/embeds/js/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@typebot.io/js",
"version": "0.0.59",
"version": "0.0.60",
"description": "Javascript library to display typebots on your website",
"type": "module",
"main": "dist/index.js",
Expand Down
12 changes: 9 additions & 3 deletions packages/embeds/js/src/features/bubble/components/Bubble.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ export const Bubble = (props: BubbleProps) => {
<Show when={isPreviewMessageDisplayed()}>
<PreviewMessage
{...previewMessage()}
placement={bubbleProps.theme?.placement}
previewMessageTheme={bubbleProps.theme?.previewMessage}
buttonSize={bubbleProps.theme?.button?.size}
onClick={handlePreviewMessageClick}
Expand All @@ -137,6 +138,7 @@ export const Bubble = (props: BubbleProps) => {
</Show>
<BubbleButton
{...bubbleProps.theme?.button}
placement={bubbleProps.theme?.placement}
toggleBot={toggleBot}
isBotOpened={isBotOpened()}
/>
Expand All @@ -146,16 +148,20 @@ export const Bubble = (props: BubbleProps) => {
height: 'calc(100% - 80px)',
transition:
'transform 200ms cubic-bezier(0, 1.2, 1, 1), opacity 150ms ease-out',
'transform-origin': 'bottom right',
'transform-origin':
props.theme?.placement === 'left' ? 'bottom left' : 'bottom right',
transform: isBotOpened() ? 'scale3d(1, 1, 1)' : 'scale3d(0, 0, 1)',
'box-shadow': 'rgb(0 0 0 / 16%) 0px 5px 40px',
'background-color': bubbleProps.theme?.chatWindow?.backgroundColor,
'z-index': 42424242,
}}
class={
'fixed sm:right-5 rounded-lg w-full sm:w-[400px] max-h-[704px]' +
'fixed rounded-lg w-full sm:w-[400px] max-h-[704px]' +
(isBotOpened() ? ' opacity-1' : ' opacity-0 pointer-events-none') +
(props.theme?.button?.size === 'large' ? ' bottom-24' : ' bottom-20')
(props.theme?.button?.size === 'large'
? ' bottom-24'
: ' bottom-20') +
(props.theme?.placement === 'left' ? ' left-5' : ' right-5')
}
>
<Show when={isBotStarted()}>
Expand Down
17 changes: 10 additions & 7 deletions packages/embeds/js/src/features/bubble/components/BubbleButton.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { Show } from 'solid-js'
import { isNotDefined, isSvgSrc } from '@typebot.io/lib'
import { ButtonTheme } from '../types'
import { BubbleTheme, ButtonTheme } from '../types'
import { isLight } from '@typebot.io/lib/hexToRgb'

type Props = ButtonTheme & {
isBotOpened: boolean
toggleBot: () => void
}
type Props = Pick<BubbleTheme, 'placement'> &
ButtonTheme & {
isBotOpened: boolean
toggleBot: () => void
}

const defaultButtonColor = '#0042DA'
const defaultDarkIconColor = '#27272A'
Expand All @@ -20,8 +21,9 @@ export const BubbleButton = (props: Props) => (
part="button"
onClick={() => props.toggleBot()}
class={
'fixed bottom-5 right-5 shadow-md rounded-full hover:scale-110 active:scale-95 transition-transform duration-200 flex justify-center items-center animate-fade-in' +
(props.size === 'large' ? ' w-16 h-16' : ' w-12 h-12')
'fixed bottom-5 shadow-md rounded-full hover:scale-110 active:scale-95 transition-transform duration-200 flex justify-center items-center animate-fade-in' +
(props.size === 'large' ? ' w-16 h-16' : ' w-12 h-12') +
(props.placement === 'left' ? ' left-5' : ' right-5')
}
style={{
'background-color': props.backgroundColor ?? defaultButtonColor,
Expand Down Expand Up @@ -49,6 +51,7 @@ export const BubbleButton = (props: Props) => (
</Show>
<Show when={props.customIconSrc && isImageSrc(props.customIconSrc)}>
<img
part="button-icon"
src={props.customIconSrc}
class={
'duration-200 transition' +
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
import { createSignal, Show } from 'solid-js'
import {
BubbleTheme,
ButtonTheme,
PreviewMessageParams,
PreviewMessageTheme,
} from '../types'

export type PreviewMessageProps = Pick<
PreviewMessageParams,
'avatarUrl' | 'message'
> & {
buttonSize: ButtonTheme['size']
previewMessageTheme?: PreviewMessageTheme
onClick: () => void
onCloseClick: () => void
}
export type PreviewMessageProps = Pick<BubbleTheme, 'placement'> &
Pick<PreviewMessageParams, 'avatarUrl' | 'message'> & {
buttonSize: ButtonTheme['size']
previewMessageTheme?: PreviewMessageTheme
onClick: () => void
onCloseClick: () => void
}

const defaultBackgroundColor = '#F7F8FF'
const defaultTextColor = '#303235'
Expand All @@ -27,8 +26,9 @@ export const PreviewMessage = (props: PreviewMessageProps) => {
part="preview-message"
onClick={() => props.onClick()}
class={
'fixed right-5 max-w-[256px] rounded-md duration-200 flex items-center gap-4 shadow-md animate-fade-in cursor-pointer hover:shadow-lg p-4' +
(props.buttonSize === 'large' ? ' bottom-24' : ' bottom-20')
'fixed max-w-[256px] rounded-md duration-200 flex items-center gap-4 shadow-md animate-fade-in cursor-pointer hover:shadow-lg p-4' +
(props.buttonSize === 'large' ? ' bottom-24' : ' bottom-20') +
(props.placement === 'left' ? ' left-5' : ' right-5')
}
style={{
'background-color':
Expand Down
1 change: 1 addition & 0 deletions packages/embeds/js/src/features/bubble/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export type BubbleTheme = {
chatWindow?: ChatWindowTheme
button?: ButtonTheme
previewMessage?: PreviewMessageTheme
placement?: 'left' | 'right'
}

export type ChatWindowTheme = {
Expand Down
2 changes: 1 addition & 1 deletion packages/embeds/react/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@typebot.io/react",
"version": "0.0.59",
"version": "0.0.60",
"description": "React library to display typebots on your website",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down

4 comments on commit 57f3e5c

@vercel
Copy link

@vercel vercel bot commented on 57f3e5c May 31, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

docs – ./apps/docs

docs-typebot-io.vercel.app
docs-git-main-typebot-io.vercel.app
docs.typebot.io

@vercel
Copy link

@vercel vercel bot commented on 57f3e5c May 31, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on 57f3e5c May 31, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

viewer-v2 – ./apps/viewer

83701274.21000000.lol
90945247.21000000.one
abutton.wpwakanda.com
acelera.maxbot.com.br
aidigitalmarketing.kr
atendimento.vrauu.com
bbutton.wpwakanda.com
app.photosbackupin1.click
bot.aidigitalmarketing.kr
bot.amicidisanfaustino.it
bot.arraesecenteno.com.br
bot.blackboxsports.com.br
bot.cabinrentalagency.com
bot.fusionstarreviews.com
boyfriend-breakup.riku.ai
brigadeirosemdrama.com.br
chat.ertcrebateportal.com
chat.thehomebuyersusa.com
chat.thisiscrushhouse.com
healthandsafetycourses.uk
sellmyharleylouisiana.com
testbot.sharemyreview.net
typebot-viewer.vercel.app
verfica.botmachine.com.br
ap-help.algorithmpress.com
ap-main.algorithmpress.com
asking.aschenputtel.agency
bcorporate.carlosbusch.com
bot.adventureconsulting.hu
bot2.fusionstarreviews.com
casestudyemb.wpwakanda.com
chat.atlasoutfittersk9.com
configurator.bouclidom.com
demo.virtuesocialmedia.com
gabinete.baleia.formulario
help.atlasoutfittersk9.com
herbalife.barrettamario.it
homepageonly.wpwakanda.com
liveconvert.kandalearn.com
mainmenu1one.wpwakanda.com
newsletter.itshcormeos.com
prenotazione.aldoemaria.it
rsvp.virtuesocialmedia.com
tarian.theiofoundation.org
ted.meujalecobrasil.com.br
type.dericsoncalari.com.br
baleia.eventos.progenbr.com
bot.pinpointinteractive.com
bot.polychromes-project.com
bot.seidinembroseanchetu.it
chat.semanalimpanome.com.br
designguide.techyscouts.com
liveconvert2.kandalearn.com
poll.mosaicohairboutique.it
presente.empresarias.com.mx
register.algorithmpress.com
sell.sellthemotorhome.co.uk
anamnese.odontopavani.com.br
austin.channelautomation.com
bot.marketingplusmindset.com
bot.seidibergamoseanchetu.it
desabafe.sergiolimajr.com.br
download.venturemarketing.in
open.campus.aalen.university
piazzatorre.barrettamario.it
poll.mosaicohairboutique.com
type.cookieacademyonline.com
upload.atlasoutfittersk9.com
bot.brigadeirosemdrama.com.br
tuttirecepcao.fratucci.com.br
forms.escoladeautomacao.com.br
onboarding.libertydreamcare.ie
recepcao.tutti.fratucci.com.br
type.talitasouzamarques.com.br
agendamento.sergiolimajr.com.br
anamnese.clinicamegasjdr.com.br
bookings.littlepartymonkeys.com
bot.comercializadoraomicron.com
elevateyourmind.groovepages.com
viewer-v2-typebot-io.vercel.app
yourfeedback.comebackreward.com
baleia.testeeventos.progenbr.com
bot.cabin-rentals-of-georgia.net
open.campus.bot.aalen.university
sondaggio.mosaicohairboutique.it
baleia.testegabinete.progenbr.com
gerador.verificadordehospedes.com
personal-trainer.barrettamario.it
sondaggio.mosaicohairboutique.com
preagendamento.sergiolimajr.com.br
studiotecnicoimmobiliaremerelli.it
download.thailandmicespecialist.com
register.thailandmicespecialist.com
bot.studiotecnicoimmobiliaremerelli.it
pesquisa.escolamodacomproposito.com.br
anamnese.clinicaramosodontologia.com.br
gabinete.baleia.formulario.progenbr.com
chrome-os-inquiry-system.itschromeos.com
viewer-v2-git-main-typebot-io.vercel.app
main-menu-for-itschromeos.itschromeos.com

@vercel
Copy link

@vercel vercel bot commented on 57f3e5c May 31, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

builder-v2 – ./apps/builder

builder-v2-git-main-typebot-io.vercel.app
builder-v2-typebot-io.vercel.app
app.typebot.io

Please sign in to comment.