From 7e17772c142e00c1c0959ce4c7cb281a1b848bbc Mon Sep 17 00:00:00 2001 From: Justin Date: Wed, 23 Mar 2022 08:40:21 -0400 Subject: [PATCH] Dynamically truncate the Account's name/username in hidden content --- app/soapbox/components/account.tsx | 30 ++++++++++--------- app/soapbox/components/ui/hstack/hstack.tsx | 1 + .../ui/components/profile-dropdown.tsx | 2 +- app/soapbox/hooks/index.ts | 1 + app/soapbox/hooks/useOnScreen.ts | 19 ++++++++++++ 5 files changed, 38 insertions(+), 15 deletions(-) create mode 100644 app/soapbox/hooks/useOnScreen.ts diff --git a/app/soapbox/components/account.tsx b/app/soapbox/components/account.tsx index 47dc5d769..cc4efe3fb 100644 --- a/app/soapbox/components/account.tsx +++ b/app/soapbox/components/account.tsx @@ -4,7 +4,7 @@ import { Link } from 'react-router-dom'; import HoverRefWrapper from 'soapbox/components/hover_ref_wrapper'; import VerificationBadge from 'soapbox/components/verification_badge'; import ActionButton from 'soapbox/features/ui/components/action_button'; -import { useAppSelector } from 'soapbox/hooks'; +import { useAppSelector, useOnScreen } from 'soapbox/hooks'; import { getAcct } from 'soapbox/utils/accounts'; import { displayFqn } from 'soapbox/utils/state'; @@ -52,8 +52,9 @@ const Account = ({ timestampUrl, withRelationship = true, }: IAccount) => { - const overflowRef = React.useRef(null); - const actionRef = React.useRef(null); + const overflowRef = React.useRef(null); + const actionRef = React.useRef(null); + const isOnScreen = useOnScreen(overflowRef); const [style, setStyle] = React.useState({ visibility: 'hidden' }); @@ -93,18 +94,19 @@ const Account = ({ }; React.useEffect(() => { - const style: React.CSSProperties = {}; + if (isOnScreen) { + const style: React.CSSProperties = {}; + const actionWidth = actionRef.current?.clientWidth; - const actionWidth = actionRef.current?.clientWidth; + if (overflowRef.current) { + style.maxWidth = overflowRef.current.clientWidth - 30 - avatarSize - actionWidth; + } else { + style.visibility = 'hidden'; + } - if (overflowRef.current) { - style.maxWidth = overflowRef.current.clientWidth - 30 - avatarSize - actionWidth; - } else { - style.visibility = 'hidden'; + setStyle(style); } - - setStyle(style); - }, [overflowRef, actionRef]); + }, [isOnScreen, overflowRef, actionRef]); if (!account) { return null; @@ -161,8 +163,8 @@ const Account = ({ - - @{username} + + @{username} {(timestamp) ? ( <> diff --git a/app/soapbox/components/ui/hstack/hstack.tsx b/app/soapbox/components/ui/hstack/hstack.tsx index 224a322b5..d97697670 100644 --- a/app/soapbox/components/ui/hstack/hstack.tsx +++ b/app/soapbox/components/ui/hstack/hstack.tsx @@ -29,6 +29,7 @@ interface IHStack { justifyContent?: 'between' | 'center', space?: 0.5 | 1 | 1.5 | 2 | 3 | 4 | 6, grow?: boolean, + style?: React.CSSProperties } const HStack: React.FC = (props) => { diff --git a/app/soapbox/features/ui/components/profile-dropdown.tsx b/app/soapbox/features/ui/components/profile-dropdown.tsx index 43f31cfa3..7ff98ea1a 100644 --- a/app/soapbox/features/ui/components/profile-dropdown.tsx +++ b/app/soapbox/features/ui/components/profile-dropdown.tsx @@ -116,7 +116,7 @@ const ProfileDropdown: React.FC = ({ account, children }) => { const itemProps = menuItem.action ? { onSelect: menuItem.action } : { to: menuItem.to, as: Link }; return ( - + {menuItem.text} ); diff --git a/app/soapbox/hooks/index.ts b/app/soapbox/hooks/index.ts index 88f47b434..9fe270dd4 100644 --- a/app/soapbox/hooks/index.ts +++ b/app/soapbox/hooks/index.ts @@ -1 +1,2 @@ export { useAppSelector } from './useAppSelector'; +export { useOnScreen } from './useOnScreen'; diff --git a/app/soapbox/hooks/useOnScreen.ts b/app/soapbox/hooks/useOnScreen.ts new file mode 100644 index 000000000..1ae207326 --- /dev/null +++ b/app/soapbox/hooks/useOnScreen.ts @@ -0,0 +1,19 @@ +import * as React from 'react'; + +export const useOnScreen = (ref: React.MutableRefObject) => { + const [isIntersecting, setIntersecting] = React.useState(false); + + const observer = new IntersectionObserver( + ([entry]) => setIntersecting(entry.isIntersecting), + ); + + React.useEffect(() => { + observer.observe(ref.current); + + return () => { + observer.disconnect(); + }; + }, []); + + return isIntersecting; +};