Commit c76664de authored by tom goriunov's avatar tom goriunov Committed by GitHub

Public tags cutoff problem (#2048)

* change max width for tag on mobile

* Public tags cutoff problem

Fixes #2007

* fix tests

* update test
parent f92012f4
...@@ -37,7 +37,7 @@ const PublicTagsSubmitResultSuccess = ({ data }: Props) => { ...@@ -37,7 +37,7 @@ const PublicTagsSubmitResultSuccess = ({ data }: Props) => {
.map((tag) => ( .map((tag) => (
<EntityTag <EntityTag
key={ tag.name } key={ tag.name }
truncate maxW={{ base: '100%', lg: '300px' }}
data={{ data={{
...tag, ...tag,
slug: '', slug: '',
......
...@@ -58,7 +58,7 @@ const PublicTagsSubmitResultWithErrors = ({ data }: Props) => { ...@@ -58,7 +58,7 @@ const PublicTagsSubmitResultWithErrors = ({ data }: Props) => {
{ item.tags.map((tag) => ( { item.tags.map((tag) => (
<EntityTag <EntityTag
key={ tag.name } key={ tag.name }
truncate maxW={{ base: '100%', lg: '300px' }}
data={{ ...tag, slug: '', ordinal: 0 }} data={{ ...tag, slug: '', ordinal: 0 }}
/> />
)) } )) }
......
...@@ -29,7 +29,7 @@ test('protocol tag +@dark-mode', async({ render }) => { ...@@ -29,7 +29,7 @@ test('protocol tag +@dark-mode', async({ render }) => {
}); });
test('tag with link and long name +@dark-mode', async({ render }) => { test('tag with link and long name +@dark-mode', async({ render }) => {
const component = await render(<EntityTag data={ addressMetadataMock.infoTagWithLink } truncate/>); const component = await render(<EntityTag data={ addressMetadataMock.infoTagWithLink } maxW="300px"/>);
await expect(component).toHaveScreenshot(); await expect(component).toHaveScreenshot();
}); });
......
import type { ResponsiveValue } from '@chakra-ui/react';
import { chakra, Image, Skeleton, Tag } from '@chakra-ui/react'; import { chakra, Image, Skeleton, Tag } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
...@@ -13,10 +14,10 @@ import { getTagLinkParams } from './utils'; ...@@ -13,10 +14,10 @@ import { getTagLinkParams } from './utils';
interface Props { interface Props {
data: TEntityTag; data: TEntityTag;
isLoading?: boolean; isLoading?: boolean;
truncate?: boolean; maxW?: ResponsiveValue<string>;
} }
const EntityTag = ({ data, isLoading, truncate }: Props) => { const EntityTag = ({ data, isLoading, maxW }: Props) => {
if (isLoading) { if (isLoading) {
return <Skeleton borderRadius="sm" w="100px" h="24px"/>; return <Skeleton borderRadius="sm" w="100px" h="24px"/>;
...@@ -55,7 +56,8 @@ const EntityTag = ({ data, isLoading, truncate }: Props) => { ...@@ -55,7 +56,8 @@ const EntityTag = ({ data, isLoading, truncate }: Props) => {
display="flex" display="flex"
alignItems="center" alignItems="center"
minW={ 0 } minW={ 0 }
maxW={ truncate ? { base: '125px', lg: '300px' } : undefined } w="fit-content"
maxW={ maxW }
bg={ data.meta?.bgColor } bg={ data.meta?.bgColor }
color={ data.meta?.textColor } color={ data.meta?.textColor }
colorScheme={ hasLink ? 'gray-blue' : 'gray' } colorScheme={ hasLink ? 'gray-blue' : 'gray' }
......
import React from 'react';
import * as addressMetadataMock from 'mocks/metadata/address';
import { test, expect } from 'playwright/lib';
import EntityTags from './EntityTags';
test('mixed name length +@mobile', async({ render }) => {
const data = [
addressMetadataMock.protocolTagWithMeta,
addressMetadataMock.infoTagWithLink,
addressMetadataMock.genericTag,
addressMetadataMock.tagWithTooltip,
];
const component = await render(<EntityTags tags={ data }/>);
await expect(component).toHaveScreenshot();
});
test('one tag with long name +@mobile -@default', async({ render }) => {
const data = [
addressMetadataMock.infoTagWithLink,
];
const component = await render(<EntityTags tags={ data }/>);
await expect(component).toHaveScreenshot();
});
...@@ -28,10 +28,15 @@ const EntityTags = ({ tags, className, isLoading }: Props) => { ...@@ -28,10 +28,15 @@ const EntityTags = ({ tags, className, isLoading }: Props) => {
} }
const content = (() => { const content = (() => {
const tagMaxW = {
base: tags.length === 1 ? '100%' : '60%',
lg: '300px',
};
if (tags.length > visibleNum) { if (tags.length > visibleNum) {
return ( return (
<> <>
{ tags.slice(0, visibleNum).map((tag) => <EntityTag key={ tag.slug } data={ tag } isLoading={ isLoading } truncate/>) } { tags.slice(0, visibleNum).map((tag) => <EntityTag key={ tag.slug } data={ tag } isLoading={ isLoading } maxW={ tagMaxW }/>) }
{ metaSuitesPlaceholder } { metaSuitesPlaceholder }
<Popover trigger="click" placement="bottom-start" isLazy> <Popover trigger="click" placement="bottom-start" isLazy>
<PopoverTrigger> <PopoverTrigger>
...@@ -53,14 +58,14 @@ const EntityTags = ({ tags, className, isLoading }: Props) => { ...@@ -53,14 +58,14 @@ const EntityTags = ({ tags, className, isLoading }: Props) => {
return ( return (
<> <>
{ tags.map((tag) => <EntityTag key={ tag.slug } data={ tag } isLoading={ isLoading } truncate/>) } { tags.map((tag) => <EntityTag key={ tag.slug } data={ tag } isLoading={ isLoading } maxW={ tagMaxW }/>) }
{ metaSuitesPlaceholder } { metaSuitesPlaceholder }
</> </>
); );
})(); })();
return ( return (
<Flex className={ className } columnGap={ 2 } rowGap={ 2 } flexWrap="wrap" alignItems="center" flexGrow={ 1 }> <Flex className={ className } columnGap={ 2 } rowGap={ 2 } flexWrap="nowrap" alignItems="center" flexGrow={ 1 } maxW="100%">
{ content } { content }
</Flex> </Flex>
); );
......
...@@ -8,7 +8,6 @@ import * as TokenEntity from 'ui/shared/entities/token/TokenEntity'; ...@@ -8,7 +8,6 @@ import * as TokenEntity from 'ui/shared/entities/token/TokenEntity';
import EntityTags from 'ui/shared/EntityTags/EntityTags'; import EntityTags from 'ui/shared/EntityTags/EntityTags';
import formatUserTags from 'ui/shared/EntityTags/formatUserTags'; import formatUserTags from 'ui/shared/EntityTags/formatUserTags';
import IconSvg from 'ui/shared/IconSvg'; import IconSvg from 'ui/shared/IconSvg';
import NetworkExplorers from 'ui/shared/NetworkExplorers';
import PageTitle from '../PageTitle'; import PageTitle from '../PageTitle';
...@@ -42,7 +41,6 @@ const LongNameAndManyTags = () => { ...@@ -42,7 +41,6 @@ const LongNameAndManyTags = () => {
] } ] }
flexGrow={ 1 } flexGrow={ 1 }
/> />
<NetworkExplorers type="token" pathParam="token-hash" ml="auto"/>
</> </>
); );
......
import type { PlacementWithLogical } from '@chakra-ui/react'; import type { PlacementWithLogical } from '@chakra-ui/react';
import { Tooltip } from '@chakra-ui/react'; import { Tooltip, useDisclosure } from '@chakra-ui/react';
import debounce from 'lodash/debounce'; import debounce from 'lodash/debounce';
import React from 'react'; import React from 'react';
import useFontFaceObserver from 'use-font-face-observer'; import useFontFaceObserver from 'use-font-face-observer';
...@@ -15,6 +15,7 @@ interface Props { ...@@ -15,6 +15,7 @@ interface Props {
const TruncatedTextTooltip = ({ children, label, placement }: Props) => { const TruncatedTextTooltip = ({ children, label, placement }: Props) => {
const childRef = React.useRef<HTMLElement>(null); const childRef = React.useRef<HTMLElement>(null);
const [ isTruncated, setTruncated ] = React.useState(false); const [ isTruncated, setTruncated ] = React.useState(false);
const { isOpen, onToggle, onOpen, onClose } = useDisclosure();
const isFontFaceLoaded = useFontFaceObserver([ const isFontFaceLoaded = useFontFaceObserver([
{ family: BODY_TYPEFACE }, { family: BODY_TYPEFACE },
...@@ -55,14 +56,36 @@ const TruncatedTextTooltip = ({ children, label, placement }: Props) => { ...@@ -55,14 +56,36 @@ const TruncatedTextTooltip = ({ children, label, placement }: Props) => {
// and it is not cleared how to manage case with two or more children // and it is not cleared how to manage case with two or more children
const child = React.Children.only(children) as React.ReactElement & { const child = React.Children.only(children) as React.ReactElement & {
ref?: React.Ref<React.ReactNode>; ref?: React.Ref<React.ReactNode>;
onClick?: () => void;
onMouseEnter?: () => void;
onMouseLeave?: () => void;
}; };
const handleClick = React.useCallback((event: React.MouseEvent) => {
event.stopPropagation();
onToggle();
}, [ onToggle ]);
const modifiedChildren = React.cloneElement( const modifiedChildren = React.cloneElement(
child, child,
{ ref: childRef }, {
ref: childRef,
onClick: handleClick,
onMouseEnter: onOpen,
onMouseLeave: onClose,
},
); );
if (isTruncated) { if (isTruncated) {
return <Tooltip label={ label } maxW={{ base: '100vw', lg: '400px' }} placement={ placement }>{ modifiedChildren }</Tooltip>; return (
<Tooltip
label={ label }
maxW={{ base: '100vw', lg: '400px' }}
placement={ placement }
isOpen={ isOpen }
>
{ modifiedChildren }
</Tooltip>
);
} }
return modifiedChildren; return modifiedChildren;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment