Skip to content

Commit

Permalink
⚡ (theme) Add corner roundness customization
Browse files Browse the repository at this point in the history
Closes #415
  • Loading branch information
baptisteArno committed Mar 22, 2023
1 parent 3992227 commit 65d33e0
Show file tree
Hide file tree
Showing 30 changed files with 195 additions and 67 deletions.
39 changes: 39 additions & 0 deletions apps/builder/src/components/icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -552,3 +552,42 @@ export const CloseIcon = (props: IconProps) => (
<line x1="6" y1="6" x2="18" y2="18"></line>
</Icon>
)

export const NoRadiusIcon = (props: IconProps) => (
<Icon viewBox="0 0 20 20" {...props}>
<mask id="path-1-inside-1_1009_3" fill="white">
<path d="M0 0H20V20H0V0Z" />
</mask>
<path
d="M0 0V-2H-2V0H0ZM0 20H-2V22H0V20ZM0 2H20V-2H0V2ZM20 18H0V22H20V18ZM2 20V0H-2V20H2Z"
fill="black"
mask="url(#path-1-inside-1_1009_3)"
/>
</Icon>
)

export const MediumRadiusIcon = (props: IconProps) => (
<Icon viewBox="0 0 20 20" {...props}>
<mask id="path-1-inside-1_1009_4" fill="white">
<path d="M0 4C0 1.79086 1.79086 0 4 0H20V20H4C1.79086 20 0 18.2091 0 16V4Z" />
</mask>
<path
d="M-2 4C-2 0.686292 0.686292 -2 4 -2H20V2H4C2.89543 2 2 2.89543 2 4H-2ZM20 22H4C0.686292 22 -2 19.3137 -2 16H2C2 17.1046 2.89543 18 4 18H20V22ZM4 22C0.686292 22 -2 19.3137 -2 16V4C-2 0.686292 0.686292 -2 4 -2V2C2.89543 2 2 2.89543 2 4V16C2 17.1046 2.89543 18 4 18V22ZM20 0V20V0Z"
fill="black"
mask="url(#path-1-inside-1_1009_4)"
/>
</Icon>
)

export const LargeRadiusIcon = (props: IconProps) => (
<Icon viewBox="0 0 20 20" {...props}>
<mask id="path-1-inside-1_1009_5" fill="white">
<path d="M0 10C0 4.47715 4.47715 0 10 0H20V20H10C4.47715 20 0 15.5228 0 10V10Z" />
</mask>
<path
d="M-2 10C-2 3.37258 3.37258 -2 10 -2H20V2H10C5.58172 2 2 5.58172 2 10H-2ZM20 22H10C3.37258 22 -2 16.6274 -2 10H2C2 14.4183 5.58172 18 10 18H20V22ZM10 22C3.37258 22 -2 16.6274 -2 10C-2 3.37258 3.37258 -2 10 -2V2C5.58172 2 2 5.58172 2 10C2 14.4183 5.58172 18 10 18V22ZM20 0V20V0Z"
fill="black"
mask="url(#path-1-inside-1_1009_5)"
/>
</Icon>
)
Original file line number Diff line number Diff line change
Expand Up @@ -7,35 +7,32 @@ import {
useRadioGroup,
UseRadioProps,
} from '@chakra-ui/react'
import { BackgroundType } from '@typebot.io/schemas'
import { ReactNode } from 'react'

type Props = {
backgroundType: BackgroundType
onBackgroundTypeChange: (type: BackgroundType) => void
type Props<T extends string> = {
options: (T | { value: T; label: ReactNode })[]
defaultValue: T
onSelect: (newValue: T) => void
}
export const BackgroundTypeRadioButtons = ({
backgroundType,
onBackgroundTypeChange,
}: Props) => {
const options = ['Color', 'Image', 'None']

export const RadioButtons = <T extends string>({
options,
defaultValue,
onSelect,
}: Props<T>) => {
const { getRootProps, getRadioProps } = useRadioGroup({
name: 'background-type',
defaultValue: backgroundType,
onChange: (nextVal: string) =>
onBackgroundTypeChange(nextVal as BackgroundType),
defaultValue,
onChange: onSelect,
})

const group = getRootProps()

return (
<HStack {...group}>
{options.map((value) => {
const radio = getRadioProps({ value })
{options.map((item) => {
const radio = getRadioProps({ value: parseValue(item) })
return (
<RadioCard key={value} {...radio}>
{value}
<RadioCard key={parseValue(item)} {...radio}>
{parseLabel(item)}
</RadioCard>
)
})}
Expand Down Expand Up @@ -76,3 +73,9 @@ export const RadioCard = (props: UseRadioProps & { children: ReactNode }) => {
</Box>
)
}

const parseValue = (item: string | { value: string; label: ReactNode }) =>
typeof item === 'string' ? item : item.value

const parseLabel = (item: string | { value: string; label: ReactNode }) =>
typeof item === 'string' ? item : item.label
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
import {
LargeRadiusIcon,
MediumRadiusIcon,
NoRadiusIcon,
} from '@/components/icons'
import { RadioButtons } from '@/components/inputs/RadioButtons'
import { Heading, Stack } from '@chakra-ui/react'
import {
AvatarProps,
Expand Down Expand Up @@ -59,6 +65,29 @@ export const ChatThemeSettings = ({
onHostBubblesChange={handleHostBubblesChange}
/>
</Stack>
<Stack borderWidth={1} rounded="md" p="4" spacing={4}>
<Heading fontSize="lg">Corners roundness</Heading>
<RadioButtons
options={[
{
label: <NoRadiusIcon />,
value: 'none',
},
{
label: <MediumRadiusIcon />,
value: 'medium',
},
{
label: <LargeRadiusIcon />,
value: 'large',
},
]}
defaultValue={chatTheme.roundness ?? 'medium'}
onSelect={(roundness) =>
onChatThemeChange({ ...chatTheme, roundness })
}
/>
</Stack>
<Stack borderWidth={1} rounded="md" p="4" spacing={4}>
<Heading fontSize="lg">User bubbles</Heading>
<GuestBubbles
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { RadioButtons } from '@/components/inputs/RadioButtons'
import { Stack, Text } from '@chakra-ui/react'
import { Background, BackgroundType } from '@typebot.io/schemas'
import React from 'react'
import { BackgroundContent } from './BackgroundContent'
import { BackgroundTypeRadioButtons } from './BackgroundTypeRadioButtons'

type Props = {
background?: Background
Expand All @@ -25,9 +25,14 @@ export const BackgroundSelector = ({
return (
<Stack spacing={4}>
<Text>Background</Text>
<BackgroundTypeRadioButtons
backgroundType={background?.type ?? defaultBackgroundType}
onBackgroundTypeChange={handleBackgroundTypeChange}
<RadioButtons
options={[
BackgroundType.COLOR,
BackgroundType.IMAGE,
BackgroundType.NONE,
]}
defaultValue={background?.type ?? defaultBackgroundType}
onSelect={handleBackgroundTypeChange}
/>
<BackgroundContent
background={background}
Expand Down
26 changes: 26 additions & 0 deletions apps/builder/src/features/theme/theme.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,32 @@ test.describe.parallel('Theme page', () => {

await expect(page.locator('.typebot-container img')).toBeHidden()

// Roundness
await expect(page.getByRole('button', { name: 'Go' })).toHaveCSS(
'border-radius',
'6px'
)
await page
.getByRole('region', { name: 'Chat' })
.getByRole('radiogroup')
.locator('div')
.first()
.click()
await expect(page.getByRole('button', { name: 'Go' })).toHaveCSS(
'border-radius',
'0px'
)
await page
.getByRole('region', { name: 'Chat' })
.getByRole('radiogroup')
.locator('div')
.nth(2)
.click()
await expect(page.getByRole('button', { name: 'Go' })).toHaveCSS(
'border-radius',
'20px'
)

// Host bubbles
await page.click(
'[data-testid="host-bubbles-theme"] >> [aria-label="Pick a color"] >> nth=0'
Expand Down
2 changes: 1 addition & 1 deletion packages/embeds/js/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@typebot.io/js",
"version": "0.0.28",
"version": "0.0.29",
"description": "Javascript library to display typebots on your website",
"type": "module",
"main": "dist/index.js",
Expand Down
25 changes: 20 additions & 5 deletions packages/embeds/js/src/assets/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
--typebot-header-bg-color: #ffffff;
--typebot-header-color: #303235;

--typebot-border-radius: 6px;

/* Phone input */
--PhoneInputCountryFlag-borderColor: transparent;
--PhoneInput-color--focus: transparent;
Expand Down Expand Up @@ -127,15 +129,11 @@ textarea {
'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
}

.custom-header {
color: var(--typebot-header-color);
background-color: var(--typebot-header-bg-color);
}

.typebot-button {
color: var(--typebot-button-color);
background-color: var(--typebot-button-bg-color);
border: 1px solid var(--typebot-button-bg-color);
border-radius: var(--typebot-border-radius);
}

.typebot-button.selectable {
Expand All @@ -151,17 +149,26 @@ textarea {
.typebot-host-bubble > .bubble-typing {
background-color: var(--typebot-host-bubble-bg-color);
border: var(--typebot-host-bubble-border);
border-radius: 6px;
}

.typebot-host-bubble img,
.typebot-host-bubble iframe,
.typebot-host-bubble video {
border-radius: var(--typebot-border-radius);
}

.typebot-guest-bubble {
color: var(--typebot-guest-bubble-color);
background-color: var(--typebot-guest-bubble-bg-color);
border-radius: 6px;
}

.typebot-input {
color: var(--typebot-input-color);
background-color: var(--typebot-input-bg-color);
box-shadow: 0 2px 6px -1px rgba(0, 0, 0, 0.1);
border-radius: var(--typebot-border-radius);
}

.typebot-input-error-message {
Expand Down Expand Up @@ -202,6 +209,7 @@ textarea {

.upload-progress-bar {
background-color: var(--typebot-button-bg-color);
border-radius: var(--typebot-border-radius);
}

.total-files-indicator {
Expand All @@ -221,15 +229,22 @@ textarea {
.secondary-button {
background-color: var(--typebot-host-bubble-bg-color);
color: var(--typebot-host-bubble-color);
border-radius: var(--typebot-border-radius);
}

.typebot-country-select {
color: var(--typebot-input-color);
background-color: var(--typebot-input-bg-color);
border-radius: var(--typebot-border-radius);
}

.typebot-date-input {
color-scheme: light;
color: var(--typebot-input-color);
background-color: var(--typebot-input-bg-color);
border-radius: var(--typebot-border-radius);
}

.typebot-popup-blocked-toast {
border-radius: var(--typebot-border-radius);
}
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ export const ConversationContainer = (props: Props) => {
return (
<div
ref={chatContainer}
class="overflow-y-scroll w-full min-h-full rounded px-3 pt-10 relative scrollable-container typebot-chat-view scroll-smooth"
class="overflow-y-scroll w-full min-h-full px-3 pt-10 relative scrollable-container typebot-chat-view scroll-smooth"
>
<For each={chatChunks()}>
{(chatChunk, index) => (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ type Props = {
export const PopupBlockedToast = (props: Props) => {
return (
<div
class="w-full max-w-xs p-4 text-gray-500 bg-white rounded-lg shadow flex flex-col gap-2"
class="w-full max-w-xs p-4 text-gray-500 bg-white shadow flex flex-col gap-2 typebot-popup-blocked-toast"
role="alert"
>
<span class="mb-1 text-sm font-semibold text-gray-900">
Expand All @@ -19,7 +19,7 @@ export const PopupBlockedToast = (props: Props) => {
<a
href={props.url}
target="_blank"
class="py-1 px-4 justify-center text-sm font-semibold rounded-md text-white focus:outline-none flex items-center disabled:opacity-50 disabled:cursor-not-allowed disabled:brightness-100 transition-all filter hover:brightness-90 active:brightness-75 typebot-button"
class="py-1 px-4 justify-center text-sm font-semibold text-white focus:outline-none flex items-center disabled:opacity-50 disabled:cursor-not-allowed disabled:brightness-100 transition-all filter hover:brightness-90 active:brightness-75 typebot-button"
rel="noreferrer"
onClick={() => props.onLinkClick()}
>
Expand Down
2 changes: 1 addition & 1 deletion packages/embeds/js/src/components/SendButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export const SendButton = (props: SendButtonProps) => {
disabled={props.isDisabled || props.isLoading}
{...props}
class={
'py-2 px-4 justify-center font-semibold rounded-md text-white focus:outline-none flex items-center disabled:opacity-50 disabled:cursor-not-allowed disabled:brightness-100 transition-all filter hover:brightness-90 active:brightness-75 typebot-button ' +
'py-2 px-4 justify-center font-semibold text-white focus:outline-none flex items-center disabled:opacity-50 disabled:cursor-not-allowed disabled:brightness-100 transition-all filter hover:brightness-90 active:brightness-75 typebot-button ' +
props.class
}
>
Expand Down
2 changes: 1 addition & 1 deletion packages/embeds/js/src/components/bubbles/GuestBubble.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export const GuestBubble = (props: Props) => (
style={{ 'margin-left': '50px' }}
>
<span
class="px-4 py-2 rounded-lg mr-2 whitespace-pre-wrap max-w-full typebot-guest-bubble"
class="px-4 py-2 mr-2 whitespace-pre-wrap max-w-full typebot-guest-bubble"
data-testid="guest-bubble"
>
{props.message}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export const LoadingBubble = () => (
<div class="flex mb-2 w-full items-center">
<div class={'flex relative items-start typebot-host-bubble'}>
<div
class="flex items-center absolute px-4 py-2 rounded-lg bubble-typing "
class="flex items-center absolute px-4 py-2 bubble-typing "
style={{
width: '64px',
height: '32px',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export const AudioBubble = (props: Props) => {
<div class="flex mb-2 w-full items-center">
<div class={'flex relative z-10 items-start typebot-host-bubble'}>
<div
class="flex items-center absolute px-4 py-2 rounded-lg bubble-typing z-10 "
class="flex items-center absolute px-4 py-2 bubble-typing z-10 "
style={{
width: isTyping() ? '64px' : '100%',
height: isTyping() ? '32px' : '100%',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export const EmbedBubble = (props: Props) => {
class={'flex relative z-10 items-start typebot-host-bubble w-full'}
>
<div
class="flex items-center absolute px-4 py-2 rounded-lg bubble-typing z-10 "
class="flex items-center absolute px-4 py-2 bubble-typing z-10 "
style={{
width: isTyping() ? '64px' : '100%',
height: isTyping() ? '32px' : '100%',
Expand All @@ -46,7 +46,7 @@ export const EmbedBubble = (props: Props) => {
id="embed-bubble-content"
src={props.content.url}
class={
'w-full z-20 p-4 text-fade-in rounded-2xl ' +
'w-full z-20 p-4 text-fade-in ' +
(isTyping() ? 'opacity-0' : 'opacity-100')
}
style={{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export const ImageBubble = (props: Props) => {
<div class="flex mb-2 w-full items-center">
<div class={'flex relative z-10 items-start typebot-host-bubble'}>
<div
class="flex items-center absolute px-4 py-2 rounded-lg bubble-typing z-10 "
class="flex items-center absolute px-4 py-2 bubble-typing z-10 "
style={{
width: isTyping() ? '64px' : '100%',
height: isTyping() ? '32px' : '100%',
Expand All @@ -56,7 +56,7 @@ export const ImageBubble = (props: Props) => {
ref={image}
src={props.url}
class={
'text-fade-in w-full rounded-md ' +
'text-fade-in w-full ' +
(isTyping() ? 'opacity-0' : 'opacity-100')
}
style={{
Expand Down
Loading

4 comments on commit 65d33e0

@vercel
Copy link

@vercel vercel bot commented on 65d33e0 Mar 22, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on 65d33e0 Mar 22, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

docs – ./apps/docs

docs.typebot.io
docs-git-main-typebot-io.vercel.app
docs-typebot-io.vercel.app

@vercel
Copy link

@vercel vercel bot commented on 65d33e0 Mar 22, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

viewer-v2 – ./apps/viewer

pant.maxbot.com.br
pantherview.cr8.ai
positivobra.com.br
rollingball.cr8.ai
survey.digienge.io
this-is-a-test.com
zap.techadviser.in
ai.digitaldaftar.in
bot.boston-voip.com
bot.cabinpromos.com
bot.digitalbled.com
bot.dsignagency.com
bot.eventhub.com.au
bot.jepierre.com.br
bot.leadgenpod.site
bium.gratirabbit.com
bot.ansuraniphone.my
bot.barrettamario.it
bot.cotemeuplano.com
bot.leadbooster.help
bot.mycompay.reviews
chat.hayurihijab.com
chatbee.agfunnel.com
click.sevenoways.com
connect.growthguy.in
forms.bonanza.design
hello.advergreen.com
kuiz.sistemniaga.com
menu.numero-primo.it
menukb.wpwakanda.com
offer.botscientis.us
sellmycarglasgow.com
talkbot.agfunnel.com
tenorioadvogados.com
uppity.wpwakanda.com
abutton.wpwakanda.com
acelera.maxbot.com.br
aidigitalmarketing.kr
bbutton.wpwakanda.com
bot.coachayongzul.com
bot.digitalpointer.id
bot.eikju.photography
bot.incusservices.com
bot.meuesocial.com.br
bot.mycompany.reviews
bot.outstandbrand.com
bot.ramonmatos.com.br
bot.robertohairlab.it
bot.sharemyreview.net
bot.truongnguyen.live
botz.cloudsiteapp.com
cdd.searchcube.com.sg
chat.missarkansas.org
chatbot.ownacademy.co
criar.somaperuzzo.com
homerun.wpwakanda.com
sbutton.wpwakanda.com
815639944.21000000.one
83720273.bouclidom.com
aplicacao.bmind.com.br
bot.seidinembroseanchetu.it
chat.semanalimpanome.com.br
chatbot.berbelanjabiz.trade
designguide.techyscouts.com
liveconvert2.kandalearn.com
presente.empresarias.com.mx
sell.sellthemotorhome.co.uk
anamnese.odontopavani.com.br
austin.channelautomation.com
bot.marketingplusmindset.com
bot.seidibergamoseanchetu.it
desabafe.sergiolimajr.com.br
download.venturemarketing.in
piazzatorre.barrettamario.it
type.cookieacademyonline.com
upload.atlasoutfittersk9.com
bot.brigadeirosemdrama.com.br
forms.escoladeautomacao.com.br
onboarding.libertydreamcare.ie
type.talitasouzamarques.com.br
agendamento.sergiolimajr.com.br
anamnese.clinicamegasjdr.com.br
bookings.littlepartymonkeys.com
bot.comercializadoraomicron.com
elevateyourmind.groovepages.com
viewer-v2-typebot-io.vercel.app
yourfeedback.comebackreward.com
bot.cabin-rentals-of-georgia.net
gerador.verificadordehospedes.com
personal-trainer.barrettamario.it
preagendamento.sergiolimajr.com.br
studiotecnicoimmobiliaremerelli.it
download.thailandmicespecialist.com
register.thailandmicespecialist.com
bot.studiotecnicoimmobiliaremerelli.it
pesquisa.escolamodacomproposito.com.br
anamnese.clinicaramosodontologia.com.br
chrome-os-inquiry-system.itschromeos.com
viewer-v2-git-main-typebot-io.vercel.app
main-menu-for-itschromeos.itschromeos.com

@vercel
Copy link

@vercel vercel bot commented on 65d33e0 Mar 22, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

builder-v2 – ./apps/builder

builder-v2-typebot-io.vercel.app
app.typebot.io
builder-v2-git-main-typebot-io.vercel.app

Please sign in to comment.