chore: convert emotion styles to tailwind (#19357)

This commit is contained in:
Brett Kolodny
2025-08-18 15:00:58 -04:00
committed by GitHub
parent 3e7c8c9052
commit 95388f7576
6 changed files with 41 additions and 163 deletions
+16 -79
View File
@@ -1,4 +1,3 @@
import type { Interpolation, Theme } from "@emotion/react";
import Skeleton from "@mui/material/Skeleton";
import Tooltip from "@mui/material/Tooltip";
import { watchAgentMetadata } from "api/api";
@@ -18,7 +17,7 @@ import {
useRef,
useState,
} from "react";
import { MONOSPACE_FONT_FAMILY } from "theme/constants";
import { cn } from "utils/cn";
import type { OneWayWebSocket } from "utils/OneWayWebSocket";
type ItemStatus = "stale" | "valid" | "loading";
@@ -32,7 +31,7 @@ export const AgentMetadataView: FC<AgentMetadataViewProps> = ({ metadata }) => {
return null;
}
return (
<section css={styles.root}>
<section className="flex items-baseline flex-wrap gap-8 gap-y-4">
{metadata.map((m) => (
<MetadataItem key={m.description.key} item={m} />
))}
@@ -122,7 +121,7 @@ export const AgentMetadata: FC<AgentMetadataProps> = ({
if (activeMetadata === undefined) {
return (
<section css={styles.root}>
<section className="flex items-baseline flex-wrap gap-8 gap-y-4">
<AgentMetadataSkeleton />
</section>
);
@@ -134,17 +133,17 @@ export const AgentMetadata: FC<AgentMetadataProps> = ({
const AgentMetadataSkeleton: FC = () => {
return (
<Stack alignItems="baseline" direction="row" spacing={6}>
<div css={styles.metadata}>
<div className="leading-relaxed flex flex-col overflow-visible flex-shrink-0">
<Skeleton width={40} height={12} variant="text" />
<Skeleton width={65} height={14} variant="text" />
</div>
<div css={styles.metadata}>
<div className="leading-relaxed flex flex-col overflow-visible flex-shrink-0">
<Skeleton width={40} height={12} variant="text" />
<Skeleton width={65} height={14} variant="text" />
</div>
<div css={styles.metadata}>
<div className="leading-relaxed flex flex-col overflow-visible flex-shrink-0">
<Skeleton width={40} height={12} variant="text" />
<Skeleton width={65} height={14} variant="text" />
</div>
@@ -182,29 +181,29 @@ const MetadataItem: FC<MetadataItemProps> = ({ item }) => {
// could be buggy. But, how common is that anyways?
const value =
status === "loading" ? (
<Skeleton width={65} height={12} variant="text" css={styles.skeleton} />
<Skeleton width={65} height={12} variant="text" className="mt-[6px]" />
) : status === "stale" ? (
<Tooltip title="This data is stale and no longer up to date">
<StaticWidth css={[styles.metadataValue, styles.metadataStale]}>
<StaticWidth className="text-ellipsis overflow-hidden whitespace-nowrap max-w-64 text-sm text-content-disabled cursor-pointer">
{item.result.value}
</StaticWidth>
</Tooltip>
) : (
<StaticWidth
css={[
styles.metadataValue,
item.result.error.length === 0
? styles.metadataValueSuccess
: styles.metadataValueError,
]}
className={cn(
"text-ellipsis overflow-hidden whitespace-nowrap max-w-64 text-sm text-content-success",
item.result.error.length > 0 && "text-content-destructive",
)}
>
{item.result.value}
</StaticWidth>
);
return (
<div css={styles.metadata}>
<div css={styles.metadataLabel}>{item.description.display_name}</div>
<div className="leading-relaxed flex flex-col overflow-visible flex-shrink-0">
<div className="text-content-secondary text-ellipsis overflow-hidden whitespace-nowrap text-[13px]">
{item.description.display_name}
</div>
<div>{value}</div>
</div>
);
@@ -236,65 +235,3 @@ const StaticWidth: FC<HTMLAttributes<HTMLDivElement>> = ({
</div>
);
};
// These are more or less copied from
// site/src/modules/resources/ResourceCard.tsx
const styles = {
root: {
display: "flex",
alignItems: "baseline",
flexWrap: "wrap",
gap: 32,
rowGap: 16,
},
metadata: {
lineHeight: "1.6",
display: "flex",
flexDirection: "column",
overflow: "visible",
flexShrink: 0,
},
metadataLabel: (theme) => ({
color: theme.palette.text.secondary,
textOverflow: "ellipsis",
overflow: "hidden",
whiteSpace: "nowrap",
fontSize: 13,
}),
metadataValue: {
textOverflow: "ellipsis",
overflow: "hidden",
whiteSpace: "nowrap",
maxWidth: "16em",
fontSize: 14,
},
metadataValueSuccess: (theme) => ({
color: theme.roles.success.fill.outline,
}),
metadataValueError: (theme) => ({
color: theme.palette.error.main,
}),
metadataStale: (theme) => ({
color: theme.palette.text.disabled,
cursor: "pointer",
}),
skeleton: {
marginTop: 4,
},
inlineCommand: (theme) => ({
fontFamily: MONOSPACE_FONT_FAMILY,
display: "inline-block",
fontWeight: 600,
margin: 0,
borderRadius: 4,
color: theme.palette.text.primary,
}),
} satisfies Record<string, Interpolation<Theme>>;
@@ -1,4 +1,3 @@
import { useTheme } from "@emotion/react";
import type { WorkspaceAgent } from "api/typesGenerated";
import { PopoverTrigger } from "components/deprecated/Popover/Popover";
import {
@@ -27,11 +26,6 @@ export const AgentOutdatedTooltip: FC<AgentOutdatedTooltipProps> = ({
status,
onUpdate,
}) => {
const theme = useTheme();
const versionLabelStyles = {
fontWeight: 600,
color: theme.palette.text.primary,
};
const title =
status === agentVersionStatus.Outdated
? "Agent Outdated"
@@ -45,7 +39,7 @@ export const AgentOutdatedTooltip: FC<AgentOutdatedTooltipProps> = ({
return (
<HelpTooltip>
<PopoverTrigger>
<span role="status" css={{ cursor: "pointer" }}>
<span role="status" className="cursor-pointer">
{status === agentVersionStatus.Outdated ? "Outdated" : "Deprecated"}
</span>
</PopoverTrigger>
@@ -57,12 +51,16 @@ export const AgentOutdatedTooltip: FC<AgentOutdatedTooltipProps> = ({
</div>
<Stack spacing={0.5}>
<span css={versionLabelStyles}>Agent version</span>
<span className="font-semibold text-content-primary">
Agent version
</span>
<span>{agent.version}</span>
</Stack>
<Stack spacing={0.5}>
<span css={versionLabelStyles}>Server version</span>
<span className="font-semibold text-content-primary">
Server version
</span>
<span>{serverVersion}</span>
</Stack>
@@ -1,4 +1,3 @@
import { useTheme } from "@emotion/react";
import type * as TypesGen from "api/typesGenerated";
import { DropdownMenuItem } from "components/DropdownMenu/DropdownMenu";
import { Spinner } from "components/Spinner/Spinner";
@@ -41,7 +40,6 @@ export const AppLink: FC<AppLinkProps> = ({
const { proxy } = useProxy();
const host = proxy.preferredWildcardHostname;
const [iconError, setIconError] = useState(false);
const theme = useTheme();
const link = useAppLink(app, { agent, workspace });
// canClick is ONLY false when it's a subdomain app and the admin hasn't
@@ -64,8 +62,7 @@ export const AppLink: FC<AppLinkProps> = ({
icon = (
<CircleAlertIcon
aria-hidden="true"
className="size-icon-sm"
css={{ color: theme.palette.warning.light }}
className="size-icon-sm text-content-warning"
/>
);
primaryTooltip = "Unhealthy";
@@ -76,8 +73,7 @@ export const AppLink: FC<AppLinkProps> = ({
icon = (
<CircleAlertIcon
aria-hidden="true"
className="size-icon-sm"
css={{ color: theme.palette.grey[300] }}
className="size-icon-sm text-content-secondary"
/>
);
primaryTooltip =
@@ -4,20 +4,7 @@ import type { FC, PropsWithChildren } from "react";
export const AppPreview: FC<PropsWithChildren> = ({ children }) => {
return (
<Stack
css={(theme) => ({
padding: "2px 12px",
borderRadius: 9999,
border: `1px solid ${theme.palette.divider}`,
color: theme.palette.text.primary,
background: theme.palette.background.paper,
flexShrink: 0,
width: "fit-content",
fontSize: 12,
"& img, & svg": {
width: 13,
},
})}
className="flex items-center h-8 px-3 rounded-full border border-solid border-surface-quaternary text-content-primary bg-surface-secondary flex-shrink-0 w-fit text-xs [&>svg]:w-[13px] [&>img]:w-[13px]"
alignItems="center"
direction="row"
spacing={1}
+3 -24
View File
@@ -1,4 +1,3 @@
import { type Interpolation, type Theme, useTheme } from "@emotion/react";
import Button from "@mui/material/Button";
import type { WorkspaceAgent, WorkspaceResource } from "api/typesGenerated";
import { DropdownArrow } from "components/DropdownArrow/DropdownArrow";
@@ -16,7 +15,6 @@ interface ResourcesProps {
}
export const Resources: FC<ResourcesProps> = ({ resources, agentRow }) => {
const theme = useTheme();
const [shouldDisplayHideResources, setShouldDisplayHideResources] =
useState(false);
const displayResources = shouldDisplayHideResources
@@ -28,11 +26,7 @@ export const Resources: FC<ResourcesProps> = ({ resources, agentRow }) => {
const hasHideResources = resources.some((r) => r.hide);
return (
<Stack
direction="column"
spacing={0}
css={{ background: theme.palette.background.default }}
>
<Stack direction="column" spacing={0} className="bg-surface-primary">
{displayResources.map((resource) => (
<ResourceCard
key={resource.id}
@@ -41,9 +35,9 @@ export const Resources: FC<ResourcesProps> = ({ resources, agentRow }) => {
/>
))}
{hasHideResources && (
<div css={styles.buttonWrapper}>
<div className="flex items-center justify-center mt-4">
<Button
css={styles.showMoreButton}
className="rounded-full w-full max-w-[260px]"
size="small"
onClick={() => setShouldDisplayHideResources((v) => !v)}
>
@@ -55,18 +49,3 @@ export const Resources: FC<ResourcesProps> = ({ resources, agentRow }) => {
</Stack>
);
};
const styles = {
buttonWrapper: {
display: "flex",
alignItems: "center",
justifyContent: "center",
marginTop: 16,
},
showMoreButton: {
borderRadius: 9999,
width: "100%",
maxWidth: 260,
},
} satisfies Record<string, Interpolation<Theme>>;
@@ -1,19 +1,17 @@
import type { Interpolation, Theme } from "@emotion/react";
import { deploymentSSHConfig } from "api/queries/deployment";
import { Button } from "components/Button/Button";
import { CodeExample } from "components/CodeExample/CodeExample";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "components/deprecated/Popover/Popover";
import {
HelpTooltipLink,
HelpTooltipLinksGroup,
HelpTooltipText,
} from "components/HelpTooltip/HelpTooltip";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "components/Popover/Popover";
import { Stack } from "components/Stack/Stack";
import { type ClassName, useClassName } from "hooks/useClassName";
import { ChevronDownIcon } from "lucide-react";
import type { FC } from "react";
import { useQuery } from "react-query";
@@ -30,26 +28,28 @@ export const AgentSSHButton: FC<AgentSSHButtonProps> = ({
agentName,
workspaceOwnerUsername,
}) => {
const paper = useClassName(classNames.paper, []);
const { data } = useQuery(deploymentSSHConfig());
const sshSuffix = data?.hostname_suffix;
return (
<Popover>
<PopoverTrigger>
<PopoverTrigger asChild={true}>
<Button size="sm" variant="subtle">
Connect via SSH
<ChevronDownIcon />
</Button>
</PopoverTrigger>
<PopoverContent horizontal="right" classes={{ paper }}>
<PopoverContent
align="end"
className="py-4 px-6 w-80 text-content-secondary mt-[2px] bg-surface-secondary"
>
<HelpTooltipText>
Run the following commands to connect with SSH:
</HelpTooltipText>
<ol style={{ margin: 0, padding: 0 }}>
<Stack spacing={0.5} css={styles.codeExamples}>
<Stack spacing={0.5} className="mt-3">
<SSHStep
helpText="Configure SSH hosts on machine:"
codeExample="coder config-ssh"
@@ -93,27 +93,8 @@ interface SSHStepProps {
const SSHStep: FC<SSHStepProps> = ({ helpText, codeExample }) => (
<li style={{ listStylePosition: "inside" }}>
<HelpTooltipText style={{ display: "inline" }}>
<strong css={styles.codeExampleLabel}>{helpText}</strong>
<strong className="text-xs">{helpText}</strong>
</HelpTooltipText>
<CodeExample secret={false} code={codeExample} />
</li>
);
const classNames = {
paper: (css, theme) => css`
padding: 16px 24px 24px;
width: 304px;
color: ${theme.palette.text.secondary};
margin-top: 2px;
`,
} satisfies Record<string, ClassName>;
const styles = {
codeExamples: {
marginTop: 12,
},
codeExampleLabel: {
fontSize: 12,
},
} satisfies Record<string, Interpolation<Theme>>;