diff --git a/web/components/single-line.css b/web/components/single-line.css new file mode 100644 index 000000000..137ff62ed --- /dev/null +++ b/web/components/single-line.css @@ -0,0 +1,5 @@ +.singleLine { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} diff --git a/web/components/single-line.react.js b/web/components/single-line.react.js new file mode 100644 index 000000000..ec577a45d --- /dev/null +++ b/web/components/single-line.react.js @@ -0,0 +1,25 @@ +// @flow + +import classNames from 'classnames'; +import * as React from 'react'; + +import { firstLine } from 'lib/utils/string-utils.js'; + +import css from './single-line.css'; + +type Props = { + +children: string, + +className?: string, +}; + +function SingleLine(props: Props): React.Node { + const { children, className } = props; + + const text = firstLine(children); + + const singleLineClassName = classNames([css.singleLine, className]); + + return
{text}
; +} + +export default SingleLine; diff --git a/web/modals/user-profile/user-profile.css b/web/modals/user-profile/user-profile.css index 073227f6f..0a64ae971 100644 --- a/web/modals/user-profile/user-profile.css +++ b/web/modals/user-profile/user-profile.css @@ -1,57 +1,58 @@ .container { padding: 0 32px 32px; width: 552px; max-width: 80vw; } .userInfoContainer { display: flex; align-items: center; margin-bottom: 24px; } .userAvatarContainer:hover { cursor: pointer; } .usernameContainer { - padding-left: 16px; + margin-left: 16px; + overflow: hidden; } .usernameText { font-size: var(--xxl-font-24); color: var(--fg); font-weight: 500; } .copyUsernameContainer { display: flex; align-items: center; color: var(--purple-link); margin-top: 8px; } .copyUsernameContainer:hover { cursor: pointer; } .copyUsernameText { font-size: var(--xs-font-12); margin-left: 4px; } .multiButtonRowContainer { display: flex; column-gap: 8px; } .actionButton { column-gap: 8px; flex: 1; width: 100%; } .incomingFriendRequestText { color: var(--fg); margin: 24px 0 8px 0; } diff --git a/web/modals/user-profile/user-profile.react.js b/web/modals/user-profile/user-profile.react.js index d16300110..64f3d5433 100644 --- a/web/modals/user-profile/user-profile.react.js +++ b/web/modals/user-profile/user-profile.react.js @@ -1,99 +1,100 @@ // @flow import * as React from 'react'; import { useModalContext } from 'lib/components/modal-provider.react.js'; import SWMansionIcon from 'lib/components/SWMansionIcon.react.js'; import { relationshipBlockedInEitherDirection } from 'lib/shared/relationship-utils.js'; import { stringForUserExplicit } from 'lib/shared/user-utils.js'; import type { UserProfileThreadInfo } from 'lib/types/thread-types'; import type { UserInfo } from 'lib/types/user-types'; import sleep from 'lib/utils/sleep.js'; import UserProfileActionButtons from './user-profile-action-buttons.react.js'; import UserProfileAvatarModal from './user-profile-avatar-modal.react.js'; import css from './user-profile.css'; import UserAvatar from '../../avatars/user-avatar.react.js'; +import SingleLine from '../../components/single-line.react.js'; type Props = { +userInfo: ?UserInfo, +userProfileThreadInfo: ?UserProfileThreadInfo, }; function UserProfile(props: Props): React.Node { const { userInfo, userProfileThreadInfo } = props; const { pushModal } = useModalContext(); const usernameText = stringForUserExplicit(userInfo); const [usernameCopied, setUsernameCopied] = React.useState(false); const onClickUserAvatar = React.useCallback(() => { pushModal(); }, [pushModal, userInfo?.id]); const onClickCopyUsername = React.useCallback(async () => { if (usernameCopied) { return; } await navigator.clipboard.writeText(usernameText); setUsernameCopied(true); await sleep(3000); setUsernameCopied(false); }, [usernameCopied, usernameText]); const actionButtons = React.useMemo(() => { if ( !userProfileThreadInfo || relationshipBlockedInEitherDirection(userInfo?.relationshipStatus) ) { return null; } return ( ); }, [userInfo?.relationshipStatus, userProfileThreadInfo]); const userProfile = React.useMemo( () => (
-
{usernameText}
+ {usernameText}

{!usernameCopied ? 'Copy username' : 'Username copied!'}

{actionButtons}
), [ actionButtons, onClickCopyUsername, onClickUserAvatar, userInfo?.id, usernameCopied, usernameText, ], ); return userProfile; } export default UserProfile;