@ -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;
|
||||
@ -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 {
|
||||
@ -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 {
|
||||
@ -202,6 +209,7 @@ textarea {
|
||||
|
||||
.upload-progress-bar {
|
||||
background-color: var(--typebot-button-bg-color);
|
||||
border-radius: var(--typebot-border-radius);
|
||||
}
|
||||
|
||||
.total-files-indicator {
|
||||
@ -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);
|
||||
}
|
||||
|
@ -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) => (
|
||||
|
@ -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">
|
||||
@ -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()}
|
||||
>
|
||||
|
@ -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
|
||||
}
|
||||
>
|
||||
|
@ -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}
|
||||
|
@ -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',
|
||||
|
@ -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%',
|
||||
|
@ -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%',
|
||||
@ -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={{
|
||||
|
@ -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%',
|
||||
@ -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={{
|
||||
|
@ -49,9 +49,9 @@ export const TextBubble = (props: Props) => {
|
||||
return (
|
||||
<div class="flex flex-col animate-fade-in">
|
||||
<div class="flex mb-2 w-full items-center">
|
||||
<div class={'flex relative items-start typebot-host-bubble'}>
|
||||
<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: isTyping() ? '64px' : '100%',
|
||||
height: isTyping() ? '32px' : '100%',
|
||||
|
@ -36,7 +36,7 @@ export const VideoBubble = (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%',
|
||||
@ -68,7 +68,7 @@ const VideoContent = (props: VideoContentProps) => {
|
||||
<video
|
||||
controls
|
||||
class={
|
||||
'p-4 focus:outline-none w-full z-10 text-fade-in rounded-md ' +
|
||||
'p-4 focus:outline-none w-full z-10 text-fade-in ' +
|
||||
(props.isTyping ? 'opacity-0' : 'opacity-100')
|
||||
}
|
||||
style={{
|
||||
@ -97,7 +97,7 @@ const VideoContent = (props: VideoContentProps) => {
|
||||
: 'https://www.youtube.com/embed'
|
||||
}/${props.content.id}`}
|
||||
class={
|
||||
'w-full p-4 text-fade-in z-10 rounded-md ' +
|
||||
'w-full p-4 text-fade-in z-10 ' +
|
||||
(props.isTyping ? 'opacity-0' : 'opacity-100')
|
||||
}
|
||||
height={props.isTyping ? '32px' : '200px'}
|
||||
|
@ -49,7 +49,7 @@ export const ChoiceForm = (props: Props) => {
|
||||
type="button"
|
||||
on:click={() => handleClick(index())}
|
||||
class={
|
||||
'py-2 px-4 text-left font-semibold rounded-md transition-all filter hover:brightness-90 active:brightness-75 duration-100 focus:outline-none typebot-button ' +
|
||||
'py-2 px-4 text-left font-semibold transition-all filter hover:brightness-90 active:brightness-75 duration-100 focus:outline-none typebot-button ' +
|
||||
(selectedIndices().some(
|
||||
(selectedIndex) => selectedIndex === index()
|
||||
) || !props.block.options?.isMultipleChoice
|
||||
|
@ -19,7 +19,7 @@ export const DateForm = (props: Props) => {
|
||||
<div class="flex flex-col">
|
||||
<div class="flex items-center">
|
||||
<form
|
||||
class={'flex justify-between rounded-lg typebot-input pr-2 items-end'}
|
||||
class={'flex justify-between typebot-input pr-2 items-end'}
|
||||
onSubmit={(e) => {
|
||||
if (inputValues().from === '' && inputValues().to === '') return
|
||||
e.preventDefault()
|
||||
|
@ -34,9 +34,7 @@ export const EmailInput = (props: Props) => {
|
||||
|
||||
return (
|
||||
<div
|
||||
class={
|
||||
'flex items-end justify-between rounded-lg pr-2 typebot-input w-full'
|
||||
}
|
||||
class={'flex items-end justify-between pr-2 typebot-input w-full'}
|
||||
data-testid="input"
|
||||
style={{
|
||||
'max-width': '350px',
|
||||
|
@ -116,7 +116,7 @@ export const FileUploadForm = (props: Props) => {
|
||||
<label
|
||||
for="dropzone-file"
|
||||
class={
|
||||
'typebot-upload-input py-6 flex flex-col justify-center items-center w-full bg-gray-50 rounded-lg border-2 border-gray-300 border-dashed cursor-pointer hover:bg-gray-100 px-8 mb-2 ' +
|
||||
'typebot-upload-input py-6 flex flex-col justify-center items-center w-full bg-gray-50 border-2 border-gray-300 border-dashed cursor-pointer hover:bg-gray-100 px-8 mb-2 ' +
|
||||
(isDraggingOver() ? 'dragging-over' : '')
|
||||
}
|
||||
onDragOver={handleDragOver}
|
||||
@ -181,7 +181,7 @@ export const FileUploadForm = (props: Props) => {
|
||||
<div class="flex justify-end">
|
||||
<button
|
||||
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 '
|
||||
}
|
||||
on:click={() =>
|
||||
props.onSkip(
|
||||
@ -207,7 +207,7 @@ export const FileUploadForm = (props: Props) => {
|
||||
<Show when={selectedFiles().length}>
|
||||
<button
|
||||
class={
|
||||
'secondary-button 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 mr-2'
|
||||
'secondary-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 mr-2'
|
||||
}
|
||||
on:click={clearFiles}
|
||||
>
|
||||
|
@ -34,9 +34,7 @@ export const NumberInput = (props: NumberInputProps) => {
|
||||
|
||||
return (
|
||||
<div
|
||||
class={
|
||||
'flex items-end justify-between rounded-lg pr-2 typebot-input w-full'
|
||||
}
|
||||
class={'flex items-end justify-between pr-2 typebot-input w-full'}
|
||||
data-testid="input"
|
||||
style={{
|
||||
'max-width': '350px',
|
||||
|
@ -77,7 +77,7 @@ export const StripePaymentForm = (props: Props) => {
|
||||
<form
|
||||
id="payment-form"
|
||||
onSubmit={handleSubmit}
|
||||
class="flex flex-col rounded-lg p-4 typebot-input w-full items-center"
|
||||
class="flex flex-col p-4 typebot-input w-full items-center"
|
||||
>
|
||||
<slot name={slotName} ref={paymentElementSlot} />
|
||||
<Show when={isMounted()}>
|
||||
|
@ -91,7 +91,7 @@ export const PhoneInput = (props: PhoneInputProps) => {
|
||||
|
||||
return (
|
||||
<div
|
||||
class={'flex items-end justify-between rounded-lg pr-2 typebot-input'}
|
||||
class={'flex items-end justify-between pr-2 typebot-input'}
|
||||
data-testid="input"
|
||||
style={{
|
||||
'max-width': '400px',
|
||||
@ -99,7 +99,7 @@ export const PhoneInput = (props: PhoneInputProps) => {
|
||||
onKeyDown={submitWhenEnter}
|
||||
>
|
||||
<div class="flex">
|
||||
<div class="relative typebot-country-select flex justify-center items-center rounded-md">
|
||||
<div class="relative typebot-country-select flex justify-center items-center">
|
||||
<div class="pl-2 pr-1 flex items-center gap-2">
|
||||
<span>
|
||||
{
|
||||
|
@ -89,7 +89,7 @@ const RatingButton = (props: RatingButtonProps) => {
|
||||
props.onClick(props.idx)
|
||||
}}
|
||||
class={
|
||||
'py-2 px-4 mr-2 mb-2 text-left font-semibold rounded-md transition-all filter hover:brightness-90 active:brightness-75 duration-100 focus:outline-none typebot-button ' +
|
||||
'py-2 px-4 mr-2 mb-2 text-left font-semibold transition-all filter hover:brightness-90 active:brightness-75 duration-100 focus:outline-none typebot-button ' +
|
||||
(props.isOneClickSubmitEnabled ||
|
||||
(isDefined(props.rating) && props.idx <= props.rating)
|
||||
? ''
|
||||
|
@ -35,9 +35,7 @@ export const TextInput = (props: Props) => {
|
||||
|
||||
return (
|
||||
<div
|
||||
class={
|
||||
'flex items-end justify-between rounded-lg pr-2 typebot-input w-full'
|
||||
}
|
||||
class={'flex items-end justify-between pr-2 typebot-input w-full'}
|
||||
data-testid="input"
|
||||
style={{
|
||||
'max-width': props.block.options.isLong ? undefined : '350px',
|
||||
|
@ -40,9 +40,7 @@ export const UrlInput = (props: Props) => {
|
||||
|
||||
return (
|
||||
<div
|
||||
class={
|
||||
'flex items-end justify-between rounded-lg pr-2 typebot-input w-full'
|
||||
}
|
||||
class={'flex items-end justify-between pr-2 typebot-input w-full'}
|
||||
data-testid="input"
|
||||
style={{
|
||||
'max-width': '350px',
|
||||
|
@ -59,11 +59,12 @@ const setChatTheme = (
|
||||
chatTheme: ChatTheme,
|
||||
documentStyle: CSSStyleDeclaration
|
||||
) => {
|
||||
const { hostBubbles, guestBubbles, buttons, inputs } = chatTheme
|
||||
const { hostBubbles, guestBubbles, buttons, inputs, roundness } = chatTheme
|
||||
if (hostBubbles) setHostBubbles(hostBubbles, documentStyle)
|
||||
if (guestBubbles) setGuestBubbles(guestBubbles, documentStyle)
|
||||
if (buttons) setButtons(buttons, documentStyle)
|
||||
if (inputs) setInputs(inputs, documentStyle)
|
||||
if (roundness) setRoundness(roundness, documentStyle)
|
||||
}
|
||||
|
||||
const setHostBubbles = (
|
||||
@ -151,3 +152,20 @@ const parseBackgroundValue = ({ type, content }: Background) => {
|
||||
return `url(${content})`
|
||||
}
|
||||
}
|
||||
|
||||
const setRoundness = (
|
||||
roundness: NonNullable<ChatTheme['roundness']>,
|
||||
documentStyle: CSSStyleDeclaration
|
||||
) => {
|
||||
switch (roundness) {
|
||||
case 'none':
|
||||
documentStyle.setProperty('--typebot-border-radius', '0')
|
||||
break
|
||||
case 'medium':
|
||||
documentStyle.setProperty('--typebot-border-radius', '6px')
|
||||
break
|
||||
case 'large':
|
||||
documentStyle.setProperty('--typebot-border-radius', '20px')
|
||||
break
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user