Skip to content

Commit

Permalink
refactor: get rid of Simplebar (vanilla js based scrollbar) (#2900)
Browse files Browse the repository at this point in the history
This PR include this other one
[PR#2903](#2903)

## Work done so far
1. [Getting rid of `scrollbar` webchat property
customization](b8b676e):
We don't want to support this feature anymore. This was done before in
order to have "nice" styles in Internet Explorer and similar browsers.
As IE is not supported anymore, we can remove this.
2. [Having ids for relevant botonic
containers](79a2bf8):
In this way we can have a better way to access the values of these well
differentiated areas of the webchat.
3. [Ensuring elements within webchat are spaced
correctly](cd37e6f):
This is, spacing elements between in webchat for every container to push
the other siblings with same distances.
4. [Remove Simplebar in favour of a new component created by
us](e1a937c):
Simplebar was giving lots of headaches to us, so we can change it by
containers with the ids created in point 2.
5. [Fix replies container not
scrolling](72f3eeb)
6. [chatArea container to englobe messages list and replies
containers](7dcafa0)
7. [Recalculate chatarea size when iOS safari virtual keyboard is
shown](383ff18):
As we have modified the containers which where important to calculate
when the webchat has to be resized in iOS, we needed to adapt and update
a little bit this logic.

## Current state

As per the list described above, the functionality should be the same as
before. The important thing to notice here is that **WE DON'T RELY
ANYMORE** on simplebar selectors `'.simplebar-content'` and
`'.simplebar-content-wrapper'`, so bots using them should be adapted.

## Next steps
* Create reusable hooks to do calculations over DOM elements or use
[Resizer observer
API](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver) to
have the code up to date with new standards and good code practices.
* Remove related logic not needed anymore after removing simplebar
dependency (possibly tricky parts of the code related to ShadowDOM).

---------

Co-authored-by: Oriol Raventos <[email protected]>
  • Loading branch information
vanbasten17 and Iru89 authored Oct 3, 2024
1 parent 610976e commit 65ab8aa
Show file tree
Hide file tree
Showing 31 changed files with 554 additions and 456 deletions.
1 change: 0 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion packages/botonic-react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
"react-json-tree": "^0.15.0",
"react-router-dom": "^5.3.4",
"react-textarea-autosize": "^8.5.3",
"simplebar-react": "^2.4.3",
"styled-components": "^5.3.0",
"ua-parser-js": "^1.0.39",
"uuid": "^8.3.2"
Expand Down
18 changes: 8 additions & 10 deletions packages/botonic-react/src/components/carousel.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,14 @@ import RightArrow from '../assets/rightArrow.svg'
import { COLORS, WEBCHAT } from '../constants'
import { WebchatContext } from '../contexts'
import { resolveImage } from '../util/environment'
import { StyledScrollbar } from '../webchat/components/styled-scrollbar'
import { ButtonsDisabler } from './buttons-disabler'
import { Message } from './message'

const ScrollableCarousel = styled.div`
overscroll-behavior: contain;
-webkit-overflow-scrolling: touch;
`

const StyledCarousel = styled.div`
padding: 10px 0px;
display: flex;
Expand Down Expand Up @@ -62,10 +66,6 @@ const serialize = carouselProps => {
export const Carousel = props => {
const { getThemeProperty } = useContext(WebchatContext)
let content = props.children
const scrollbarOptions = {
...{ enable: true, autoHide: true },
...getThemeProperty(WEBCHAT.CUSTOM_PROPERTIES.scrollbar),
}
const [hasLeftArrow, setLeftArrow] = useState(false)
const [hasRightArrow, setRightArrow] = useState(true)
const carouselRef = useRef(null)
Expand All @@ -77,6 +77,7 @@ export const Carousel = props => {
WEBCHAT.CUSTOM_PROPERTIES.customCarouselRightArrow,
undefined
)
// TODO: Investigate why when set to false, scroll is enabled via dragging the bar but not hovering the carousel elements
const carouselArrowsEnabled = getThemeProperty(
WEBCHAT.CUSTOM_PROPERTIES.enableCarouselArrows,
true
Expand Down Expand Up @@ -150,18 +151,15 @@ export const Carousel = props => {

if (isBrowser()) {
content = (
<StyledScrollbar
scrollbar={scrollbarOptions}
autoHide={scrollbarOptions.autoHide}
>
<ScrollableCarousel>
<StyledCarousel
ref={carouselRef}
carouselArrowsEnabled={carouselArrowsEnabled}
>
<StyledItems>{carouselProps.children}</StyledItems>
{carouselArrowsEnabled && getArrows()}
</StyledCarousel>
</StyledScrollbar>
</ScrollableCarousel>
)
}

Expand Down
6 changes: 0 additions & 6 deletions packages/botonic-react/src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,10 @@ export const WEBCHAT = {
pointerEvents: 'none',
},
},
SELECTORS: {
SCROLLABLE_CONTENT: '#botonic-scrollable-content',
SIMPLEBAR_CONTENT: '.simplebar-content',
SIMPLEBAR_WRAPPER: '.simplebar-content-wrapper',
},
CUSTOM_PROPERTIES: {
// General
enableAnimations: 'animations.enable',
markdownStyle: 'markdownStyle',
scrollbar: 'scrollbar',
imagePreviewer: 'imagePreviewer',
// Mobile
mobileBreakpoint: 'mobileBreakpoint',
Expand Down
6 changes: 6 additions & 0 deletions packages/botonic-react/src/contexts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -100,4 +100,10 @@ export const WebchatContext = createContext<WebchatContextProps>({
trackEvent: async () => {
return
},
webchatRef: { current: null },
chatAreaRef: { current: null },
inputPanelRef: { current: null },
headerRef: { current: null },
scrollableMessagesListRef: { current: null },
repliesRef: { current: null },
})
57 changes: 6 additions & 51 deletions packages/botonic-react/src/index-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,51 +55,6 @@ export interface CustomMessageType {
customTypeName: string
}

// TODO: Reuse types to be reused in respective components
// export class WebchatApp {
// constructor(options: WebchatAppArgs)
// addBotMessage(message: WebchatMessage): void
// addBotText(text: string): void
// addUserMessage(message: WebchatMessage): void
// addUserPayload(payload: string): void
// addUserText(text: string): void
// clearMessages(): void
// close(): void
// closeCoverComponent(): void
// destroy(): void
// getComponent(
// host: HTMLElement,
// optionsAtRuntime?: WebchatAppArgs
// ): React.ForwardRefExoticComponent<any>
// getLastMessageUpdate(): string
// getMessages(): WebchatMessage[]
// getVisibility(): Promise<boolean>
// isWebchatVisible({ appId: string }): Promise<boolean>
// onCloseWebchat(args: any): void
// onInitWebchat(args: any): void
// onOpenWebchat(args: any): void
// onServiceEvent(event: Event): void
// onStateChange(args: OnStateChangeArgs): void
// onUserInput(args: OnUserInputArgs): Promise<void>
// open(): void
// openCoverComponent(): void
// render(dest?: HTMLElement, optionsAtRuntime?: WebchatAppArgs): void
// resendUnsentInputs(): Promise<void>
// resolveWebchatVisibility(optionsAtRuntime: {
// appId: string
// visibility: () => boolean
// }): Promise<boolean>
// setTyping(enable: boolean): void
// toggle(): void
// toggleCoverComponent(): void
// updateMessageInfo(msgId: string, messageInfo: MessageInfo): void
// updateLastMessageDate(date: string): void
// updateUser(user: Partial<CoreSessionUser>): void
// updateWebchatSettings(settings: WebchatSettingsProps): void
// renderCustomComponent(customComponent: React.ReactNode): void
// unmountCustomComponent(): void
// }

export interface WebchatArgs {
blockInputs?: BlockInputOption[]
coverComponent?: CoverComponentOptions
Expand Down Expand Up @@ -216,10 +171,10 @@ export interface WebchatContextProps {
updateWebchatDevSettings: (settings: WebchatSettingsProps) => void
webchatState: WebchatState
trackEvent: TrackEventFunction
webchatRef: React.MutableRefObject<HTMLDivElement | null>
chatAreaRef: React.MutableRefObject<HTMLDivElement | null>
inputPanelRef: React.MutableRefObject<HTMLDivElement | null>
headerRef: React.MutableRefObject<HTMLDivElement | null>
scrollableMessagesListRef: React.MutableRefObject<HTMLDivElement | null>
repliesRef: React.MutableRefObject<HTMLDivElement | null>
}

// export class DevApp extends WebchatApp {
// constructor(args: WebchatAppArgs)
// onUserInput(args: OnUserInputArgs): Promise<void>
// render(dest: HTMLElement, optionsAtRuntime: WebchatAppArgs): void
// }
37 changes: 2 additions & 35 deletions packages/botonic-react/src/util/dom.js
Original file line number Diff line number Diff line change
@@ -1,40 +1,7 @@
import { WEBCHAT } from '../constants'

export const getScrollableContent = webchatElement => {
return webchatElement.querySelector(WEBCHAT.SELECTORS.SCROLLABLE_CONTENT)
}

export const getScrollableArea = webchatElement => {
const getArea = area => {
const botonicScrollableContent = getScrollableContent(webchatElement)
const scrollableArea =
botonicScrollableContent && botonicScrollableContent.querySelector(area)
return scrollableArea
}
return {
full: getArea(WEBCHAT.SELECTORS.SIMPLEBAR_CONTENT),
visible: getArea(WEBCHAT.SELECTORS.SIMPLEBAR_WRAPPER),
}
}

export const scrollToBottom = ({
timeout = 200,
behavior = 'smooth',
host,
} = {}) => {
const webchatElement = getWebchatElement(host)
if (!webchatElement) return
const frame = getScrollableArea(webchatElement).visible
if (frame) {
setTimeout(
() => frame.scrollTo({ top: frame.scrollHeight, behavior: behavior }),
timeout
)
}
}
import { BotonicContainerId } from '../webchat/constants'

export const getWebchatElement = host =>
host && host.querySelector(`#${WEBCHAT.DEFAULTS.ID}`)
host && host.querySelector(`#${BotonicContainerId.Webchat}`)

// https://stackoverflow.com/questions/9457891/how-to-detect-if-domcontentloaded-was-fired
export const onDOMLoaded = callback => {
Expand Down
60 changes: 0 additions & 60 deletions packages/botonic-react/src/webchat/components/styled-scrollbar.jsx

This file was deleted.

This file was deleted.

9 changes: 9 additions & 0 deletions packages/botonic-react/src/webchat/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Convert to an enum when all the files using these values are migrated to ts{x}
export const BotonicContainerId = {
Webchat: 'botonic-webchat',
Header: 'botonic-header',
ChatArea: 'botonic-chat-area',
ScrollableMessagesList: 'botonic-scrollable-messages-list',
RepliesContainer: 'botonic-replies-container',
InputPanel: 'botonic-input-panel',
}
43 changes: 0 additions & 43 deletions packages/botonic-react/src/webchat/devices/device-adapter.js

This file was deleted.

Loading

0 comments on commit 65ab8aa

Please sign in to comment.