Skip to content

Commit

Permalink
feat(graph): update tags to render on a single line by default with e…
Browse files Browse the repository at this point in the history
…xpand option (nrwl#27829)
  • Loading branch information
MaxKless authored Sep 9, 2024
1 parent d72a1d4 commit b8486fb
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ import { GraphError } from 'nx/src/command-line/graph/graph';
/* eslint-enable @nx/enforce-module-boundaries */
import { EyeIcon } from '@heroicons/react/24/outline';
import { PropertyInfoTooltip, Tooltip } from '@nx/graph/ui-tooltips';
import { TooltipTriggerText } from '../target-configuration-details/tooltip-trigger-text';
import { twMerge } from 'tailwind-merge';
import { Pill } from '../pill';
import { TargetTechnologies } from '../target-technologies/target-technologies';
import { TagList } from '../tag-list/tag-list';
import { TargetConfigurationGroupList } from '../target-configuration-details-group-list/target-configuration-details-group-list';
import { TooltipTriggerText } from '../target-configuration-details/tooltip-trigger-text';
import { TargetTechnologies } from '../target-technologies/target-technologies';

export interface ProjectDetailsProps {
project: ProjectGraphProjectNode;
Expand Down Expand Up @@ -97,21 +97,14 @@ export const ProjectDetails = ({
)}
</div>
<div className="flex flex-wrap justify-between py-2">
<div>
<div className="min-w-0">
{projectData.metadata?.description ? (
<p className="mb-2 text-sm capitalize text-gray-500 dark:text-slate-400">
{projectData.metadata?.description}
</p>
) : null}
{projectData.tags && projectData.tags.length ? (
<p>
<span className="font-medium">Tags:</span>
{projectData.tags?.map((tag) => (
<span className="ml-2 font-mono lowercase">
<Pill text={tag} />
</span>
))}
</p>
<TagList tags={projectData.tags} />
) : null}
{projectData.root ? (
<p>
Expand Down
42 changes: 42 additions & 0 deletions graph/ui-project-details/src/lib/tag-list/tag-list.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import type { Meta, StoryObj } from '@storybook/react';
import { TagList } from './tag-list';

const meta: Meta<typeof TagList> = {
component: TagList,
title: 'TagList',
};
export default meta;

type Story = StoryObj<typeof TagList>;

export const FewTags: Story = {
args: {
tags: ['tag1', 'tag2', 'tag3'],
},
};
export const ManyTags: Story = {
args: {
tags: [
'tag1',
'tag2',
'tag3',
'tag4',
'tag5',
'tag6',
'tag7',
'tag8',
'tag9',
'tag10',
'tag11',
'tag12',
'tag13',
'tag14',
'tag15',
'tag16',
'tag17',
'tag18',
'tag19',
'tag20',
],
},
};
78 changes: 78 additions & 0 deletions graph/ui-project-details/src/lib/tag-list/tag-list.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import React, { useState, useRef, useEffect } from 'react';
import { Pill } from '../pill';

interface TagListProps {
tags: string[];
}

export function TagList({ tags }: TagListProps) {
const [isExpanded, _setIsExpanded] = useState(false);
const [isOverflowing, setIsOverflowing] = useState(false);
const tagsContainerRef = useRef<HTMLSpanElement>(null);

const checkOverflow = () => {
requestAnimationFrame(() => {
if (tagsContainerRef.current) {
setIsOverflowing(
tagsContainerRef.current.scrollWidth >
tagsContainerRef.current.offsetWidth
);
}
});
};

const setExpanded = (value: boolean) => {
_setIsExpanded(value);
checkOverflow();
};

useEffect(() => {
checkOverflow();

window.addEventListener('resize', checkOverflow);
return () => window.removeEventListener('resize', checkOverflow);
}, [tagsContainerRef]);

return (
<div className="relative max-w-full">
<p className="flex min-w-0 font-medium leading-loose">
<span className="inline-block">Tags:</span>

<span
className={`inline-block ${
isExpanded ? 'whitespace-normal' : 'whitespace-nowrap'
} w-full max-w-full overflow-hidden transition-all duration-300`}
style={{
maskImage:
isOverflowing && !isExpanded
? 'linear-gradient(to right, black 80%, transparent 100%)'
: 'none',
}}
ref={tagsContainerRef}
>
{tags.map((tag) => (
<span key={tag} className="ml-2 font-mono lowercase">
<Pill text={tag} />
</span>
))}
{isExpanded && (
<button
onClick={() => setExpanded(false)}
className="inline-block px-2 align-middle"
>
Show less
</button>
)}
</span>
{isOverflowing && !isExpanded && (
<button
onClick={() => setExpanded(true)}
className="ml-1 inline-block whitespace-nowrap"
>
Show more
</button>
)}
</p>
</div>
);
}

0 comments on commit b8486fb

Please sign in to comment.