diff --git a/ee/tabby-ui/app/(dashboard)/experiments/components/feature-list.tsx b/ee/tabby-ui/app/(dashboard)/experiments/components/feature-list.tsx
new file mode 100644
index 000000000000..1d0ac663f672
--- /dev/null
+++ b/ee/tabby-ui/app/(dashboard)/experiments/components/feature-list.tsx
@@ -0,0 +1,29 @@
+'use client'
+
+import { useEnableCodeBrowserQuickActionBar } from '@/lib/experiment-flags'
+import { Switch } from '@/components/ui/switch'
+
+export default function FeatureList() {
+ const [quickActionBar, toggleQuickActionBar] =
+ useEnableCodeBrowserQuickActionBar()
+ return (
+ <>
+ {!quickActionBar.loading && (
+
+
+
+ {quickActionBar.title}
+
+
+ {quickActionBar.description}
+
+
+
+
+ )}
+ >
+ )
+}
diff --git a/ee/tabby-ui/app/(dashboard)/experiments/page.tsx b/ee/tabby-ui/app/(dashboard)/experiments/page.tsx
new file mode 100644
index 000000000000..2071520705af
--- /dev/null
+++ b/ee/tabby-ui/app/(dashboard)/experiments/page.tsx
@@ -0,0 +1,18 @@
+import { Metadata } from 'next'
+
+import FeatureList from './components/feature-list'
+
+export const metadata: Metadata = {
+ title: 'Experiment Flags'
+}
+
+export default function IndexPage() {
+ return (
+
+
+ Experiment Flags
+
+
+
+ )
+}
diff --git a/ee/tabby-ui/components/ui/switch.tsx b/ee/tabby-ui/components/ui/switch.tsx
index ac2671143f0b..22432b9cda1c 100644
--- a/ee/tabby-ui/components/ui/switch.tsx
+++ b/ee/tabby-ui/components/ui/switch.tsx
@@ -11,7 +11,7 @@ const Switch = React.forwardRef<
>(({ className, ...props }, ref) => (
void, boolean] => {
+ const [storageValue, setStorageValue] = useState(defaultValue)
+ const [loading, setLoading] = useState(true)
+
+ useEffect(() => {
+ const value = localStorage.getItem(storageKey)
+ if (value) {
+ setStorageValue(JSON.parse(value))
+ }
+ setLoading(false)
+ }, [])
+
+ const upateStorageValue = (newValue: boolean) => {
+ setStorageValue(newValue)
+ localStorage.setItem(storageKey, JSON.stringify(newValue))
+ }
+
+ return [storageValue, upateStorageValue, loading]
+}
class ExperimentFlag {
constructor(
private storageKey: string,
+ readonly title: string,
readonly description: string,
readonly defaultValue: boolean
) {}
@@ -21,11 +45,18 @@ class ExperimentFlag {
class ExperimentFlagFactory {
private storageKey: string
+ private title: string
private description: string
private defaultValue: boolean
- constructor(storageKey: string, description: string, defaultValue?: boolean) {
+ constructor(
+ storageKey: string,
+ title: string,
+ description: string,
+ defaultValue?: boolean
+ ) {
this.storageKey = `EXP_${storageKey}`
+ this.title = title
this.description = description
this.defaultValue = defaultValue ?? false
}
@@ -33,24 +64,30 @@ class ExperimentFlagFactory {
defineGlobalVar() {
return new ExperimentFlag(
this.storageKey,
+ this.title,
this.description,
this.defaultValue
)
}
defineHook() {
- return (): [{ value: boolean; description: string }, () => void] => {
- const [storageValue, setStorageValue] = useLocalStorage(
- this.storageKey,
- this.defaultValue
- )
+ return (): [
+ { value: boolean; title: string; description: string; loading: boolean },
+ () => void
+ ] => {
+ const [storageValue, setStorageValue, loading] =
+ useLocalStorageForExperimentFlag(this.storageKey, this.defaultValue)
+
const toggleFlag = () => {
setStorageValue(!storageValue)
}
+
return [
{
value: storageValue,
- description: this.description
+ title: this.title,
+ description: this.description,
+ loading
},
toggleFlag
]
@@ -60,7 +97,8 @@ class ExperimentFlagFactory {
const enableCodeBrowserQuickActionBarFactory = new ExperimentFlagFactory(
'enable_code_browser_quick_action_bar',
- 'Show a quick action popup upon selecting code snippets',
+ 'Quick Action Bar',
+ 'Enable Quick Action Bar to display a convenient toolbar when you select code, offering options to explain the code, add unit tests, and more.',
false
)