mirror of
https://github.com/coder/coder.git
synced 2026-06-02 20:48:20 +00:00
refactor: use a global tooltip provider with a consistent 100 millisecond delay duration (#20869)
Part 1 of 2 - this sets up the TooltipProvider for Storybook in preview.tsx and for the app in App.tsx along with removing TooltipProvider in some of the usages of Tooltip - I tested existing components that haven't had the TooltipProvider removed and they still function correctly. So should be fine until the 2nd PR to complete the migration. --------- Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -11,6 +11,7 @@ import isChromatic from "chromatic/isChromatic";
|
||||
import { StrictMode } from "react";
|
||||
import { QueryClient, QueryClientProvider } from "react-query";
|
||||
import { withRouter } from "storybook-addon-remix-react-router";
|
||||
import { TooltipProvider } from "../src/components/Tooltip/Tooltip";
|
||||
import "theme/globalFonts";
|
||||
import type { Decorator, Loader, Parameters } from "@storybook/react-vite";
|
||||
import themes from "../src/theme";
|
||||
@@ -100,8 +101,10 @@ const withTheme: Decorator = (Story, context) => {
|
||||
<StyledEngineProvider injectFirst>
|
||||
<MuiThemeProvider theme={themes[selected]}>
|
||||
<EmotionThemeProvider theme={themes[selected]}>
|
||||
<CssBaseline />
|
||||
<Story />
|
||||
<TooltipProvider delayDuration={100}>
|
||||
<CssBaseline />
|
||||
<Story />
|
||||
</TooltipProvider>
|
||||
</EmotionThemeProvider>
|
||||
</MuiThemeProvider>
|
||||
</StyledEngineProvider>
|
||||
|
||||
+5
-2
@@ -1,5 +1,6 @@
|
||||
import "./theme/globalFonts";
|
||||
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
|
||||
import { TooltipProvider } from "components/Tooltip/Tooltip";
|
||||
import {
|
||||
type FC,
|
||||
type ReactNode,
|
||||
@@ -53,8 +54,10 @@ export const AppProviders: FC<AppProvidersProps> = ({
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<AuthProvider>
|
||||
<ThemeProvider>
|
||||
{children}
|
||||
<GlobalSnackbar />
|
||||
<TooltipProvider delayDuration={100}>
|
||||
{children}
|
||||
<GlobalSnackbar />
|
||||
</TooltipProvider>
|
||||
</ThemeProvider>
|
||||
</AuthProvider>
|
||||
{showDevtools && <ReactQueryDevtools initialIsOpen={showDevtools} />}
|
||||
|
||||
@@ -3,7 +3,6 @@ import { Button } from "components/Button/Button";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "components/Tooltip/Tooltip";
|
||||
import { EyeIcon, EyeOffIcon } from "lucide-react";
|
||||
@@ -77,21 +76,19 @@ export const CodeExample: FC<CodeExampleProps> = ({
|
||||
|
||||
<div className="flex items-center gap-1">
|
||||
{showRevealButton && redactPattern && !secret && (
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
size="icon"
|
||||
variant="subtle"
|
||||
onClick={() => setShowFullValue(!showFullValue)}
|
||||
>
|
||||
{icon}
|
||||
<span className="sr-only">{showButtonLabel}</span>
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{showButtonLabel}</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
size="icon"
|
||||
variant="subtle"
|
||||
onClick={() => setShowFullValue(!showFullValue)}
|
||||
>
|
||||
{icon}
|
||||
<span className="sr-only">{showButtonLabel}</span>
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{showButtonLabel}</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
<CopyButton text={code} label="Copy code" />
|
||||
</div>
|
||||
|
||||
@@ -15,7 +15,6 @@ import {
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "components/Tooltip/Tooltip";
|
||||
import { Check, ChevronDown, CornerDownLeft, Info } from "lucide-react";
|
||||
@@ -138,21 +137,19 @@ export const Combobox: FC<ComboboxProps> = ({
|
||||
<Check className="size-icon-sm" />
|
||||
)}
|
||||
{option.description && (
|
||||
<TooltipProvider delayDuration={100}>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<span
|
||||
className="flex"
|
||||
onMouseEnter={(e) => e.stopPropagation()}
|
||||
>
|
||||
<Info className="w-3.5 h-3.5 text-content-secondary" />
|
||||
</span>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="right" sideOffset={10}>
|
||||
{option.description}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<span
|
||||
className="flex"
|
||||
onMouseEnter={(e) => e.stopPropagation()}
|
||||
>
|
||||
<Info className="w-3.5 h-3.5 text-content-secondary" />
|
||||
</span>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="right" sideOffset={10}>
|
||||
{option.description}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
</CommandItem>
|
||||
|
||||
@@ -2,7 +2,6 @@ import { Button, type ButtonProps } from "components/Button/Button";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "components/Tooltip/Tooltip";
|
||||
import { useClipboard } from "hooks/useClipboard";
|
||||
@@ -22,21 +21,19 @@ export const CopyButton: FC<CopyButtonProps> = ({
|
||||
const { showCopiedSuccess, copyToClipboard } = useClipboard();
|
||||
|
||||
return (
|
||||
<TooltipProvider delayDuration={100}>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
size="icon"
|
||||
variant="subtle"
|
||||
onClick={() => copyToClipboard(text)}
|
||||
{...buttonProps}
|
||||
>
|
||||
{showCopiedSuccess ? <CheckIcon /> : <CopyIcon />}
|
||||
<span className="sr-only">{label}</span>
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{label}</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
size="icon"
|
||||
variant="subtle"
|
||||
onClick={() => copyToClipboard(text)}
|
||||
{...buttonProps}
|
||||
>
|
||||
{showCopiedSuccess ? <CheckIcon /> : <CopyIcon />}
|
||||
<span className="sr-only">{label}</span>
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{label}</TooltipContent>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "components/Tooltip/Tooltip";
|
||||
import { useClickable } from "hooks/useClickable";
|
||||
@@ -37,55 +36,53 @@ export const CopyableValue: FC<CopyableValueProps> = ({
|
||||
});
|
||||
|
||||
return (
|
||||
<TooltipProvider delayDuration={100}>
|
||||
<Tooltip
|
||||
open={tooltipOpen}
|
||||
onOpenChange={(shouldBeOpen) => {
|
||||
// Always keep the tooltip open when in focus to handle issues when onOpenChange is unexpectedly false
|
||||
if (!shouldBeOpen && isFocused) return;
|
||||
setTooltipOpen(shouldBeOpen);
|
||||
}}
|
||||
>
|
||||
<TooltipTrigger asChild>
|
||||
<span
|
||||
ref={clickableProps.ref}
|
||||
{...attrs}
|
||||
className={cn("cursor-pointer", className)}
|
||||
role={role ?? clickableProps.role}
|
||||
tabIndex={tabIndex ?? clickableProps.tabIndex}
|
||||
onClick={(event) => {
|
||||
clickableProps.onClick(event);
|
||||
onClick?.(event);
|
||||
}}
|
||||
onKeyDown={(event) => {
|
||||
clickableProps.onKeyDown(event);
|
||||
onKeyDown?.(event);
|
||||
}}
|
||||
onKeyUp={(event) => {
|
||||
clickableProps.onKeyUp(event);
|
||||
onKeyUp?.(event);
|
||||
}}
|
||||
onMouseEnter={() => {
|
||||
setIsFocused(true);
|
||||
setTooltipOpen(true);
|
||||
}}
|
||||
onMouseLeave={() => {
|
||||
setTooltipOpen(false);
|
||||
}}
|
||||
onFocus={() => {
|
||||
setIsFocused(true);
|
||||
}}
|
||||
onBlur={() => {
|
||||
setTooltipOpen(false);
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</span>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side={side}>
|
||||
{showCopiedSuccess ? "Copied!" : "Click to copy"}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
<Tooltip
|
||||
open={tooltipOpen}
|
||||
onOpenChange={(shouldBeOpen) => {
|
||||
// Always keep the tooltip open when in focus to handle issues when onOpenChange is unexpectedly false
|
||||
if (!shouldBeOpen && isFocused) return;
|
||||
setTooltipOpen(shouldBeOpen);
|
||||
}}
|
||||
>
|
||||
<TooltipTrigger asChild>
|
||||
<span
|
||||
ref={clickableProps.ref}
|
||||
{...attrs}
|
||||
className={cn("cursor-pointer", className)}
|
||||
role={role ?? clickableProps.role}
|
||||
tabIndex={tabIndex ?? clickableProps.tabIndex}
|
||||
onClick={(event) => {
|
||||
clickableProps.onClick(event);
|
||||
onClick?.(event);
|
||||
}}
|
||||
onKeyDown={(event) => {
|
||||
clickableProps.onKeyDown(event);
|
||||
onKeyDown?.(event);
|
||||
}}
|
||||
onKeyUp={(event) => {
|
||||
clickableProps.onKeyUp(event);
|
||||
onKeyUp?.(event);
|
||||
}}
|
||||
onMouseEnter={() => {
|
||||
setIsFocused(true);
|
||||
setTooltipOpen(true);
|
||||
}}
|
||||
onMouseLeave={() => {
|
||||
setTooltipOpen(false);
|
||||
}}
|
||||
onFocus={() => {
|
||||
setIsFocused(true);
|
||||
}}
|
||||
onBlur={() => {
|
||||
setTooltipOpen(false);
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</span>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side={side}>
|
||||
{showCopiedSuccess ? "Copied!" : "Click to copy"}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -2,7 +2,6 @@ import { Link } from "components/Link/Link";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "components/Tooltip/Tooltip";
|
||||
import type { FC, HTMLAttributes, ReactNode } from "react";
|
||||
@@ -47,40 +46,38 @@ export const FeatureStageBadge: FC<FeatureStageBadgeProps> = ({
|
||||
const sizeClasses = badgeSizeClasses[size];
|
||||
|
||||
return (
|
||||
<TooltipProvider delayDuration={100}>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<span
|
||||
className={cn(
|
||||
"block max-w-fit cursor-default flex-shrink-0 leading-none whitespace-nowrap border rounded-md transition-colors duration-200 ease-in-out bg-transparent border-solid border-transparent",
|
||||
sizeClasses,
|
||||
colorClasses,
|
||||
className,
|
||||
)}
|
||||
{...delegatedProps}
|
||||
>
|
||||
<span className="sr-only"> (This is a</span>
|
||||
<span className="first-letter:uppercase">
|
||||
{labelText && `${labelText} `}
|
||||
{featureStageBadgeTypes[contentType]}
|
||||
</span>
|
||||
<span className="sr-only"> feature)</span>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<span
|
||||
className={cn(
|
||||
"block max-w-fit cursor-default flex-shrink-0 leading-none whitespace-nowrap border rounded-md transition-colors duration-200 ease-in-out bg-transparent border-solid border-transparent",
|
||||
sizeClasses,
|
||||
colorClasses,
|
||||
className,
|
||||
)}
|
||||
{...delegatedProps}
|
||||
>
|
||||
<span className="sr-only"> (This is a</span>
|
||||
<span className="first-letter:uppercase">
|
||||
{labelText && `${labelText} `}
|
||||
{featureStageBadgeTypes[contentType]}
|
||||
</span>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent align="start" className="max-w-xs text-sm">
|
||||
<p className="m-0">
|
||||
This feature has not yet reached general availability (GA).
|
||||
</p>
|
||||
<span className="sr-only"> feature)</span>
|
||||
</span>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent align="start" className="max-w-xs text-sm">
|
||||
<p className="m-0">
|
||||
This feature has not yet reached general availability (GA).
|
||||
</p>
|
||||
|
||||
<Link
|
||||
href={docs("/install/releases/feature-stages")}
|
||||
className="font-semibold"
|
||||
>
|
||||
Learn about feature stages
|
||||
<span className="sr-only"> (link opens in new tab)</span>
|
||||
</Link>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
<Link
|
||||
href={docs("/install/releases/feature-stages")}
|
||||
className="font-semibold"
|
||||
>
|
||||
Learn about feature stages
|
||||
<span className="sr-only"> (link opens in new tab)</span>
|
||||
</Link>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -11,7 +11,6 @@ import {
|
||||
TooltipContent,
|
||||
type TooltipContentProps,
|
||||
type TooltipProps,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "components/Tooltip/Tooltip";
|
||||
import { CircleHelpIcon, ExternalLinkIcon } from "lucide-react";
|
||||
@@ -33,11 +32,7 @@ export const HelpTooltipTrigger = TooltipTrigger;
|
||||
export const HelpTooltipIcon = CircleHelpIcon;
|
||||
|
||||
export const HelpTooltip: FC<TooltipProps> = (props) => {
|
||||
return (
|
||||
<TooltipProvider>
|
||||
<Tooltip delayDuration={0} {...props} />
|
||||
</TooltipProvider>
|
||||
);
|
||||
return <Tooltip {...props} />;
|
||||
};
|
||||
|
||||
export const HelpTooltipContent: FC<TooltipContentProps> = ({
|
||||
|
||||
@@ -14,7 +14,6 @@ import {
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "components/Tooltip/Tooltip";
|
||||
import { useDebouncedValue } from "hooks/debounce";
|
||||
@@ -684,21 +683,19 @@ export const MultiSelectCombobox = forwardRef<
|
||||
)}
|
||||
{option.label}
|
||||
{option.description && (
|
||||
<TooltipProvider delayDuration={100}>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<span className="flex items-center pointer-events-auto">
|
||||
<Info className="!w-3.5 !h-3.5 text-content-secondary" />
|
||||
</span>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent
|
||||
side="right"
|
||||
sideOffset={10}
|
||||
>
|
||||
{option.description}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<span className="flex items-center pointer-events-auto">
|
||||
<Info className="!w-3.5 !h-3.5 text-content-secondary" />
|
||||
</span>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent
|
||||
side="right"
|
||||
sideOffset={10}
|
||||
>
|
||||
{option.description}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
</CommandItem>
|
||||
|
||||
@@ -2,7 +2,6 @@ import { Pill } from "components/Pill/Pill";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "components/Tooltip/Tooltip";
|
||||
import type { FC } from "react";
|
||||
@@ -33,11 +32,9 @@ export const StatusPill: FC<StatusPillProps> = ({
|
||||
return pill;
|
||||
}
|
||||
return (
|
||||
<TooltipProvider>
|
||||
<Tooltip delayDuration={150}>
|
||||
<TooltipTrigger asChild>{pill}</TooltipTrigger>
|
||||
<TooltipContent>{label}</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>{pill}</TooltipTrigger>
|
||||
<TooltipContent>{label}</TooltipContent>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -7,7 +7,6 @@ import { CoderIcon } from "components/Icons/CoderIcon";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "components/Tooltip/Tooltip";
|
||||
import type { ProxyContextValue } from "contexts/ProxyContext";
|
||||
@@ -230,21 +229,19 @@ const TasksNavItem: FC<TasksNavItemProps> = ({ user }) => {
|
||||
>
|
||||
Tasks
|
||||
{idleCount > 0 && (
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Badge
|
||||
variant="info"
|
||||
size="xs"
|
||||
className="ml-2"
|
||||
aria-label={idleTasksLabel(idleCount)}
|
||||
>
|
||||
{idleCount}
|
||||
</Badge>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{idleTasksLabel(idleCount)}</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Badge
|
||||
variant="info"
|
||||
size="xs"
|
||||
className="ml-2"
|
||||
aria-label={idleTasksLabel(idleCount)}
|
||||
>
|
||||
{idleCount}
|
||||
</Badge>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{idleTasksLabel(idleCount)}</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
</NavLink>
|
||||
);
|
||||
|
||||
@@ -14,7 +14,6 @@ import { Stack } from "components/Stack/Stack";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "components/Tooltip/Tooltip";
|
||||
import { useProxy } from "contexts/ProxyContext";
|
||||
@@ -346,19 +345,17 @@ export const AgentDevcontainerCard: FC<AgentDevcontainerCardProps> = ({
|
||||
)
|
||||
: "";
|
||||
return (
|
||||
<TooltipProvider key={portLabel}>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<AgentButton disabled={!hasHostBind} asChild>
|
||||
<a href={linkDest}>
|
||||
<ExternalLinkIcon />
|
||||
{portLabel}
|
||||
</a>
|
||||
</AgentButton>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{helperText}</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
<Tooltip key={portLabel}>
|
||||
<TooltipTrigger asChild>
|
||||
<AgentButton disabled={!hasHostBind} asChild>
|
||||
<a href={linkDest}>
|
||||
<ExternalLinkIcon />
|
||||
{portLabel}
|
||||
</a>
|
||||
</AgentButton>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{helperText}</TooltipContent>
|
||||
</Tooltip>
|
||||
);
|
||||
})}
|
||||
</section>
|
||||
|
||||
@@ -5,7 +5,6 @@ import type { Line } from "components/Logs/LogLine";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "components/Tooltip/Tooltip";
|
||||
import { type ComponentProps, forwardRef, type JSX } from "react";
|
||||
@@ -148,33 +147,31 @@ export const AgentLogs = forwardRef<List, AgentLogsProps>(
|
||||
</List>
|
||||
|
||||
{overflowed && (
|
||||
<TooltipProvider delayDuration={100}>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Badge
|
||||
asChild
|
||||
className="max-w-fit py-1.5 px-3 absolute bottom-3 left-1/2 -translate-x-1/2"
|
||||
>
|
||||
<span>Logs overflowed</span>
|
||||
</Badge>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Badge
|
||||
asChild
|
||||
className="w-full text-sm text-content-secondary bg-surface-primary max-w-prose leading-relaxed m-0 p-4"
|
||||
className="max-w-fit py-1.5 px-3 absolute bottom-3 left-1/2 -translate-x-1/2"
|
||||
>
|
||||
<p>
|
||||
Startup logs exceeded the max size of{" "}
|
||||
<span className="tracking-wide font-mono">1MB</span>, and will
|
||||
not continue to be written to the database. Logs will continue
|
||||
to be written to the{" "}
|
||||
<span className="font-mono bg-surface-tertiary rounded-md px-1.5 py-0.5">
|
||||
/tmp/coder-startup-script.log
|
||||
</span>{" "}
|
||||
file in the workspace.
|
||||
</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
<span>Logs overflowed</span>
|
||||
</Badge>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent
|
||||
asChild
|
||||
className="w-full text-sm text-content-secondary bg-surface-primary max-w-prose leading-relaxed m-0 p-4"
|
||||
>
|
||||
<p>
|
||||
Startup logs exceeded the max size of{" "}
|
||||
<span className="tracking-wide font-mono">1MB</span>, and will
|
||||
not continue to be written to the database. Logs will continue
|
||||
to be written to the{" "}
|
||||
<span className="font-mono bg-surface-tertiary rounded-md px-1.5 py-0.5">
|
||||
/tmp/coder-startup-script.log
|
||||
</span>{" "}
|
||||
file in the workspace.
|
||||
</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -6,7 +6,6 @@ import { Spinner } from "components/Spinner/Spinner";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "components/Tooltip/Tooltip";
|
||||
import { useProxy } from "contexts/ProxyContext";
|
||||
@@ -137,20 +136,18 @@ export const AppLink: FC<AppLinkProps> = ({
|
||||
|
||||
if (primaryTooltip || app.tooltip) {
|
||||
return (
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>{button}</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
{primaryTooltip ? (
|
||||
primaryTooltip
|
||||
) : app.tooltip ? (
|
||||
<Markdown className="text-content-secondary prose-sm font-medium wrap-anywhere">
|
||||
{app.tooltip}
|
||||
</Markdown>
|
||||
) : null}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>{button}</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
{primaryTooltip ? (
|
||||
primaryTooltip
|
||||
) : app.tooltip ? (
|
||||
<Markdown className="text-content-secondary prose-sm font-medium wrap-anywhere">
|
||||
{app.tooltip}
|
||||
</Markdown>
|
||||
) : null}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,6 @@ import { Spinner } from "components/Spinner/Spinner";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "components/Tooltip/Tooltip";
|
||||
import { useFormik } from "formik";
|
||||
@@ -218,40 +217,36 @@ export const PortForwardPopoverView: FC<PortForwardPopoverViewProps> = ({
|
||||
: "authenticated";
|
||||
|
||||
const disabledPublicMenuItem = (
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
{/* Tooltips don't work directly on disabled MenuItem components so you must wrap in div. */}
|
||||
<div>
|
||||
<MenuItem value="public" disabled>
|
||||
Public
|
||||
</MenuItem>
|
||||
</div>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent disablePortal>
|
||||
This workspace template does not allow sharing ports publicly.
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
{/* Tooltips don't work directly on disabled MenuItem components so you must wrap in div. */}
|
||||
<div>
|
||||
<MenuItem value="public" disabled>
|
||||
Public
|
||||
</MenuItem>
|
||||
</div>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent disablePortal>
|
||||
This workspace template does not allow sharing ports publicly.
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
);
|
||||
|
||||
const disabledAuthenticatedMenuItem = (
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
{/* Tooltips don't work directly on disabled MenuItem components so you must wrap in div. */}
|
||||
<div>
|
||||
<MenuItem value="authenticated" disabled>
|
||||
Authenticated
|
||||
</MenuItem>
|
||||
</div>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent disablePortal>
|
||||
This workspace template does not allow sharing ports outside of its
|
||||
organization.
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
{/* Tooltips don't work directly on disabled MenuItem components so you must wrap in div. */}
|
||||
<div>
|
||||
<MenuItem value="authenticated" disabled>
|
||||
Authenticated
|
||||
</MenuItem>
|
||||
</div>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent disablePortal>
|
||||
This workspace template does not allow sharing ports outside of its
|
||||
organization.
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
);
|
||||
|
||||
return (
|
||||
@@ -338,19 +333,15 @@ export const PortForwardPopoverView: FC<PortForwardPopoverViewProps> = ({
|
||||
required
|
||||
css={styles.newPortInput}
|
||||
/>
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button type="submit" size="icon" variant="subtle">
|
||||
<ExternalLinkIcon />
|
||||
<span className="sr-only">Connect to port</span>
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent disablePortal>
|
||||
Connect to port
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button type="submit" size="icon" variant="subtle">
|
||||
<ExternalLinkIcon />
|
||||
<span className="sr-only">Connect to port</span>
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent disablePortal>Connect to port</TooltipContent>
|
||||
</Tooltip>
|
||||
</form>
|
||||
</Stack>
|
||||
</Stack>
|
||||
@@ -405,30 +396,28 @@ export const PortForwardPopoverView: FC<PortForwardPopoverViewProps> = ({
|
||||
alignItems="center"
|
||||
>
|
||||
{canSharePorts && (
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
size="icon"
|
||||
variant="subtle"
|
||||
onClick={async () => {
|
||||
await upsertSharedPortMutation.mutateAsync({
|
||||
agent_name: agent.name,
|
||||
port: port.port,
|
||||
protocol: listeningPortProtocol,
|
||||
share_level: defaultShareLevel,
|
||||
});
|
||||
}}
|
||||
>
|
||||
<ShareIcon />
|
||||
<span className="sr-only">Share</span>
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent disablePortal>
|
||||
Share this port
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
size="icon"
|
||||
variant="subtle"
|
||||
onClick={async () => {
|
||||
await upsertSharedPortMutation.mutateAsync({
|
||||
agent_name: agent.name,
|
||||
port: port.port,
|
||||
protocol: listeningPortProtocol,
|
||||
share_level: defaultShareLevel,
|
||||
});
|
||||
}}
|
||||
>
|
||||
<ShareIcon />
|
||||
<span className="sr-only">Share</span>
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent disablePortal>
|
||||
Share this port
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
||||
@@ -24,7 +24,6 @@ import { Spinner } from "components/Spinner/Spinner";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "components/Tooltip/Tooltip";
|
||||
import { useAuthenticated } from "hooks/useAuthenticated";
|
||||
@@ -414,23 +413,21 @@ const ExternalAuthButtons: FC<ExternalAuthButtonProps> = ({
|
||||
</Button>
|
||||
|
||||
{shouldRetry && !auth.authenticated && (
|
||||
<TooltipProvider>
|
||||
<Tooltip delayDuration={100}>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={startPollingExternalAuth}
|
||||
>
|
||||
<RedoIcon />
|
||||
<span className="sr-only">Refresh external auth</span>
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
Retry connecting to {auth.display_name}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={startPollingExternalAuth}
|
||||
>
|
||||
<RedoIcon />
|
||||
<span className="sr-only">Refresh external auth</span>
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
Retry connecting to {auth.display_name}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -2,7 +2,6 @@ import type { WorkspaceAppStatus as APIWorkspaceAppStatus } from "api/typesGener
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "components/Tooltip/Tooltip";
|
||||
import capitalize from "lodash/capitalize";
|
||||
@@ -28,23 +27,21 @@ export const WorkspaceAppStatus = ({
|
||||
const message = status.message || capitalize(status.state);
|
||||
return (
|
||||
<div className="flex flex-col text-content-secondary">
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<div className="flex items-center gap-2">
|
||||
<AppStatusStateIcon
|
||||
latest
|
||||
disabled={disabled}
|
||||
state={status.state}
|
||||
/>
|
||||
<span className="whitespace-nowrap max-w-72 overflow-hidden text-ellipsis text-sm text-content-primary font-medium">
|
||||
{message}
|
||||
</span>
|
||||
</div>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{message}</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<div className="flex items-center gap-2">
|
||||
<AppStatusStateIcon
|
||||
latest
|
||||
disabled={disabled}
|
||||
state={status.state}
|
||||
/>
|
||||
<span className="whitespace-nowrap max-w-72 overflow-hidden text-ellipsis text-sm text-content-primary font-medium">
|
||||
{message}
|
||||
</span>
|
||||
</div>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{message}</TooltipContent>
|
||||
</Tooltip>
|
||||
<span className="text-xs first-letter:uppercase block pl-6">
|
||||
{status.state}
|
||||
</span>
|
||||
|
||||
@@ -7,7 +7,6 @@ import {
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "components/Tooltip/Tooltip";
|
||||
import type React from "react";
|
||||
@@ -60,19 +59,17 @@ export const WorkspaceStatusIndicator: FC<WorkspaceStatusIndicatorProps> = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<StatusIndicator variant={variantByStatusType[type]}>
|
||||
<StatusIndicatorDot />
|
||||
<span className="sr-only">Workspace status:</span> {text}
|
||||
{children}
|
||||
</StatusIndicator>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
Your workspace is running but some agents are unhealthy.
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<StatusIndicator variant={variantByStatusType[type]}>
|
||||
<StatusIndicatorDot />
|
||||
<span className="sr-only">Workspace status:</span> {text}
|
||||
{children}
|
||||
</StatusIndicator>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
Your workspace is running but some agents are unhealthy.
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -14,7 +14,6 @@ import { Switch } from "components/Switch/Switch";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "components/Tooltip/Tooltip";
|
||||
import { UserAutocomplete } from "components/UserAutocomplete/UserAutocomplete";
|
||||
@@ -386,26 +385,24 @@ export const CreateWorkspacePageViewExperimental: FC<
|
||||
<span className="flex flex-row items-center gap-2">
|
||||
<h1 className="text-3xl font-semibold m-0">New workspace</h1>
|
||||
|
||||
<TooltipProvider delayDuration={100}>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<CircleHelp className="size-icon-xs text-content-secondary" />
|
||||
</TooltipTrigger>
|
||||
<TooltipContent className="max-w-xs text-sm">
|
||||
Dynamic Parameters enhances Coder's existing parameter system
|
||||
with real-time validation, conditional parameter behavior, and
|
||||
richer input types.
|
||||
<br />
|
||||
<Link
|
||||
href={docs(
|
||||
"/admin/templates/extending-templates/dynamic-parameters",
|
||||
)}
|
||||
>
|
||||
View docs
|
||||
</Link>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<CircleHelp className="size-icon-xs text-content-secondary" />
|
||||
</TooltipTrigger>
|
||||
<TooltipContent className="max-w-xs text-sm">
|
||||
Dynamic Parameters enhances Coder's existing parameter system
|
||||
with real-time validation, conditional parameter behavior, and
|
||||
richer input types.
|
||||
<br />
|
||||
<Link
|
||||
href={docs(
|
||||
"/admin/templates/extending-templates/dynamic-parameters",
|
||||
)}
|
||||
>
|
||||
View docs
|
||||
</Link>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</span>
|
||||
</header>
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ import { Spinner } from "components/Spinner/Spinner";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "components/Tooltip/Tooltip";
|
||||
import { Check, Redo } from "lucide-react";
|
||||
@@ -77,19 +76,17 @@ export const ExternalAuthButton: FC<ExternalAuthButtonProps> = ({
|
||||
)}
|
||||
|
||||
{displayRetry && !auth.authenticated && (
|
||||
<TooltipProvider>
|
||||
<Tooltip delayDuration={100}>
|
||||
<TooltipTrigger asChild>
|
||||
<Button variant="outline" size="icon" onClick={onStartPolling}>
|
||||
<Redo />
|
||||
<span className="sr-only">Refresh external auth</span>
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
Retry login with {auth.display_name}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button variant="outline" size="icon" onClick={onStartPolling}>
|
||||
<Redo />
|
||||
<span className="sr-only">Refresh external auth</span>
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
Retry login with {auth.display_name}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
+22
-25
@@ -16,7 +16,6 @@ import {
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "components/Tooltip/Tooltip";
|
||||
import { useFormik } from "formik";
|
||||
@@ -67,31 +66,29 @@ export const AppearanceSettingsPageView: FC<
|
||||
</SettingsHeader>
|
||||
|
||||
<Badges>
|
||||
<TooltipProvider>
|
||||
<Tooltip delayDuration={0}>
|
||||
{isEntitled && !isPremium ? (
|
||||
<EnterpriseBadge />
|
||||
) : (
|
||||
<TooltipTrigger asChild>
|
||||
<span>
|
||||
<PremiumBadge />
|
||||
</span>
|
||||
</TooltipTrigger>
|
||||
)}
|
||||
<Tooltip>
|
||||
{isEntitled && !isPremium ? (
|
||||
<EnterpriseBadge />
|
||||
) : (
|
||||
<TooltipTrigger asChild>
|
||||
<span>
|
||||
<PremiumBadge />
|
||||
</span>
|
||||
</TooltipTrigger>
|
||||
)}
|
||||
|
||||
<TooltipContent
|
||||
sideOffset={-28}
|
||||
collisionPadding={16}
|
||||
className="p-0"
|
||||
>
|
||||
<PopoverPaywall
|
||||
message="Appearance"
|
||||
description="With a Premium license, you can customize the appearance and branding of your deployment."
|
||||
documentationLink="https://coder.com/docs/admin/appearance"
|
||||
/>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
<TooltipContent
|
||||
sideOffset={-28}
|
||||
collisionPadding={16}
|
||||
className="p-0"
|
||||
>
|
||||
<PopoverPaywall
|
||||
message="Appearance"
|
||||
description="With a Premium license, you can customize the appearance and branding of your deployment."
|
||||
documentationLink="https://coder.com/docs/admin/appearance"
|
||||
/>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</Badges>
|
||||
|
||||
<Fieldset
|
||||
|
||||
@@ -41,7 +41,6 @@ import {
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "components/Tooltip/Tooltip";
|
||||
import { useFormik } from "formik";
|
||||
@@ -417,23 +416,21 @@ const OrganizationRow: FC<OrganizationRowProps> = ({
|
||||
<div className="flex flex-row items-center gap-2 text-content-primary">
|
||||
{idpOrg}
|
||||
{!exists && (
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<TriangleAlert className="size-icon-xs cursor-pointer text-content-warning" />
|
||||
</TooltipTrigger>
|
||||
<TooltipContent
|
||||
align="start"
|
||||
alignOffset={-8}
|
||||
sideOffset={8}
|
||||
className="p-2 text-xs text-content-secondary max-w-sm"
|
||||
>
|
||||
This value has not be seen in the specified claim field
|
||||
before. You might want to check your IdP configuration and
|
||||
ensure that this value is not misspelled.
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<TriangleAlert className="size-icon-xs cursor-pointer text-content-warning" />
|
||||
</TooltipTrigger>
|
||||
<TooltipContent
|
||||
align="start"
|
||||
alignOffset={-8}
|
||||
sideOffset={8}
|
||||
className="p-2 text-xs text-content-secondary max-w-sm"
|
||||
>
|
||||
This value has not be seen in the specified claim field before.
|
||||
You might want to check your IdP configuration and ensure that
|
||||
this value is not misspelled.
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
</TableCell>
|
||||
|
||||
@@ -2,7 +2,6 @@ import { Pill } from "components/Pill/Pill";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "components/Tooltip/Tooltip";
|
||||
import type { FC } from "react";
|
||||
@@ -47,36 +46,34 @@ interface OverflowPillProps {
|
||||
|
||||
const OverflowPillList: FC<OverflowPillProps> = ({ organizations }) => {
|
||||
return (
|
||||
<TooltipProvider>
|
||||
<Tooltip delayDuration={0}>
|
||||
<TooltipTrigger asChild>
|
||||
<Pill
|
||||
className="min-h-4 min-w-6 bg-surface-secondary border-none px-3 py-1"
|
||||
data-testid="overflow-pill"
|
||||
>
|
||||
+{organizations.length}
|
||||
</Pill>
|
||||
</TooltipTrigger>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Pill
|
||||
className="min-h-4 min-w-6 bg-surface-secondary border-none px-3 py-1"
|
||||
data-testid="overflow-pill"
|
||||
>
|
||||
+{organizations.length}
|
||||
</Pill>
|
||||
</TooltipTrigger>
|
||||
|
||||
<TooltipContent className="px-4 py-3 border-surface-quaternary">
|
||||
<ul className="flex flex-col gap-2 list-none my-0 pl-0">
|
||||
{organizations.map((organization) => (
|
||||
<li key={organization.name}>
|
||||
<Pill
|
||||
className={cn(
|
||||
"border-none w-fit",
|
||||
organization.isUUID
|
||||
? "bg-surface-destructive"
|
||||
: "bg-surface-secondary",
|
||||
)}
|
||||
>
|
||||
{organization.name}
|
||||
</Pill>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
<TooltipContent className="px-4 py-3 border-surface-quaternary">
|
||||
<ul className="flex flex-col gap-2 list-none my-0 pl-0">
|
||||
{organizations.map((organization) => (
|
||||
<li key={organization.name}>
|
||||
<Pill
|
||||
className={cn(
|
||||
"border-none w-fit",
|
||||
organization.isUUID
|
||||
? "bg-surface-destructive"
|
||||
: "bg-surface-secondary",
|
||||
)}
|
||||
>
|
||||
{organization.name}
|
||||
</Pill>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
|
||||
+22
-25
@@ -15,7 +15,6 @@ import { Stack } from "components/Stack/Stack";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "components/Tooltip/Tooltip";
|
||||
import type { FC } from "react";
|
||||
@@ -53,31 +52,29 @@ export const ObservabilitySettingsPageView: FC<
|
||||
</SettingsHeader>
|
||||
|
||||
<Badges>
|
||||
<TooltipProvider>
|
||||
<Tooltip delayDuration={0}>
|
||||
{featureAuditLogEnabled && !isPremium ? (
|
||||
<EnterpriseBadge />
|
||||
) : (
|
||||
<TooltipTrigger asChild>
|
||||
<span>
|
||||
<PremiumBadge />
|
||||
</span>
|
||||
</TooltipTrigger>
|
||||
)}
|
||||
<Tooltip>
|
||||
{featureAuditLogEnabled && !isPremium ? (
|
||||
<EnterpriseBadge />
|
||||
) : (
|
||||
<TooltipTrigger asChild>
|
||||
<span>
|
||||
<PremiumBadge />
|
||||
</span>
|
||||
</TooltipTrigger>
|
||||
)}
|
||||
|
||||
<TooltipContent
|
||||
sideOffset={-28}
|
||||
collisionPadding={16}
|
||||
className="p-0"
|
||||
>
|
||||
<PopoverPaywall
|
||||
message="Observability"
|
||||
description="With a Premium license, you can monitor your application with logs and metrics."
|
||||
documentationLink="https://coder.com/docs/admin/appearance"
|
||||
/>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
<TooltipContent
|
||||
sideOffset={-28}
|
||||
collisionPadding={16}
|
||||
className="p-0"
|
||||
>
|
||||
<PopoverPaywall
|
||||
message="Observability"
|
||||
description="With a Premium license, you can monitor your application with logs and metrics."
|
||||
documentationLink="https://coder.com/docs/admin/appearance"
|
||||
/>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</Badges>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@ import { Spinner } from "components/Spinner/Spinner";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "components/Tooltip/Tooltip";
|
||||
import { useFormik } from "formik";
|
||||
@@ -82,29 +81,27 @@ export const CreateOrganizationPageView: FC<
|
||||
)}
|
||||
|
||||
<Badges>
|
||||
<TooltipProvider>
|
||||
<Tooltip delayDuration={0}>
|
||||
{isEntitled && (
|
||||
<TooltipTrigger asChild>
|
||||
<span>
|
||||
<PremiumBadge />
|
||||
</span>
|
||||
</TooltipTrigger>
|
||||
)}
|
||||
<Tooltip>
|
||||
{isEntitled && (
|
||||
<TooltipTrigger asChild>
|
||||
<span>
|
||||
<PremiumBadge />
|
||||
</span>
|
||||
</TooltipTrigger>
|
||||
)}
|
||||
|
||||
<TooltipContent
|
||||
sideOffset={-28}
|
||||
collisionPadding={16}
|
||||
className="p-0"
|
||||
>
|
||||
<PopoverPaywall
|
||||
message="Organizations"
|
||||
description="Create multiple organizations within a single Coder deployment, allowing several platform teams to operate with isolated users, templates, and distinct underlying infrastructure."
|
||||
documentationLink={docs("/admin/users/organizations")}
|
||||
/>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
<TooltipContent
|
||||
sideOffset={-28}
|
||||
collisionPadding={16}
|
||||
className="p-0"
|
||||
>
|
||||
<PopoverPaywall
|
||||
message="Organizations"
|
||||
description="Create multiple organizations within a single Coder deployment, allowing several platform teams to operate with isolated users, templates, and distinct underlying infrastructure."
|
||||
documentationLink={docs("/admin/users/organizations")}
|
||||
/>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</Badges>
|
||||
|
||||
<header className="flex flex-col items-center">
|
||||
|
||||
@@ -5,7 +5,6 @@ import { Pill } from "components/Pill/Pill";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "components/Tooltip/Tooltip";
|
||||
import type { FC } from "react";
|
||||
@@ -77,34 +76,29 @@ const OverflowPermissionPill: FC<OverflowPermissionPillProps> = ({
|
||||
const theme = useTheme();
|
||||
|
||||
return (
|
||||
<TooltipProvider>
|
||||
<Tooltip delayDuration={0}>
|
||||
<TooltipTrigger asChild>
|
||||
<Pill
|
||||
css={{
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
borderColor: theme.palette.divider,
|
||||
}}
|
||||
data-testid="overflow-permissions-pill"
|
||||
>
|
||||
+{resources.length} more
|
||||
</Pill>
|
||||
</TooltipTrigger>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Pill
|
||||
css={{
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
borderColor: theme.palette.divider,
|
||||
}}
|
||||
data-testid="overflow-permissions-pill"
|
||||
>
|
||||
+{resources.length} more
|
||||
</Pill>
|
||||
</TooltipTrigger>
|
||||
|
||||
<TooltipContent className="px-4 py-3 border-surface-quaternary">
|
||||
<ul className="flex flex-col gap-2 list-none my-0 pl-0">
|
||||
{resources.map((resource) => (
|
||||
<li key={resource}>
|
||||
<PermissionsPill
|
||||
resource={resource}
|
||||
permissions={permissions}
|
||||
/>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
<TooltipContent className="px-4 py-3 border-surface-quaternary">
|
||||
<ul className="flex flex-col gap-2 list-none my-0 pl-0">
|
||||
{resources.map((resource) => (
|
||||
<li key={resource}>
|
||||
<PermissionsPill resource={resource} permissions={permissions} />
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -25,7 +25,6 @@ import { TableCell, TableRow } from "components/Table/Table";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "components/Tooltip/Tooltip";
|
||||
import { useFormik } from "formik";
|
||||
@@ -370,23 +369,21 @@ const GroupRow: FC<GroupRowProps> = ({
|
||||
<div className="flex flex-row items-center gap-2 text-content-primary">
|
||||
{idpGroup}
|
||||
{!exists && (
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<TriangleAlert className="size-icon-xs cursor-pointer text-content-warning" />
|
||||
</TooltipTrigger>
|
||||
<TooltipContent
|
||||
align="start"
|
||||
alignOffset={-8}
|
||||
sideOffset={8}
|
||||
className="p-2 text-xs text-content-secondary max-w-sm"
|
||||
>
|
||||
This value has not be seen in the specified claim field
|
||||
before. You might want to check your IdP configuration and
|
||||
ensure that this value is not misspelled.
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<TriangleAlert className="size-icon-xs cursor-pointer text-content-warning" />
|
||||
</TooltipTrigger>
|
||||
<TooltipContent
|
||||
align="start"
|
||||
alignOffset={-8}
|
||||
sideOffset={8}
|
||||
className="p-2 text-xs text-content-secondary max-w-sm"
|
||||
>
|
||||
This value has not be seen in the specified claim field before.
|
||||
You might want to check your IdP configuration and ensure that
|
||||
this value is not misspelled.
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
</TableCell>
|
||||
|
||||
@@ -4,7 +4,6 @@ import { Pill } from "components/Pill/Pill";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "components/Tooltip/Tooltip";
|
||||
import type { FC } from "react";
|
||||
@@ -36,25 +35,23 @@ interface OverflowPillProps {
|
||||
|
||||
const OverflowPill: FC<OverflowPillProps> = ({ roles }) => {
|
||||
return (
|
||||
<TooltipProvider>
|
||||
<Tooltip delayDuration={0}>
|
||||
<TooltipTrigger asChild>
|
||||
<Pill data-testid="overflow-pill">+{roles.length} more</Pill>
|
||||
</TooltipTrigger>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Pill data-testid="overflow-pill">+{roles.length} more</Pill>
|
||||
</TooltipTrigger>
|
||||
|
||||
<TooltipContent className="px-4 py-3 border-surface-quaternary">
|
||||
<ul className="flex flex-col gap-2 list-none my-0 pl-0">
|
||||
{roles.map((role) => (
|
||||
<li key={role}>
|
||||
<Pill css={isUUID(role) ? styles.errorPill : styles.pill}>
|
||||
{role}
|
||||
</Pill>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
<TooltipContent className="px-4 py-3 border-surface-quaternary">
|
||||
<ul className="flex flex-col gap-2 list-none my-0 pl-0">
|
||||
{roles.map((role) => (
|
||||
<li key={role}>
|
||||
<Pill css={isUUID(role) ? styles.errorPill : styles.pill}>
|
||||
{role}
|
||||
</Pill>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@ import { TableCell, TableRow } from "components/Table/Table";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "components/Tooltip/Tooltip";
|
||||
import { useFormik } from "formik";
|
||||
@@ -285,23 +284,21 @@ const RoleRow: FC<RoleRowProps> = ({
|
||||
<div className="flex flex-row items-center gap-2 text-content-primary">
|
||||
{idpRole}
|
||||
{!exists && (
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<TriangleAlert className="size-icon-xs cursor-pointer text-content-warning" />
|
||||
</TooltipTrigger>
|
||||
<TooltipContent
|
||||
align="start"
|
||||
alignOffset={-8}
|
||||
sideOffset={8}
|
||||
className="p-2 text-xs text-content-secondary max-w-sm"
|
||||
>
|
||||
This value has not be seen in the specified claim field
|
||||
before. You might want to check your IdP configuration and
|
||||
ensure that this value is not misspelled.
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<TriangleAlert className="size-icon-xs cursor-pointer text-content-warning" />
|
||||
</TooltipTrigger>
|
||||
<TooltipContent
|
||||
align="start"
|
||||
alignOffset={-8}
|
||||
sideOffset={8}
|
||||
className="p-2 text-xs text-content-secondary max-w-sm"
|
||||
>
|
||||
This value has not be seen in the specified claim field before.
|
||||
You might want to check your IdP configuration and ensure that
|
||||
this value is not misspelled.
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
</TableCell>
|
||||
|
||||
+16
-19
@@ -3,7 +3,6 @@ import { Button } from "components/Button/Button";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "components/Tooltip/Tooltip";
|
||||
import { BanIcon } from "lucide-react";
|
||||
@@ -22,24 +21,22 @@ export const CancelJobButton: FC<CancelJobButtonProps> = ({ job }) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
disabled={!isCancellable}
|
||||
aria-label="Cancel job"
|
||||
size="icon"
|
||||
variant="outline"
|
||||
onClick={() => {
|
||||
setIsDialogOpen(true);
|
||||
}}
|
||||
>
|
||||
<BanIcon />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>Cancel job</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
disabled={!isCancellable}
|
||||
aria-label="Cancel job"
|
||||
size="icon"
|
||||
variant="outline"
|
||||
onClick={() => {
|
||||
setIsDialogOpen(true);
|
||||
}}
|
||||
>
|
||||
<BanIcon />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>Cancel job</TooltipContent>
|
||||
</Tooltip>
|
||||
|
||||
<CancelJobConfirmationDialog
|
||||
open={isDialogOpen}
|
||||
|
||||
+15
-18
@@ -37,7 +37,6 @@ import {
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "components/Tooltip/Tooltip";
|
||||
import { XIcon } from "lucide-react";
|
||||
@@ -122,23 +121,21 @@ const OrganizationProvisionerJobsPageView: FC<
|
||||
{filter.ids}
|
||||
</Badge>
|
||||
<div className="size-10 flex items-center justify-center absolute top-0 right-0">
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
size="icon"
|
||||
variant="subtle"
|
||||
onClick={() => {
|
||||
onFilterChange({ ...filter, ids: "" });
|
||||
}}
|
||||
>
|
||||
<span className="sr-only">Clear ID</span>
|
||||
<XIcon />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>Clear ID</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
size="icon"
|
||||
variant="subtle"
|
||||
onClick={() => {
|
||||
onFilterChange({ ...filter, ids: "" });
|
||||
}}
|
||||
>
|
||||
<span className="sr-only">Clear ID</span>
|
||||
<XIcon />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>Clear ID</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
+14
-17
@@ -1,7 +1,6 @@
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "components/Tooltip/Tooltip";
|
||||
import { InfoIcon } from "lucide-react";
|
||||
@@ -10,22 +9,20 @@ export const LastConnectionHead: FC = () => {
|
||||
return (
|
||||
<span className="flex items-center gap-1 whitespace-nowrap text-xs font-medium text-content-secondary">
|
||||
Last connection
|
||||
<TooltipProvider>
|
||||
<Tooltip delayDuration={0}>
|
||||
<TooltipTrigger asChild>
|
||||
<span className="flex items-center">
|
||||
<span className="sr-only">More info</span>
|
||||
<InfoIcon
|
||||
tabIndex={0}
|
||||
className="cursor-pointer size-icon-xs p-0.5"
|
||||
/>
|
||||
</span>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent className="max-w-xs">
|
||||
Last time the provisioner connected to the control plane
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<span className="flex items-center">
|
||||
<span className="sr-only">More info</span>
|
||||
<InfoIcon
|
||||
tabIndex={0}
|
||||
className="cursor-pointer size-icon-xs p-0.5"
|
||||
/>
|
||||
</span>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent className="max-w-xs">
|
||||
Last time the provisioner connected to the control plane
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
+15
-18
@@ -22,7 +22,6 @@ import {
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "components/Tooltip/Tooltip";
|
||||
import { XIcon } from "lucide-react";
|
||||
@@ -75,23 +74,21 @@ export const OrganizationProvisionersPageView: FC<
|
||||
{filter.ids}
|
||||
</Badge>
|
||||
<div className="size-10 flex items-center justify-center absolute top-0 right-0">
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
size="icon"
|
||||
variant="subtle"
|
||||
onClick={() => {
|
||||
onFilterChange({ ...filter, ids: "" });
|
||||
}}
|
||||
>
|
||||
<span className="sr-only">Clear ID</span>
|
||||
<XIcon />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>Clear ID</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
size="icon"
|
||||
variant="subtle"
|
||||
onClick={() => {
|
||||
onFilterChange({ ...filter, ids: "" });
|
||||
}}
|
||||
>
|
||||
<span className="sr-only">Clear ID</span>
|
||||
<XIcon />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>Clear ID</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+14
-17
@@ -6,7 +6,6 @@ import {
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "components/Tooltip/Tooltip";
|
||||
import { InfoIcon } from "lucide-react";
|
||||
@@ -63,22 +62,20 @@ export const ProvisionerKey: FC<ProvisionerKeyProps> = ({ name }) => {
|
||||
<span className="flex items-center gap-1 whitespace-nowrap text-xs font-medium text-content-secondary">
|
||||
{name}
|
||||
{info && (
|
||||
<TooltipProvider>
|
||||
<Tooltip delayDuration={0}>
|
||||
<TooltipTrigger asChild>
|
||||
<span className="flex items-center">
|
||||
<span className="sr-only">More info</span>
|
||||
<InfoIcon
|
||||
tabIndex={0}
|
||||
className="cursor-pointer size-icon-xs p-0.5"
|
||||
/>
|
||||
</span>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent className="max-w-xs">
|
||||
{infoByType[type]}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<span className="flex items-center">
|
||||
<span className="sr-only">More info</span>
|
||||
<InfoIcon
|
||||
tabIndex={0}
|
||||
className="cursor-pointer size-icon-xs p-0.5"
|
||||
/>
|
||||
</span>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent className="max-w-xs">
|
||||
{infoByType[type]}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
</span>
|
||||
);
|
||||
|
||||
+20
-23
@@ -2,7 +2,6 @@ import { StatusIndicator } from "components/StatusIndicator/StatusIndicator";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "components/Tooltip/Tooltip";
|
||||
import { TriangleAlertIcon } from "lucide-react";
|
||||
@@ -22,27 +21,25 @@ export const ProvisionerVersion: FC<ProvisionerVersionProps> = ({
|
||||
Up to date
|
||||
</span>
|
||||
) : (
|
||||
<TooltipProvider>
|
||||
<Tooltip delayDuration={0}>
|
||||
<TooltipTrigger asChild>
|
||||
<StatusIndicator
|
||||
variant="warning"
|
||||
size="sm"
|
||||
className="cursor-pointer"
|
||||
tabIndex={0}
|
||||
>
|
||||
<TriangleAlertIcon className="size-icon-xs" />
|
||||
Outdated
|
||||
</StatusIndicator>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent className="max-w-xs">
|
||||
<p className="m-0">
|
||||
This provisioner is out of date. You may experience issues when
|
||||
using a provisioner version that doesn't match your Coder
|
||||
deployment. Please upgrade to a newer version.
|
||||
</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<StatusIndicator
|
||||
variant="warning"
|
||||
size="sm"
|
||||
className="cursor-pointer"
|
||||
tabIndex={0}
|
||||
>
|
||||
<TriangleAlertIcon className="size-icon-xs" />
|
||||
Outdated
|
||||
</StatusIndicator>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent className="max-w-xs">
|
||||
<p className="m-0">
|
||||
This provisioner is out of date. You may experience issues when using
|
||||
a provisioner version that doesn't match your Coder deployment. Please
|
||||
upgrade to a newer version.
|
||||
</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -10,7 +10,6 @@ import { ScrollArea } from "components/ScrollArea/ScrollArea";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "components/Tooltip/Tooltip";
|
||||
import capitalize from "lodash/capitalize";
|
||||
@@ -99,19 +98,17 @@ export const AppStatuses: FC<AppStatusesProps> = ({
|
||||
|
||||
{latestStatus.uri &&
|
||||
(latestStatus.uri.startsWith("file://") ? (
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger>
|
||||
<span className="flex items-center gap-1">
|
||||
<FileIcon className="size-icon-xs" />
|
||||
{truncateURI(latestStatus.uri)}
|
||||
</span>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
This file is located in your workspace
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger>
|
||||
<span className="flex items-center gap-1">
|
||||
<FileIcon className="size-icon-xs" />
|
||||
{truncateURI(latestStatus.uri)}
|
||||
</span>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
This file is located in your workspace
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
) : (
|
||||
<Button asChild variant="outline" size="sm">
|
||||
<a href={latestStatus.uri} target="_blank" rel="noreferrer">
|
||||
@@ -132,25 +129,23 @@ export const AppStatuses: FC<AppStatusesProps> = ({
|
||||
</Button>
|
||||
)}
|
||||
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
disabled={otherStatuses.length === 0}
|
||||
size="icon"
|
||||
variant="subtle"
|
||||
onClick={() => {
|
||||
setDisplayStatuses((display) => !display);
|
||||
}}
|
||||
>
|
||||
{displayStatuses ? <ChevronUpIcon /> : <ChevronDownIcon />}
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
{displayStatuses ? "Hide statuses" : "Show statuses"}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
disabled={otherStatuses.length === 0}
|
||||
size="icon"
|
||||
variant="subtle"
|
||||
onClick={() => {
|
||||
setDisplayStatuses((display) => !display);
|
||||
}}
|
||||
>
|
||||
{displayStatuses ? <ChevronUpIcon /> : <ChevronDownIcon />}
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
{displayStatuses ? "Hide statuses" : "Show statuses"}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
render as testingLibraryRender,
|
||||
waitFor,
|
||||
} from "@testing-library/react";
|
||||
import { TooltipProvider } from "components/Tooltip/Tooltip";
|
||||
import { RequireAuth } from "contexts/auth/RequireAuth";
|
||||
import type { ProxyProvider } from "contexts/ProxyContext";
|
||||
import { ThemeOverride } from "contexts/ThemeProvider";
|
||||
@@ -239,7 +240,9 @@ export const waitForLoaderToBeRemoved = async (): Promise<void> => {
|
||||
export const renderComponent = (component: React.ReactNode) => {
|
||||
return testingLibraryRender(component, {
|
||||
wrapper: ({ children }) => (
|
||||
<ThemeOverride theme={themes[DEFAULT_THEME]}>{children}</ThemeOverride>
|
||||
<ThemeOverride theme={themes[DEFAULT_THEME]}>
|
||||
<TooltipProvider delayDuration={100}>{children}</TooltipProvider>
|
||||
</ThemeOverride>
|
||||
),
|
||||
});
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user