From 5afb29704202db65c73be0e4a16109cc506b4a61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kayla=20=E3=81=AF=E3=81=AA?= Date: Tue, 28 Apr 2026 12:02:13 -0600 Subject: [PATCH] refactor(site): remove `Stack` component (#24503) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Remove the deprecated `Stack` component and replace all usages with Tailwind flex utility classes. - Replaced `` → `
` (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 --- site/src/components/Badges/Badges.tsx | 5 +- .../Dialogs/DeleteDialog/DeleteDialog.tsx | 7 +-- site/src/components/FileUpload/FileUpload.tsx | 21 ++++---- site/src/components/Form/Form.tsx | 11 ++-- .../FullPageForm/FullPageForm.stories.tsx | 5 +- .../RichParameterInput/RichParameterInput.tsx | 40 +++++++------- site/src/components/Sidebar/Sidebar.tsx | 9 ++-- site/src/components/Stack/Stack.stories.tsx | 47 ---------------- site/src/components/Stack/Stack.tsx | 42 --------------- site/src/components/StackLabel/StackLabel.tsx | 8 ++- .../management/DeploymentSidebarView.tsx | 9 ++-- site/src/modules/resources/AgentMetadata.tsx | 5 +- .../resources/AgentOutdatedTooltip.tsx | 13 +++-- .../src/modules/resources/AgentRowPreview.tsx | 54 +++++++------------ .../modules/resources/AppLink/AppPreview.tsx | 10 +--- site/src/modules/resources/ResourceCard.tsx | 13 ++--- site/src/modules/resources/Resources.tsx | 5 +- .../modules/resources/SSHButton/SSHButton.tsx | 5 +- .../DynamicParameter/DynamicParameter.tsx | 9 ++-- .../ChangeWorkspaceVersionDialog.tsx | 21 +++----- .../DownloadLogsDialog.tsx | 5 +- site/src/pages/AuditPage/AuditPageView.tsx | 5 +- .../ConnectionLogPageView.tsx | 5 +- .../StarterTemplates.tsx | 9 ++-- .../CreateTemplatePage/VariableInput.tsx | 5 +- .../pages/CreateTokenPage/CreateTokenForm.tsx | 5 +- .../CreateWorkspacePage/SelectedTemplate.tsx | 12 ++--- .../AIGovernanceSettingsPageView.tsx | 5 +- .../AnnouncementBannerDialog.tsx | 9 ++-- .../AddNewLicensePageView.tsx | 13 ++--- .../LicensesSettingsPageView.tsx | 25 ++++----- .../NetworkSettingsPageView.tsx | 5 +- .../NotificationsPage/NotificationEvents.tsx | 5 +- .../CreateOAuth2AppPageView.tsx | 13 ++--- .../EditOAuth2AppPageView.tsx | 21 +++----- .../OAuth2AppsSettingsPageView.tsx | 9 +--- .../ObservabilitySettingsPageView.tsx | 5 +- .../OverviewPage/OverviewPageView.tsx | 5 +- .../SecuritySettingsPageView.tsx | 5 +- .../UserAuthSettingsPageView.tsx | 5 +- .../CreateEditRolePageView.tsx | 9 +--- .../CustomRolesPage/CustomRolesPage.tsx | 9 +--- .../CustomRolesPage/CustomRolesPageView.tsx | 13 ++--- .../OrganizationMembersPage.tsx | 5 +- .../OrganizationMembersPageView.tsx | 13 +++-- .../StarterTemplatePageView.tsx | 5 +- .../TemplateInsightsPage.tsx | 8 +-- .../pages/TemplatePage/TemplatePageHeader.tsx | 10 ++-- .../TemplateVersionsPage/VersionRow.tsx | 28 ++++------ .../TemplateSettingsForm.tsx | 20 +++---- .../TemplateScheduleAutostart.tsx | 15 ++---- .../TemplateScheduleForm.tsx | 6 +-- .../TemplateSettingsLayout.tsx | 5 +- .../TemplateVariablesPageView.tsx | 5 +- .../TemplateVersionEditorPage/FileDialog.tsx | 9 ++-- .../PublishTemplateVersionDialog.tsx | 9 ++-- .../TemplateVersionPageView.tsx | 5 +- .../pages/TemplatesPage/EmptyTemplates.tsx | 6 +-- .../pages/TemplatesPage/TemplatesPageView.tsx | 5 +- .../AccountPage/AccountPage.tsx | 5 +- .../ExternalAuthPage/ExternalAuthPageView.tsx | 6 +-- .../OAuth2ProviderPageView.tsx | 5 +- .../SSHKeysPage/SSHKeysPageView.tsx | 5 +- .../SchedulePage/ScheduleForm.tsx | 5 +- site/src/pages/UserSettingsPage/Section.tsx | 5 +- .../SecurityPage/SecurityPage.tsx | 5 +- .../SecurityPage/SingleSignOnSection.tsx | 5 +- .../TokensPage/TokensPage.tsx | 5 +- .../TokensPage/TokensPageView.tsx | 5 +- .../WorkspaceProxyPage/WorkspaceProxyView.tsx | 5 +- .../pages/UsersPage/UsersTable/UsersTable.tsx | 13 +++-- .../WorkspaceBuildPageView.tsx | 6 +-- .../WorkspaceSettingsLayout.tsx | 5 +- .../WorkspacesPage/WorkspacesPageView.tsx | 9 ++-- 74 files changed, 265 insertions(+), 519 deletions(-) delete mode 100644 site/src/components/Stack/Stack.stories.tsx delete mode 100644 site/src/components/Stack/Stack.tsx diff --git a/site/src/components/Badges/Badges.tsx b/site/src/components/Badges/Badges.tsx index 35b52cefb8..7b5f7989dc 100644 --- a/site/src/components/Badges/Badges.tsx +++ b/site/src/components/Badges/Badges.tsx @@ -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 = ({ children }) => { return ( - - {children} - +
{children}
); }; diff --git a/site/src/components/Dialogs/DeleteDialog/DeleteDialog.tsx b/site/src/components/Dialogs/DeleteDialog/DeleteDialog.tsx index 851dd5534c..2c91e4aa0b 100644 --- a/site/src/components/Dialogs/DeleteDialog/DeleteDialog.tsx +++ b/site/src/components/Dialogs/DeleteDialog/DeleteDialog.tsx @@ -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 = ({ confirmText={confirmText} description={ <> - +

{verb ?? "Deleting"} this {entity} is irreversible!

- {Boolean(info) &&
{info}
} -

Type {name} below to confirm.

- +
= ({ if (!isUploading && file) { return ( - - +
{file.name} - +
-
+
); } @@ -66,7 +63,7 @@ export const FileUpload: FC = ({ {...clickable} {...fileDrop} > - +
{isUploading ? ( @@ -75,11 +72,11 @@ export const FileUpload: FC = ({ )}
- +
{title} {description} - - +
+
= ({ ); }; -export const FormFields: FC> = (props) => { +export const FormFields: FC> = ({ + className, + ...props +}) => { return ( - diff --git a/site/src/components/FullPageForm/FullPageForm.stories.tsx b/site/src/components/FullPageForm/FullPageForm.stories.tsx index 2820f075e2..ac270a45ba 100644 --- a/site/src/components/FullPageForm/FullPageForm.stories.tsx +++ b/site/src/components/FullPageForm/FullPageForm.stories.tsx @@ -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 = (props) => ( @@ -13,14 +12,14 @@ const Template: FC = (props) => ( e.preventDefault(); }} > - +
- +
); diff --git a/site/src/components/RichParameterInput/RichParameterInput.tsx b/site/src/components/RichParameterInput/RichParameterInput.tsx index 9654422c89..e0d0d4bbe8 100644 --- a/site/src/components/RichParameterInput/RichParameterInput.tsx +++ b/site/src/components/RichParameterInput/RichParameterInput.tsx @@ -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 = ({ parameter, isPreset }) => { return ( ); }; @@ -235,10 +235,12 @@ export const RichParameterInput: FC = ({ const [hideSuggestion, setHideSuggestion] = useState(false); return ( - @@ -276,7 +278,7 @@ export const RichParameterInput: FC = ({ )} - + ); }; @@ -332,7 +334,7 @@ const RichParameterField: FC = ({ value={option.value} control={} label={ - +
{option.icon && ( = ({ /> )} {option.description ? ( - {small ? ( @@ -366,11 +370,11 @@ const RichParameterField: FC = ({ )} - +
) : ( option.name )} -
+ } /> ))} diff --git a/site/src/components/Sidebar/Sidebar.tsx b/site/src/components/Sidebar/Sidebar.tsx index 0a21f8dec6..f95098792d 100644 --- a/site/src/components/Sidebar/Sidebar.tsx +++ b/site/src/components/Sidebar/Sidebar.tsx @@ -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 = ({ linkTo, }) => { return ( - +
{avatar}
{linkTo ? ( @@ -45,7 +44,7 @@ export const SidebarHeader: FC = ({ {subtitle}
- +
); }; @@ -100,10 +99,10 @@ export const SidebarNavItem: FC = ({ ) } > - +
{children} - +
); }; diff --git a/site/src/components/Stack/Stack.stories.tsx b/site/src/components/Stack/Stack.stories.tsx deleted file mode 100644 index 7931b96aa5..0000000000 --- a/site/src/components/Stack/Stack.stories.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import type { Meta, StoryObj } from "@storybook/react-vite"; -import { Stack } from "./Stack"; - -const meta: Meta = { - title: "components/Stack", - component: Stack, - args: { - children: ( - <> - チェンソーマン - ジョジョの奇妙な冒険 - スパイファミリー - 葬送のフリーレン - 少女革命ウテナ - PSYCHO-PASS サイコパス - 機動戦士ガンダム 水星の魔女 - 勇気爆発バーンブレイバーン - Re:ゼロから始める異世界生活 - ダンジョン飯 - - ), - }, -}; - -export default meta; -type Story = StoryObj; - -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", - }, -}; diff --git a/site/src/components/Stack/Stack.tsx b/site/src/components/Stack/Stack.tsx deleted file mode 100644 index e2a660167a..0000000000 --- a/site/src/components/Stack/Stack.tsx +++ /dev/null @@ -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 = (props) => { - const { - children, - direction = "column", - spacing = 2, - alignItems, - justifyContent, - wrap, - ...divProps - } = props; - - return ( -
- {children} -
- ); -}; diff --git a/site/src/components/StackLabel/StackLabel.tsx b/site/src/components/StackLabel/StackLabel.tsx index ad33fecb57..0f701f29f5 100644 --- a/site/src/components/StackLabel/StackLabel.tsx +++ b/site/src/components/StackLabel/StackLabel.tsx @@ -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> = ({ +export const StackLabel: FC> = ({ className, ...props }) => { return ( - ); diff --git a/site/src/modules/management/DeploymentSidebarView.tsx b/site/src/modules/management/DeploymentSidebarView.tsx index 75d6528e7b..2e6306ac10 100644 --- a/site/src/modules/management/DeploymentSidebarView.tsx +++ b/site/src/modules/management/DeploymentSidebarView.tsx @@ -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 = ({ )} {permissions.viewAnyGroup && ( - +
Groups {showOrganizations && } - +
)} {permissions.viewOrganizationIDPSyncSettings && ( @@ -108,9 +107,9 @@ export const DeploymentSidebarView: FC = ({ )} {permissions.editDeploymentConfig && ( - +
Manage Coder Agents - +
)} diff --git a/site/src/modules/resources/AgentMetadata.tsx b/site/src/modules/resources/AgentMetadata.tsx index 7668a9d718..8942ea4778 100644 --- a/site/src/modules/resources/AgentMetadata.tsx +++ b/site/src/modules/resources/AgentMetadata.tsx @@ -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 = ({ const AgentMetadataSkeleton: FC = () => { return ( - +
@@ -154,7 +153,7 @@ const AgentMetadataSkeleton: FC = () => {
- +
); }; diff --git a/site/src/modules/resources/AgentOutdatedTooltip.tsx b/site/src/modules/resources/AgentOutdatedTooltip.tsx index 499a17b2bf..8fbbaf01a5 100644 --- a/site/src/modules/resources/AgentOutdatedTooltip.tsx +++ b/site/src/modules/resources/AgentOutdatedTooltip.tsx @@ -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 = ({ - +
{title} {text}
- +
Agent version {agent.version} - +
- +
Server version {serverVersion} - +
= ({ Update workspace -
+
); diff --git a/site/src/modules/resources/AgentRowPreview.tsx b/site/src/modules/resources/AgentRowPreview.tsx index 4c5253060a..00db3bde07 100644 --- a/site/src/modules/resources/AgentRowPreview.tsx +++ b/site/src/modules/resources/AgentRowPreview.tsx @@ -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 = ({ alignValues, }) => { return ( - - +
- - = ({ > Agent: {agent.name} - +
- = ({ {agent.operating_system} - +
- Apps: - +
{/* We display all modules returned in agent.apps */} {agent.apps.map((app) => ( @@ -130,11 +114,11 @@ export const AgentRowPreview: FC = ({ {agent.apps.length === 0 && agent.display_apps.length === 0 && ( None )} - - - - - +
+ + + + ); }; diff --git a/site/src/modules/resources/AppLink/AppPreview.tsx b/site/src/modules/resources/AppLink/AppPreview.tsx index cd9c39280b..4389c79722 100644 --- a/site/src/modules/resources/AppLink/AppPreview.tsx +++ b/site/src/modules/resources/AppLink/AppPreview.tsx @@ -1,14 +1,8 @@ import type { FC, PropsWithChildren } from "react"; -import { Stack } from "#/components/Stack/Stack"; export const AppPreview: FC = ({ children }) => { return ( - +
{children} - +
); }; diff --git a/site/src/modules/resources/ResourceCard.tsx b/site/src/modules/resources/ResourceCard.tsx index 71e99544ed..c7cc0a9edf 100644 --- a/site/src/modules/resources/ResourceCard.tsx +++ b/site/src/modules/resources/ResourceCard.tsx @@ -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 = ({ resource, agentRow }) => { return (
- - +
@@ -111,7 +108,7 @@ export const ResourceCard: FC = ({ resource, agentRow }) => {
{resource.type}
{resource.name}
-
+
= ({ resource, agentRow }) => { )} - +
{resource.agents && resource.agents.length > 0 && (
{resource.agents.map(agentRow)}
diff --git a/site/src/modules/resources/Resources.tsx b/site/src/modules/resources/Resources.tsx index 090243fd66..6cdb932696 100644 --- a/site/src/modules/resources/Resources.tsx +++ b/site/src/modules/resources/Resources.tsx @@ -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 = ({ resources, agentRow }) => { const hasHideResources = resources.some((r) => r.hide); return ( - +
{displayResources.map((resource) => ( = ({ resources, agentRow }) => {
)} -
+ ); }; diff --git a/site/src/modules/resources/SSHButton/SSHButton.tsx b/site/src/modules/resources/SSHButton/SSHButton.tsx index a4f0f01b5b..0a6761d0d9 100644 --- a/site/src/modules/resources/SSHButton/SSHButton.tsx +++ b/site/src/modules/resources/SSHButton/SSHButton.tsx @@ -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 = ({
    - +
    = ({ helpText="Connect to the agent:" codeExample={`ssh ${agentName}.${workspaceName}.${workspaceOwnerUsername}.${sshSuffix}`} /> - +
diff --git a/site/src/modules/workspaces/DynamicParameter/DynamicParameter.tsx b/site/src/modules/workspaces/DynamicParameter/DynamicParameter.tsx index 36743eba0a..9254cb29bc 100644 --- a/site/src/modules/workspaces/DynamicParameter/DynamicParameter.tsx +++ b/site/src/modules/workspaces/DynamicParameter/DynamicParameter.tsx @@ -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 = ({ const [showMaskedInput, setShowMaskedInput] = useState(false); return ( - +
= ({ )} )} - +
); }; @@ -552,7 +551,7 @@ const MaskableTextArea: FC = ({ const [showMaskedInput, setShowMaskedInput] = useState(false); return ( - +