Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

3156: Align Typing Indicator and hide on new message #3159

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

hannaseithe
Copy link
Contributor

Short Description

I aligned the Typing Indicator with the other messages' position & when a new message from Zammad comes in, the Indicator will be hidden.

Proposed Changes

  • the Typing Indicator is now aligned with the other messages' position
  • the Typing Indicator gets hidden when a new message from Zammad comes in
  • when the Typing Indicator appears we scroll into view

Side Effects

  • no side Effects that I am aware of

Testing

  • check that the Indicator is in the right position
  • check that the Indicator vanishes when a new message from Zammad comes in (not the First one)
  • check that the chat window scrolls all the way down when the Indicator appears

Resolved Issues

Fixes: #3156


@hannaseithe hannaseithe marked this pull request as ready for review March 19, 2025 09:10
Copy link
Contributor

@bahaaTuffaha bahaaTuffaha left a comment

Choose a reason for hiding this comment

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

It's working great.. but it needs a bit of cleaning up 🚀
Also I think it needs a release note 🙂

@@ -17,6 +17,7 @@ const InitialMessage = styled.div`

const TypingIndicatorWrapper = styled(Message)`
width: max-content;
margin-left: 33px;
Copy link
Contributor

@bahaaTuffaha bahaaTuffaha Mar 20, 2025

Choose a reason for hiding this comment

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

🔧 The robot icon is 24px + 8px gap = 32px
And keep in mind that we started to use a multiply of 4 for ui.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The robot icon width is 25px in my branch - is this a recent change?

"And keep in mind that we started to use a multiply of 4 for ui." What exactly does this mean?

Copy link
Contributor

@bahaaTuffaha bahaaTuffaha Mar 24, 2025

Choose a reason for hiding this comment

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

We have a new design coming for integreat you can check it out:
https://www.figma.com/design/o5p3ArtrrmOqG6lJggAQE5/%F0%9F%9F%A8-Designsystem-Integreat-(MUI)?node-id=2831-17369&p=f&t=2YiZzVRBygegXzei-0

Its better to use numbers for styling that is dividable by 4 like 32 or 16 for ex. to keep styling consistent.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So should I change the icon width to 24px then?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I’ve kept it at 33px for now. I think aligning to 'multiples of 4' makes sense once the new design is introduced and the CSS is updated consistently. Changing this now would introduce an inconsistency with the current icon size (25px) rather than improving it.

Copy link
Member

Choose a reason for hiding this comment

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

Since you didn't change this, it is optional. However, I agree with @bahaaTuffaha that we generally prefer to have multiples of 4. Obviously only makes sense if you change the icon size to 24 as well.

On another note however, I think setting a hardcoded width based on some value in some other file is usually not best practice and may break in the future. A better solution would perhaps be to use the whole ChatMessage component normally instead. Seems like that is not easily possible though since it requires a normal message model. So not sure what exactly to do here :/

At least at the moment this is broken on rtl layouts (e.g. arbabic) due to the use of margin-left:
image

const ChatConversation = ({ messages, hasError, className }: ChatConversationProps): ReactElement => {
const { t } = useTranslation('chat')
const [messagesCount, setMessagesCount] = useState(0)
const [typingIndicatorVisible, setTypingIndicatorVisible] = useState(false)
Copy link
Contributor

@bahaaTuffaha bahaaTuffaha Mar 20, 2025

Choose a reason for hiding this comment

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

🔧 Undo this line.

Comment on lines 65 to 77
useEffect(() => {
if (waitingForAnswer) {
setTypingIndicatorVisible(true)

const typingIndicatorTimeout = setTimeout(() => {
setTypingIndicatorVisible(false)
}, TYPING_INDICATOR_TIMEOUT)

return () => clearTimeout(typingIndicatorTimeout)
}
return () => undefined
}, [waitingForAnswer])

Copy link
Contributor

Choose a reason for hiding this comment

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

You can reuse the same scrolling functionality for both and adding an optional arg as callback that wont be called unless it finish changing the state.

 const scrollToBottom = async (beforeScroll?: () => void) => {
    if (beforeScroll) {
      await beforeScroll()
    }
    messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' })
  }

  useEffect(() => {
    if (messagesCount < messages.length) {
      scrollToBottom()
      setMessagesCount(messages.length)
    }
  }, [messages, messagesCount, typingIndicatorVisible])

  useEffect(() => {
    if (waitingForAnswer) {
      scrollToBottom(() => setTypingIndicatorVisible(true))
      const timeout = setTimeout(() => setTypingIndicatorVisible(false), 60000)
      return () => clearTimeout(timeout)
    }
    setTypingIndicatorVisible(false)
  }, [waitingForAnswer])

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This '() => setTypingIndicatorVisible(true)' is a synchronous function and to my understanding finishes when the state is changed (doesn't wait for rendering). I think the easiest solution is to have the useEffect for 'TypingIndicatorVisible' (because then it is already rendered)

Copy link
Contributor

Choose a reason for hiding this comment

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

🤔 hmm the function contents are synchronous but am waiting for that callback await beforeScroll() to be done before changing the scrolling ref...

Copy link
Contributor Author

@hannaseithe hannaseithe Mar 24, 2025

Choose a reason for hiding this comment

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

But if you await a synchronous function it just immediately executes it.
From what I understood:

  • With your version we catch it at the point of state-changed. (Edit: This is actually not true, its only after the state changes are queued)
  • With my version we are a little bit further down the line: state-changed > virtual DOM changed > actual DOM changed (although not yet rendered)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have decided to keep the useEffect() logic, in order to trigger the scrolling after the DOM was actually changed. But I have kept the scrolldown function as you suggested it.

@hannaseithe
Copy link
Contributor Author

Also I think it needs a release note 🙂

Where do I create a release note? I havent done that yet (btw this is not a new feature, but a bug fix)

@bahaaTuffaha
Copy link
Contributor

bahaaTuffaha commented Mar 24, 2025

Also I think it needs a release note 🙂

Where do I create a release note? I havent done that yet (btw this is not a new feature, but a bug fix)

There is a folder called release-notes copy the file ReleaseNoteTemplate.yml into unreleased folder and adjust what necessary... You can look at examples from before.

If the release note is unnecessary for this bug we can remove it 😄

@hannaseithe hannaseithe force-pushed the 3156-fix-chat-typing-indicator branch from 3baca01 to 7dbb9e1 Compare March 25, 2025 10:11
@@ -17,6 +17,7 @@ const InitialMessage = styled.div`

const TypingIndicatorWrapper = styled(Message)`
width: max-content;
margin-left: 33px;
Copy link
Member

Choose a reason for hiding this comment

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

Since you didn't change this, it is optional. However, I agree with @bahaaTuffaha that we generally prefer to have multiples of 4. Obviously only makes sense if you change the icon size to 24 as well.

On another note however, I think setting a hardcoded width based on some value in some other file is usually not best practice and may break in the future. A better solution would perhaps be to use the whole ChatMessage component normally instead. Seems like that is not easily possible though since it requires a normal message model. So not sure what exactly to do here :/

At least at the moment this is broken on rtl layouts (e.g. arbabic) due to the use of margin-left:
image

Comment on lines +59 to +62
const scrollToBottom = async (beforeScroll?: () => void | Promise<void>) => {
if (beforeScroll) {
await beforeScroll()
}
Copy link
Member

Choose a reason for hiding this comment

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

🔧 This is never actually used, is it?

Suggested change
const scrollToBottom = async (beforeScroll?: () => void | Promise<void>) => {
if (beforeScroll) {
await beforeScroll()
}
const scrollToBottom = () => {

Comment on lines +83 to +87
useEffect(() => {
if (typingIndicatorVisible) {
scrollToBottom()
}
}, [typingIndicatorVisible])
Copy link
Member

Choose a reason for hiding this comment

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

🤔 Why is this necessary?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Fix Chat Typing indicator
3 participants