2
0

feat(theme): Add custom css settings

This commit is contained in:
Baptiste Arnaud
2022-01-24 15:29:01 +01:00
parent b0abe5b8fa
commit 21448bcc8a
9 changed files with 88 additions and 28 deletions

View File

@ -159,6 +159,7 @@ export const WebhookSettings = ({
<AccordionPanel pb={4} as={Stack} spacing="6">
<CodeEditor
value={webhook?.body ?? ''}
lang="json"
onChange={handleBodyChange}
/>
</AccordionPanel>
@ -181,7 +182,9 @@ export const WebhookSettings = ({
<Button onClick={handleTestRequestClick} colorScheme="blue">
Test the request
</Button>
{testResponse && <CodeEditor isReadOnly value={testResponse} />}
{testResponse && (
<CodeEditor isReadOnly lang="json" value={testResponse} />
)}
{(testResponse || options?.responseVariableMapping) && (
<Accordion allowToggle allowMultiple>
<AccordionItem>

View File

@ -1,15 +1,18 @@
import { Box, BoxProps } from '@chakra-ui/react'
import { EditorState, EditorView, basicSetup } from '@codemirror/basic-setup'
import { json } from '@codemirror/lang-json'
import { css } from '@codemirror/lang-css'
import { useEffect, useRef } from 'react'
type Props = {
value: string
lang: 'css' | 'json'
onChange?: (value: string) => void
isReadOnly?: boolean
}
export const CodeEditor = ({
value,
lang,
onChange,
isReadOnly = false,
...props
@ -31,14 +34,15 @@ export const CodeEditor = ({
if (update.docChanged && onChange)
onChange(update.state.doc.toJSON().join(' '))
})
const extensions = [
updateListenerExtension,
basicSetup,
EditorState.readOnly.of(isReadOnly),
]
extensions.push(lang === 'json' ? json() : css())
const editor = new EditorView({
state: EditorState.create({
extensions: [
updateListenerExtension,
basicSetup,
json(),
EditorState.readOnly.of(isReadOnly),
],
extensions,
}),
parent: editorContainer.current,
})

View File

@ -0,0 +1,17 @@
import { CodeEditor } from 'components/shared/CodeEditor'
import React from 'react'
type Props = {
customCss?: string
onCustomCssChange: (css: string) => void
}
export const CustomCssSettings = ({ customCss, onCustomCssChange }: Props) => {
return (
<CodeEditor
value={customCss ?? ''}
lang="css"
onChange={onCustomCssChange}
/>
)
}

View File

@ -8,12 +8,13 @@ import {
HStack,
Stack,
} from '@chakra-ui/react'
import { ChatIcon, CodeIcon, LayoutIcon, PencilIcon } from 'assets/icons'
import { ChatIcon, CodeIcon, PencilIcon } from 'assets/icons'
import { headerHeight } from 'components/shared/TypebotHeader'
import { useTypebot } from 'contexts/TypebotContext'
import { ChatTheme, GeneralTheme } from 'models'
import React from 'react'
import { ChatThemeSettings } from './ChatSettings'
import { CustomCssSettings } from './CustomCssSettings/CustomCssSettings'
import { GeneralSettings } from './GeneralSettings'
export const SideMenu = () => {
@ -25,6 +26,9 @@ export const SideMenu = () => {
const handleGeneralThemeChange = (general: GeneralTheme) =>
updateTypebot({ theme: { ...typebot?.theme, general } })
const handleCustomCssChange = (customCss: string) =>
updateTypebot({ theme: { ...typebot?.theme, customCss } })
return (
<Stack
flex="1"
@ -55,21 +59,6 @@ export const SideMenu = () => {
/>
</AccordionPanel>
</AccordionItem>
<AccordionItem>
<AccordionButton py={6}>
<HStack flex="1" pl={2}>
<LayoutIcon />
<Heading fontSize="lg">Layout</Heading>
</HStack>
<AccordionIcon />
</AccordionButton>
<AccordionPanel pb={4}>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim
ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
aliquip ex ea commodo consequat.
</AccordionPanel>
</AccordionItem>
<AccordionItem>
<AccordionButton py={6}>
<HStack flex="1" pl={2}>
@ -94,10 +83,10 @@ export const SideMenu = () => {
<AccordionIcon />
</AccordionButton>
<AccordionPanel pb={4}>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim
ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
aliquip ex ea commodo consequat.
<CustomCssSettings
customCss={typebot?.theme?.customCss}
onCustomCssChange={handleCustomCssChange}
/>
</AccordionPanel>
</AccordionItem>
</Accordion>

View File

@ -0,0 +1,26 @@
import { getIframeBody } from 'cypress/support'
describe('Custom CSS settings', () => {
beforeEach(() => {
cy.task('seed')
cy.signOut()
})
it('should reflect changes in real time', () => {
cy.loadTypebotFixtureInDatabase('typebots/theme/theme.json')
cy.signIn('test2@gmail.com')
cy.visit('/typebots/typebot4/theme')
cy.findByRole('button', { name: 'Custom CSS' }).click()
cy.findByTestId('code-editor').type(
'.typebot-button {background-color: green}',
{
parseSpecialCharSequences: false,
}
)
getIframeBody()
.findByTestId('button')
.should('have.css', 'background-color')
.should('eq', 'rgb(0, 128, 0)')
})
})

View File

@ -13,6 +13,7 @@
"@chakra-ui/css-reset": "^1.1.1",
"@chakra-ui/react": "^1.7.4",
"@codemirror/basic-setup": "^0.19.1",
"@codemirror/lang-css": "^0.19.3",
"@codemirror/lang-json": "^0.19.1",
"@codemirror/text": "^0.19.6",
"@dnd-kit/core": "^4.0.3",

View File

@ -48,6 +48,7 @@ export const TypebotViewer = ({
{phoneNumberInputStyle}
{phoneSyle}
{style}
{typebot.theme?.customCss}
</style>
}
style={{ width: '100%', height: '100%', border: 'none' }}

View File

@ -1,6 +1,7 @@
export type Theme = {
general?: GeneralTheme
chat?: ChatTheme
customCss?: string
}
export type GeneralTheme = {

View File

@ -811,7 +811,7 @@
"@codemirror/state" "^0.19.0"
"@codemirror/view" "^0.19.23"
"@codemirror/highlight@^0.19.0":
"@codemirror/highlight@^0.19.0", "@codemirror/highlight@^0.19.6":
version "0.19.7"
resolved "https://registry.yarnpkg.com/@codemirror/highlight/-/highlight-0.19.7.tgz#91a0c9994c759f5f153861e3aae74ff9e7c7c35b"
integrity sha512-3W32hBCY0pbbv/xidismw+RDMKuIag+fo4kZIbD7WoRj+Ttcaxjf+vP6RttRHXLaaqbWh031lTeON8kMlDhMYw==
@ -831,6 +831,17 @@
"@codemirror/state" "^0.19.2"
"@codemirror/view" "^0.19.0"
"@codemirror/lang-css@^0.19.3":
version "0.19.3"
resolved "https://registry.yarnpkg.com/@codemirror/lang-css/-/lang-css-0.19.3.tgz#7a17adf78c6fcdab4ad5ee4e360631c41e949e4a"
integrity sha512-tyCUJR42/UlfOPLb94/p7dN+IPsYSIzHbAHP2KQHANj0I+Orqp+IyIOS++M8TuCX4zkWh9dvi8s92yy/Tn8Ifg==
dependencies:
"@codemirror/autocomplete" "^0.19.0"
"@codemirror/highlight" "^0.19.6"
"@codemirror/language" "^0.19.0"
"@codemirror/state" "^0.19.0"
"@lezer/css" "^0.15.2"
"@codemirror/lang-json@^0.19.1":
version "0.19.1"
resolved "https://registry.yarnpkg.com/@codemirror/lang-json/-/lang-json-0.19.1.tgz#616588d1422529965243c10af6c44ad0b9134fb0"
@ -1338,6 +1349,13 @@
resolved "https://registry.yarnpkg.com/@lezer/common/-/common-0.15.11.tgz#965b5067036305f12e8a3efc344076850be1d3a8"
integrity sha512-vv0nSdIaVCRcJ8rPuDdsrNVfBOYe/4Szr/LhF929XyDmBndLDuWiCCHooGlGlJfzELyO608AyDhVsuX/ZG36NA==
"@lezer/css@^0.15.2":
version "0.15.2"
resolved "https://registry.yarnpkg.com/@lezer/css/-/css-0.15.2.tgz#e96995da67df90bb4b191aaa8a486349cca5d8e7"
integrity sha512-tnMOMZY0Zs6JQeVjqfmREYMV0GnmZR1NitndLWioZMD6mA7VQF/PPKPmJX1f+ZgVZQc5Am0df9mX3aiJnNJlKQ==
dependencies:
"@lezer/lr" "^0.15.0"
"@lezer/json@^0.15.0":
version "0.15.0"
resolved "https://registry.yarnpkg.com/@lezer/json/-/json-0.15.0.tgz#b96c1161eb8514e05f4eaaec95c68376e76e539f"