2
0

(theme) Custom font option (#1268)

Closes #1249

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **New Features**
- Introduced components for customizing fonts, including Google and
custom font options.
- Enhanced theme customization by simplifying theme objects and adding
new font customization options.
- Implemented dynamic font injection for web pages based on
user-selected font configurations.

- **Bug Fixes**
- Fixed a condition in theme template card rendering to correctly check
avatar enablement.
- Corrected font property handling across various components to support
both string and object types.

- **Refactor**
	- Updated option properties in RadioButtons component to be readonly.
- Simplified logic for setting CSS variables for fonts, including checks
for font types and existence.

- **Documentation**
- Added constants and schemas for supporting new font types in theme
customization.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Baptiste Arnaud
2024-02-20 10:36:57 +01:00
committed by GitHub
parent 927feae32b
commit 7cf1a3e26d
19 changed files with 341 additions and 158 deletions

View File

@@ -12,11 +12,12 @@ import {
} from '@/utils/storage'
import { setCssVariablesValue } from '@/utils/setCssVariablesValue'
import immutableCss from '../assets/immutable.css'
import { InputBlock } from '@typebot.io/schemas'
import { Font, InputBlock } from '@typebot.io/schemas'
import { StartFrom } from '@typebot.io/schemas'
import { defaultTheme } from '@typebot.io/schemas/features/typebot/theme/constants'
import { clsx } from 'clsx'
import { HTTPError } from 'ky'
import { injectFont } from '@/utils/injectFont'
export type BotProps = {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -25,6 +26,7 @@ export type BotProps = {
resultId?: string
prefilledVariables?: Record<string, unknown>
apiHost?: string
font?: Font
onNewInputBlock?: (inputBlock: InputBlock) => void
onAnswer?: (answer: { message: string; blockId: string }) => void
onInit?: () => void
@@ -42,6 +44,7 @@ export const Bot = (props: BotProps & { class?: string }) => {
const [error, setError] = createSignal<Error | undefined>()
const initializeBot = async () => {
if (props.font) injectFont(props.font)
setIsInitialized(true)
const urlParams = new URLSearchParams(location.search)
props.onInit?.()
@@ -193,34 +196,16 @@ const BotContent = (props: BotContentProps) => {
return setIsMobile(entries[0].target.clientWidth < 400)
})
const injectCustomFont = () => {
const existingFont = document.getElementById('bot-font')
if (
existingFont
?.getAttribute('href')
?.includes(
props.initialChatReply.typebot?.theme?.general?.font ??
defaultTheme.general.font
)
)
return
const font = document.createElement('link')
font.href = `https://fonts.bunny.net/css2?family=${
props.initialChatReply.typebot?.theme?.general?.font ??
defaultTheme.general.font
}:ital,wght@0,300;0,400;0,600;1,300;1,400;1,600&display=swap');')`
font.rel = 'stylesheet'
font.id = 'bot-font'
document.head.appendChild(font)
}
onMount(() => {
if (!botContainer) return
resizeObserver.observe(botContainer)
})
createEffect(() => {
injectCustomFont()
injectFont(
props.initialChatReply.typebot.theme.general?.font ??
defaultTheme.general.font
)
if (!botContainer) return
setCssVariablesValue(props.initialChatReply.typebot.theme, botContainer)
})

View File

@@ -0,0 +1,32 @@
import { isEmpty } from '@typebot.io/lib'
import { Font } from '@typebot.io/schemas'
import { defaultTheme } from '@typebot.io/schemas/features/typebot/theme/constants'
const googleFontCdnBaseUrl = 'https://fonts.bunny.net/css2'
export const injectFont = (font: Font) => {
const existingFont = document.getElementById('bot-font')
if (typeof font === 'string' || font.type === 'Google') {
const fontFamily =
(typeof font === 'string' ? font : font.family) ??
defaultTheme.general.font.family
if (existingFont?.getAttribute('href')?.includes(fontFamily)) return
const fontElement = document.createElement('link')
fontElement.href = `${googleFontCdnBaseUrl}?family=${fontFamily}:ital,wght@0,300;0,400;0,600;1,300;1,400;1,600&display=swap`
fontElement.rel = 'stylesheet'
fontElement.id = 'bot-font'
document.head.appendChild(fontElement)
return
}
if (font.type === 'Custom') {
if (existingFont?.getAttribute('href') === font.url || isEmpty(font.url))
return
const fontElement = document.createElement('link')
fontElement.href = font.url
fontElement.rel = 'stylesheet'
fontElement.id = 'bot-font'
document.head.appendChild(fontElement)
}
}

View File

@@ -68,7 +68,9 @@ const setGeneralTheme = (
)
documentStyle.setProperty(
cssVariableNames.general.fontFamily,
generalTheme.font ?? defaultTheme.general.font
(typeof generalTheme.font === 'string'
? generalTheme.font
: generalTheme.font?.family) ?? defaultTheme.general.font.family
)
}