2
0

(theme) Support for image background

Closes #414
This commit is contained in:
Baptiste Arnaud
2023-03-22 14:45:10 +01:00
parent 1cf2195b4a
commit 3992227afc
6 changed files with 77 additions and 19 deletions

View File

@ -26,7 +26,7 @@ export const ImageUploadContent = ({
}: Props) => { }: Props) => {
const [currentTab, setCurrentTab] = useState< const [currentTab, setCurrentTab] = useState<
'link' | 'upload' | 'giphy' | 'emoji' 'link' | 'upload' | 'giphy' | 'emoji'
>(isEmojiEnabled ? 'emoji' : 'upload') >(isEmojiEnabled ? 'emoji' : 'link')
const handleSubmit = (url: string) => { const handleSubmit = (url: string) => {
onSubmit(url) onSubmit(url)
@ -45,13 +45,6 @@ export const ImageUploadContent = ({
Emoji Emoji
</Button> </Button>
)} )}
<Button
variant={currentTab === 'upload' ? 'solid' : 'ghost'}
onClick={() => setCurrentTab('upload')}
size="sm"
>
Upload
</Button>
<Button <Button
variant={currentTab === 'link' ? 'solid' : 'ghost'} variant={currentTab === 'link' ? 'solid' : 'ghost'}
onClick={() => setCurrentTab('link')} onClick={() => setCurrentTab('link')}
@ -59,6 +52,13 @@ export const ImageUploadContent = ({
> >
Embed link Embed link
</Button> </Button>
<Button
variant={currentTab === 'upload' ? 'solid' : 'ghost'}
onClick={() => setCurrentTab('upload')}
size="sm"
>
Upload
</Button>
{isGiphyEnabled && ( {isGiphyEnabled && (
<Button <Button
variant={currentTab === 'giphy' ? 'solid' : 'ghost'} variant={currentTab === 'giphy' ? 'solid' : 'ghost'}

View File

@ -1,4 +1,15 @@
import { Flex, Text } from '@chakra-ui/react' import { ImageUploadContent } from '@/components/ImageUploadContent'
import { useTypebot } from '@/features/editor/providers/TypebotProvider'
import {
Flex,
Popover,
PopoverContent,
PopoverTrigger,
Text,
Image,
Button,
} from '@chakra-ui/react'
import { isNotEmpty } from '@typebot.io/lib'
import { Background, BackgroundType } from '@typebot.io/schemas' import { Background, BackgroundType } from '@typebot.io/schemas'
import React from 'react' import React from 'react'
import { ColorPicker } from '../../../../components/ColorPicker' import { ColorPicker } from '../../../../components/ColorPicker'
@ -14,6 +25,7 @@ export const BackgroundContent = ({
background, background,
onBackgroundContentChange, onBackgroundContentChange,
}: BackgroundContentProps) => { }: BackgroundContentProps) => {
const { typebot } = useTypebot()
const handleContentChange = (content: string) => const handleContentChange = (content: string) =>
onBackgroundContentChange(content) onBackgroundContentChange(content)
@ -30,9 +42,30 @@ export const BackgroundContent = ({
) )
case BackgroundType.IMAGE: case BackgroundType.IMAGE:
return ( return (
<Flex> <Popover isLazy placement="top">
<Text>Image</Text> <PopoverTrigger>
</Flex> {isNotEmpty(background.content) ? (
<Image
src={background.content}
alt="Background image"
cursor="pointer"
_hover={{ filter: 'brightness(.9)' }}
transition="filter 200ms"
rounded="md"
/>
) : (
<Button>Select an image</Button>
)}
</PopoverTrigger>
<PopoverContent p="4">
<ImageUploadContent
filePath={`typebots/${typebot?.id}/background`}
defaultUrl={background.content}
onSubmit={handleContentChange}
isGiphyEnabled={false}
/>
</PopoverContent>
</Popover>
) )
default: default:
return <></> return <></>

View File

@ -16,7 +16,8 @@ export const BackgroundSelector = ({
onBackgroundChange, onBackgroundChange,
}: Props) => { }: Props) => {
const handleBackgroundTypeChange = (type: BackgroundType) => const handleBackgroundTypeChange = (type: BackgroundType) =>
background && onBackgroundChange({ ...background, type }) background &&
onBackgroundChange({ ...background, type, content: undefined })
const handleBackgroundContentChange = (content: string) => const handleBackgroundContentChange = (content: string) =>
background && onBackgroundChange({ ...background, content }) background && onBackgroundChange({ ...background, content })

View File

@ -18,7 +18,7 @@ export const BackgroundTypeRadioButtons = ({
backgroundType, backgroundType,
onBackgroundTypeChange, onBackgroundTypeChange,
}: Props) => { }: Props) => {
const options = ['Color', 'None'] const options = ['Color', 'Image', 'None']
const { getRootProps, getRadioProps } = useRadioGroup({ const { getRootProps, getRadioProps } = useRadioGroup({
name: 'background-type', name: 'background-type',
@ -55,10 +55,9 @@ export const RadioCard = (props: UseRadioProps & { children: ReactNode }) => {
<Flex <Flex
{...checkbox} {...checkbox}
cursor="pointer" cursor="pointer"
borderWidth="1px" borderWidth="2px"
borderRadius="md" borderRadius="md"
_checked={{ _checked={{
borderWidth: '2px',
borderColor: 'blue.400', borderColor: 'blue.400',
}} }}
_hover={{ _hover={{

View File

@ -7,6 +7,8 @@ const hostAvatarUrl =
'https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1760&q=80' 'https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1760&q=80'
const guestAvatarUrl = const guestAvatarUrl =
'https://images.unsplash.com/photo-1494790108377-be9c29b29330?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1287&q=80' 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1287&q=80'
const backgroundImageUrl =
'https://images.unsplash.com/photo-1508739773434-c26b3d09e071?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2940&q=80'
test.describe.parallel('Theme page', () => { test.describe.parallel('Theme page', () => {
test.describe('General', () => { test.describe('General', () => {
@ -38,6 +40,20 @@ test.describe.parallel('Theme page', () => {
'background-color', 'background-color',
'rgb(42, 157, 143)' 'rgb(42, 157, 143)'
) )
await page.click('text=Color')
await page.click('text="Image"')
await page.getByRole('button', { name: 'Select an image' }).click()
await page
.getByPlaceholder('Paste the image link...')
.fill(backgroundImageUrl)
await expect(
page.getByRole('img', { name: 'Background image' })
).toHaveAttribute('src', backgroundImageUrl)
await expect(page.locator('.typebot-container')).toHaveCSS(
'background-image',
`url("${backgroundImageUrl}")`
)
}) })
}) })

View File

@ -137,8 +137,17 @@ const setTypebotBackground = (
background?.type === BackgroundType.IMAGE background?.type === BackgroundType.IMAGE
? cssVariableNames.general.bgImage ? cssVariableNames.general.bgImage
: cssVariableNames.general.bgColor, : cssVariableNames.general.bgColor,
background.type === BackgroundType.NONE parseBackgroundValue(background)
? 'transparent'
: background.content ?? '#ffffff'
) )
} }
const parseBackgroundValue = ({ type, content }: Background) => {
switch (type) {
case BackgroundType.NONE:
return 'transparent'
case BackgroundType.COLOR:
return content ?? '#ffffff'
case BackgroundType.IMAGE:
return `url(${content})`
}
}