cleanup(graph): misc project details view enhancements (#21311)

This commit is contained in:
MaxKless 2024-01-26 17:00:58 +01:00 committed by GitHub
parent 7ab0de8f68
commit 12d7caa099
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 367 additions and 149 deletions

View File

@ -1,3 +1,7 @@
/*! purgecss start ignore */
@import './syntax-highlight.css';
/*! purgecss end ignore */
@tailwind components;
@tailwind base;
@tailwind utilities;
@ -6,3 +10,37 @@
.dark {
color-scheme: dark;
}
/**
* Tooltips
*/
[data-tooltip] {
position: relative;
}
[data-tooltip]:before {
background-color: hsla(214, 61%, 11%, 1);
border-radius: 0.375rem;
color: hsla(0, 0%, 95%, 1);
content: attr(data-tooltip);
left: 0;
opacity: 0;
padding: 0.25rem 0.5rem;
position: absolute;
text-align: center;
text-transform: capitalize;
top: 120%;
transition: opacity 150ms ease-out;
visibility: hidden;
z-index: 1;
width: max-content;
}
[data-tooltip][data-tooltip-align-right]:before {
left: auto;
right: 0;
}
[data-tooltip]:hover:before {
opacity: 1;
visibility: visible;
}

View File

@ -0,0 +1,79 @@
html {
--interactive-muted: #94a3b8;
}
.dark {
--interactive-muted: #64748b;
}
.hljs .hljs-comment,
.hljs .hljs-quote {
color: var(--interactive-muted);
}
.hljs .hljs-addition,
.hljs .hljs-keyword,
.hljs .hljs-selector-tag {
color: #859900;
}
.hljs .hljs-doctag,
.hljs .hljs-literal,
.hljs .hljs-meta .hljs .hljs-meta-string,
.hljs .hljs-number,
.hljs .hljs-regexp,
.hljs .hljs-string {
color: #2aa198;
}
.hljs .hljs-name,
.hljs .hljs-section,
.hljs .hljs-selector-class,
.hljs .hljs-selector-id,
.hljs .hljs-title {
color: #268bd2;
}
.hljs .hljs-attr,
.hljs .hljs-attribute,
.hljs .hljs-class .hljs .hljs-title,
.hljs .hljs-template-variable,
.hljs .hljs-type,
.hljs .hljs-variable {
color: #b58900;
}
.hljs .hljs-bullet,
.hljs .hljs-link,
.hljs .hljs-meta,
.hljs .hljs-meta .hljs .hljs-keyword,
.hljs .hljs-selector-attr,
.hljs .hljs-selector-pseudo,
.hljs .hljs-subst,
.hljs .hljs-symbol {
color: #cb4b16;
}
.hljs .hljs-built_in,
.hljs .hljs-deletion {
color: #dc322f;
}
.hljs .hljs-formula {
background: #073642;
}
.hljs .hljs-emphasis {
font-style: italic;
}
.hljs .hljs-strong {
font-weight: 700;
}
.linenumber {
border-color: rgb(59 130 246);
background: #e5e7eb;
}
html.dark .linenumber {
background: #e5e7eb33;
}

View File

@ -52,8 +52,9 @@ export function ProjectDetailsPage() {
<div className="flex flex-col justify-center w-full text-slate-700 dark:text-slate-400">
<ScrollRestoration />
{environment !== 'nx-console' ? (
<header className="flex w-full justify-center items-center px-4 py-2 border-b-2 border-slate-900/10 mb-8 dark:border-slate-300/10">
<div className="flex flex-grow items-center justify-between max-w-6xl">
<header className="flex w-full justify-center items-center py-2 mx-auto border-b-2 border-slate-900/10 mb-8 dark:border-slate-300/10">
<div className="flex flex-grow items-center justify-between max-w-6xl px-8 ">
<Link to={routeConstructor('/projects', false)}>
<svg
className="h-10 w-auto text-slate-900 dark:text-white"
viewBox="0 0 24 24"
@ -63,25 +64,13 @@ export function ProjectDetailsPage() {
<title>Nx</title>
<path d="M11.987 14.138l-3.132 4.923-5.193-8.427-.012 8.822H0V4.544h3.691l5.247 8.833.005-3.998 3.044 4.759zm.601-5.761c.024-.048 0-3.784.008-3.833h-3.65c.002.059-.005 3.776-.003 3.833h3.645zm5.634 4.134a2.061 2.061 0 0 0-1.969 1.336 1.963 1.963 0 0 1 2.343-.739c.396.161.917.422 1.33.283a2.1 2.1 0 0 0-1.704-.88zm3.39 1.061c-.375-.13-.8-.277-1.109-.681-.06-.08-.116-.17-.176-.265a2.143 2.143 0 0 0-.533-.642c-.294-.216-.68-.322-1.18-.322a2.482 2.482 0 0 0-2.294 1.536 2.325 2.325 0 0 1 4.002.388.75.75 0 0 0 .836.334c.493-.105.46.36 1.203.518v-.133c-.003-.446-.246-.55-.75-.733zm2.024 1.266a.723.723 0 0 0 .347-.638c-.01-2.957-2.41-5.487-5.37-5.487a5.364 5.364 0 0 0-4.487 2.418c-.01-.026-1.522-2.39-1.538-2.418H8.943l3.463 5.423-3.379 5.32h3.54l1.54-2.366 1.568 2.366h3.541l-3.21-5.052a.7.7 0 0 1-.084-.32 2.69 2.69 0 0 1 2.69-2.691h.001c1.488 0 1.736.89 2.057 1.308.634.826 1.9.464 1.9 1.541a.707.707 0 0 0 1.066.596zm.35.133c-.173.372-.56.338-.755.639-.176.271.114.412.114.412s.337.156.538-.311c.104-.231.14-.488.103-.74z" />
</svg>
<ul className="flex items-center">
<li>
<Link
to={routeConstructor(
`/projects/${encodeURIComponent(project.name)}`,
true
)}
title="View in Graph"
>
Graph
</Link>
</li>
<li className="ml-4">
<ThemePanel />
</li>
</ul>
</div>
</header>
) : null}
) : (
<div className="py-2"></div>
)}
<div className="flex-grow mx-auto w-full max-w-6xl px-8 mb-8">
<ProjectDetailsWrapper
project={project}

View File

@ -17,7 +17,7 @@ export function JsonCodeBlockPreTag({
return (
<div
className={twMerge(
'hljs not-prose w-full overflow-hidden',
'hljs not-prose w-full overflow-hidden rounded-md',
'font-mono text-sm',
'border border-slate-200 bg-slate-50/50 dark:border-slate-700 dark:bg-slate-800/60'
)}
@ -103,10 +103,13 @@ export function sourcesRenderer(
}
}
return (
<span className="flex group/line" key={`code-group${idx}`}>
<span
className="flex group/line min-w-0 flex shrink-1"
key={`code-group${idx}`}
>
<span>{element}</span>
{sourceElement && (
<span className="hidden group-hover/line:inline pl-2">
<span className="opacity-0 min-w-0 flex shrink-1 group-hover/line:opacity-100 transition-opacity duration-150 ease-in-out inline pl-2">
{sourceElement}
</span>
)}

View File

@ -0,0 +1,28 @@
import { twMerge } from 'tailwind-merge';
export function Pill({
text,
color = 'grey',
tooltip,
}: {
text: string;
color?: 'grey' | 'green' | 'yellow';
tooltip?: string;
}) {
return (
<span
data-tooltip={tooltip}
className={twMerge(
'inline-flex items-center rounded-md px-2 py-1 text-xs font-medium ring-1 ring-inset',
color === 'grey' &&
'bg-slate-400/10 text-slate-600 ring-slate-400/40 dark:text-slate-400 dark:ring-slate-400/30',
color === 'green' &&
'dark:bg-green-500/10 bg-green-400/10 dark:text-green-400 text-green-500 dark:ring-green-500/20 ring-green-500/40',
color === 'yellow' &&
'bg-yellow-50 dark:bg-yellow-900/30 text-yellow-600 dark:text-yellow-400 dark:ring-yellow-500/20 ring-yellow-500/40'
)}
>
{text}
</span>
);
}

View File

@ -20,6 +20,7 @@ import {
useRef,
} from 'react';
import { twMerge } from 'tailwind-merge';
import { Pill } from '../pill';
export interface ProjectDetailsProps {
project: ProjectGraphProjectNode;
@ -90,34 +91,42 @@ export const ProjectDetails = forwardRef(
>
<h1
className={twMerge(
`flex items-center`,
`flex items-center justify-between dark:text-slate-100`,
isCompact ? `text-2xl gap-1` : `text-4xl mb-4 gap-2`
)}
>
{name}{' '}
<span>{name}</span>
<span>
{onViewInProjectGraph ? (
<EyeIcon
className="h-5 w-5 cursor-pointer"
<button
className="text-base cursor-pointer items-center inline-flex gap-2 text-slate-600 dark:text-slate-300 ring-2 ring-inset ring-slate-400/40 dark:ring-slate-400/30 hover:bg-slate-50 dark:hover:bg-slate-800/60 rounded-md py-1 px-2"
onClick={() => onViewInProjectGraph({ projectName: name })}
></EyeIcon>
>
<EyeIcon className="h-5 w-5 "></EyeIcon>
<span>View In Graph</span>
</button>
) : null}{' '}
</span>
</h1>
<div className={isCompact ? `px-4 py-2` : `p-4`}>
{projectData.tags ? (
<div className="py-2 ">
{projectData.tags && projectData.tags.length ? (
<p>
<span className="font-medium inline-block w-10">Tags:</span>
{projectData.tags?.map((tag) => (
<span className="bg-slate-300 rounded-md p-1 mr-2">
{tag}
<span className="ml-2 font-mono">
<Pill text={tag} />
</span>
))}
</p>
) : null}
<p>
<span className="font-bold">Root:</span> {root}
<span className="font-medium inline-block w-10">Root:</span>
<span className="font-mono"> {root}</span>
</p>
{displayType ? (
<p>
<span className="font-bold">Type:</span> {displayType}
<span className="font-medium inline-block w-10">Type:</span>
<span className="font-mono"> {displayType}</span>
</p>
) : null}
</div>
@ -128,13 +137,13 @@ export const ProjectDetails = forwardRef(
openAction="hover"
content={(<PropertyInfoTooltip type="targets" />) as any}
>
<span>
<span className="text-slate-800 dark:text-slate-200">
<TooltipTriggerText>Targets</TooltipTriggerText>
</span>
</Tooltip>
</h2>
<ul>
{projectTargets.map((targetName) => {
{projectTargets.sort(sortNxReleasePublishLast).map((targetName) => {
const target = projectData.targets?.[targetName];
return target && targetRefs.current[targetName] ? (
<li className="mb-4 last:mb-0" key={`target-${targetName}`}>
@ -160,4 +169,10 @@ export const ProjectDetails = forwardRef(
}
);
function sortNxReleasePublishLast(a: string, b: string) {
if (a === 'nx-release-publish') return 1;
if (b === 'nx-release-publish') return -1;
return 1;
}
export default ProjectDetails;

View File

@ -3,6 +3,7 @@ import { JSX, useEffect, useState } from 'react';
interface CopyToClipboardProps {
onCopy: () => void;
tooltipAlignment?: 'left' | 'right';
}
export function CopyToClipboard(props: CopyToClipboardProps): JSX.Element {
@ -16,9 +17,12 @@ export function CopyToClipboard(props: CopyToClipboardProps): JSX.Element {
}
});
return (
<span
data-tooltip="Copy to clipboard"
data-tooltip-align-right={props.tooltipAlignment === 'right'}
>
<ClipboardIcon
title="Copy to clipboard"
className={`inline h-4 w-5 cursor-pointer ${
className={`inline h-4 w-5 !cursor-pointer ${
copied ? 'text-sky-500' : ''
}`}
onClick={(e) => {
@ -27,5 +31,6 @@ export function CopyToClipboard(props: CopyToClipboardProps): JSX.Element {
props.onCopy();
}}
></ClipboardIcon>
</span>
);
}

View File

@ -33,7 +33,9 @@ export function FadingCollapsible({ children }: { children: ReactNode }) {
>
<div
className={`${
collapsed && isCollapsible ? 'hover:bg-slate-700' : ''
collapsed && isCollapsible
? 'hover:bg-slate-200 dark:hover:bg-slate-700'
: ''
} rounded-md`}
style={fadeStyles}
>

View File

@ -1,15 +1,17 @@
import { SourcemapInfoToolTip, Tooltip } from '@nx/graph/ui-tooltips';
import { InformationCircleIcon } from '@heroicons/react/24/outline';
import { twMerge } from 'tailwind-merge';
export function SourceInfo(props: {
data: Array<string>;
propertyKey: string;
color?: string;
}) {
// Target property key is in the form `target.${targetName}`
// Every other property within in the target has the form `target.${targetName}.${propertyName}
const isTarget = props.propertyKey.split('.').length === 2;
return (
<span className="inline-flex items-center gap-2">
<span className="inline-flex shrink-1 min-w-0 items-center gap-2">
<Tooltip
openAction="hover"
strategy="fixed"
@ -28,7 +30,12 @@ export function SourceInfo(props: {
{/*<span className="italic text-gray-500">*/}
{/* <InformationCircleIcon className="w-3 h-3" />*/}
{/*</span>*/}
<span className="italic text-gray-500">
<span
className={twMerge(
'italic text-sm min-w-0 truncate',
props.color ?? 'text-gray-500'
)}
>
{isTarget ? 'Created' : 'Set'} by {props.data?.[1]} from{' '}
{props.data?.[0]}
</span>

View File

@ -4,7 +4,9 @@ import {
ChevronDownIcon,
ChevronUpIcon,
EyeIcon,
InformationCircleIcon,
PlayIcon,
QuestionMarkCircleIcon,
} from '@heroicons/react/24/outline';
// nx-ignore-next-line
@ -31,6 +33,7 @@ import {
} from '@nx/graph/ui-tooltips';
import { TooltipTriggerText } from './tooltip-trigger-text';
import { twMerge } from 'tailwind-merge';
import { Pill } from '../pill';
/* eslint-disable-next-line */
export interface TargetProps {
@ -140,40 +143,43 @@ export const TargetConfigurationDetails = forwardRef(
: true);
return (
<div className="rounded-md border border-slate-500 relative overflow-hidden">
<div className="rounded-md border border-slate-200 dark:border-slate-700/60 relative overflow-hidden">
<header
className={twMerge(
`group hover:bg-slate-200 dark:hover:bg-slate-800 cursor-pointer`,
`group hover:bg-slate-50 dark:hover:bg-slate-800/60 cursor-pointer`,
isCompact ? 'px-2 py-1' : 'p-2',
!collapsed
? 'bg-slate-200 dark:bg-slate-800 border-b-2 border-slate-900/10 dark:border-slate-300/10 '
? 'bg-slate-50 dark:bg-slate-800/60 border-b dark:border-slate-700/60 dark:border-slate-300/10 '
: ''
)}
onClick={handleCollapseToggle}
>
<div className="flex justify-between items-center">
<div className="flex items-center">
<h3 className="font-bold mr-2">{targetName}</h3>
{collapsed && (
<p className="text-slate-600 mr-2">
{singleCommand ? singleCommand : targetConfiguration.executor}
<div className="flex items-center justify-between gap-2">
<div className="flex items-center gap-2">
{collapsed ? (
<ChevronDownIcon className="h-3 w-3" />
) : (
<ChevronUpIcon className="h-3 w-3" />
)}
<h3 className="font-medium dark:text-slate-300">{targetName}</h3>
{collapsed &&
targetConfiguration?.executor !== '@nx/js:release-publish' && (
<p className="text-slate-400 text-sm">
{singleCommand
? singleCommand
: targetConfiguration.executor}
</p>
)}
</div>
<div className="flex items-center">
{onViewInTaskGraph && (
<EyeIcon
className={`h-4 w-4 mr-2 ${
collapsed
? 'hidden group-hover:inline-block'
: 'inline-block'
}`}
title="View in Task Graph"
onClick={(e) => {
e.stopPropagation();
onViewInTaskGraph({ projectName, targetName });
}}
/>
{targetName === 'nx-release-publish' && (
<Tooltip
openAction="hover"
strategy="fixed"
content={(<PropertyInfoTooltip type="release" />) as any}
>
<span className="inline-flex">
<Pill text="nx release" color="grey" />
</span>
</Tooltip>
)}
{targetConfiguration.cache && (
<Tooltip
@ -181,47 +187,74 @@ export const TargetConfigurationDetails = forwardRef(
strategy="fixed"
content={(<PropertyInfoTooltip type="cacheable" />) as any}
>
<span className="rounded-full inline-block text-xs bg-sky-500 dark:bg-sky-800 px-2 text-slate-50 mr-2">
Cacheable
<span className="inline-flex">
<Pill text="Cacheable" color="green" />
</span>
</Tooltip>
)}
</div>
<div className="flex items-center gap-2">
{onViewInTaskGraph && (
<button
className="text-slate-600 dark:text-slate-300 text-sm ring-1 ring-inset ring-slate-400/40 dark:ring-slate-400/30 hover:bg-slate-200 dark:hover:bg-slate-700/60 p-1 bg-inherit rounded-md"
// TODO: fix tooltip overflow in collapsed state
data-tooltip={collapsed ? false : 'View in Task Graph'}
data-tooltip-align-right
>
<EyeIcon
className={`h-5 w-5 !cursor-pointer`}
onClick={(e) => {
e.stopPropagation();
onViewInTaskGraph({ projectName, targetName });
}}
/>
</button>
)}
{onRunTarget && (
<span
className="text-slate-600 dark:text-slate-300 text-sm ring-1 ring-inset ring-slate-400/40 dark:ring-slate-400/30 hover:bg-slate-200 dark:hover:bg-slate-700/60 p-1 bg-inherit rounded-md"
// TODO: fix tooltip overflow in collapsed state
data-tooltip={collapsed ? false : 'Run Target'}
data-tooltip-align-right
>
<PlayIcon
className="h-5 w-5 mr-2"
className="h-5 w-5 !cursor-pointer"
onClick={(e) => {
e.stopPropagation();
onRunTarget({ projectName, targetName });
}}
/>
)}
{collapsed ? (
<ChevronDownIcon className="h-3 w-3" />
) : (
<ChevronUpIcon className="h-3 w-3" />
</span>
)}
</div>
</div>
{!collapsed && (
<div className="flex items-center text-sm mt-2">
<span className="flex-1 flex items-center">
<div className="flex items-center text-sm mt-2 ml-5">
<span className="flex-1 flex min-w-0 items-center">
<SourceInfo
data={sourceMap[`targets.${targetName}`]}
propertyKey={`targets.${targetName}`}
color="text-gray-500 dark:text-slate-400"
/>
</span>
{targetName !== 'nx-release-publish' && (
<div className="flex items-center gap-2">
<code className="ml-4 bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-300 font-mono px-2 py-1 rounded">
nx run {projectName}:{targetName}
</code>
<span className="ml-2">
<span>
<CopyToClipboard
onCopy={() =>
handleCopyClick(`nx run ${projectName}:${targetName}`)
}
tooltipAlignment="right"
/>
</span>
</div>
)}
</div>
)}
</header>
{/* body */}
{!collapsed && (
@ -229,7 +262,7 @@ export const TargetConfigurationDetails = forwardRef(
<div className="mb-4 group">
<h4 className="mb-4">
{singleCommand ? (
<span className="font-bold">
<span className="font-medium">
Command
<span className="hidden group-hover:inline ml-2 mb-1">
<CopyToClipboard
@ -244,7 +277,7 @@ export const TargetConfigurationDetails = forwardRef(
openAction="hover"
content={(<PropertyInfoTooltip type="executors" />) as any}
>
<span className="font-bold">
<span className="font-medium">
<TooltipTriggerText>Executor</TooltipTriggerText>
</span>
</Tooltip>
@ -252,6 +285,7 @@ export const TargetConfigurationDetails = forwardRef(
</h4>
<p className="pl-5">
{executorLink ? (
<span>
<ExternalLink
href={executorLink ?? 'https://nx.dev/nx-api'}
text={
@ -259,8 +293,8 @@ export const TargetConfigurationDetails = forwardRef(
? singleCommand
: targetConfiguration.executor
}
title="View Documentation"
/>
</span>
) : singleCommand ? (
singleCommand
) : (
@ -276,7 +310,7 @@ export const TargetConfigurationDetails = forwardRef(
openAction="hover"
content={(<PropertyInfoTooltip type="inputs" />) as any}
>
<span className="font-bold">
<span className="font-medium">
<TooltipTriggerText>Inputs</TooltipTriggerText>
</span>
</Tooltip>
@ -305,7 +339,7 @@ export const TargetConfigurationDetails = forwardRef(
>
<TargetConfigurationProperty data={input}>
{sourceInfo && (
<span className="hidden group-hover/line:inline pl-4">
<span className="opacity-0 flex shrink-1 min-w-0 group-hover/line:opacity-100 transition-opacity duration-150 ease-in-out inline pl-4">
<SourceInfo
data={sourceInfo}
propertyKey={`targets.${targetName}.inputs`}
@ -326,7 +360,7 @@ export const TargetConfigurationDetails = forwardRef(
openAction="hover"
content={(<PropertyInfoTooltip type="outputs" />) as any}
>
<span className="font-bold">
<span className="font-medium">
<TooltipTriggerText>Outputs</TooltipTriggerText>
</span>
</Tooltip>
@ -355,7 +389,7 @@ export const TargetConfigurationDetails = forwardRef(
>
<TargetConfigurationProperty data={output}>
{sourceInfo && (
<span className="hidden group-hover/line:inline pl-4">
<span className="opacity-0 flex shrink-1 min-w-0 group-hover/line:opacity-100 transition-opacity duration-150 ease-in-out inline pl-4">
<SourceInfo
data={sourceInfo}
propertyKey={`targets.${targetName}.outputs`}
@ -376,11 +410,11 @@ export const TargetConfigurationDetails = forwardRef(
openAction="hover"
content={(<PropertyInfoTooltip type="dependsOn" />) as any}
>
<span className="font-bold">
<span className="font-medium">
<TooltipTriggerText>Depends On</TooltipTriggerText>
</span>
</Tooltip>
<span className="hidden group-hover:inline ml-2 mb-1">
<span className="opacity-0 group-hover/line:opacity-100 transition-opacity duration-150 ease-in-out inline pl-4">
<CopyToClipboard
onCopy={() =>
handleCopyClick(
@ -405,7 +439,7 @@ export const TargetConfigurationDetails = forwardRef(
key={`dependsOn-${idx}`}
>
<TargetConfigurationProperty data={dep}>
<span className="hidden group-hover/line:inline pl-4 h-6">
<span className="opacity-0 flex shrink-1 min-w-0 group-hover/line:opacity-100 transition-opacity duration-150 ease-in-out inline pl-4">
{sourceInfo && (
<SourceInfo
data={sourceInfo}
@ -428,7 +462,7 @@ export const TargetConfigurationDetails = forwardRef(
openAction="hover"
content={(<PropertyInfoTooltip type="options" />) as any}
>
<span className="font-bold">
<span className="font-medium">
<TooltipTriggerText>Options</TooltipTriggerText>
</span>
</Tooltip>
@ -443,7 +477,7 @@ export const TargetConfigurationDetails = forwardRef(
`targets.${targetName}.options.${propertyName}`
);
return sourceInfo ? (
<span className="pl-4">
<span className="pl-4 flex shrink-1 min-w-0">
<SourceInfo
data={sourceInfo}
propertyKey={`targets.${targetName}.options.${propertyName}`}
@ -468,16 +502,17 @@ export const TargetConfigurationDetails = forwardRef(
(<PropertyInfoTooltip type="configurations" />) as any
}
>
<span className="font-bold">
<span className="font-medium">
<TooltipTriggerText>Configurations</TooltipTriggerText>
</span>
</Tooltip>{' '}
{targetConfiguration.defaultConfiguration && (
<span
className="ml-3 font-bold rounded-full inline-block text-xs bg-sky-500 px-2 text-slate-50 mr-6"
title="Default Configuration"
>
{targetConfiguration.defaultConfiguration}
<span className="ml-3 cursor-help">
<Pill
tooltip="Default Configuration"
text={targetConfiguration.defaultConfiguration}
color="yellow"
/>
</span>
)}
</h4>
@ -490,7 +525,7 @@ export const TargetConfigurationDetails = forwardRef(
`targets.${targetName}.configurations.${propertyName}`
);
return sourceInfo ? (
<span className="pl-4">
<span className="pl-4 flex shrink-1 min-w-0">
<SourceInfo
data={sourceInfo}
propertyKey={`targets.${targetName}.configurations.${propertyName}`}

View File

@ -11,7 +11,7 @@ export function TargetConfigurationProperty({
}: RenderPropertyProps): JSX.Element | null {
if (typeof data === 'string') {
return (
<span>
<span className="font-mono flex shrink-1 text-sm">
{data}
{children}
</span>
@ -20,7 +20,7 @@ export function TargetConfigurationProperty({
return (
<ul>
{data.map((item, index) => (
<li key={index}>
<li key={index} className="font-mono flex shrink-1 text-sm">
{String(item)}
{children}
</li>
@ -31,7 +31,7 @@ export function TargetConfigurationProperty({
return (
<ul>
{Object.entries(data).map(([key, value], index) => (
<li key={index}>
<li key={index} className="font-mono flex shrink-1 text-sm">
<strong>{key}</strong>: {String(value)}
{children}
</li>

View File

@ -6,7 +6,7 @@ export function TooltipTriggerText({
children: string | ReactNode;
}) {
return (
<span className="underline underline-offset-8 decoration-2 decoration-dotted decoration-slate-700/50 dark:decoration-slate-400/50">
<span className="underline cursor-help underline-offset-8 decoration-2 decoration-dotted decoration-slate-700/50 dark:decoration-slate-400/50">
{children}
</span>
);

View File

@ -13,7 +13,7 @@ export function ExternalLink({
<a
href={href}
title={title}
className="text-slate-500 dark:text-slate-300 hover:underline inline-flex items-center gap-2"
className="text-slate-500 dark:text-slate-400 hover:underline inline-flex items-center gap-2"
target="_blank"
>
{text} <ArrowTopRightOnSquareIcon className="w-4 h-4 inline" />

View File

@ -8,7 +8,8 @@ type PropertyInfoTooltipType =
| 'outputs'
| 'dependsOn'
| 'options'
| 'configurations';
| 'configurations'
| 'release';
type PropertyInfoTooltipTypeOptions = {
docsUrl: string;
@ -73,6 +74,12 @@ const PROPERTY_INFO_TOOLTIP_TYPE_OPTIONS: Record<
description:
'Configurations are sets of Options to allow a Target to be used in different scenarios.',
},
release: {
heading: 'nx release',
description:
"The nx-release-publish target is used to publish your project with nxrelease. Don't invoke this directly - use nx release publish instead.",
docsUrl: 'https://nx.dev/nx-api/nx/documents/release',
},
};
export function PropertyInfoTooltip({ type }: PropertyInfoTooltipProps) {
@ -80,10 +87,10 @@ export function PropertyInfoTooltip({ type }: PropertyInfoTooltipProps) {
return (
<div className="text-sm text-slate-700 dark:text-slate-400 max-w-lg">
<h4 className="flex justify-between items-center border-b text-base">
<h4 className="flex justify-between items-center border-b border-slate-200 dark:border-slate-700/60 text-base">
<span className="font-mono">{propertyInfo.heading}</span>
</h4>
<div className="flex flex-col font-mono border-b py-2">
<div className="flex flex-col font-mono border-b border-slate-200 dark:border-slate-700/60 py-2">
<p className="flex grow items-center gap-2 whitespace-pre-wrap">
{propertyInfo.description}
</p>

View File

@ -24,7 +24,7 @@ export function SourcemapInfoToolTip({
return (
<div className="text-sm text-slate-700 dark:text-slate-400 max-w-md sm:max-w-full">
<div className="flex flex-col font-mono border-b py-2">
<div className="flex flex-col font-mono border-b border-slate-200 dark:border-slate-700/60 py-2">
<p className="flex grow items-center gap-2">
<span className="font-bold">{isTarget ? 'Created' : 'Set'} by:</span>
<span className="inline-flex grow justify-between items-center">

View File

@ -26,6 +26,7 @@ import {
useHover,
useRole,
safePolygon,
useTransitionStyles,
} from '@floating-ui/react';
export type TooltipProps = HTMLAttributes<HTMLDivElement> & {
@ -76,6 +77,13 @@ export function Tooltip({
],
});
const { isMounted, styles: animationStyles } = useTransitionStyles(context, {
duration: 200,
initial: {
opacity: openAction === 'hover' ? 0 : 1,
},
});
const staticSide: string =
{
top: 'bottom',
@ -98,6 +106,7 @@ export function Tooltip({
outsidePressEvent: 'mousedown',
});
const hover = useHover(context, {
restMs: 300,
enabled: openAction === 'hover',
delay: { open: 0, close: 150 },
handleClose: safePolygon({ buffer }),
@ -121,7 +130,7 @@ export function Tooltip({
{!externalReference && !!children
? cloneElement(children, cloneProps)
: children}
{isOpen ? (
{isOpen && isMounted ? (
<div
ref={refs.setFloating}
style={{
@ -129,6 +138,7 @@ export function Tooltip({
top: showTooltipArrow ? y : y + 8 ?? 0,
left: x ?? 0,
width: 'max-content',
...animationStyles,
}}
className="z-10 min-w-[250px] rounded-md border border-slate-500"
{...getFloatingProps()}