From 0dfcb7d71df179c21bae575a49462e51a2baa1d0 Mon Sep 17 00:00:00 2001 From: Jwalin Shah Date: Tue, 21 Apr 2026 14:00:32 -0700 Subject: [PATCH] feat(onboarding): add beta notice banner (#729) (#736) Shows a dismissible amber banner at the top of the onboarding flow on first launch. Dismissal is persisted to localStorage so it only shows once per installation. Co-authored-by: Jwalin Shah --- app/src/pages/onboarding/Onboarding.tsx | 6 +- .../onboarding/components/BetaBanner.tsx | 61 +++++++++++++++++++ 2 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 app/src/pages/onboarding/components/BetaBanner.tsx diff --git a/app/src/pages/onboarding/Onboarding.tsx b/app/src/pages/onboarding/Onboarding.tsx index cec4421ba..59e16dece 100644 --- a/app/src/pages/onboarding/Onboarding.tsx +++ b/app/src/pages/onboarding/Onboarding.tsx @@ -4,6 +4,7 @@ import { useCoreState } from '../../providers/CoreStateProvider'; import { referralApi } from '../../services/api/referralApi'; import { userApi } from '../../services/api/userApi'; import { getDefaultEnabledTools } from '../../utils/toolDefinitions'; +import BetaBanner from './components/BetaBanner'; import ContextGatheringStep from './steps/ContextGatheringStep'; import ReferralApplyStep from './steps/ReferralApplyStep'; import SkillsStep from './steps/SkillsStep'; @@ -208,7 +209,10 @@ const Onboarding = ({ onComplete, onDefer }: OnboardingProps) => { )} -
{renderStep()}
+
+ + {renderStep()} +
); }; diff --git a/app/src/pages/onboarding/components/BetaBanner.tsx b/app/src/pages/onboarding/components/BetaBanner.tsx new file mode 100644 index 000000000..1a0f87c15 --- /dev/null +++ b/app/src/pages/onboarding/components/BetaBanner.tsx @@ -0,0 +1,61 @@ +import { useState } from 'react'; + +const DISMISSED_KEY = 'openhuman_beta_banner_dismissed'; + +const BetaBanner = () => { + const [visible, setVisible] = useState(() => { + try { + return localStorage.getItem(DISMISSED_KEY) !== 'true'; + } catch { + return true; + } + }); + + if (!visible) return null; + + const handleDismiss = () => { + try { + localStorage.setItem(DISMISSED_KEY, 'true'); + } catch { + // localStorage unavailable — dismiss for this session only + } + setVisible(false); + }; + + return ( +
+ {/* Beta pill */} + + Beta + + + {/* Message */} +

+ OpenHuman is in beta — you may hit rough edges. Your feedback helps us ship faster. +

+ + {/* Dismiss */} + +
+ ); +}; + +export default BetaBanner;