fix(engine): 🐛 Fix scrolling behavior and avatar position
This commit is contained in:
@ -154,6 +154,13 @@ textarea {
|
||||
.typebot-button {
|
||||
color: var(--typebot-button-color);
|
||||
background-color: var(--typebot-button-bg-color);
|
||||
border: 1px solid var(--typebot-button-bg-color);
|
||||
}
|
||||
|
||||
.typebot-button.selectable {
|
||||
color: var(--typebot-host-bubble-color);
|
||||
background-color: var(--typebot-host-bubble-bg-color);
|
||||
border: 1px solid var(--typebot-button-bg-color);
|
||||
}
|
||||
|
||||
.typebot-host-bubble {
|
||||
|
@ -38,10 +38,10 @@ export const AvatarSideContainer = () => {
|
||||
unmountOnExit
|
||||
>
|
||||
<div
|
||||
className="fixed w-6 h-6 xs:w-10 xs:h-10 mb-4 xs:mb-2 flex items-center top-0"
|
||||
className="absolute w-6 h-6 xs:w-10 xs:h-10 mb-4 xs:mb-2 flex items-center top-0"
|
||||
style={{
|
||||
top: `calc(${topOffset}px - ${marginBottom}px)`,
|
||||
transition: 'top 500ms ease-out',
|
||||
transition: 'top 350ms ease-out',
|
||||
}}
|
||||
>
|
||||
<HostAvatar typebotName={typebot.name} />
|
||||
|
@ -1,5 +1,4 @@
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { animateScroll as scroll } from 'react-scroll'
|
||||
import { TransitionGroup, CSSTransition } from 'react-transition-group'
|
||||
import { ChatStep } from './ChatStep'
|
||||
import { AvatarSideContainer } from './AvatarSideContainer'
|
||||
@ -20,6 +19,7 @@ type ChatBlockProps = {
|
||||
steps: PublicStep[]
|
||||
startStepIndex: number
|
||||
blockIndex: number
|
||||
onScroll: () => void
|
||||
onBlockEnd: (edgeId?: string) => void
|
||||
}
|
||||
|
||||
@ -27,6 +27,7 @@ export const ChatBlock = ({
|
||||
steps,
|
||||
startStepIndex,
|
||||
blockIndex,
|
||||
onScroll,
|
||||
onBlockEnd,
|
||||
}: ChatBlockProps) => {
|
||||
const { typebot, updateVariableValue } = useTypebot()
|
||||
@ -41,7 +42,7 @@ export const ChatBlock = ({
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
autoScrollToBottom()
|
||||
onScroll()
|
||||
onNewStepDisplayed()
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [displayedSteps])
|
||||
@ -69,13 +70,6 @@ export const ChatBlock = ({
|
||||
}
|
||||
}
|
||||
|
||||
const autoScrollToBottom = () => {
|
||||
scroll.scrollToBottom({
|
||||
duration: 500,
|
||||
containerId: 'scrollable-container',
|
||||
})
|
||||
}
|
||||
|
||||
const displayNextStep = (answerContent?: string) => {
|
||||
const currentStep = [...displayedSteps].pop()
|
||||
if (currentStep) {
|
||||
|
@ -55,7 +55,9 @@ export const TextBubble = ({ step, onTransitionEnd }: Props) => {
|
||||
const sendAvatarOffset = () => {
|
||||
if (!messageContainer.current) return
|
||||
const containerDimensions = messageContainer.current.getBoundingClientRect()
|
||||
updateLastAvatarOffset(containerDimensions.top + containerDimensions.height)
|
||||
updateLastAvatarOffset(
|
||||
messageContainer.current.offsetTop + containerDimensions.height
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -44,8 +44,8 @@ export const ChoiceForm = ({ step, onSubmit }: ChoiceFormProps) => {
|
||||
className={
|
||||
'py-2 px-4 font-semibold rounded-md transition-all filter hover:brightness-90 active:brightness-75 duration-100 focus:outline-none mr-2 mb-2 typebot-button ' +
|
||||
(selectedIndices.includes(idx) || !step.options?.isMultipleChoice
|
||||
? 'active'
|
||||
: '')
|
||||
? ''
|
||||
: 'selectable')
|
||||
}
|
||||
data-testid="button"
|
||||
>
|
||||
|
@ -17,7 +17,7 @@ export const SendButton = ({
|
||||
disabled={isDisabled}
|
||||
{...props}
|
||||
className={
|
||||
'py-2 px-4 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 active ' +
|
||||
'py-2 px-4 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 ' +
|
||||
props.className
|
||||
}
|
||||
>
|
||||
|
@ -7,6 +7,7 @@ import { useAnswers } from '../contexts/AnswersContext'
|
||||
import { deepEqual } from 'fast-equals'
|
||||
import { Answer, Edge, PublicBlock, PublicTypebot } from 'models'
|
||||
import { byId } from 'utils'
|
||||
import { animateScroll as scroll } from 'react-scroll'
|
||||
|
||||
type Props = {
|
||||
typebot: PublicTypebot
|
||||
@ -27,6 +28,7 @@ export const ConversationContainer = ({
|
||||
const [localAnswer, setLocalAnswer] = useState<Answer | undefined>()
|
||||
const { answers } = useAnswers()
|
||||
const bottomAnchor = useRef<HTMLDivElement | null>(null)
|
||||
const scrollableContainer = useRef<HTMLDivElement | null>(null)
|
||||
|
||||
const displayNextBlock = (edgeId?: string) => {
|
||||
const nextEdge = typebot.edges.find(byId(edgeId))
|
||||
@ -60,10 +62,18 @@ export const ConversationContainer = ({
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [answers])
|
||||
|
||||
const autoScrollToBottom = () => {
|
||||
if (!scrollableContainer.current) return
|
||||
scroll.scrollToBottom({
|
||||
duration: 500,
|
||||
container: scrollableContainer.current,
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={scrollableContainer}
|
||||
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"
|
||||
id="scrollable-container"
|
||||
>
|
||||
{displayedBlocks.map((displayedBlock, idx) => (
|
||||
<ChatBlock
|
||||
@ -71,11 +81,12 @@ export const ConversationContainer = ({
|
||||
steps={displayedBlock.block.steps}
|
||||
startStepIndex={displayedBlock.startStepIndex}
|
||||
blockIndex={idx}
|
||||
onScroll={autoScrollToBottom}
|
||||
onBlockEnd={displayNextBlock}
|
||||
/>
|
||||
))}
|
||||
{/* We use a block to simulate padding because it makes iOS scroll flicker */}
|
||||
<div className="w-full" ref={bottomAnchor} />
|
||||
<div className="w-full h-32" ref={bottomAnchor} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
Reference in New Issue
Block a user