🦴 Add theme page backbone
This commit is contained in:
@ -4,10 +4,9 @@
|
||||
|
||||
:root {
|
||||
--typebot-container-bg-image: none;
|
||||
--typebot-container-bg-color: #f7f8ff;
|
||||
--typebot-container-font-family: 'Inter';
|
||||
--typebot-container-bg-color: transparent;
|
||||
--typebot-container-font-family: 'Open Sans';
|
||||
--typebot-chat-view-max-width: 700px;
|
||||
--typebot-chat-view-bg-color: #ffffff;
|
||||
--typebot-chat-view-color: #303235;
|
||||
|
||||
--typebot-button-active-bg-color: #0042da;
|
||||
@ -318,7 +317,6 @@ textarea {
|
||||
|
||||
.typebot-chat-view {
|
||||
max-width: var(--typebot-chat-view-max-width);
|
||||
background-color: var(--typebot-chat-view-bg-color);
|
||||
}
|
||||
|
||||
.typebot-button.active {
|
||||
|
@ -3,6 +3,8 @@ import { PublicTypebot } from '..'
|
||||
|
||||
import { Block } from '..'
|
||||
import { ChatBlock } from './ChatBlock/ChatBlock'
|
||||
import { useFrame } from 'react-frame-component'
|
||||
import { setCssVariablesValue } from '../services/theme'
|
||||
|
||||
export const ConversationContainer = ({
|
||||
typebot,
|
||||
@ -11,6 +13,7 @@ export const ConversationContainer = ({
|
||||
typebot: PublicTypebot
|
||||
onNewBlockVisisble: (blockId: string) => void
|
||||
}) => {
|
||||
const { document: frameDocument } = useFrame()
|
||||
const [displayedBlocks, setDisplayedBlocks] = useState<Block[]>([])
|
||||
|
||||
const [isConversationEnded, setIsConversationEnded] = useState(false)
|
||||
@ -28,6 +31,10 @@ export const ConversationContainer = ({
|
||||
if (firstBlockId) displayNextBlock(firstBlockId)
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
setCssVariablesValue(typebot.theme, frameDocument.body.style)
|
||||
}, [typebot.theme, frameDocument])
|
||||
|
||||
return (
|
||||
<div
|
||||
className="overflow-y-scroll w-full lg:w-3/4 min-h-full rounded lg:px-5 px-3 pt-10 relative scrollable-container typebot-chat-view"
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React from 'react'
|
||||
import { PublicTypebot } from '../models'
|
||||
import React, { useMemo } from 'react'
|
||||
import { BackgroundType, PublicTypebot } from '../models'
|
||||
import { TypebotContext } from '../contexts/TypebotContext'
|
||||
import Frame from 'react-frame-component'
|
||||
//@ts-ignore
|
||||
@ -9,25 +9,47 @@ import { ResultContext } from '../contexts/ResultsContext'
|
||||
|
||||
export type TypebotViewerProps = {
|
||||
typebot: PublicTypebot
|
||||
onNewBlockVisisble: (blockId: string) => void
|
||||
onNewBlockVisisble?: (blockId: string) => void
|
||||
}
|
||||
export const TypebotViewer = ({
|
||||
typebot,
|
||||
onNewBlockVisisble,
|
||||
}: TypebotViewerProps) => {
|
||||
const containerBgColor = useMemo(
|
||||
() =>
|
||||
typebot.theme.general.background.type === BackgroundType.COLOR
|
||||
? typebot.theme.general.background.content
|
||||
: 'transparent',
|
||||
[typebot.theme.general.background]
|
||||
)
|
||||
const handleNewBlockVisible = (blockId: string) => {
|
||||
if (onNewBlockVisisble) onNewBlockVisisble(blockId)
|
||||
}
|
||||
|
||||
return (
|
||||
<Frame
|
||||
id="typebot-iframe"
|
||||
head={<style>{style}</style>}
|
||||
style={{ width: '100%' }}
|
||||
>
|
||||
<style
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: `@import url('https://fonts.googleapis.com/css2?family=${typebot.theme.general.font}:wght@300;400;600&display=swap');`,
|
||||
}}
|
||||
/>
|
||||
<TypebotContext typebot={typebot}>
|
||||
<ResultContext typebotId={typebot.id}>
|
||||
<div className="flex text-base overflow-hidden bg-cover h-screen w-screen typebot-container flex-col items-center">
|
||||
<div
|
||||
className="flex text-base overflow-hidden bg-cover h-screen w-screen flex-col items-center typebot-container"
|
||||
style={{
|
||||
// We set this as inline style to avoid color flashing (due to SSR)
|
||||
backgroundColor: containerBgColor,
|
||||
}}
|
||||
>
|
||||
<div className="flex w-full h-full justify-center">
|
||||
<ConversationContainer
|
||||
typebot={typebot}
|
||||
onNewBlockVisisble={onNewBlockVisisble}
|
||||
onNewBlockVisisble={handleNewBlockVisible}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,10 +1,11 @@
|
||||
import { PublicTypebot as PublicTypebotFromPrisma } from 'db'
|
||||
import { Block, StartBlock } from '.'
|
||||
import { Block, StartBlock, Theme } from '.'
|
||||
|
||||
export type PublicTypebot = Omit<
|
||||
PublicTypebotFromPrisma,
|
||||
'blocks' | 'startBlock'
|
||||
'blocks' | 'startBlock' | 'theme'
|
||||
> & {
|
||||
blocks: Block[]
|
||||
startBlock: StartBlock
|
||||
theme: Theme
|
||||
}
|
||||
|
@ -1,8 +1,12 @@
|
||||
import { Typebot as TypebotFromPrisma } from 'db'
|
||||
|
||||
export type Typebot = Omit<TypebotFromPrisma, 'blocks' | 'startBlock'> & {
|
||||
export type Typebot = Omit<
|
||||
TypebotFromPrisma,
|
||||
'blocks' | 'startBlock' | 'theme'
|
||||
> & {
|
||||
blocks: Block[]
|
||||
startBlock: StartBlock
|
||||
theme: Theme
|
||||
}
|
||||
|
||||
export type StartBlock = {
|
||||
@ -53,11 +57,20 @@ export type TextInputStep = StepBase & {
|
||||
type: StepType.TEXT_INPUT
|
||||
}
|
||||
|
||||
export type Button = {
|
||||
id: string
|
||||
content: string
|
||||
target: {
|
||||
type: 'block' | 'step'
|
||||
id: string
|
||||
export type Theme = {
|
||||
general: {
|
||||
font: string
|
||||
background: Background
|
||||
}
|
||||
}
|
||||
|
||||
export enum BackgroundType {
|
||||
COLOR = 'Color',
|
||||
IMAGE = 'Image',
|
||||
NONE = 'None',
|
||||
}
|
||||
|
||||
export type Background = {
|
||||
type: BackgroundType
|
||||
content: string
|
||||
}
|
||||
|
25
packages/bot-engine/src/services/theme.ts
Normal file
25
packages/bot-engine/src/services/theme.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import { BackgroundType, Theme } from '../models'
|
||||
|
||||
const cssVariableNames = {
|
||||
container: {
|
||||
bg: {
|
||||
image: '--typebot-container-bg-image',
|
||||
color: '--typebot-container-bg-color',
|
||||
},
|
||||
fontFamily: '--typebot-container-font-family',
|
||||
},
|
||||
}
|
||||
|
||||
export const setCssVariablesValue = (
|
||||
theme: Theme,
|
||||
documentStyle: CSSStyleDeclaration
|
||||
) => {
|
||||
const { background, font } = theme.general
|
||||
documentStyle.setProperty(
|
||||
background.type === BackgroundType.IMAGE
|
||||
? cssVariableNames.container.bg.image
|
||||
: cssVariableNames.container.bg.color,
|
||||
background.content
|
||||
)
|
||||
documentStyle.setProperty(cssVariableNames.container.fontFamily, font)
|
||||
}
|
Reference in New Issue
Block a user