Skip to content

Commit

Permalink
refactor(feedback-modal): use Refs for DOM elements
Browse files Browse the repository at this point in the history
  • Loading branch information
RobsonOlv committed Jun 15, 2022
1 parent b20506a commit 1e2dfa3
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 35 deletions.
64 changes: 53 additions & 11 deletions src/components/feedback-modal/functions.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,31 @@
import { SxStyleProp } from '@vtex/brand-ui'
import { ModalProps } from '.'
import styles from './styles'

export const setModalPosition = (modalState: ModalProps): SxStyleProp => {
const { top, left, width } = document
.getElementsByClassName(
`feedback-button-${modalState.feedback ? 'positive' : 'negative'}`
)[0]
.getBoundingClientRect()
const modalWidth = 320,
modalHeight = 180
const modalLeft = ['initial', `${left - (modalWidth - width) / 2 + 8}px`]
const modalTop = ['initial', `${top - modalHeight}px`]
const modalWidth = 320,
modalHeight = 180

export const modalPositionStyle = (
chosenButtonRef: HTMLElement | undefined
): SxStyleProp => {
if (!chosenButtonRef) return false

const {
top: buttonTop,
bottom: buttonBottom,
left: buttonLeft,
width: buttonWidth,
} = chosenButtonRef.getBoundingClientRect()

const modalLeft = [
'initial',
`${buttonLeft - (modalWidth - buttonWidth) / 2 + 8}px`,
]
const modalTop = [
'initial',
buttonTop > modalHeight
? `${buttonTop - modalHeight}px`
: `${buttonBottom}px`,
]

const modalBox: SxStyleProp = {
...styles.box,
Expand All @@ -21,3 +35,31 @@ export const setModalPosition = (modalState: ModalProps): SxStyleProp => {
}
return modalBox
}

export const arrowDirectionStyle = (
chosenButtonRef: HTMLElement | undefined,
element: 'arrow' | 'card'
): SxStyleProp | false => {
if (!chosenButtonRef) return false

const { top: buttonTop } = chosenButtonRef.getBoundingClientRect()

if (buttonTop >= modalHeight) return false

if (element === 'arrow') {
const arrowDirection: SxStyleProp = {
...styles.arrow,
transform: 'rotate(180deg)',
top: '0',
bottom: 'initial',
}
return arrowDirection
}

const cardPosition: SxStyleProp = {
...styles.card,
mt: '14px',
}

return cardPosition
}
64 changes: 45 additions & 19 deletions src/components/feedback-modal/index.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,49 @@
import { Box, Button, Input, Text, Icon } from '@vtex/brand-ui'
import { Dispatch, SetStateAction, useEffect, useRef } from 'react'
import { Box, Button, Input, Text, Icon, IconProps } from '@vtex/brand-ui'
import {
Dispatch,
MutableRefObject,
SetStateAction,
useEffect,
useRef,
} from 'react'
import useClickOutside from 'utils/hooks/useClickOutside'

import { setModalPosition } from './functions'
import { arrowDirectionStyle, modalPositionStyle } from './functions'
import styles from './styles'
export interface ModalProps {
modalToggle: boolean
feedback?: boolean
}

const FeedBackModalArrow = (props: IconProps) => {
return (
<Icon
{...props}
width="20"
height="14"
viewBox="0 0 20 14"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
{' '}
<path
d="M10.8432 12.3275C10.4448 12.8914 9.60821 12.8914 9.20976 12.3275L0.500234 6.7935e-05L19.5527 6.56171e-05L10.8432 12.3275Z"
fill="white"
/>
</Icon>
)
}

const FeedBackModal = ({
modalState,
changeModalState,
changeFeedBack,
buttonChoosedRef,
}: {
modalState: ModalProps
changeModalState: Dispatch<SetStateAction<ModalProps>>
changeFeedBack: Dispatch<SetStateAction<boolean | undefined>>
buttonChoosedRef: MutableRefObject<HTMLElement | undefined>
}) => {
const cardRef = useRef<HTMLDivElement>()
const { body, documentElement } = document
Expand All @@ -41,8 +68,15 @@ const FeedBackModal = ({
useClickOutside(cardRef, changeModalState)
return (
<Box sx={styles.container}>
<Box ref={cardRef} sx={setModalPosition(modalState)}>
<Box sx={styles.card}>
<Box
ref={cardRef}
sx={modalPositionStyle(buttonChoosedRef.current) || styles.box}
>
<Box
sx={
arrowDirectionStyle(buttonChoosedRef.current, 'card') || styles.card
}
>
<Text>Leave a comment</Text>
<Input sx={styles.input} id="feedback-modal-input" label="" />
<Button
Expand All @@ -53,20 +87,12 @@ const FeedBackModal = ({
send feedback
</Button>
</Box>
<Icon
sx={styles.arrow}
width="20"
height="14"
viewBox="0 0 20 14"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
{' '}
<path
d="M10.8432 12.3275C10.4448 12.8914 9.60821 12.8914 9.20976 12.3275L0.500234 6.7935e-05L19.5527 6.56171e-05L10.8432 12.3275Z"
fill="white"
/>
</Icon>
<FeedBackModalArrow
sx={
arrowDirectionStyle(buttonChoosedRef.current, 'arrow') ||
styles.arrow
}
/>
</Box>
</Box>
)
Expand Down
13 changes: 8 additions & 5 deletions src/components/feedback-section/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Flex, Text, Link } from '@vtex/brand-ui'
import EditIcon from 'components/icons/edit-icon'
import LikeIcon from 'components/icons/like-icon'
import LikeSelectedIcon from 'components/icons/like-selected-icon'
import { useState } from 'react'
import { useRef, useState } from 'react'
import { getMessages } from 'utils/get-messages'
import { setButtonStyle } from './functions'
import FeedbackModal, { ModalProps } from 'components/feedback-modal'
Expand All @@ -16,6 +16,8 @@ const FeedbackSection = () => {
const [modalState, changeModalState] = useState<ModalProps>({
modalToggle: false,
})
const likeButton = useRef<HTMLElement>()
const dislikeButton = useRef<HTMLElement>()

const openModal = (choice: boolean) => {
changeModalState({
Expand All @@ -36,9 +38,9 @@ const FeedbackSection = () => {
</Text>
<Flex sx={styles.likeContainer}>
<Flex
className="feedback-button-positive"
ref={likeButton}
sx={setButtonStyle(feedback, true)}
onClick={() => openModal(true)}
onClick={feedback === undefined ? () => openModal(true) : null}
>
{feedback === undefined || !feedback ? (
<LikeIcon sx={styles.likeIcon} />
Expand All @@ -50,9 +52,9 @@ const FeedbackSection = () => {
</Text>
</Flex>
<Flex
className="feedback-button-negative"
ref={dislikeButton}
sx={setButtonStyle(feedback, false)}
onClick={() => openModal(false)}
onClick={feedback === undefined ? () => openModal(false) : null}
>
{feedback === undefined || feedback ? (
<LikeIcon sx={styles.dislikeIcon} />
Expand All @@ -78,6 +80,7 @@ const FeedbackSection = () => {
changeFeedBack={changeFeedback}
changeModalState={changeModalState}
modalState={modalState}
buttonChoosedRef={modalState.feedback ? likeButton : dislikeButton}
/>
) : null}
</Flex>
Expand Down

0 comments on commit 1e2dfa3

Please sign in to comment.