diff --git a/package-lock.json b/package-lock.json
index 717d6f0be..7309370b8 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -67,6 +67,7 @@
"@testing-library/dom": "^10.4.1",
"@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^16.3.2",
+ "@testing-library/user-event": "^14.6.1",
"@types/js-yaml": "^4.0.9",
"@types/node": "^25.0.9",
"@types/react": "^19.2.9",
@@ -4277,6 +4278,20 @@
}
}
},
+ "node_modules/@testing-library/user-event": {
+ "version": "14.6.1",
+ "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.6.1.tgz",
+ "integrity": "sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12",
+ "npm": ">=6"
+ },
+ "peerDependencies": {
+ "@testing-library/dom": ">=7.21.4"
+ }
+ },
"node_modules/@tybys/wasm-util": {
"version": "0.10.1",
"resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz",
diff --git a/package.json b/package.json
index 41d13f65d..4b2d0dc8c 100644
--- a/package.json
+++ b/package.json
@@ -110,6 +110,7 @@
"@testing-library/dom": "^10.4.1",
"@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^16.3.2",
+ "@testing-library/user-event": "^14.6.1",
"@types/js-yaml": "^4.0.9",
"@types/node": "^25.0.9",
"@types/react": "^19.2.9",
@@ -128,10 +129,10 @@
"jsdom": "^27.4.0",
"knip": "^5.82.1",
"prettier": "^3.8.1",
+ "tsx": "^4.21.0",
"typescript": "^5.9.3",
"typescript-eslint": "^8.53.1",
"vite": "^7.3.1",
- "vitest": "^3.0.5",
- "tsx": "^4.21.0"
+ "vitest": "^3.0.5"
}
}
diff --git a/src/betaFlags.ts b/src/betaFlags.ts
index 113db41fb..6d6711e37 100644
--- a/src/betaFlags.ts
+++ b/src/betaFlags.ts
@@ -9,12 +9,14 @@ export const ExistingBetaFlags = {
description:
"Highlight the tasks on the Pipeline canvas when the component is hovered over in the component library.",
default: false,
+ category: "beta",
} as BetaFlag,
["remote-component-library-search"]: {
name: "Published Components Library",
description: "Enable the Published Components Library feature.",
default: isRemoteComponentLibraryEnabled,
+ category: "beta",
} as BetaFlag,
["github-component-library"]: {
@@ -22,12 +24,14 @@ export const ExistingBetaFlags = {
description:
"Enable the GitHub Component Library. All lib folders will be based on GitHub components",
default: false,
+ category: "beta",
} as BetaFlag,
["redirect-on-new-pipeline-run"]: {
name: "Redirect on new pipeline run",
description: "Automatically open a new tab after starting a new execution.",
default: false,
+ category: "setting",
} as BetaFlag,
["created-by-me-default"]: {
@@ -35,6 +39,7 @@ export const ExistingBetaFlags = {
description:
"Automatically select the 'Created by me' filter when viewing the pipeline run list.",
default: false,
+ category: "setting",
} as BetaFlag,
["in-app-component-editor"]: {
@@ -42,6 +47,7 @@ export const ExistingBetaFlags = {
description:
"Enable the in-app component editor for creating and editing pipeline components.",
default: true,
+ category: "beta",
} as BetaFlag,
["partial-selection"]: {
@@ -49,5 +55,6 @@ export const ExistingBetaFlags = {
description:
"Allow nodes to be selected when partially covered by the selection box. Use Shift+drag for full selection, or Shift+Cmd+drag (Shift+Ctrl on Windows) for partial selection.",
default: false,
+ category: "beta",
} as BetaFlag,
};
diff --git a/src/components/shared/Settings/BetaFeatures.tsx b/src/components/shared/Settings/BetaFeatures.tsx
new file mode 100644
index 000000000..11c8289b9
--- /dev/null
+++ b/src/components/shared/Settings/BetaFeatures.tsx
@@ -0,0 +1,28 @@
+import { BlockStack } from "@/components/ui/layout";
+import { Paragraph } from "@/components/ui/typography";
+import type { Flag } from "@/types/configuration";
+
+import { Setting } from "./Setting";
+
+interface BetaFeaturesProps {
+ betaFlags: Flag[];
+ onChange: (key: string, enabled: boolean) => void;
+}
+
+export function BetaFeatures({ betaFlags, onChange }: BetaFeaturesProps) {
+ return (
+
+ Beta Features
+ {betaFlags.length === 0 && (
+ No beta features available.
+ )}
+ {betaFlags.map((flag) => (
+ onChange(flag.key, enabled)}
+ />
+ ))}
+
+ );
+}
diff --git a/src/components/shared/Settings/PersonalPreferencesDialog.tsx b/src/components/shared/Settings/PersonalPreferencesDialog.tsx
index b9cfe3046..6a53bb118 100644
--- a/src/components/shared/Settings/PersonalPreferencesDialog.tsx
+++ b/src/components/shared/Settings/PersonalPreferencesDialog.tsx
@@ -9,10 +9,10 @@ import {
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
-import { BlockStack } from "@/components/ui/layout";
-import { Paragraph } from "@/components/ui/typography";
+import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
-import { Setting } from "./Setting";
+import { BetaFeatures } from "./BetaFeatures";
+import { Settings } from "./Settings";
import { useBetaFlagsReducer } from "./useBetaFlagReducer";
interface PersonalPreferencesDialogProps {
@@ -24,12 +24,19 @@ export function PersonalPreferencesDialog({
open,
setOpen,
}: PersonalPreferencesDialogProps) {
- const [betaFlags, dispatch] = useBetaFlagsReducer(ExistingBetaFlags);
+ const [allFlags, dispatch] = useBetaFlagsReducer(ExistingBetaFlags);
const handleSetFlag = (flag: string, enabled: boolean) => {
dispatch({ type: "setFlag", payload: { key: flag, enabled } });
};
+ const betaFlags = Object.values(allFlags).filter(
+ (flag) => flag.category === "beta",
+ );
+ const settings = Object.values(allFlags).filter(
+ (flag) => flag.category === "setting",
+ );
+
return (