2
0

(embed) Add size and icon picker in bubble settings (#508)

This commit is contained in:
Baptiste Arnaud
2023-05-15 15:22:04 +02:00
committed by GitHub
parent 123926f273
commit 0f91b34497
15 changed files with 256 additions and 108 deletions

View File

@@ -19,7 +19,7 @@ import tinyColor from 'tinycolor2'
const colorsSelection: `#${string}`[] = [ const colorsSelection: `#${string}`[] = [
'#666460', '#666460',
'#AFABA3', '#FFFFFF',
'#A87964', '#A87964',
'#D09C46', '#D09C46',
'#DE8031', '#DE8031',
@@ -27,7 +27,7 @@ const colorsSelection: `#${string}`[] = [
'#4A8BB2', '#4A8BB2',
'#9B74B7', '#9B74B7',
'#C75F96', '#C75F96',
'#C75F96', '#0042DA',
] ]
type Props = { type Props = {
@@ -78,18 +78,19 @@ export const ColorPicker = ({ value, defaultValue, onColorChange }: Props) => {
</PopoverHeader> </PopoverHeader>
<PopoverBody as={Stack}> <PopoverBody as={Stack}>
<SimpleGrid columns={5} spacing={2}> <SimpleGrid columns={5} spacing={2}>
{colorsSelection.map((c) => ( {colorsSelection.map((color) => (
<Button <Button
key={c} key={color}
aria-label={c} aria-label={color}
background={c} background={color}
height="22px" height="22px"
width="22px" width="22px"
padding={0} padding={0}
minWidth="unset" minWidth="unset"
borderRadius={3} borderRadius={3}
_hover={{ background: c }} borderWidth={color === '#FFFFFF' ? 1 : undefined}
onClick={handleClick(c)} _hover={{ background: color }}
onClick={handleClick(color)}
/> />
))} ))}
</SimpleGrid> </SimpleGrid>

View File

@@ -57,10 +57,9 @@ export const EditableEmojiOrImageIcon = ({
filePath={uploadFilePath} filePath={uploadFilePath}
defaultUrl={icon ?? ''} defaultUrl={icon ?? ''}
onSubmit={onChangeIcon} onSubmit={onChangeIcon}
isGiphyEnabled={false} excludedTabs={['giphy', 'unsplash']}
isUnsplashEnabled={false}
isEmojiEnabled={true}
onClose={onClose} onClose={onClose}
initialTab="icon"
/> />
</PopoverContent> </PopoverContent>
</> </>

View File

@@ -26,6 +26,13 @@ export const IconPicker = ({ onIconSelected }: Props) => {
) )
const searchQuery = useRef<string>('') const searchQuery = useRef<string>('')
const [selectedColor, setSelectedColor] = useState(initialIconColor) const [selectedColor, setSelectedColor] = useState(initialIconColor)
const isWhite = useMemo(
() =>
selectedColor.toLowerCase() === '#ffffff' ||
selectedColor.toLowerCase() === '#fff' ||
selectedColor === 'white',
[selectedColor]
)
useEffect(() => { useEffect(() => {
if (!bottomElement.current) return if (!bottomElement.current) return
@@ -68,10 +75,9 @@ export const IconPicker = ({ onIconSelected }: Props) => {
const selectIcon = async (iconName: string) => { const selectIcon = async (iconName: string) => {
const svg = await (await fetch(`/icons/${iconName}.svg`)).text() const svg = await (await fetch(`/icons/${iconName}.svg`)).text()
const dataUri = `data:image/svg+xml;utf8,${svg.replace( const dataUri = `data:image/svg+xml;utf8,${svg
'<svg', .replace('<svg', `<svg fill='${encodeURIComponent(selectedColor)}'`)
`<svg fill='${encodeURIComponent(selectedColor)}'` .replace(/"/g, "'")}`
)}`
onIconSelected(dataUri) onIconSelected(dataUri)
} }
@@ -96,8 +102,9 @@ export const IconPicker = ({ onIconSelected }: Props) => {
> >
{displayedIconNames.map((iconName) => ( {displayedIconNames.map((iconName) => (
<Button <Button
variant="ghost"
size="sm" size="sm"
variant={isWhite ? 'solid' : 'ghost'}
colorScheme={isWhite ? 'blackAlpha' : undefined}
fontSize="xl" fontSize="xl"
w="38px" w="38px"
h="38px" h="38px"

View File

@@ -10,30 +10,52 @@ import { IconPicker } from './IconPicker'
type Tabs = 'link' | 'upload' | 'giphy' | 'emoji' | 'unsplash' | 'icon' type Tabs = 'link' | 'upload' | 'giphy' | 'emoji' | 'unsplash' | 'icon'
type Props = { type Props = {
filePath: string filePath: string | undefined
includeFileName?: boolean includeFileName?: boolean
defaultUrl?: string defaultUrl?: string
isEmojiEnabled?: boolean
isGiphyEnabled?: boolean
isUnsplashEnabled?: boolean
imageSize?: 'small' | 'regular' | 'thumb' imageSize?: 'small' | 'regular' | 'thumb'
initialTab?: Tabs
onSubmit: (url: string) => void onSubmit: (url: string) => void
onClose?: () => void onClose?: () => void
} & (
| {
includedTabs?: Tabs[]
} }
| {
excludedTabs?: Tabs[]
}
)
const defaultDisplayedTabs: Tabs[] = [
'link',
'upload',
'giphy',
'emoji',
'unsplash',
'icon',
]
export const ImageUploadContent = ({ export const ImageUploadContent = ({
filePath, filePath,
includeFileName, includeFileName,
defaultUrl, defaultUrl,
onSubmit, onSubmit,
isEmojiEnabled = false,
isGiphyEnabled = true,
isUnsplashEnabled = true,
imageSize = 'regular', imageSize = 'regular',
onClose, onClose,
initialTab,
...props
}: Props) => { }: Props) => {
const includedTabs =
'includedTabs' in props
? props.includedTabs ?? defaultDisplayedTabs
: defaultDisplayedTabs
const excludedTabs = 'excludedTabs' in props ? props.excludedTabs ?? [] : []
const displayedTabs = defaultDisplayedTabs.filter(
(tab) => !excludedTabs.includes(tab) && includedTabs.includes(tab)
)
const [currentTab, setCurrentTab] = useState<Tabs>( const [currentTab, setCurrentTab] = useState<Tabs>(
isEmojiEnabled ? 'emoji' : 'link' initialTab ?? displayedTabs[0]
) )
const handleSubmit = (url: string) => { const handleSubmit = (url: string) => {
@@ -44,7 +66,25 @@ export const ImageUploadContent = ({
return ( return (
<Stack> <Stack>
<HStack> <HStack>
{isEmojiEnabled && ( {displayedTabs.includes('link') && (
<Button
variant={currentTab === 'link' ? 'solid' : 'ghost'}
onClick={() => setCurrentTab('link')}
size="sm"
>
Link
</Button>
)}
{displayedTabs.includes('upload') && (
<Button
variant={currentTab === 'upload' ? 'solid' : 'ghost'}
onClick={() => setCurrentTab('upload')}
size="sm"
>
Upload
</Button>
)}
{displayedTabs.includes('emoji') && (
<Button <Button
variant={currentTab === 'emoji' ? 'solid' : 'ghost'} variant={currentTab === 'emoji' ? 'solid' : 'ghost'}
onClick={() => setCurrentTab('emoji')} onClick={() => setCurrentTab('emoji')}
@@ -53,21 +93,7 @@ export const ImageUploadContent = ({
Emoji Emoji
</Button> </Button>
)} )}
<Button {displayedTabs.includes('giphy') && (
variant={currentTab === 'link' ? 'solid' : 'ghost'}
onClick={() => setCurrentTab('link')}
size="sm"
>
Link
</Button>
<Button
variant={currentTab === 'upload' ? 'solid' : 'ghost'}
onClick={() => setCurrentTab('upload')}
size="sm"
>
Upload
</Button>
{isGiphyEnabled && (
<Button <Button
variant={currentTab === 'giphy' ? 'solid' : 'ghost'} variant={currentTab === 'giphy' ? 'solid' : 'ghost'}
onClick={() => setCurrentTab('giphy')} onClick={() => setCurrentTab('giphy')}
@@ -76,7 +102,7 @@ export const ImageUploadContent = ({
Giphy Giphy
</Button> </Button>
)} )}
{isUnsplashEnabled && ( {displayedTabs.includes('unsplash') && (
<Button <Button
variant={currentTab === 'unsplash' ? 'solid' : 'ghost'} variant={currentTab === 'unsplash' ? 'solid' : 'ghost'}
onClick={() => setCurrentTab('unsplash')} onClick={() => setCurrentTab('unsplash')}
@@ -85,6 +111,7 @@ export const ImageUploadContent = ({
Unsplash Unsplash
</Button> </Button>
)} )}
{displayedTabs.includes('icon') && (
<Button <Button
variant={currentTab === 'icon' ? 'solid' : 'ghost'} variant={currentTab === 'icon' ? 'solid' : 'ghost'}
onClick={() => setCurrentTab('icon')} onClick={() => setCurrentTab('icon')}
@@ -92,6 +119,7 @@ export const ImageUploadContent = ({
> >
Icon Icon
</Button> </Button>
)}
</HStack> </HStack>
<BodyContent <BodyContent
@@ -115,14 +143,15 @@ const BodyContent = ({
onSubmit, onSubmit,
}: { }: {
includeFileName?: boolean includeFileName?: boolean
filePath: string filePath: string | undefined
tab: Tabs tab: Tabs
defaultUrl?: string defaultUrl?: string
imageSize: 'small' | 'regular' | 'thumb' imageSize: 'small' | 'regular' | 'thumb'
onSubmit: (url: string) => void onSubmit: (url: string) => void
}) => { }) => {
switch (tab) { switch (tab) {
case 'upload': case 'upload': {
if (!filePath) return null
return ( return (
<UploadFileContent <UploadFileContent
filePath={filePath} filePath={filePath}
@@ -130,6 +159,7 @@ const BodyContent = ({
onNewUrl={onSubmit} onNewUrl={onSubmit}
/> />
) )
}
case 'link': case 'link':
return <EmbedLinkContent defaultUrl={defaultUrl} onNewUrl={onSubmit} /> return <EmbedLinkContent defaultUrl={defaultUrl} onNewUrl={onSubmit} />
case 'giphy': case 'giphy':

View File

@@ -9,11 +9,6 @@ import { JavascriptBubbleSnippet } from '../JavascriptBubbleSnippet'
export const parseDefaultBubbleTheme = (typebot?: Typebot) => ({ export const parseDefaultBubbleTheme = (typebot?: Typebot) => ({
button: { button: {
backgroundColor: typebot?.theme.chat.buttons.backgroundColor, backgroundColor: typebot?.theme.chat.buttons.backgroundColor,
iconColor: typebot?.theme.chat.buttons.color,
},
previewMessage: {
backgroundColor: typebot?.theme.general.background.content ?? 'white',
textColor: 'black',
}, },
}) })

View File

@@ -1,8 +1,17 @@
import { Stack, Heading, HStack, Flex, Text, Image } from '@chakra-ui/react' import {
Stack,
Heading,
HStack,
Flex,
Text,
Image,
chakra,
} from '@chakra-ui/react'
import { BubbleProps } from '@typebot.io/js' import { BubbleProps } from '@typebot.io/js'
import { isDefined } from '@typebot.io/lib' import { isDefined, isSvgSrc } from '@typebot.io/lib'
import { PreviewMessageSettings } from './PreviewMessageSettings' import { PreviewMessageSettings } from './PreviewMessageSettings'
import { ThemeSettings } from './ThemeSettings' import { ThemeSettings } from './ThemeSettings'
import { isLight } from '@typebot.io/lib/hexToRgb'
type Props = { type Props = {
defaultPreviewMessageAvatar: string defaultPreviewMessageAvatar: string
@@ -79,24 +88,72 @@ export const BubbleSettings = ({
<Flex <Flex
align="center" align="center"
justifyContent="center" justifyContent="center"
boxSize="3rem" transition="all 0.2s ease-in-out"
boxSize={theme?.button?.size === 'large' ? '64px' : '48px'}
bgColor={theme?.button?.backgroundColor} bgColor={theme?.button?.backgroundColor}
rounded="full" rounded="full"
boxShadow="0 0 #0000,0 0 #0000,0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -2px rgba(0,0,0,.1)"
> >
<svg <BubbleIcon buttonTheme={theme?.button} />
viewBox="0 0 24 24"
style={{
stroke: theme?.button?.iconColor,
}}
width="30px"
strokeWidth="2px"
fill="transparent"
>
<path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z" />
</svg>
</Flex> </Flex>
</Stack> </Stack>
</Stack> </Stack>
</Stack> </Stack>
) )
} }
const BubbleIcon = ({
buttonTheme,
}: {
buttonTheme: NonNullable<BubbleProps['theme']>['button']
}) => {
if (!buttonTheme?.customIconSrc)
return (
<svg
viewBox="0 0 24 24"
style={{
stroke: buttonTheme?.backgroundColor
? isLight(buttonTheme?.backgroundColor)
? '#000'
: '#fff'
: '#fff',
transition: 'all 0.2s ease-in-out',
}}
width={buttonTheme?.size === 'large' ? '36px' : '28px'}
strokeWidth="2px"
fill="transparent"
>
<path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z" />
</svg>
)
if (
buttonTheme.customIconSrc.startsWith('http') ||
buttonTheme.customIconSrc.startsWith('data:image/svg+xml')
)
return (
<Image
src={buttonTheme.customIconSrc}
transition="all 0.2s ease-in-out"
boxSize={
isSvgSrc(buttonTheme.customIconSrc)
? buttonTheme?.size === 'large'
? '36px'
: '28px'
: '90%'
}
rounded={isSvgSrc(buttonTheme.customIconSrc) ? undefined : 'full'}
alt="Bubble button icon"
objectFit={isSvgSrc(buttonTheme.customIconSrc) ? undefined : 'cover'}
/>
)
return (
<chakra.span
transition="all 0.2s ease-in-out"
fontSize={buttonTheme.size === 'large' ? '36px' : '24px'}
lineHeight={buttonTheme.size === 'large' ? '40px' : '32px'}
>
{buttonTheme.customIconSrc}
</chakra.span>
)
}

View File

@@ -1,5 +1,21 @@
import { ColorPicker } from '@/components/ColorPicker' import { ColorPicker } from '@/components/ColorPicker'
import { Heading, HStack, Input, Stack, Text } from '@chakra-ui/react' import { ImageUploadContent } from '@/components/ImageUploadContent'
import { ChevronDownIcon } from '@/components/icons'
import {
Button,
Heading,
HStack,
Menu,
MenuButton,
MenuItem,
MenuList,
Popover,
PopoverAnchor,
PopoverContent,
Stack,
Text,
useDisclosure,
} from '@chakra-ui/react'
import { ButtonTheme } from '@typebot.io/js/dist/features/bubble/types' import { ButtonTheme } from '@typebot.io/js/dist/features/bubble/types'
import React from 'react' import React from 'react'
@@ -9,6 +25,8 @@ type Props = {
} }
export const ButtonThemeSettings = ({ buttonTheme, onChange }: Props) => { export const ButtonThemeSettings = ({ buttonTheme, onChange }: Props) => {
const { isOpen, onOpen, onClose } = useDisclosure()
const updateBackgroundColor = (backgroundColor: string) => { const updateBackgroundColor = (backgroundColor: string) => {
onChange({ onChange({
...buttonTheme, ...buttonTheme,
@@ -16,48 +34,58 @@ export const ButtonThemeSettings = ({ buttonTheme, onChange }: Props) => {
}) })
} }
const updateIconColor = (iconColor: string) => {
onChange({
...buttonTheme,
iconColor,
})
}
const updateCustomIconSrc = (customIconSrc: string) => { const updateCustomIconSrc = (customIconSrc: string) => {
onChange({ onChange({
...buttonTheme, ...buttonTheme,
customIconSrc, customIconSrc,
}) })
onClose()
} }
const updateSize = (size: ButtonTheme['size']) =>
onChange({
...buttonTheme,
size,
})
return ( return (
<Stack spacing={4} borderWidth="1px" rounded="md" p="4"> <Stack spacing={4} borderWidth="1px" rounded="md" p="4">
<Heading size="sm">Button</Heading> <Heading size="sm">Button</Heading>
<Stack spacing={4}> <Stack spacing={4}>
<HStack justify="space-between"> <HStack justify="space-between">
<Text>Background color</Text> <Text>Size</Text>
<Menu>
<MenuButton as={Button} size="sm" rightIcon={<ChevronDownIcon />}>
{buttonTheme?.size ?? 'medium'}
</MenuButton>
<MenuList>
<MenuItem onClick={() => updateSize('medium')}>medium</MenuItem>
<MenuItem onClick={() => updateSize('large')}>large</MenuItem>
</MenuList>
</Menu>
</HStack>
<HStack justify="space-between">
<Text>Color</Text>
<ColorPicker <ColorPicker
defaultValue={buttonTheme?.backgroundColor} defaultValue={buttonTheme?.backgroundColor}
onColorChange={updateBackgroundColor} onColorChange={updateBackgroundColor}
/> />
</HStack> </HStack>
<HStack justify="space-between">
<Text>Icon color</Text>
<ColorPicker
defaultValue={buttonTheme?.iconColor}
onColorChange={updateIconColor}
/>
</HStack>
<HStack justify="space-between"> <HStack justify="space-between">
<Text>Custom icon</Text> <Text>Custom icon</Text>
<Input <Popover isLazy isOpen={isOpen}>
placeholder={'Paste image link (.png, .svg)'} <PopoverAnchor>
value={buttonTheme?.customIconSrc} <Button size="sm" onClick={onOpen}>
onChange={(e) => updateCustomIconSrc(e.target.value)} Pick an image
minW="0" </Button>
w="300px" </PopoverAnchor>
size="sm" <PopoverContent p="4" w="500px">
<ImageUploadContent
onSubmit={updateCustomIconSrc}
filePath={undefined}
/> />
</PopoverContent>
</Popover>
</HStack> </HStack>
</Stack> </Stack>
</Stack> </Stack>

View File

@@ -19,7 +19,8 @@ const parseButtonTheme = (
) )
const iconColorLine = parseStringParam('iconColor', iconColor) const iconColorLine = parseStringParam('iconColor', iconColor)
const customIconLine = parseStringParam('customIconSrc', customIconSrc) const customIconLine = parseStringParam('customIconSrc', customIconSrc)
const line = `button: {${backgroundColorLine}${iconColorLine}${customIconLine}},` const sizeLine = parseStringParam('size', button.size)
const line = `button: {${backgroundColorLine}${iconColorLine}${customIconLine}${sizeLine}},`
if (line === 'button: {},') return '' if (line === 'button: {},') return ''
return line return line
} }

View File

@@ -64,7 +64,7 @@ export const MetadataForm = ({
filePath={`typebots/${typebotId}/favIcon`} filePath={`typebots/${typebotId}/favIcon`}
defaultUrl={metadata.favIconUrl ?? ''} defaultUrl={metadata.favIconUrl ?? ''}
onSubmit={handleFavIconSubmit} onSubmit={handleFavIconSubmit}
isGiphyEnabled={false} excludedTabs={['giphy', 'unsplash', 'emoji']}
imageSize="thumb" imageSize="thumb"
/> />
</PopoverContent> </PopoverContent>
@@ -90,7 +90,7 @@ export const MetadataForm = ({
filePath={`typebots/${typebotId}/ogImage`} filePath={`typebots/${typebotId}/ogImage`}
defaultUrl={metadata.imageUrl} defaultUrl={metadata.imageUrl}
onSubmit={handleImageSubmit} onSubmit={handleImageSubmit}
isGiphyEnabled={false} excludedTabs={['giphy', 'icon', 'emoji']}
/> />
</PopoverContent> </PopoverContent>
</Popover> </Popover>

View File

@@ -62,7 +62,7 @@ export const BackgroundContent = ({
filePath={`typebots/${typebot?.id}/background`} filePath={`typebots/${typebot?.id}/background`}
defaultUrl={background.content} defaultUrl={background.content}
onSubmit={handleContentChange} onSubmit={handleContentChange}
isGiphyEnabled={false} excludedTabs={['giphy', 'icon']}
/> />
</PopoverContent> </PopoverContent>
</Popover> </Popover>

View File

@@ -1,6 +1,6 @@
{ {
"name": "@typebot.io/js", "name": "@typebot.io/js",
"version": "0.0.50", "version": "0.0.51",
"description": "Javascript library to display typebots on your website", "description": "Javascript library to display typebots on your website",
"type": "module", "type": "module",
"main": "dist/index.js", "main": "dist/index.js",

View File

@@ -1,6 +1,7 @@
import { Show } from 'solid-js' import { Show } from 'solid-js'
import { isNotDefined } from '@typebot.io/lib' import { isNotDefined, isSvgSrc } from '@typebot.io/lib'
import { ButtonTheme } from '../types' import { ButtonTheme } from '../types'
import { isLight } from '@typebot.io/lib/hexToRgb'
type Props = ButtonTheme & { type Props = ButtonTheme & {
isBotOpened: boolean isBotOpened: boolean
@@ -8,7 +9,9 @@ type Props = ButtonTheme & {
} }
const defaultButtonColor = '#0042DA' const defaultButtonColor = '#0042DA'
const defaultIconColor = 'white'
const isImageSrc = (src: string) =>
src.startsWith('http') || src.startsWith('data:image/svg+xml')
export const BubbleButton = (props: Props) => { export const BubbleButton = (props: Props) => {
return ( return (
@@ -28,7 +31,11 @@ export const BubbleButton = (props: Props) => {
<svg <svg
viewBox="0 0 24 24" viewBox="0 0 24 24"
style={{ style={{
stroke: props.iconColor ?? defaultIconColor, stroke:
props.iconColor ??
isLight(props.backgroundColor ?? defaultButtonColor)
? '#27272A'
: '#fff',
}} }}
class={ class={
`stroke-2 fill-transparent absolute duration-200 transition ` + `stroke-2 fill-transparent absolute duration-200 transition ` +
@@ -41,18 +48,42 @@ export const BubbleButton = (props: Props) => {
<path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z" /> <path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z" />
</svg> </svg>
</Show> </Show>
<Show when={props.customIconSrc}> <Show when={props.customIconSrc && isImageSrc(props.customIconSrc)}>
<img <img
src={props.customIconSrc} src={props.customIconSrc}
class={ class={
'rounded-full object-cover' + 'duration-200 transition' +
(props.size === 'large' ? ' w-9 h-9' : ' w-7 h-7') (props.isBotOpened
? ' scale-0 opacity-0'
: ' scale-100 opacity-100') +
(isSvgSrc(props.customIconSrc)
? props.size === 'large'
? ' w-9 h-9'
: ' w-7 h-7'
: ' w-[90%] h-[90%]') +
(isSvgSrc(props.customIconSrc) ? '' : ' object-cover rounded-full')
} }
alt="Bubble button icon" alt="Bubble button icon"
elementtiming={'Bubble button icon'} elementtiming={'Bubble button icon'}
fetchpriority={'high'} fetchpriority={'high'}
/> />
</Show> </Show>
<Show when={props.customIconSrc && !isImageSrc(props.customIconSrc)}>
<span
class={
'text-4xl duration-200 transition' +
(props.isBotOpened
? ' scale-0 opacity-0'
: ' scale-100 opacity-100')
}
style={{
'font-family':
"-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'",
}}
>
{props.customIconSrc}
</span>
</Show>
<svg <svg
viewBox="0 0 24 24" viewBox="0 0 24 24"

View File

@@ -7,8 +7,7 @@ import {
Theme, Theme,
} from '@typebot.io/schemas' } from '@typebot.io/schemas'
import { BackgroundType } from '@typebot.io/schemas/features/typebot/theme/enums' import { BackgroundType } from '@typebot.io/schemas/features/typebot/theme/enums'
import { hexToRgb } from './hexToRgb' import { isLight, hexToRgb } from '@typebot.io/lib/hexToRgb'
import { isLight } from './hexToRgb'
const cssVariableNames = { const cssVariableNames = {
general: { general: {

View File

@@ -1,6 +1,6 @@
{ {
"name": "@typebot.io/react", "name": "@typebot.io/react",
"version": "0.0.50", "version": "0.0.51",
"description": "React library to display typebots on your website", "description": "React library to display typebots on your website",
"main": "dist/index.js", "main": "dist/index.js",
"types": "dist/index.d.ts", "types": "dist/index.d.ts",