2
0

fix(engine): 🐛 Fix scrolling behavior and avatar position

This commit is contained in:
Baptiste Arnaud
2022-02-07 08:05:53 +01:00
parent 1f320c5d99
commit f4336b83cc
7 changed files with 31 additions and 17 deletions

View File

@ -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 {

View File

@ -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} />

View File

@ -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) {

View File

@ -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 (

View File

@ -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"
>

View File

@ -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
}
>

View File

@ -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>
)
}