refactor(site): remove Stack component (#24503)

## Summary

Remove the deprecated `Stack` component and replace all usages with
Tailwind flex utility classes.

- Replaced `<Stack>` → `<div className="flex flex-col gap-4">` (and
variants per props)
- Updated `StackLabel` and `FormFields` to no longer depend on `Stack`
- Deleted `Stack.tsx` and `Stack.stories.tsx`

74 files changed, -226 lines net.

> 🤖 Generated by Coder Agents

---------

Co-authored-by: Jake Howell <jacob@coder.com>
This commit is contained in:
Kayla はな
2026-04-28 12:02:13 -06:00
committed by GitHub
co-authored by Jake Howell
parent 55ed6cfa06
commit 5afb297042
74 changed files with 265 additions and 519 deletions
+1 -4
View File
@@ -1,5 +1,4 @@
import { Badge } from "#/components/Badge/Badge";
import { Stack } from "#/components/Stack/Stack";
export const EnabledBadge: React.FC = () => {
return (
@@ -51,8 +50,6 @@ export const DeprecatedBadge: React.FC = () => {
export const Badges: React.FC<React.PropsWithChildren> = ({ children }) => {
return (
<Stack className="mb-4" direction="row" alignItems="center" spacing={1}>
{children}
</Stack>
<div className="flex flex-row items-center gap-2 mb-4">{children}</div>
);
};
@@ -1,7 +1,6 @@
import type { Interpolation, Theme } from "@emotion/react";
import TextField from "@mui/material/TextField";
import { type FC, type FormEvent, useId, useState } from "react";
import { Stack } from "../../Stack/Stack";
import { ConfirmDialog } from "../ConfirmDialog/ConfirmDialog";
interface DeleteDialogProps {
@@ -62,17 +61,15 @@ export const DeleteDialog: FC<DeleteDialogProps> = ({
confirmText={confirmText}
description={
<>
<Stack spacing={1.5}>
<div className="flex flex-col gap-3">
<p>
{verb ?? "Deleting"} this {entity} is irreversible!
</p>
{Boolean(info) && <div css={styles.callout}>{info}</div>}
<p>
Type <strong>{name}</strong> below to confirm.
</p>
</Stack>
</div>
<form onSubmit={onSubmit}>
<TextField
+9 -12
View File
@@ -3,7 +3,6 @@ import CircularProgress from "@mui/material/CircularProgress";
import { CloudUploadIcon, FolderIcon, TrashIcon } from "lucide-react";
import { type DragEvent, type FC, type ReactNode, useRef } from "react";
import { Button } from "#/components/Button/Button";
import { Stack } from "#/components/Stack/Stack";
import { useClickable } from "#/hooks/useClickable";
interface FileUploadProps {
@@ -35,16 +34,14 @@ export const FileUpload: FC<FileUploadProps> = ({
if (!isUploading && file) {
return (
<Stack
<div
css={styles.file}
direction="row"
justifyContent="space-between"
alignItems="center"
className="flex flex-row justify-between items-center gap-4"
>
<Stack direction="row" alignItems="center">
<div className="flex flex-row items-center gap-4">
<FolderIcon className="size-icon-sm" />
<span>{file.name}</span>
</Stack>
</div>
<Button
variant="subtle"
@@ -54,7 +51,7 @@ export const FileUpload: FC<FileUploadProps> = ({
>
<TrashIcon className="size-icon-sm" />
</Button>
</Stack>
</div>
);
}
@@ -66,7 +63,7 @@ export const FileUpload: FC<FileUploadProps> = ({
{...clickable}
{...fileDrop}
>
<Stack alignItems="center" spacing={1}>
<div className="flex flex-col items-center gap-2">
<div css={styles.iconWrapper}>
{isUploading ? (
<CircularProgress size={32} />
@@ -75,11 +72,11 @@ export const FileUpload: FC<FileUploadProps> = ({
)}
</div>
<Stack alignItems="center" spacing={0.5}>
<div className="flex flex-col items-center gap-1">
<span css={styles.title}>{title}</span>
<span css={styles.description}>{description}</span>
</Stack>
</Stack>
</div>
</div>
</div>
<input
+6 -5
View File
@@ -8,7 +8,6 @@ import {
useContext,
} from "react";
import { AlphaBadge, DeprecatedBadge } from "#/components/Badges/Badges";
import { Stack } from "#/components/Stack/Stack";
import { cn } from "#/utils/cn";
type FormContextValue = { direction?: "horizontal" | "vertical" };
@@ -120,11 +119,13 @@ export const FormSection: FC<FormSectionProps> = ({
);
};
export const FormFields: FC<ComponentProps<typeof Stack>> = (props) => {
export const FormFields: FC<ComponentProps<"div">> = ({
className,
...props
}) => {
return (
<Stack
direction="column"
spacing={3}
<div
className={cn("flex flex-col gap-6", className)}
{...props}
css={styles.formSectionFields}
/>
@@ -3,7 +3,6 @@ import type { Meta, StoryObj } from "@storybook/react-vite";
import type { FC } from "react";
import { Button } from "#/components/Button/Button";
import { FormFooter } from "#/components/Form/Form";
import { Stack } from "../Stack/Stack";
import { FullPageForm, type FullPageFormProps } from "./FullPageForm";
const Template: FC<FullPageFormProps> = (props) => (
@@ -13,14 +12,14 @@ const Template: FC<FullPageFormProps> = (props) => (
e.preventDefault();
}}
>
<Stack>
<div className="flex flex-col gap-4">
<TextField fullWidth label="Field 1" name="field1" />
<TextField fullWidth label="Field 2" name="field2" />
<FormFooter>
<Button variant="outline">Cancel</Button>
<Button type="submit">Save</Button>
</FormFooter>
</Stack>
</div>
</form>
</FullPageForm>
);
@@ -12,12 +12,12 @@ import { Button } from "#/components/Button/Button";
import { ExternalImage } from "#/components/ExternalImage/ExternalImage";
import { MemoizedMarkdown } from "#/components/Markdown/Markdown";
import { Pill } from "#/components/Pill/Pill";
import { Stack } from "#/components/Stack/Stack";
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from "#/components/Tooltip/Tooltip";
import { cn } from "#/utils/cn";
import type {
AutofillBuildParameter,
AutofillSource,
@@ -182,7 +182,7 @@ const ParameterLabel: FC<ParameterLabelProps> = ({ parameter, isPreset }) => {
return (
<label htmlFor={parameter.name}>
<Stack direction="row" alignItems="center">
<div className="flex flex-row items-center gap-4">
{parameter.icon && (
<span css={styles.labelIconWrapper}>
<ExternalImage
@@ -194,16 +194,16 @@ const ParameterLabel: FC<ParameterLabelProps> = ({ parameter, isPreset }) => {
)}
{hasDescription ? (
<Stack spacing={0}>
<div className="flex flex-col gap-0">
{labelPrimary}
<MemoizedMarkdown css={styles.labelCaption}>
{parameter.description}
</MemoizedMarkdown>
</Stack>
</div>
) : (
labelPrimary
)}
</Stack>
</div>
</label>
);
};
@@ -235,10 +235,12 @@ export const RichParameterInput: FC<RichParameterInputProps> = ({
const [hideSuggestion, setHideSuggestion] = useState(false);
return (
<Stack
direction="column"
spacing={size === "small" ? 1.25 : 2}
className={size}
<div
className={cn(
"flex flex-col",
size === "small" ? "gap-2.5" : "gap-4",
size,
)}
data-testid={`parameter-field-${parameter.name}`}
>
<ParameterLabel parameter={parameter} isPreset={isPreset} />
@@ -276,7 +278,7 @@ export const RichParameterInput: FC<RichParameterInputProps> = ({
</div>
)}
</div>
</Stack>
</div>
);
};
@@ -332,7 +334,7 @@ const RichParameterField: FC<RichParameterInputProps> = ({
value={option.value}
control={<Radio size="small" />}
label={
<Stack direction="row" alignItems="center">
<div className="flex flex-row items-center gap-4">
{option.icon && (
<ExternalImage
css={styles.optionIcon}
@@ -341,11 +343,13 @@ const RichParameterField: FC<RichParameterInputProps> = ({
/>
)}
{option.description ? (
<Stack
spacing={small ? 1 : 0}
alignItems={small ? "center" : undefined}
direction={small ? "row" : "column"}
className={small ? undefined : "py-1"}
<div
className={cn(
"flex",
small
? "flex-row gap-2 items-center"
: "flex-col gap-0 py-1",
)}
>
{small ? (
<Tooltip>
@@ -366,11 +370,11 @@ const RichParameterField: FC<RichParameterInputProps> = ({
</MemoizedMarkdown>
</>
)}
</Stack>
</div>
) : (
option.name
)}
</Stack>
</div>
}
/>
))}
+4 -5
View File
@@ -1,6 +1,5 @@
import type { ElementType, FC, ReactNode } from "react";
import { Link, NavLink } from "react-router";
import { Stack } from "#/components/Stack/Stack";
import { cn } from "#/utils/cn";
interface SidebarProps {
@@ -31,7 +30,7 @@ export const SidebarHeader: FC<SidebarHeaderProps> = ({
linkTo,
}) => {
return (
<Stack direction="row" spacing={1} className="mb-4">
<div className="flex flex-row gap-2 mb-4">
{avatar}
<div className="overflow-hidden flex flex-col">
{linkTo ? (
@@ -45,7 +44,7 @@ export const SidebarHeader: FC<SidebarHeaderProps> = ({
{subtitle}
</span>
</div>
</Stack>
</div>
);
};
@@ -100,10 +99,10 @@ export const SidebarNavItem: FC<SidebarNavItemProps> = ({
)
}
>
<Stack alignItems="center" spacing={1.5} direction="row">
<div className="flex flex-row gap-3 items-center">
<Icon className="size-4" />
{children}
</Stack>
</div>
</NavLink>
);
};
@@ -1,47 +0,0 @@
import type { Meta, StoryObj } from "@storybook/react-vite";
import { Stack } from "./Stack";
const meta: Meta<typeof Stack> = {
title: "components/Stack",
component: Stack,
args: {
children: (
<>
<span>チェンソーマン</span>
<span>ジョジョの奇妙な冒険</span>
<span>スパイファミリー</span>
<span>葬送のフリーレン</span>
<span>少女革命ウテナ</span>
<span>PSYCHO-PASS サイコパス</span>
<span>機動戦士ガンダム 水星の魔女</span>
<span>勇気爆発バーンブレイバーン</span>
<span>Re:ゼロから始める異世界生活</span>
<span>ダンジョン飯</span>
</>
),
},
};
export default meta;
type Story = StoryObj<typeof Stack>;
export const Vertical: Story = {};
export const VerticalCenter: Story = {
args: {
alignItems: "center",
},
};
export const Horizontal: Story = {
args: {
direction: "row",
},
};
export const HorizontalWrap: Story = {
args: {
direction: "row",
wrap: "wrap",
},
};
-42
View File
@@ -1,42 +0,0 @@
import type { CSSObject } from "@emotion/react";
type StackProps = React.ComponentPropsWithRef<"div"> & {
className?: string;
direction?: "column" | "row";
spacing?: number;
alignItems?: CSSObject["alignItems"];
justifyContent?: CSSObject["justifyContent"];
wrap?: CSSObject["flexWrap"];
};
/**
* @deprecated Stack component is deprecated. Use Tailwind flex utilities instead.
*/
export const Stack: React.FC<StackProps> = (props) => {
const {
children,
direction = "column",
spacing = 2,
alignItems,
justifyContent,
wrap,
...divProps
} = props;
return (
<div
{...divProps}
css={{
display: "flex",
flexDirection: direction,
gap: spacing * 8,
alignItems: alignItems,
justifyContent: justifyContent,
flexWrap: wrap,
maxWidth: "100%",
}}
>
{children}
</div>
);
};
@@ -1,5 +1,4 @@
import type { ComponentProps, FC } from "react";
import { Stack } from "#/components/Stack/Stack";
import { cn } from "#/utils/cn";
/**
@@ -7,14 +6,13 @@ import { cn } from "#/utils/cn";
* buttons, checkboxes, or switches to ensure proper styling.
*/
export const StackLabel: FC<ComponentProps<typeof Stack>> = ({
export const StackLabel: FC<ComponentProps<"div">> = ({
className,
...props
}) => {
return (
<Stack
spacing={0.5}
className={cn("pl-3 font-medium", className)}
<div
className={cn("flex flex-col gap-1 pl-3 font-medium", className)}
{...props}
/>
);
@@ -5,7 +5,6 @@ import {
Sidebar as BaseSidebar,
SettingsSidebarNavItem as SidebarNavItem,
} from "#/components/Sidebar/Sidebar";
import { Stack } from "#/components/Stack/Stack";
import type { Permissions } from "#/modules/permissions";
import { getPrereleaseFlag } from "#/utils/buildInfo";
@@ -86,9 +85,9 @@ export const DeploymentSidebarView: FC<DeploymentSidebarViewProps> = ({
)}
{permissions.viewAnyGroup && (
<SidebarNavItem href="/deployment/groups">
<Stack direction="row" alignItems="center" spacing={0.5}>
<div className="flex flex-row items-center gap-1">
Groups {showOrganizations && <ArrowUpRightIcon size={16} />}
</Stack>
</div>
</SidebarNavItem>
)}
{permissions.viewOrganizationIDPSyncSettings && (
@@ -108,9 +107,9 @@ export const DeploymentSidebarView: FC<DeploymentSidebarViewProps> = ({
)}
{permissions.editDeploymentConfig && (
<SidebarNavItem href="/agents/settings/agents">
<Stack direction="row" alignItems="center" spacing={0.5}>
<div className="flex flex-row items-center gap-1">
Manage Coder Agents <ArrowUpRightIcon size={16} />
</Stack>
</div>
</SidebarNavItem>
)}
</div>
+2 -3
View File
@@ -15,7 +15,6 @@ import type {
WorkspaceAgentMetadata,
} from "#/api/typesGenerated";
import { Skeleton } from "#/components/Skeleton/Skeleton";
import { Stack } from "#/components/Stack/Stack";
import {
Tooltip,
TooltipContent,
@@ -139,7 +138,7 @@ export const AgentMetadata: FC<AgentMetadataProps> = ({
const AgentMetadataSkeleton: FC = () => {
return (
<Stack alignItems="baseline" direction="row" spacing={6}>
<div className="flex flex-row items-baseline gap-12">
<div className="leading-relaxed flex flex-col overflow-visible flex-shrink-0">
<Skeleton width={40} height={6} variant="text" />
<Skeleton width={65} height={8} variant="text" />
@@ -154,7 +153,7 @@ const AgentMetadataSkeleton: FC = () => {
<Skeleton width={40} height={6} variant="text" />
<Skeleton width={65} height={8} variant="text" />
</div>
</Stack>
</div>
);
};
@@ -10,7 +10,6 @@ import {
HelpPopoverTitle,
HelpPopoverTrigger,
} from "#/components/HelpPopover/HelpPopover";
import { Stack } from "#/components/Stack/Stack";
import { agentVersionStatus } from "../../utils/workspace";
type AgentOutdatedTooltipProps = {
@@ -46,25 +45,25 @@ export const AgentOutdatedTooltip: FC<AgentOutdatedTooltipProps> = ({
</span>
</HelpPopoverTrigger>
<HelpPopoverContent>
<Stack spacing={1}>
<div className="flex flex-col gap-2">
<div>
<HelpPopoverTitle>{title}</HelpPopoverTitle>
<HelpPopoverText>{text}</HelpPopoverText>
</div>
<Stack spacing={0.5}>
<div className="flex flex-col gap-1">
<span className="font-semibold text-content-primary">
Agent version
</span>
<span>{agent.version}</span>
</Stack>
</div>
<Stack spacing={0.5}>
<div className="flex flex-col gap-1">
<span className="font-semibold text-content-primary">
Server version
</span>
<span>{serverVersion}</span>
</Stack>
</div>
<HelpPopoverLinksGroup>
<HelpPopoverAction
@@ -78,7 +77,7 @@ export const AgentOutdatedTooltip: FC<AgentOutdatedTooltipProps> = ({
Update workspace
</HelpPopoverAction>
</HelpPopoverLinksGroup>
</Stack>
</div>
</HelpPopoverContent>
</HelpPopover>
);
+19 -35
View File
@@ -3,7 +3,6 @@ import type { FC } from "react";
import type { WorkspaceAgent } from "#/api/typesGenerated";
import { TerminalIcon } from "#/components/Icons/TerminalIcon";
import { VSCodeIcon } from "#/components/Icons/VSCodeIcon";
import { Stack } from "#/components/Stack/Stack";
import { DisplayAppNameMap } from "./AppLink/AppLink";
import { AppPreview } from "./AppLink/AppPreview";
import { BaseIcon } from "./AppLink/BaseIcon";
@@ -22,27 +21,21 @@ export const AgentRowPreview: FC<AgentRowPreviewProps> = ({
alignValues,
}) => {
return (
<Stack
<div
key={agent.id}
direction="row"
alignItems="center"
justifyContent="space-between"
className="flex flex-row items-center justify-between gap-4"
css={styles.agentRow}
>
<Stack direction="row" alignItems="baseline">
<div className="flex flex-row items-baseline gap-4">
<div css={styles.agentStatusWrapper}>
<div css={styles.agentStatusPreview} />
</div>
<Stack
alignItems="baseline"
direction="row"
spacing={4}
<div
className="flex flex-row items-baseline gap-8"
css={styles.agentData}
>
<Stack
direction="row"
alignItems="baseline"
spacing={1}
<div
className="flex flex-row items-baseline gap-2"
css={[
styles.noShrink,
styles.agentDataItem,
@@ -55,12 +48,10 @@ export const AgentRowPreview: FC<AgentRowPreviewProps> = ({
>
<span>Agent:</span>
<span css={styles.agentDataValue}>{agent.name}</span>
</Stack>
</div>
<Stack
direction="row"
alignItems="baseline"
spacing={1}
<div
className="flex flex-row items-baseline gap-2"
css={[
styles.noShrink,
styles.agentDataItem,
@@ -75,21 +66,14 @@ export const AgentRowPreview: FC<AgentRowPreviewProps> = ({
<span css={[styles.agentDataValue, styles.agentOS]}>
{agent.operating_system}
</span>
</Stack>
</div>
<Stack
direction="row"
alignItems="center"
spacing={1}
<div
className="flex flex-row items-center gap-2"
css={styles.agentDataItem}
>
<span>Apps:</span>
<Stack
direction="row"
alignItems="center"
spacing={0.5}
wrap="wrap"
>
<div className="flex flex-row items-center gap-1 flex-wrap">
{/* We display all modules returned in agent.apps */}
{agent.apps.map((app) => (
<AppPreview key={app.slug}>
@@ -130,11 +114,11 @@ export const AgentRowPreview: FC<AgentRowPreviewProps> = ({
{agent.apps.length === 0 && agent.display_apps.length === 0 && (
<span css={styles.agentDataValue}>None</span>
)}
</Stack>
</Stack>
</Stack>
</Stack>
</Stack>
</div>
</div>
</div>
</div>
</div>
);
};
@@ -1,14 +1,8 @@
import type { FC, PropsWithChildren } from "react";
import { Stack } from "#/components/Stack/Stack";
export const AppPreview: FC<PropsWithChildren> = ({ children }) => {
return (
<Stack
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}
>
<div className="flex flex-row items-center gap-2 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]">
{children}
</Stack>
</div>
);
};
+5 -8
View File
@@ -5,7 +5,6 @@ import { ChevronDownIcon } from "#/components/AnimatedIcons/ChevronDown";
import { Button } from "#/components/Button/Button";
import { CopyableValue } from "#/components/CopyableValue/CopyableValue";
import { MemoizedInlineMarkdown } from "#/components/Markdown/InlineMarkdown";
import { Stack } from "#/components/Stack/Stack";
import {
Tooltip,
TooltipContent,
@@ -97,13 +96,11 @@ export const ResourceCard: FC<ResourceCardProps> = ({ resource, agentRow }) => {
return (
<div key={resource.id} css={styles.resourceCard} className="resource-card">
<Stack
direction="row"
alignItems="flex-start"
<div
className="flex flex-row items-start gap-20"
css={styles.resourceCardHeader}
spacing={10}
>
<Stack direction="row" spacing={1} css={styles.resourceCardProfile}>
<div className="flex flex-row gap-2" css={styles.resourceCardProfile}>
<div>
<ResourceAvatar resource={resource} />
</div>
@@ -111,7 +108,7 @@ export const ResourceCard: FC<ResourceCardProps> = ({ resource, agentRow }) => {
<div css={styles.metadataLabel}>{resource.type}</div>
<div css={styles.metadataValue}>{resource.name}</div>
</div>
</Stack>
</div>
<div
className="grow-[2] grid gap-x-10 gap-y-6"
@@ -180,7 +177,7 @@ export const ResourceCard: FC<ResourceCardProps> = ({ resource, agentRow }) => {
</TooltipContent>
</Tooltip>
)}
</Stack>
</div>
{resource.agents && resource.agents.length > 0 && (
<div>{resource.agents.map(agentRow)}</div>
+2 -3
View File
@@ -2,7 +2,6 @@ import { type FC, type JSX, useState } from "react";
import type { WorkspaceAgent, WorkspaceResource } from "#/api/typesGenerated";
import { ChevronDownIcon } from "#/components/AnimatedIcons/ChevronDown";
import { Button } from "#/components/Button/Button";
import { Stack } from "#/components/Stack/Stack";
import { ResourceCard } from "./ResourceCard";
const countAgents = (resource: WorkspaceResource) => {
@@ -26,7 +25,7 @@ export const Resources: FC<ResourcesProps> = ({ resources, agentRow }) => {
const hasHideResources = resources.some((r) => r.hide);
return (
<Stack direction="column" spacing={0} className="bg-surface-primary">
<div className="flex flex-col bg-surface-primary">
{displayResources.map((resource) => (
<ResourceCard
key={resource.id}
@@ -50,6 +49,6 @@ export const Resources: FC<ResourcesProps> = ({ resources, agentRow }) => {
</Button>
</div>
)}
</Stack>
</div>
);
};
@@ -14,7 +14,6 @@ import {
PopoverContent,
PopoverTrigger,
} from "#/components/Popover/Popover";
import { Stack } from "#/components/Stack/Stack";
import { docs } from "#/utils/docs";
interface AgentSSHButtonProps {
@@ -49,7 +48,7 @@ export const AgentSSHButton: FC<AgentSSHButtonProps> = ({
</HelpPopoverText>
<ol style={{ margin: 0, padding: 0 }}>
<Stack spacing={0.5} className="mt-3">
<div className="flex flex-col gap-1 mt-3">
<SSHStep
helpText="Configure SSH hosts on machine:"
codeExample="coder config-ssh"
@@ -58,7 +57,7 @@ export const AgentSSHButton: FC<AgentSSHButtonProps> = ({
helpText="Connect to the agent:"
codeExample={`ssh ${agentName}.${workspaceName}.${workspaceOwnerUsername}.${sshSuffix}`}
/>
</Stack>
</div>
</ol>
<HelpPopoverLinksGroup>
@@ -36,7 +36,6 @@ import {
SelectValue,
} from "#/components/Select/Select";
import { Slider } from "#/components/Slider/Slider";
import { Stack } from "#/components/Stack/Stack";
import { Switch } from "#/components/Switch/Switch";
import { TagInput } from "#/components/TagInput/TagInput";
import { Textarea } from "#/components/Textarea/Textarea";
@@ -505,7 +504,7 @@ const MaskableInput: FC<MaskableInputProps> = ({
const [showMaskedInput, setShowMaskedInput] = useState(false);
return (
<Stack direction="row" spacing={0} alignItems="center">
<div className="flex flex-row items-center">
<Input
id={id}
type={masked && showMaskedInput ? "text" : type}
@@ -535,7 +534,7 @@ const MaskableInput: FC<MaskableInputProps> = ({
)}
</Button>
)}
</Stack>
</div>
);
};
@@ -552,7 +551,7 @@ const MaskableTextArea: FC<MaskableInputProps> = ({
const [showMaskedInput, setShowMaskedInput] = useState(false);
return (
<Stack direction="row" spacing={0} alignItems="center">
<div className="flex flex-row items-center">
<Textarea
ref={textareaRef}
id={id}
@@ -589,7 +588,7 @@ const MaskableTextArea: FC<MaskableInputProps> = ({
)}
</Button>
)}
</Stack>
</div>
);
};
@@ -15,7 +15,6 @@ import type { DialogProps } from "#/components/Dialogs/Dialog";
import { FormFields } from "#/components/Form/Form";
import { Loader } from "#/components/Loader/Loader";
import { Pill } from "#/components/Pill/Pill";
import { Stack } from "#/components/Stack/Stack";
import { TemplateUpdateMessage } from "#/modules/templates/TemplateUpdateMessage";
import { createDayString } from "#/utils/createDayString";
@@ -55,7 +54,7 @@ export const ChangeWorkspaceVersionDialog: FC<
confirmText="Change"
title="Change version"
description={
<Stack>
<div className="flex flex-col gap-4">
<p>You are about to change the version of this workspace.</p>
{validVersions ? (
<>
@@ -90,16 +89,8 @@ export const ChangeWorkspaceVersionDialog: FC<
/>
}
title={
<Stack
direction="row"
justifyContent="space-between"
style={{ width: "100%" }}
>
<Stack
direction="row"
alignItems="center"
spacing={1}
>
<div className="flex flex-row justify-between gap-4 w-full">
<div className="flex flex-row items-center gap-2">
{option.name}
{option.message && (
<InfoIcon
@@ -107,10 +98,10 @@ export const ChangeWorkspaceVersionDialog: FC<
className="size-icon-xs"
/>
)}
</Stack>
</div>
{workspace.template_active_version_id ===
option.id && <Pill type="success">Active</Pill>}
</Stack>
</div>
}
subtitle={createDayString(option.created_at)}
/>
@@ -155,7 +146,7 @@ export const ChangeWorkspaceVersionDialog: FC<
) : (
<Loader />
)}
</Stack>
</div>
}
/>
);
@@ -12,7 +12,6 @@ import {
type ConfirmDialogProps,
} from "#/components/Dialogs/ConfirmDialog/ConfirmDialog";
import { Skeleton } from "#/components/Skeleton/Skeleton";
import { Stack } from "#/components/Stack/Stack";
import { cn } from "#/utils/cn";
type DownloadLogsDialogProps = Pick<
@@ -140,7 +139,7 @@ export const DownloadLogsDialog: FC<DownloadLogsDialogProps> = ({
}
}}
description={
<Stack className="pb-4">
<div className="flex flex-col gap-4 pb-4">
<p>
Downloading logs will create a zip file containing all logs from all
jobs in this workspace. This may take a while.
@@ -162,7 +161,7 @@ export const DownloadLogsDialog: FC<DownloadLogsDialogProps> = ({
/>
))}
</ul>
</Stack>
</div>
}
/>
);
+2 -3
View File
@@ -13,7 +13,6 @@ import {
type PaginationResult,
} from "#/components/PaginationWidget/PaginationContainer";
import { PaywallPremium } from "#/components/Paywall/PaywallPremium";
import { Stack } from "#/components/Stack/Stack";
import {
Table,
TableBody,
@@ -56,10 +55,10 @@ export const AuditPageView: FC<AuditPageViewProps> = ({
<Margins className="pb-12">
<PageHeader>
<PageHeaderTitle>
<Stack direction="row" spacing={1} alignItems="center">
<div className="flex flex-row gap-2 items-center">
<span>Audit</span>
<AuditHelpPopover />
</Stack>
</div>
</PageHeaderTitle>
<PageHeaderSubtitle>View events in your audit log.</PageHeaderSubtitle>
</PageHeader>
@@ -13,7 +13,6 @@ import {
type PaginationResult,
} from "#/components/PaginationWidget/PaginationContainer";
import { PaywallPremium } from "#/components/Paywall/PaywallPremium";
import { Stack } from "#/components/Stack/Stack";
import {
Table,
TableBody,
@@ -55,10 +54,10 @@ export const ConnectionLogPageView: FC<ConnectionLogPageViewProps> = ({
<Margins className="pb-12">
<PageHeader>
<PageHeaderTitle>
<Stack direction="row" spacing={1} alignItems="center">
<div className="flex flex-row gap-2 items-center">
<span>Connection Log</span>
<ConnectionLogHelpPopover />
</Stack>
</div>
</PageHeaderTitle>
<PageHeaderSubtitle>
View workspace connection events.
@@ -2,7 +2,6 @@ import type { Interpolation, Theme } from "@emotion/react";
import type { FC } from "react";
import { Link, useSearchParams } from "react-router";
import type { TemplateExample } from "#/api/typesGenerated";
import { Stack } from "#/components/Stack/Stack";
import { TemplateExampleCard } from "#/modules/templates/TemplateExampleCard/TemplateExampleCard";
import type { StarterTemplatesByTag } from "#/utils/starterTemplates";
@@ -64,9 +63,9 @@ export const StarterTemplates: FC<StarterTemplatesProps> = ({
: undefined;
return (
<Stack direction="row" spacing={4} alignItems="flex-start">
<div className="flex flex-row gap-8 items-start">
{starterTemplatesByTag && tags && (
<Stack className="w-[202px] shrink-0 sticky">
<div className="flex flex-col gap-4 w-[202px] shrink-0 sticky">
<h2 css={styles.sectionTitle}>Choose a starter template</h2>
<span css={styles.filterCaption}>Filter</span>
{tags.map((tag) => (
@@ -78,7 +77,7 @@ export const StarterTemplates: FC<StarterTemplatesProps> = ({
{getTagLabel(tag)} ({starterTemplatesByTag[tag].length})
</Link>
))}
</Stack>
</div>
)}
<div className="flex flex-wrap gap-8 h-max">
@@ -93,7 +92,7 @@ export const StarterTemplates: FC<StarterTemplatesProps> = ({
/>
))}
</div>
</Stack>
</div>
);
};
@@ -5,7 +5,6 @@ import RadioGroup from "@mui/material/RadioGroup";
import TextField from "@mui/material/TextField";
import type { FC } from "react";
import type { TemplateVersionVariable } from "#/api/typesGenerated";
import { Stack } from "#/components/Stack/Stack";
const isBoolean = (variable: TemplateVersionVariable) => {
return variable.type === "bool";
@@ -41,7 +40,7 @@ export const VariableInput: FC<VariableInputProps> = ({
defaultValue,
}) => {
return (
<Stack direction="column" spacing={0.75}>
<div className="flex flex-col gap-1.5">
<VariableLabel variable={variable} />
<div css={styles.input}>
<VariableField
@@ -51,7 +50,7 @@ export const VariableInput: FC<VariableInputProps> = ({
defaultValue={defaultValue}
/>
</div>
</Stack>
</div>
);
};
@@ -14,7 +14,6 @@ import {
HorizontalForm,
} from "#/components/Form/Form";
import { Spinner } from "#/components/Spinner/Spinner";
import { Stack } from "#/components/Stack/Stack";
import { getFormHelpers, onChangeTrimmed } from "#/utils/formUtils";
import {
type CreateTokenData,
@@ -102,7 +101,7 @@ export const CreateTokenForm: FC<CreateTokenFormProps> = ({
classes={{ sectionInfo: classNames.sectionInfo }}
>
<FormFields>
<Stack direction="row">
<div className="flex flex-row gap-4">
<TextField
select
label="Lifetime"
@@ -153,7 +152,7 @@ export const CreateTokenForm: FC<CreateTokenFormProps> = ({
}}
/>
)}
</Stack>
</div>
</FormFields>
</FormSection>
@@ -1,7 +1,6 @@
import type { FC } from "react";
import type { Template, TemplateExample } from "#/api/typesGenerated";
import { Avatar } from "#/components/Avatar/Avatar";
import { Stack } from "#/components/Stack/Stack";
interface SelectedTemplateProps {
template: Template | TemplateExample;
@@ -9,17 +8,14 @@ interface SelectedTemplateProps {
export const SelectedTemplate: FC<SelectedTemplateProps> = ({ template }) => {
return (
<Stack
direction="row"
className="py-5 px-6 rounded-lg bg-surface-primary border border-solid border-border"
>
<div className="flex flex-row gap-4 py-5 px-6 rounded-lg bg-surface-primary border border-solid border-border">
<Avatar
variant="icon"
size="lg"
src={template.icon}
fallback={template.name}
/>
<Stack direction="column" spacing={0}>
<div className="flex flex-col">
<span className="text-base">
{"display_name" in template && template.display_name.length > 0
? template.display_name
@@ -30,7 +26,7 @@ export const SelectedTemplate: FC<SelectedTemplateProps> = ({ template }) => {
{template.description}
</span>
)}
</Stack>
</Stack>
</div>
</div>
);
};
@@ -9,7 +9,6 @@ import {
SettingsHeaderDocsLink,
SettingsHeaderTitle,
} from "#/components/SettingsHeader/SettingsHeader";
import { Stack } from "#/components/Stack/Stack";
import { deploymentGroupHasParent } from "#/utils/deployOptions";
import { docs } from "#/utils/docs";
import OptionsTable from "../OptionsTable";
@@ -24,7 +23,7 @@ export const AIGovernanceSettingsPageView: FC<
AIGovernanceSettingsPageViewProps
> = ({ options, featureAIBridgeEntitled, featureAIBridgeEnabled }) => {
return (
<Stack direction="column" spacing={6}>
<div className="flex flex-col gap-12">
<SettingsHeader>
<SettingsHeaderTitle>AI Governance</SettingsHeaderTitle>
</SettingsHeader>
@@ -70,6 +69,6 @@ export const AIGovernanceSettingsPageView: FC<
<PaywallAIGovernance />
)}
</div>
</Stack>
</div>
);
};
@@ -7,7 +7,6 @@ import { SliderPicker, TwitterPicker } from "react-color";
import type { BannerConfig } from "#/api/typesGenerated";
import { Button } from "#/components/Button/Button";
import { Dialog, DialogActionButtons } from "#/components/Dialogs/Dialog";
import { Stack } from "#/components/Stack/Stack";
import { AnnouncementBannerView } from "#/modules/dashboard/AnnouncementBanners/AnnouncementBannerView";
import { getFormHelpers } from "#/utils/formUtils";
@@ -50,7 +49,7 @@ export const AnnouncementBannerDialog: FC<AnnouncementBannerDialogProps> = ({
<div css={styles.dialogContent}>
<h3 css={styles.dialogTitle}>Announcement banner</h3>
<Stack>
<div className="flex flex-col gap-4">
<div>
<h4 css={styles.settingName}>Message</h4>
<TextField
@@ -67,7 +66,7 @@ export const AnnouncementBannerDialog: FC<AnnouncementBannerDialogProps> = ({
</div>
<div>
<h4 css={styles.settingName}>Background color</h4>
<Stack spacing={2}>
<div className="flex flex-col gap-4">
{showHuePicker ? (
<SliderPicker
color={bannerForm.values.background_color}
@@ -127,9 +126,9 @@ export const AnnouncementBannerDialog: FC<AnnouncementBannerDialogProps> = ({
Show {showHuePicker ? "palette" : "slider"}
</Button>
</div>
</Stack>
</div>
</div>
</Stack>
</div>
</div>
<DialogActions>
@@ -12,7 +12,6 @@ import {
SettingsHeaderDescription,
SettingsHeaderTitle,
} from "#/components/SettingsHeader/SettingsHeader";
import { Stack } from "#/components/Stack/Stack";
import { Fieldset } from "../Fieldset";
import { DividerWithText } from "./DividerWithText";
@@ -52,11 +51,7 @@ export const AddNewLicensePageView: FC<AddNewLicenseProps> = ({
return (
<>
<Stack
alignItems="baseline"
direction="row"
justifyContent="space-between"
>
<div className="flex flex-row gap-4 items-baseline justify-between">
<SettingsHeader>
<SettingsHeaderTitle>Add a license</SettingsHeaderTitle>
<SettingsHeaderDescription>
@@ -70,7 +65,7 @@ export const AddNewLicensePageView: FC<AddNewLicenseProps> = ({
All Licenses
</RouterLink>
</Button>
</Stack>
</div>
{savingLicenseError && <ErrorAlert error={savingLicenseError} />}
@@ -82,7 +77,7 @@ export const AddNewLicensePageView: FC<AddNewLicenseProps> = ({
description="Select a text file that contains your license key."
/>
<Stack className="pt-10">
<div className="flex flex-col gap-4 pt-10">
<DividerWithText>or</DividerWithText>
<Fieldset
@@ -111,7 +106,7 @@ export const AddNewLicensePageView: FC<AddNewLicenseProps> = ({
fullWidth
/>
</Fieldset>
</Stack>
</div>
</>
);
};
@@ -14,7 +14,6 @@ import {
} from "#/components/SettingsHeader/SettingsHeader";
import { Skeleton } from "#/components/Skeleton/Skeleton";
import { Spinner } from "#/components/Spinner/Spinner";
import { Stack } from "#/components/Stack/Stack";
import {
Tooltip,
TooltipContent,
@@ -71,11 +70,7 @@ const LicensesSettingsPageView: FC<Props> = ({
colors={[theme.palette.primary.main, theme.palette.secondary.main]}
/>
<Stack
alignItems="baseline"
direction="row"
justifyContent="space-between"
>
<div className="flex flex-row gap-4 items-baseline justify-between">
<SettingsHeader>
<SettingsHeaderTitle>Licenses</SettingsHeaderTitle>
<SettingsHeaderDescription>
@@ -83,7 +78,7 @@ const LicensesSettingsPageView: FC<Props> = ({
</SettingsHeaderDescription>
</SettingsHeader>
<Stack direction="row" spacing={2}>
<div className="flex flex-row gap-4">
<Button variant="outline" asChild>
<RouterLink to="/deployment/licenses/add">
<PlusIcon />
@@ -108,14 +103,14 @@ const LicensesSettingsPageView: FC<Props> = ({
minutes.
</TooltipContent>
</Tooltip>
</Stack>
</Stack>
</div>
</div>
<div className="flex flex-col gap-4">
{isLoading && <Skeleton height={78} />}
{!isLoading && licenses && licenses?.length > 0 && (
<Stack spacing={4} className="licenses">
<div className="flex flex-col gap-8 licenses">
{[...(licenses ?? [])]
?.sort(
(a, b) =>
@@ -133,13 +128,13 @@ const LicensesSettingsPageView: FC<Props> = ({
onRemove={removeLicense}
/>
))}
</Stack>
</div>
)}
{!isLoading && licenses?.length === 0 && (
<div className="min-h-[240px] flex items-center justify-center rounded-lg border border-solid border-border p-12">
<Stack alignItems="center" spacing={1}>
<Stack alignItems="center" spacing={0.5}>
<div className="flex flex-col gap-2 items-center">
<div className="flex flex-col gap-1 items-center">
<span className="text-base">
You don&apos;t have any licenses!
</span>
@@ -152,8 +147,8 @@ const LicensesSettingsPageView: FC<Props> = ({
</MuiLink>{" "}
to get started.
</span>
</Stack>
</Stack>
</div>
</div>
</div>
)}
@@ -11,7 +11,6 @@ import {
SettingsHeaderDocsLink,
SettingsHeaderTitle,
} from "#/components/SettingsHeader/SettingsHeader";
import { Stack } from "#/components/Stack/Stack";
import {
deploymentGroupHasParent,
useDeploymentOptions,
@@ -26,7 +25,7 @@ type NetworkSettingsPageViewProps = {
export const NetworkSettingsPageView: FC<NetworkSettingsPageViewProps> = ({
options,
}) => (
<Stack direction="column" spacing={6}>
<div className="flex flex-col gap-12">
<div>
<SettingsHeader
actions={<SettingsHeaderDocsLink href={docs("/admin/networking")} />}
@@ -70,5 +69,5 @@ export const NetworkSettingsPageView: FC<NetworkSettingsPageViewProps> = ({
)}
</Badges>
</div>
</Stack>
</div>
);
@@ -17,7 +17,6 @@ import {
import type { DeploymentValues } from "#/api/typesGenerated";
import { Alert } from "#/components/Alert/Alert";
import { Button } from "#/components/Button/Button";
import { Stack } from "#/components/Stack/Stack";
import {
Tooltip,
TooltipContent,
@@ -67,7 +66,7 @@ export const NotificationEvents: FC<NotificationEventsProps> = ({
]);
return (
<Stack spacing={4}>
<div className="flex flex-col gap-8">
{hasWebhookNotifications && !isWebhookConfigured && (
<Alert
severity="warning"
@@ -140,7 +139,7 @@ export const NotificationEvents: FC<NotificationEventsProps> = ({
</List>
</Card>
))}
</Stack>
</div>
);
};
@@ -9,7 +9,6 @@ import {
SettingsHeaderDescription,
SettingsHeaderTitle,
} from "#/components/SettingsHeader/SettingsHeader";
import { Stack } from "#/components/Stack/Stack";
import { OAuth2AppForm } from "./OAuth2AppForm";
type CreateOAuth2AppProps = {
@@ -33,11 +32,7 @@ export const CreateOAuth2AppPageView: FC<CreateOAuth2AppProps> = ({
}) => {
return (
<>
<Stack
alignItems="baseline"
direction="row"
justifyContent="space-between"
>
<div className="flex flex-row gap-4 items-baseline justify-between">
<SettingsHeader>
<SettingsHeaderTitle>Add an OAuth2 application</SettingsHeaderTitle>
<SettingsHeaderDescription>
@@ -51,9 +46,9 @@ export const CreateOAuth2AppPageView: FC<CreateOAuth2AppProps> = ({
All OAuth2 Applications
</RouterLink>
</Button>
</Stack>
</div>
<Stack>
<div className="flex flex-col gap-4">
{error ? <ErrorAlert error={error} /> : undefined}
<OAuth2AppForm
onSubmit={createApp}
@@ -62,7 +57,7 @@ export const CreateOAuth2AppPageView: FC<CreateOAuth2AppProps> = ({
defaultValues={defaultValues}
disabled={!canCreateApp}
/>
</Stack>
</div>
</>
);
};
@@ -18,7 +18,6 @@ import {
SettingsHeaderTitle,
} from "#/components/SettingsHeader/SettingsHeader";
import { Spinner } from "#/components/Spinner/Spinner";
import { Stack } from "#/components/Stack/Stack";
import {
Table,
TableBody,
@@ -81,11 +80,7 @@ export const EditOAuth2AppPageView: FC<EditOAuth2AppProps> = ({
return (
<>
<Stack
alignItems="baseline"
direction="row"
justifyContent="space-between"
>
<div className="flex flex-row gap-4 items-baseline justify-between">
<SettingsHeader>
<SettingsHeaderTitle>Edit OAuth2 application</SettingsHeaderTitle>
<SettingsHeaderDescription>
@@ -99,7 +94,7 @@ export const EditOAuth2AppPageView: FC<EditOAuth2AppProps> = ({
All OAuth2 Applications
</RouterLink>
</Button>
</Stack>
</div>
{fullNewSecret && (
<ConfirmDialog
@@ -124,7 +119,7 @@ export const EditOAuth2AppPageView: FC<EditOAuth2AppProps> = ({
/>
)}
<Stack>
<div className="flex flex-col gap-4">
{searchParams.has("created") && (
<Alert severity="info" dismissible>
Your OAuth2 application has been created. Generate a client secret
@@ -204,7 +199,7 @@ export const EditOAuth2AppPageView: FC<EditOAuth2AppProps> = ({
)}
</>
)}
</Stack>
</div>
</>
);
};
@@ -226,11 +221,7 @@ const OAuth2AppSecretsTable: FC<OAuth2AppSecretsTableProps> = ({
}) => {
return (
<>
<Stack
alignItems="baseline"
direction="row"
justifyContent="space-between"
>
<div className="flex flex-row gap-4 items-baseline justify-between">
<h2>Client secrets</h2>
<Button
disabled={mutatingResource.createSecret}
@@ -240,7 +231,7 @@ const OAuth2AppSecretsTable: FC<OAuth2AppSecretsTableProps> = ({
<Spinner loading={mutatingResource.createSecret} />
Generate secret
</Button>
</Stack>
</div>
<Table>
<TableHeader>
@@ -12,7 +12,6 @@ import {
SettingsHeaderDescription,
SettingsHeaderTitle,
} from "#/components/SettingsHeader/SettingsHeader";
import { Stack } from "#/components/Stack/Stack";
import {
Table,
TableBody,
@@ -39,11 +38,7 @@ const OAuth2AppsSettingsPageView: FC<OAuth2AppsSettingsProps> = ({
}) => {
return (
<>
<Stack
alignItems="baseline"
direction="row"
justifyContent="space-between"
>
<div className="flex flex-row gap-4 items-baseline justify-between">
<div>
<SettingsHeader>
<SettingsHeaderTitle>OAuth2 Applications</SettingsHeaderTitle>
@@ -61,7 +56,7 @@ const OAuth2AppsSettingsPageView: FC<OAuth2AppsSettingsProps> = ({
</Link>
</Button>
)}
</Stack>
</div>
{error && <ErrorAlert error={error} />}
@@ -12,7 +12,6 @@ import {
SettingsHeaderDocsLink,
SettingsHeaderTitle,
} from "#/components/SettingsHeader/SettingsHeader";
import { Stack } from "#/components/Stack/Stack";
import {
Tooltip,
TooltipContent,
@@ -32,7 +31,7 @@ export const ObservabilitySettingsPageView: FC<
ObservabilitySettingsPageViewProps
> = ({ options, featureAuditLogEnabled, isPremium }) => {
return (
<Stack direction="column" spacing={6}>
<div className="flex flex-col gap-12">
<div>
<SettingsHeader>
<SettingsHeaderTitle>Observability</SettingsHeaderTitle>
@@ -94,6 +93,6 @@ export const ObservabilitySettingsPageView: FC<
)}
/>
</div>
</Stack>
</div>
);
};
@@ -12,7 +12,6 @@ import {
SettingsHeaderDocsLink,
SettingsHeaderTitle,
} from "#/components/SettingsHeader/SettingsHeader";
import { Stack } from "#/components/Stack/Stack";
import { useDeploymentOptions } from "#/utils/deployOptions";
import { docs } from "#/utils/docs";
import OptionsTable from "../OptionsTable";
@@ -42,7 +41,7 @@ export const OverviewPageView: FC<OverviewPageViewProps> = ({
</SettingsHeaderDescription>
</SettingsHeader>
<Stack spacing={4}>
<div className="flex flex-col gap-8">
<UserEngagementChart
data={dailyActiveUsers?.entries.map((i) => ({
date: i.date,
@@ -80,7 +79,7 @@ export const OverviewPageView: FC<OverviewPageViewProps> = ({
)}
additionalValues={safeExperiments}
/>
</Stack>
</div>
</>
);
};
@@ -12,7 +12,6 @@ import {
SettingsHeaderDocsLink,
SettingsHeaderTitle,
} from "#/components/SettingsHeader/SettingsHeader";
import { Stack } from "#/components/Stack/Stack";
import {
deploymentGroupHasParent,
useDeploymentOptions,
@@ -34,7 +33,7 @@ export const SecuritySettingsPageView: FC<SecuritySettingsPageViewProps> = ({
);
return (
<Stack direction="column" spacing={6}>
<div className="flex flex-col gap-12">
<div>
<SettingsHeader>
<SettingsHeaderTitle>Security</SettingsHeaderTitle>
@@ -90,6 +89,6 @@ export const SecuritySettingsPageView: FC<SecuritySettingsPageViewProps> = ({
<OptionsTable options={tlsOptions} />
</div>
)}
</Stack>
</div>
);
};
@@ -11,7 +11,6 @@ import {
SettingsHeaderDocsLink,
SettingsHeaderTitle,
} from "#/components/SettingsHeader/SettingsHeader";
import { Stack } from "#/components/Stack/Stack";
import {
deploymentGroupHasParent,
useDeploymentOptions,
@@ -34,7 +33,7 @@ export const UserAuthSettingsPageView = ({
);
return (
<Stack direction="column" spacing={6}>
<div className="flex flex-col gap-12">
<div>
<SettingsHeader>
<SettingsHeaderTitle>User Authentication</SettingsHeaderTitle>
@@ -90,6 +89,6 @@ export const UserAuthSettingsPageView = ({
/>
)}
</div>
</Stack>
</div>
);
};
@@ -26,7 +26,6 @@ import {
SettingsHeaderTitle,
} from "#/components/SettingsHeader/SettingsHeader";
import { Spinner } from "#/components/Spinner/Spinner";
import { Stack } from "#/components/Stack/Stack";
import {
Table,
TableBody,
@@ -80,11 +79,7 @@ const CreateEditRolePageView: FC<CreateEditRolePageViewProps> = ({
return (
<>
<Stack
alignItems="baseline"
direction="row"
justifyContent="space-between"
>
<div className="flex flex-row gap-4 items-baseline justify-between">
<SettingsHeader>
<SettingsHeaderTitle>
{role ? "Edit" : "Create"} Custom Role
@@ -112,7 +107,7 @@ const CreateEditRolePageView: FC<CreateEditRolePageViewProps> = ({
{role !== undefined ? "Save" : "Create Role"}
</Button>
</div>
</Stack>
</div>
<VerticalForm onSubmit={form.handleSubmit}>
<FormFields>
@@ -12,7 +12,6 @@ import {
SettingsHeaderDescription,
SettingsHeaderTitle,
} from "#/components/SettingsHeader/SettingsHeader";
import { Stack } from "#/components/Stack/Stack";
import { useFeatureVisibility } from "#/modules/dashboard/useFeatureVisibility";
import { useOrganizationSettings } from "#/modules/management/OrganizationSettingsLayout";
import { RequirePermission } from "#/modules/permissions/RequirePermission";
@@ -71,18 +70,14 @@ const CustomRolesPage: FC = () => {
<RequirePermission
isFeatureVisible={organizationPermissions?.viewOrgRoles ?? false}
>
<Stack
alignItems="baseline"
direction="row"
justifyContent="space-between"
>
<div className="flex flex-row gap-4 items-baseline justify-between">
<SettingsHeader>
<SettingsHeaderTitle>Roles</SettingsHeaderTitle>
<SettingsHeaderDescription>
Manage roles for this organization.
</SettingsHeaderDescription>
</SettingsHeader>
</Stack>
</div>
<CustomRolesPageView
builtInRoles={builtInRoles}
@@ -13,7 +13,6 @@ import {
import { EmptyState } from "#/components/EmptyState/EmptyState";
import { PaywallPremium } from "#/components/Paywall/PaywallPremium";
import { Skeleton } from "#/components/Skeleton/Skeleton";
import { Stack } from "#/components/Stack/Stack";
import {
Table,
TableBody,
@@ -49,7 +48,7 @@ export const CustomRolesPageView: FC<CustomRolesPageViewProps> = ({
isCustomRolesEnabled,
}) => {
return (
<Stack spacing={4}>
<div className="flex flex-col gap-8">
{!isCustomRolesEnabled && (
<PaywallPremium
message="Custom Roles"
@@ -57,11 +56,7 @@ export const CustomRolesPageView: FC<CustomRolesPageViewProps> = ({
documentationLink={docs("/admin/users/groups-roles")}
/>
)}
<Stack
alignItems="baseline"
direction="row"
justifyContent="space-between"
>
<div className="flex flex-row gap-4 items-baseline justify-between">
<span>
<h2 className="mb-0 text-lg">Custom Roles</h2>
<span className="text-sm text-content-secondary leading-relaxed">
@@ -77,7 +72,7 @@ export const CustomRolesPageView: FC<CustomRolesPageViewProps> = ({
</RouterLink>
</Button>
)}
</Stack>
</div>
<RoleTable
roles={customRoles}
isCustomRolesEnabled={isCustomRolesEnabled}
@@ -101,7 +96,7 @@ export const CustomRolesPageView: FC<CustomRolesPageViewProps> = ({
canDeleteOrgRole={canDeleteOrgRole}
onDeleteRole={onDeleteRole}
/>
</Stack>
</div>
);
};
@@ -18,7 +18,6 @@ import type {
import { ConfirmDialog } from "#/components/Dialogs/ConfirmDialog/ConfirmDialog";
import { EmptyState } from "#/components/EmptyState/EmptyState";
import { useFilter } from "#/components/Filter/Filter";
import { Stack } from "#/components/Stack/Stack";
import { useAuthenticated } from "#/hooks/useAuthenticated";
import { usePaginatedQuery } from "#/hooks/usePaginatedQuery";
import { shouldShowAISeatColumn } from "#/modules/dashboard/entitlements";
@@ -163,7 +162,7 @@ const OrganizationMembersPage: FC = () => {
}
}}
description={
<Stack>
<div className="flex flex-col gap-4">
<p>
Removing this member will:
<ul>
@@ -177,7 +176,7 @@ const OrganizationMembersPage: FC = () => {
</p>
<p className="pb-5">Are you sure you want to remove this member?</p>
</Stack>
</div>
}
/>
</>
@@ -38,7 +38,6 @@ import {
SettingsHeaderTitle,
} from "#/components/SettingsHeader/SettingsHeader";
import { Spinner } from "#/components/Spinner/Spinner";
import { Stack } from "#/components/Stack/Stack";
import {
Table,
TableBody,
@@ -122,23 +121,23 @@ export const OrganizationMembersPageView: FC<
<TableRow>
<TableHead className="w-2/6">User</TableHead>
<TableHead className="w-2/6">
<Stack direction="row" spacing={1} alignItems="center">
<div className="flex flex-row items-center gap-2">
<span>Roles</span>
<TableColumnHelpPopover variant="roles" />
</Stack>
</div>
</TableHead>
<TableHead className={showAISeatColumn ? "w-1/6" : "w-2/6"}>
<Stack direction="row" spacing={1} alignItems="center">
<div className="flex flex-row items-center gap-2">
<span>Groups</span>
<TableColumnHelpPopover variant="groups" />
</Stack>
</div>
</TableHead>
{showAISeatColumn && (
<TableHead className="w-1/6">
<Stack direction="row" spacing={1} alignItems="center">
<div className="flex flex-row items-center gap-2">
<span>AI add-on</span>
<TableColumnHelpPopover variant="ai_addon" />
</Stack>
</div>
</TableHead>
)}
<TableHead className="w-px whitespace-nowrap text-right" />
@@ -14,7 +14,6 @@ import {
PageHeaderSubtitle,
PageHeaderTitle,
} from "#/components/PageHeader/PageHeader";
import { Stack } from "#/components/Stack/Stack";
interface StarterTemplatePageViewProps {
starterTemplate?: TemplateExample;
@@ -59,7 +58,7 @@ export const StarterTemplatePageView: FC<StarterTemplatePageViewProps> = ({
</>
}
>
<Stack direction="row" spacing={3} alignItems="center">
<div className="flex flex-row gap-6 items-center">
<div className="h-12 w-12 flex items-center justify-center [&_img]:w-full">
<ExternalImage src={starterTemplate.icon} />
</div>
@@ -69,7 +68,7 @@ export const StarterTemplatePageView: FC<StarterTemplatePageViewProps> = ({
{starterTemplate.description}
</PageHeaderSubtitle>
</div>
</Stack>
</div>
</PageHeader>
<div
@@ -47,7 +47,6 @@ import {
} from "#/components/HelpPopover/HelpPopover";
import { Link } from "#/components/Link/Link";
import { Loader } from "#/components/Loader/Loader";
import { Stack } from "#/components/Stack/Stack";
import {
Tooltip,
TooltipArrow,
@@ -480,10 +479,7 @@ const TemplateUsagePanel: FC<TemplateUsagePanelProps> = ({
<TooltipArrow className="fill-border" />
</TooltipContent>
</Tooltip>
<Stack
spacing={0}
className="text-[13px] shrink-0 leading-[1.5] text-content-secondary w-[120px]"
>
<div className="flex flex-col text-[13px] shrink-0 leading-[1.5] text-content-secondary w-[120px]">
{formatTime(usage.seconds)}
{usage.times_used > 0 && (
<span className="text-[12px] text-content-disabled">
@@ -491,7 +487,7 @@ const TemplateUsagePanel: FC<TemplateUsagePanelProps> = ({
{usage.times_used === 1 ? "time" : "times"}
</span>
)}
</Stack>
</div>
</div>
);
})}
@@ -38,7 +38,6 @@ import {
PageHeaderTitle,
} from "#/components/PageHeader/PageHeader";
import { Pill } from "#/components/Pill/Pill";
import { Stack } from "#/components/Stack/Stack";
import { linkToTemplate, useLinks } from "#/modules/navigation";
import type { WorkspacePermissions } from "#/modules/permissions/workspaces";
import { TemplateStats } from "./TemplateStats";
@@ -250,23 +249,22 @@ export const TemplatePageHeader: FC<TemplatePageHeaderProps> = ({
</>
}
>
<Stack direction="row">
<div className="flex flex-row gap-4">
<Avatar
size="lg"
variant="icon"
src={template.icon}
fallback={template.name}
/>
<div>
<Stack direction="row" alignItems="center" spacing={1}>
<div className="flex flex-row items-center gap-2">
<PageHeaderTitle>
{template.display_name.length > 0
? template.display_name
: template.name}
</PageHeaderTitle>
{template.deprecated && <Pill type="warning">Deprecated</Pill>}
</Stack>
</div>
{template.deprecation_message !== "" ? (
<PageHeaderSubtitle condensed>
@@ -282,7 +280,7 @@ export const TemplatePageHeader: FC<TemplatePageHeaderProps> = ({
)
)}
</div>
</Stack>
</div>
</PageHeader>
<div className="pb-8">
<TemplateStats template={template} activeVersion={activeVersion} />
@@ -6,7 +6,6 @@ import { Avatar } from "#/components/Avatar/Avatar";
import { Button } from "#/components/Button/Button";
import { InfoTooltip } from "#/components/InfoTooltip/InfoTooltip";
import { Pill } from "#/components/Pill/Pill";
import { Stack } from "#/components/Stack/Stack";
import { TableCell } from "#/components/Table/Table";
import { TimelineEntry } from "#/components/Timeline/TimelineEntry";
import { useClickableTableRow } from "#/hooks/useClickableTableRow";
@@ -41,39 +40,32 @@ export const VersionRow: FC<VersionRowProps> = ({
className={clickableProps.className}
>
<TableCell css={styles.versionCell}>
<Stack
direction="row"
alignItems="center"
<div
className="flex flex-row items-center justify-between gap-4"
css={styles.versionWrapper}
justifyContent="space-between"
>
<Stack direction="row" alignItems="center">
<div className="flex flex-row items-center gap-4">
<Avatar
fallback={version.created_by.username}
src={version.created_by.avatar_url}
/>
<Stack
<div
className="flex flex-row items-center gap-2"
css={styles.versionSummary}
direction="row"
alignItems="center"
spacing={1}
>
<span>
<strong>{version.created_by.username}</strong> created the
version <strong>{version.name}</strong>
</span>
{version.message && (
<InfoTooltip title="Message" message={version.message} />
)}
<span css={styles.versionTime}>
{new Date(version.created_at).toLocaleTimeString()}
</span>
</Stack>
</Stack>
<Stack direction="row" alignItems="center" spacing={2}>
</div>
</div>
<div className="flex flex-row items-center gap-4">
{isActive && (
<Pill role="status" type="success">
Active
@@ -132,8 +124,8 @@ export const VersionRow: FC<VersionRowProps> = ({
Promote&hellip;
</Button>
)}
</Stack>
</Stack>
</div>
</div>
</TableCell>
</TimelineEntry>
);
@@ -23,7 +23,6 @@ import {
import { IconField } from "#/components/IconField/IconField";
import { Link } from "#/components/Link/Link";
import { Spinner } from "#/components/Spinner/Spinner";
import { Stack } from "#/components/Stack/Stack";
import {
StackLabel,
StackLabelHelperText,
@@ -164,7 +163,7 @@ export const TemplateSettingsForm: FC<TemplateSettingsForm> = ({
title="Operations"
description="Regulate actions allowed on workspaces created from this template."
>
<FormFields spacing={6}>
<FormFields className="gap-12">
<FormControlLabel
control={
<Checkbox
@@ -217,15 +216,10 @@ export const TemplateSettingsForm: FC<TemplateSettingsForm> = ({
</span>
{!advancedSchedulingEnabled && (
<Stack
direction="row"
spacing={2}
alignItems="center"
className="mt-4"
>
<div className="flex flex-row gap-4 items-center mt-4">
<PremiumBadge />
<span>Premium license required to be enabled.</span>
</Stack>
</div>
)}
</StackLabelHelperText>
</StackLabel>
@@ -317,14 +311,14 @@ export const TemplateSettingsForm: FC<TemplateSettingsForm> = ({
label="Deprecation Message"
/>
{!accessControlEnabled && (
<Stack direction="row" spacing={2} alignItems="center">
<div className="flex flex-row gap-4 items-center">
<PremiumBadge />
<FormHelperText>
Premium license required to deprecate templates.
{template.deprecated &&
" You cannot change the message, but you may remove it to mark this template as no longer deprecated."}
</FormHelperText>
</Stack>
</div>
)}
</FormFields>
</FormSection>
@@ -358,12 +352,12 @@ export const TemplateSettingsForm: FC<TemplateSettingsForm> = ({
<MenuItem value="public">Public</MenuItem>
</TextField>
{!portSharingControlsEnabled && (
<Stack direction="row" spacing={2} alignItems="center">
<div className="flex flex-row gap-4 items-center">
<PremiumBadge />
<FormHelperText>
Premium license required to control max port sharing level.
</FormHelperText>
</Stack>
</div>
)}
</FormFields>
</FormSection>
@@ -1,7 +1,6 @@
import FormHelperText from "@mui/material/FormHelperText";
import type { FC } from "react";
import { Button } from "#/components/Button/Button";
import { Stack } from "#/components/Stack/Stack";
import {
sortedDays,
type TemplateAutostartRequirementDaysValue,
@@ -21,14 +20,8 @@ export const TemplateScheduleAutostart: FC<TemplateScheduleAutostartProps> = ({
onChange,
}) => {
return (
<Stack alignItems="start" spacing={1}>
<Stack
direction="row"
spacing={0}
alignItems="baseline"
justifyContent="center"
className="w-full gap-0.5"
>
<div className="flex flex-col gap-2 items-start">
<div className="flex flex-row items-baseline justify-center w-full gap-0.5">
{(
[
{ value: "monday", key: "Mon" },
@@ -60,11 +53,11 @@ export const TemplateScheduleAutostart: FC<TemplateScheduleAutostartProps> = ({
{day.key}
</Button>
))}
</Stack>
</div>
<FormHelperText>
<AutostartHelperText allowed={enabled} days={value} />
</FormHelperText>
</Stack>
</div>
);
};
@@ -56,7 +56,7 @@ const DORMANT_AUTODELETION_DEFAULT = 30 * MS_DAY_CONVERSION;
* The default form field space is 4 but since this form is quite heavy I think
* increase the space can make it feels lighter.
*/
const FORM_FIELDS_SPACING = 8;
const FORM_FIELDS_GAP = "gap-16";
export interface TemplateScheduleForm {
template: Template;
@@ -287,7 +287,7 @@ export const TemplateScheduleForm: FC<TemplateScheduleForm> = ({
title="Autostop"
description="Define when workspaces created from this template are stopped."
>
<FormFields spacing={FORM_FIELDS_SPACING}>
<FormFields className={FORM_FIELDS_GAP}>
<TextField
{...getFieldHelpers("default_ttl_ms", {
helperText: (
@@ -443,7 +443,7 @@ export const TemplateScheduleForm: FC<TemplateScheduleForm> = ({
title="Dormancy"
description="When enabled, Coder will mark workspaces as dormant after a period of time with no connections. Dormant workspaces can be auto-deleted (see below) or manually reviewed by the workspace owner or admins."
>
<FormFields spacing={FORM_FIELDS_SPACING}>
<FormFields className={FORM_FIELDS_GAP}>
<div className="flex flex-col gap-8">
<div className="flex items-start">
<Switch
@@ -7,7 +7,6 @@ import type { AuthorizationResponse, Template } from "#/api/typesGenerated";
import { ErrorAlert } from "#/components/Alert/ErrorAlert";
import { Loader } from "#/components/Loader/Loader";
import { Margins } from "#/components/Margins/Margins";
import { Stack } from "#/components/Stack/Stack";
import { pageTitle } from "#/utils/page";
import { Sidebar } from "./Sidebar";
@@ -54,7 +53,7 @@ export const TemplateSettingsLayout: FC = () => {
<title>{pageTitle(templateName, "Settings")}</title>
<Margins>
<Stack className="py-12" direction="row" spacing={10}>
<div className="flex flex-row gap-20 py-12">
{templateQuery.isError || permissionsQuery.isError ? (
<ErrorAlert error={templateQuery.error} />
) : (
@@ -72,7 +71,7 @@ export const TemplateSettingsLayout: FC = () => {
</Suspense>
</TemplateSettings.Provider>
)}
</Stack>
</div>
</Margins>
</>
);
@@ -10,7 +10,6 @@ import {
PageHeader,
PageHeaderTitle,
} from "#/components/PageHeader/PageHeader";
import { Stack } from "#/components/Stack/Stack";
import { TemplateVariablesForm } from "./TemplateVariablesForm";
interface TemplateVariablesPageViewProps {
@@ -51,14 +50,14 @@ export const TemplateVariablesPageView: FC<TemplateVariablesPageViewProps> = ({
<PageHeaderTitle>Template variables</PageHeaderTitle>
</PageHeader>
{hasError && (
<Stack className="mb-16">
<div className="flex flex-col gap-4 mb-16">
{Boolean(errors.buildError) && (
<ErrorAlert error={errors.buildError} />
)}
{Boolean(errors.publishError) && (
<ErrorAlert error={errors.publishError} />
)}
</Stack>
</div>
)}
{templateVersion && templateVariables && templateVariables.length > 0 && (
<TemplateVariablesForm
@@ -1,7 +1,6 @@
import TextField from "@mui/material/TextField";
import { type ChangeEvent, type FC, useState } from "react";
import { ConfirmDialog } from "#/components/Dialogs/ConfirmDialog/ConfirmDialog";
import { Stack } from "#/components/Stack/Stack";
import { type FileTree, isFolder, validatePath } from "#/utils/filetree";
interface CreateFileDialogProps {
@@ -59,7 +58,7 @@ export const CreateFileDialog: FC<CreateFileDialogProps> = ({
confirmText="Create"
title="Create File"
description={
<Stack spacing={4}>
<div className="flex flex-col gap-8">
<p>
Specify the path to a file to be created. This path can contain
slashes too.
@@ -81,7 +80,7 @@ export const CreateFileDialog: FC<CreateFileDialogProps> = ({
onChange={handleChange}
label="File Path"
/>
</Stack>
</div>
}
/>
);
@@ -180,7 +179,7 @@ export const RenameFileDialog: FC<RenameFileDialogProps> = ({
confirmText="Rename"
title="Rename File"
description={
<Stack>
<div className="flex flex-col gap-4">
<p>
Rename <strong>{filename}</strong> to something else. This path can
contain slashes too!
@@ -202,7 +201,7 @@ export const RenameFileDialog: FC<RenameFileDialogProps> = ({
onChange={handleChange}
label="File Path"
/>
</Stack>
</div>
}
/>
);
@@ -17,7 +17,6 @@ import {
HelpPopoverText,
HelpPopoverTitle,
} from "#/components/HelpPopover/HelpPopover";
import { Stack } from "#/components/Stack/Stack";
import type { PublishVersionData } from "#/pages/TemplateVersionEditorPage/types";
import { docs } from "#/utils/docs";
import { getFormHelpers } from "#/utils/formUtils";
@@ -74,7 +73,7 @@ export const PublishTemplateVersionDialog: FC<
title="Publish new version"
description={
<form id="publish-version" onSubmit={form.handleSubmit}>
<Stack>
<div className="flex flex-col gap-4">
<p>You are about to publish a new version of this template.</p>
<FormFields>
<TextField
@@ -93,7 +92,7 @@ export const PublishTemplateVersionDialog: FC<
rows={5}
/>
<Stack direction="row">
<div className="flex flex-row gap-4">
<FormControlLabel
label="Promote to active version"
control={
@@ -135,9 +134,9 @@ export const PublishTemplateVersionDialog: FC<
</HelpPopoverLinksGroup>
</HelpPopoverContent>
</HelpPopover>
</Stack>
</div>
</FormFields>
</Stack>
</div>
</form>
}
/>
@@ -11,7 +11,6 @@ import {
PageHeaderCaption,
PageHeaderTitle,
} from "#/components/PageHeader/PageHeader";
import { Stack } from "#/components/Stack/Stack";
import { Stats, StatsItem } from "#/components/Stats/Stats";
import { linkToTemplate, useLinks } from "#/modules/navigation";
import { TemplateFiles } from "#/modules/templates/TemplateFiles/TemplateFiles";
@@ -71,7 +70,7 @@ export const TemplateVersionPageView: FC<TemplateVersionPageViewProps> = ({
{!currentFiles && !error && <Loader />}
<Stack spacing={4}>
<div className="flex flex-col gap-8">
{Boolean(error) && <ErrorAlert error={error} />}
{currentVersion?.message && (
<TemplateUpdateMessage>
@@ -117,7 +116,7 @@ export const TemplateVersionPageView: FC<TemplateVersionPageViewProps> = ({
/>
</>
)}
</Stack>
</div>
</Margins>
);
};
@@ -4,7 +4,6 @@ import { Link as RouterLink } from "react-router";
import type { TemplateExample } from "#/api/typesGenerated";
import { Button } from "#/components/Button/Button";
import { CodeExample } from "#/components/CodeExample/CodeExample";
import { Stack } from "#/components/Stack/Stack";
import { TableEmpty } from "#/components/TableEmpty/TableEmpty";
import { TemplateExampleCard } from "#/modules/templates/TemplateExampleCard/TemplateExampleCard";
import { docs } from "#/utils/docs";
@@ -71,19 +70,18 @@ export const EmptyTemplates: FC<EmptyTemplatesProps> = ({
</>
}
cta={
<Stack alignItems="center" spacing={4}>
<div className="flex flex-col gap-8 items-center">
<div className="flex flex-wrap justify-center gap-4">
{featuredExamples.map((example) => (
<TemplateExampleCard example={example} key={example.id} />
))}
</div>
<Button size="sm" asChild className="rounded-full">
<RouterLink to="/starter-templates">
View all starter templates
</RouterLink>
</Button>
</Stack>
</div>
}
/>
);
@@ -26,7 +26,6 @@ import {
PageHeaderTitle,
} from "#/components/PageHeader/PageHeader";
import { Skeleton } from "#/components/Skeleton/Skeleton";
import { Stack } from "#/components/Stack/Stack";
import {
Table,
TableBody,
@@ -228,10 +227,10 @@ export const TemplatesPageView: FC<TemplatesPageViewProps> = ({
}
>
<PageHeaderTitle>
<Stack spacing={1} direction="row" alignItems="center">
<div className="flex flex-row gap-2 items-center">
Templates
<TemplateHelpPopover />
</Stack>
</div>
</PageHeaderTitle>
<PageHeaderSubtitle>
Select a template to create a workspace.
@@ -1,7 +1,6 @@
import type { FC } from "react";
import { useQuery } from "react-query";
import { groupsForUser } from "#/api/queries/groups";
import { Stack } from "#/components/Stack/Stack";
import { useAuthContext } from "#/contexts/auth/AuthProvider";
import { useAuthenticated } from "#/hooks/useAuthenticated";
import { useDashboard } from "#/modules/dashboard/useDashboard";
@@ -22,7 +21,7 @@ const AccountPage: FC = () => {
});
return (
<Stack spacing={6}>
<div className="flex flex-col gap-12">
<Section title="Account" description="Update your account info">
<AccountForm
editable={permissions?.updateUsers ?? false}
@@ -41,7 +40,7 @@ const AccountPage: FC = () => {
error={groupsQuery.error}
/>
)}
</Stack>
</div>
);
};
@@ -18,7 +18,6 @@ import {
} from "#/components/DropdownMenu/DropdownMenu";
import { Loader } from "#/components/Loader/Loader";
import { Spinner } from "#/components/Spinner/Spinner";
import { Stack } from "#/components/Stack/Stack";
import {
Table,
TableBody,
@@ -130,7 +129,7 @@ const ExternalAuthRow: FC<ExternalAuthRowProps> = ({
return (
<TableRow key={app.id}>
<TableCell>
<Stack direction="row" alignItems="center" spacing={1}>
<div className="flex flex-row items-center gap-2">
<Avatar variant="icon" src={app.display_icon} fallback={name} />
<span className="font-semibold">{name}</span>
{/*
@@ -147,14 +146,13 @@ const ExternalAuthRow: FC<ExternalAuthRowProps> = ({
</TooltipContent>
</Tooltip>
)}
{link?.validate_error && (
<span>
<span className="pl-[1em] text-content-destructive">Error: </span>
{link?.validate_error}
</span>
)}
</Stack>
</div>
</TableCell>
<TableCell className="text-right">
<Button
@@ -3,7 +3,6 @@ import type * as TypesGen from "#/api/typesGenerated";
import { ErrorAlert } from "#/components/Alert/ErrorAlert";
import { Avatar } from "#/components/Avatar/Avatar";
import { Button } from "#/components/Button/Button";
import { Stack } from "#/components/Stack/Stack";
import {
Table,
TableBody,
@@ -67,10 +66,10 @@ const OAuth2AppRow: FC<OAuth2AppRowProps> = ({ app, revoke }) => {
return (
<TableRow key={app.id} data-testid={`app-${app.id}`}>
<TableCell>
<Stack direction="row" spacing={1} alignItems="center">
<div className="flex flex-row gap-2 items-center">
<Avatar variant="icon" src={app.icon} fallback={app.name} />
<span className="font-semibold">{app.name}</span>
</Stack>
</div>
</TableCell>
<TableCell>
@@ -4,7 +4,6 @@ import type { GitSSHKey } from "#/api/typesGenerated";
import { ErrorAlert } from "#/components/Alert/ErrorAlert";
import { Button } from "#/components/Button/Button";
import { CodeExample } from "#/components/CodeExample/CodeExample";
import { Stack } from "#/components/Stack/Stack";
interface SSHKeysPageViewProps {
isLoading: boolean;
@@ -28,7 +27,7 @@ export const SSHKeysPageView: FC<SSHKeysPageViewProps> = ({
}
return (
<Stack>
<div className="flex flex-col gap-4">
{/* Regenerating the key is not an option if getSSHKey fails.
Only one of the error messages will exist at a single time */}
{Boolean(getSSHKeyError) && <ErrorAlert error={getSSHKeyError} />}
@@ -56,6 +55,6 @@ export const SSHKeysPageView: FC<SSHKeysPageViewProps> = ({
</div>
</>
)}
</Stack>
</div>
);
};
@@ -12,7 +12,6 @@ import { ErrorAlert } from "#/components/Alert/ErrorAlert";
import { Button } from "#/components/Button/Button";
import { Form, FormFields } from "#/components/Form/Form";
import { Spinner } from "#/components/Spinner/Spinner";
import { Stack } from "#/components/Stack/Stack";
import { getFormHelpers } from "#/utils/formUtils";
import { quietHoursDisplay, timeToCron, validTime } from "#/utils/schedule";
import { getPreferredTimezone, timeZones } from "#/utils/timeZones";
@@ -102,7 +101,7 @@ export const ScheduleForm: FC<ScheduleFormProps> = ({
</Alert>
)}
<Stack direction="row">
<div className="flex flex-row gap-4">
<TextField
{...getFieldHelpers("time")}
disabled={isLoading || !initialValues.user_can_set}
@@ -123,7 +122,7 @@ export const ScheduleForm: FC<ScheduleFormProps> = ({
</MenuItem>
))}
</TextField>
</Stack>
</div>
<TextField
disabled
+2 -3
View File
@@ -3,7 +3,6 @@ import {
FeatureStageBadge,
type featureStageBadgeTypes,
} from "#/components/FeatureStageBadge/FeatureStageBadge";
import { Stack } from "#/components/Stack/Stack";
type SectionLayout = "fixed" | "fluid";
@@ -41,7 +40,7 @@ export const Section: FC<SectionProps> = ({
<div className="mb-6 flex flex-row justify-between">
<div>
{title && (
<Stack direction="row" alignItems="center">
<div className="flex flex-row items-center gap-4">
<h4 className="text-2xl font-medium m-0 mb-2">{title}</h4>
{featureStage && (
<FeatureStageBadge
@@ -50,7 +49,7 @@ export const Section: FC<SectionProps> = ({
className="mb-[5px]"
/>
)}
</Stack>
</div>
)}
{description && typeof description === "string" && (
<p className={DESCRIPTION_CLASS}>{description}</p>
@@ -4,7 +4,6 @@ import { toast } from "sonner";
import { API } from "#/api/api";
import { authMethods, updatePassword } from "#/api/queries/users";
import { Loader } from "#/components/Loader/Loader";
import { Stack } from "#/components/Stack/Stack";
import { useAuthenticated } from "#/hooks/useAuthenticated";
import { Section } from "../Section";
import { SecurityForm } from "./SecurityForm";
@@ -71,12 +70,12 @@ export const SecurityPageView: FC<SecurityPageViewProps> = ({
oidc,
}) => {
return (
<Stack spacing={6}>
<div className="flex flex-col gap-12">
<Section title="Security" description="Update your account password">
<SecurityForm {...security.form} />
</Section>
{oidc && <SingleSignOnSection {...oidc.section} />}
</Stack>
</div>
);
};
@@ -15,7 +15,6 @@ import { Button } from "#/components/Button/Button";
import { ConfirmDialog } from "#/components/Dialogs/ConfirmDialog/ConfirmDialog";
import { EmptyState } from "#/components/EmptyState/EmptyState";
import { ExternalImage } from "#/components/ExternalImage/ExternalImage";
import { Stack } from "#/components/Stack/Stack";
import { docs } from "#/utils/docs";
import { Section } from "../Section";
@@ -258,7 +257,7 @@ const ConfirmLoginTypeChangeModal: FC<ConfirmLoginTypeChangeModalProps> = ({
title="Change login type"
confirmLoading={loading}
description={
<Stack spacing={4}>
<div className="flex flex-col gap-8">
<p>
After changing your login type, you will not be able to change it
again. Are you sure you want to proceed and change your login type?
@@ -283,7 +282,7 @@ const ConfirmLoginTypeChangeModal: FC<ConfirmLoginTypeChangeModalProps> = ({
label="Confirm your password"
type="password"
/>
</Stack>
</div>
}
/>
);
@@ -3,7 +3,6 @@ import { type FC, useState } from "react";
import { Link as RouterLink } from "react-router";
import type { APIKeyWithOwner } from "#/api/typesGenerated";
import { Button } from "#/components/Button/Button";
import { Stack } from "#/components/Stack/Stack";
import { cn } from "#/utils/cn";
import { Section } from "../Section";
import { ConfirmDeleteDialog } from "./ConfirmDeleteDialog";
@@ -68,14 +67,14 @@ const TokensPage: FC = () => {
};
const TokenActions: FC = () => (
<Stack direction="row" justifyContent="end" className="mb-2">
<div className="flex flex-row justify-end gap-4 mb-2">
<Button asChild variant="outline">
<RouterLink to="new">
<PlusIcon />
Add token
</RouterLink>
</Button>
</Stack>
</div>
);
export default TokensPage;
@@ -7,7 +7,6 @@ import type { APIKeyWithOwner } from "#/api/typesGenerated";
import { ErrorAlert } from "#/components/Alert/ErrorAlert";
import { Button } from "#/components/Button/Button";
import { ChooseOne, Cond } from "#/components/Conditionals/ChooseOne";
import { Stack } from "#/components/Stack/Stack";
import {
Table,
TableBody,
@@ -48,7 +47,7 @@ export const TokensPageView: FC<TokensPageViewProps> = ({
const theme = useTheme();
return (
<Stack>
<div className="flex flex-col gap-4">
{Boolean(getTokensError) && <ErrorAlert error={getTokensError} />}
{Boolean(deleteTokenError) && <ErrorAlert error={deleteTokenError} />}
@@ -129,6 +128,6 @@ export const TokensPageView: FC<TokensPageViewProps> = ({
</ChooseOne>
</TableBody>
</Table>
</Stack>
</div>
);
};
@@ -7,7 +7,6 @@ import {
SettingsHeaderDescription,
SettingsHeaderTitle,
} from "#/components/SettingsHeader/SettingsHeader";
import { Stack } from "#/components/Stack/Stack";
import {
Table,
TableBody,
@@ -39,7 +38,7 @@ export const WorkspaceProxyView: FC<WorkspaceProxyViewProps> = ({
selectProxyError,
}) => {
return (
<Stack>
<div className="flex flex-col gap-4">
<SettingsHeader>
<SettingsHeaderTitle>Workspace Proxies</SettingsHeaderTitle>
<SettingsHeaderDescription>
@@ -81,6 +80,6 @@ export const WorkspaceProxyView: FC<WorkspaceProxyViewProps> = ({
</ChooseOne>
</TableBody>
</Table>
</Stack>
</div>
);
};
@@ -1,7 +1,6 @@
import type { FC } from "react";
import type { GroupsByUserId } from "#/api/queries/groups";
import type * as TypesGen from "#/api/typesGenerated";
import { Stack } from "#/components/Stack/Stack";
import {
Table,
TableBody,
@@ -64,23 +63,23 @@ export const UsersTable: FC<UsersTableProps> = ({
<TableRow>
<TableHead className="w-2/6">User</TableHead>
<TableHead className="w-2/6">
<Stack direction="row" spacing={1} alignItems="center">
<div className="flex flex-row gap-2 items-center">
<span>Roles</span>
<TableColumnHelpPopover variant="roles" />
</Stack>
</div>
</TableHead>
<TableHead className="w-1/6">
<Stack direction="row" spacing={1} alignItems="center">
<div className="flex flex-row gap-2 items-center">
<span>Groups</span>
<TableColumnHelpPopover variant="groups" />
</Stack>
</div>
</TableHead>
{showAISeatColumn && (
<TableHead className="w-1/6">
<Stack direction="row" spacing={1} alignItems="center">
<div className="flex flex-row gap-2 items-center">
<span>AI add-on</span>
<TableColumnHelpPopover variant="ai_addon" />
</Stack>
</div>
</TableHead>
)}
<TableHead className="w-1/6">Login Type</TableHead>
@@ -22,7 +22,6 @@ import {
PageHeaderSubtitle,
PageHeaderTitle,
} from "#/components/PageHeader/FullWidthPageHeader";
import { Stack } from "#/components/Stack/Stack";
import { Stats, StatsItem } from "#/components/Stats/Stats";
import {
TAB_PADDING_X,
@@ -101,14 +100,13 @@ export const WorkspaceBuildPageView: FC<WorkspaceBuildPageViewProps> = ({
return (
<DashboardFullPage>
<FullWidthPageHeader sticky={false}>
<Stack direction="row">
<div className="flex flex-row gap-4">
<BuildAvatar build={build} size="lg" />
<div>
<PageHeaderTitle>Build #{build.build_number}</PageHeaderTitle>
<PageHeaderSubtitle>{build.initiator_name}</PageHeaderSubtitle>
</div>
</Stack>
</div>
<Stats
aria-label="Build details"
className="flex flex-col items-start gap-2 px-0 border-none grow basis-0 md:flex-row md:gap-x-12 md:gap-y-6"
@@ -8,7 +8,6 @@ import {
import { ErrorAlert } from "#/components/Alert/ErrorAlert";
import { Loader } from "#/components/Loader/Loader";
import { Margins } from "#/components/Margins/Margins";
import { Stack } from "#/components/Stack/Stack";
import { pageTitle } from "#/utils/page";
import { Sidebar } from "./Sidebar";
import { WorkspaceSettings } from "./useWorkspaceSettings";
@@ -37,7 +36,7 @@ export const WorkspaceSettingsLayout: FC = () => {
<title>{pageTitle(workspaceName, "Settings")}</title>
<Margins>
<Stack className="py-12" direction="row" spacing={10}>
<div className="flex flex-row gap-20 py-12">
{error ? (
<ErrorAlert error={error} />
) : (
@@ -58,7 +57,7 @@ export const WorkspaceSettingsLayout: FC = () => {
</WorkspaceSettings.Provider>
)
)}
</Stack>
</div>
</Margins>
</>
);
@@ -22,7 +22,6 @@ import {
import { PaginationAmount } from "#/components/PaginationWidget/PaginationAmount";
import { PaginationWidgetBase } from "#/components/PaginationWidget/PaginationWidgetBase";
import { Spinner } from "#/components/Spinner/Spinner";
import { Stack } from "#/components/Stack/Stack";
import { TableToolbar } from "#/components/TableToolbar/TableToolbar";
import { WorkspacesTable } from "#/pages/WorkspacesPage/WorkspacesTable";
import { mustUpdateWorkspace } from "#/utils/workspace";
@@ -99,14 +98,14 @@ export const WorkspacesPageView: FC<WorkspacesPageViewProps> = ({
}
>
<PageHeaderTitle>
<Stack direction="row" spacing={1} alignItems="center">
<div className="flex flex-row gap-2 items-center">
<span>Workspaces</span>
<WorkspaceHelpPopover />
</Stack>
</div>
</PageHeaderTitle>
</PageHeader>
<Stack>
<div className="flex flex-col gap-4">
{hasError(error) && !isApiValidationError(error) && (
<ErrorAlert error={error} />
)}
@@ -118,7 +117,7 @@ export const WorkspacesPageView: FC<WorkspacesPageViewProps> = ({
userMenu={filterState.menus.user}
organizationsMenu={filterState.menus.organizations}
/>
</Stack>
</div>
<TableToolbar>
{checkedWorkspaces.length > 0 ? (