Skip to content

Commit

Permalink
[C-2908 C-2744] fix desktop follow button (#3816)
Browse files Browse the repository at this point in the history
  • Loading branch information
dylanjeffers authored Jul 28, 2023
1 parent c0679c3 commit ccc32ce
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 108 deletions.
192 changes: 100 additions & 92 deletions packages/web/src/components/follow-button/FollowButton.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useState, useCallback, useEffect } from 'react'
import { useState, useCallback, useEffect, forwardRef, MouseEvent } from 'react'

import {
Button,
Expand Down Expand Up @@ -38,97 +38,105 @@ const defaultMessages: FollowMessages = {
unfollow: 'Unfollow'
}

export const FollowButton: React.FC<FollowButtonProps> = ({
color,
className,
following = false,
onUnfollow,
onFollow,
isDisabled,
messages = defaultMessages,
stopPropagation,
showIcon = true,
size = 'medium',
invertedColor = false,
...buttonProps
}) => {
const [isHovering, setIsHovering] = useState(false)
const [isHoveringClicked, setIsHoveringClicked] = useState(false)

const onMouseEnter = useCallback(() => {
setIsHovering(true)
}, [setIsHovering])
const onMouseLeave = useCallback(() => {
setIsHovering(false)
}, [setIsHovering])

const style = {
[styles.noIcon]: !showIcon,
[styles.full]: size === 'full',
[styles.medium]: size === 'medium',
[styles.small]: size === 'small'
}
export const FollowButton = forwardRef<HTMLButtonElement, FollowButtonProps>(
function FollowButton(props, ref) {
const {
color,
className,
following = false,
onUnfollow,
onFollow,
isDisabled,
messages = defaultMessages,
stopPropagation,
showIcon = true,
size = 'medium',
invertedColor = false,
...buttonProps
} = props
const [isHovering, setIsHovering] = useState(false)
const [isHoveringClicked, setIsHoveringClicked] = useState(false)

const onClick = useCallback(
(e: React.MouseEvent<HTMLButtonElement>) => {
if (following) {
onUnfollow?.()
} else {
onFollow?.()
}
setIsHoveringClicked(true)
if (stopPropagation) {
e.stopPropagation()
e.nativeEvent.stopImmediatePropagation()
}
},
[following, onUnfollow, onFollow, setIsHoveringClicked, stopPropagation]
)

useEffect(() => {
if (!isHovering && isHoveringClicked) setIsHoveringClicked(false)
}, [isHovering, isHoveringClicked, setIsHoveringClicked])

let buttonType
if (color) {
buttonType = ButtonType.PRIMARY
} else {
buttonType =
!following && !isHovering && !isHoveringClicked && !invertedColor
? ButtonType.SECONDARY
: ButtonType.PRIMARY_ALT
}
const handleMouseEnter = useCallback(() => {
setIsHovering(true)
}, [setIsHovering])

let icon
let text
if (!following && !isHoveringClicked) {
icon = <IconFollow width={18} height={18} />
text = messages.follow
} else if (!following && isHoveringClicked) {
icon = <IconFollowing width={18} height={18} />
text = messages.following
} else {
icon = <IconUnfollow width={18} height={18} />
text = messages.unfollow
}
const handleMouseLeave = useCallback(() => {
setIsHovering(false)
}, [setIsHovering])

if (!showIcon) icon = null

return (
<Button
{...buttonProps}
color={color}
className={cn(styles.followButton, className, style)}
textClassName={styles.followButtonText}
iconClassName={styles.followButtonIcon}
type={buttonType}
onClick={onClick}
disabled={isDisabled}
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
leftIcon={icon}
size={ButtonSize.SMALL}
text={text}
/>
)
}
const style = {
[styles.noIcon]: !showIcon,
[styles.full]: size === 'full',
[styles.medium]: size === 'medium',
[styles.small]: size === 'small'
}

const handleClick = useCallback(
(e: MouseEvent<HTMLButtonElement>) => {
if (following) {
onUnfollow?.()
} else {
onFollow?.()
}
setIsHoveringClicked(true)
if (stopPropagation) {
e.stopPropagation()
e.nativeEvent.stopImmediatePropagation()
}
},
[following, onUnfollow, onFollow, setIsHoveringClicked, stopPropagation]
)

useEffect(() => {
if (!isHovering && isHoveringClicked) setIsHoveringClicked(false)
}, [isHovering, isHoveringClicked, setIsHoveringClicked])

const isFollowing = following || (!following && isHoveringClicked)

let buttonType
if (color) {
buttonType = ButtonType.PRIMARY
} else {
buttonType =
!isFollowing && !invertedColor
? ButtonType.SECONDARY
: ButtonType.PRIMARY_ALT
}

let icon
let text

if (!following && !isHoveringClicked) {
icon = <IconFollow width={18} height={18} />
text = messages.follow
} else if (isFollowing && !isHovering) {
icon = <IconFollowing width={18} height={18} />
text = messages.following
} else if (isFollowing && isHovering) {
icon = <IconUnfollow width={18} height={18} />
text = messages.unfollow
}

if (!showIcon) icon = null

return (
<Button
ref={ref}
{...buttonProps}
color={color}
className={cn(styles.followButton, className, style)}
textClassName={styles.followButtonText}
iconClassName={styles.followButtonIcon}
type={buttonType}
onClick={handleClick}
disabled={isDisabled}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
leftIcon={icon}
size={ButtonSize.SMALL}
text={text}
/>
)
}
)
4 changes: 4 additions & 0 deletions packages/web/src/components/stat-banner/StatBanner.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@

.statButton {
text-transform: uppercase;
/* Specific value to ensure the button width doesn't change when variants
* and text changes
*/
width: 142px;
}

.iconButton svg {
Expand Down
31 changes: 15 additions & 16 deletions packages/web/src/components/stat-banner/StatBanner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ export const StatBanner = (props: StatsBannerProps) => {
onToggleSubscribe
} = props
let buttons = null
const followButtonRef = useRef<HTMLDivElement>(null)
const followButtonRef = useRef<HTMLButtonElement>(null)

const { isEnabled: isChatEnabled } = useFlag(FeatureFlags.CHAT_ENABLED)

Expand Down Expand Up @@ -247,21 +247,20 @@ export const StatBanner = (props: StatsBannerProps) => {
onToggleSubscribe={onToggleSubscribe}
/>
) : null}
<div ref={followButtonRef}>
<FollowButton
following={following}
onFollow={onFollow}
onUnfollow={onUnfollow}
widthToHideText={BUTTON_COLLAPSE_WIDTHS.second}
className={styles.statButton}
/>
<ArtistRecommendationsPopup
anchorRef={followButtonRef}
artistId={profileId!}
isVisible={areArtistRecommendationsVisible}
onClose={onCloseArtistRecommendations!}
/>
</div>
<FollowButton
ref={followButtonRef}
following={following}
onFollow={onFollow}
onUnfollow={onUnfollow}
widthToHideText={BUTTON_COLLAPSE_WIDTHS.second}
className={styles.statButton}
/>
<ArtistRecommendationsPopup
anchorRef={followButtonRef}
artistId={profileId!}
isVisible={areArtistRecommendationsVisible}
onClose={onCloseArtistRecommendations!}
/>
</div>
</>
)
Expand Down

0 comments on commit ccc32ce

Please sign in to comment.