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 )