diff --git a/frontend/__snapshots__/scenes-app-max-ai--welcome--dark.png b/frontend/__snapshots__/scenes-app-max-ai--welcome--dark.png index b7b361d6826..c844325595b 100644 Binary files a/frontend/__snapshots__/scenes-app-max-ai--welcome--dark.png and b/frontend/__snapshots__/scenes-app-max-ai--welcome--dark.png differ diff --git a/frontend/__snapshots__/scenes-app-max-ai--welcome--light.png b/frontend/__snapshots__/scenes-app-max-ai--welcome--light.png index a2883e6e32c..a968d4cd3be 100644 Binary files a/frontend/__snapshots__/scenes-app-max-ai--welcome--light.png and b/frontend/__snapshots__/scenes-app-max-ai--welcome--light.png differ diff --git a/frontend/__snapshots__/scenes-app-max-ai--welcome-loading-suggestions--dark.png b/frontend/__snapshots__/scenes-app-max-ai--welcome-loading-suggestions--dark.png index 820fd669da2..be67ab75d12 100644 Binary files a/frontend/__snapshots__/scenes-app-max-ai--welcome-loading-suggestions--dark.png and b/frontend/__snapshots__/scenes-app-max-ai--welcome-loading-suggestions--dark.png differ diff --git a/frontend/__snapshots__/scenes-app-max-ai--welcome-loading-suggestions--light.png b/frontend/__snapshots__/scenes-app-max-ai--welcome-loading-suggestions--light.png index d09949248bb..cf026b65c49 100644 Binary files a/frontend/__snapshots__/scenes-app-max-ai--welcome-loading-suggestions--light.png and b/frontend/__snapshots__/scenes-app-max-ai--welcome-loading-suggestions--light.png differ diff --git a/frontend/__snapshots__/scenes-app-max-ai--welcome-suggestions-available--dark.png b/frontend/__snapshots__/scenes-app-max-ai--welcome-suggestions-available--dark.png index 1b0205298a1..10ef2c718a5 100644 Binary files a/frontend/__snapshots__/scenes-app-max-ai--welcome-suggestions-available--dark.png and b/frontend/__snapshots__/scenes-app-max-ai--welcome-suggestions-available--dark.png differ diff --git a/frontend/__snapshots__/scenes-app-max-ai--welcome-suggestions-available--light.png b/frontend/__snapshots__/scenes-app-max-ai--welcome-suggestions-available--light.png index 5de13f2dc0f..5cfea77caa4 100644 Binary files a/frontend/__snapshots__/scenes-app-max-ai--welcome-suggestions-available--light.png and b/frontend/__snapshots__/scenes-app-max-ai--welcome-suggestions-available--light.png differ diff --git a/frontend/src/lib/components/HedgehogBuddy/HedgehogBuddy.tsx b/frontend/src/lib/components/HedgehogBuddy/HedgehogBuddy.tsx index 1f7d2c8cd5f..70b61d48410 100644 --- a/frontend/src/lib/components/HedgehogBuddy/HedgehogBuddy.tsx +++ b/frontend/src/lib/components/HedgehogBuddy/HedgehogBuddy.tsx @@ -959,7 +959,7 @@ export const HedgehogBuddy = React.forwardRef { onPositionChange?.(actor) - }, [actor.x, actor.y]) + }, [actor.x, actor.y, actor.direction]) const onClick = (): void => { !actor.isDragging && _onClick?.(actor) diff --git a/frontend/src/lib/lemon-ui/Popover/Popover.tsx b/frontend/src/lib/lemon-ui/Popover/Popover.tsx index 94801efe092..f14e507a994 100644 --- a/frontend/src/lib/lemon-ui/Popover/Popover.tsx +++ b/frontend/src/lib/lemon-ui/Popover/Popover.tsx @@ -199,7 +199,7 @@ export const Popover = React.forwardRef(function P if (visible && referenceRef?.current && floatingElement) { return autoUpdate(referenceRef.current, floatingElement, update) } - }, [visible, referenceRef?.current, floatingElement, ...additionalRefs]) + }, [visible, placement, referenceRef?.current, floatingElement, ...additionalRefs]) const floatingContainer = useFloatingContainer() diff --git a/frontend/src/scenes/max/Intro.tsx b/frontend/src/scenes/max/Intro.tsx index b2f3de90cfc..c43cd86b53d 100644 --- a/frontend/src/scenes/max/Intro.tsx +++ b/frontend/src/scenes/max/Intro.tsx @@ -1,8 +1,11 @@ -import { useValues } from 'kea' +import { offset } from '@floating-ui/react' +import { LemonButton, Popover } from '@posthog/lemon-ui' +import { useActions, useValues } from 'kea' import { HedgehogBuddy } from 'lib/components/HedgehogBuddy/HedgehogBuddy' import { hedgehogBuddyLogic } from 'lib/components/HedgehogBuddy/hedgehogBuddyLogic' -import { useMemo } from 'react' +import { useMemo, useState } from 'react' +import { maxGlobalLogic } from './maxGlobalLogic' import { maxLogic } from './maxLogic' const HEADLINES = [ @@ -14,8 +17,12 @@ const HEADLINES = [ export function Intro(): JSX.Element { const { hedgehogConfig } = useValues(hedgehogBuddyLogic) + const { acceptDataProcessing } = useActions(maxGlobalLogic) + const { dataProcessingAccepted } = useValues(maxGlobalLogic) const { sessionId } = useValues(maxLogic) + const [hedgehogDirection, setHedgehogDirection] = useState<'left' | 'right'>('right') + const headline = useMemo(() => { return HEADLINES[parseInt(sessionId.split('-').at(-1) as string, 16) % HEADLINES.length] }, []) @@ -23,22 +30,52 @@ export function Intro(): JSX.Element { return ( <>
- { - if (Math.random() < 0.01) { - actor.setOnFire() - } else { - actor.setRandomAnimation() + +

+ Hi! I use OpenAI services to analyze your data, +
+ so that you can focus on building. This can include +
+ personal data of your users, if you're capturing it. +
+ Your data won't be used for training models. +

+ acceptDataProcessing()}> + Got it, I accept OpenAI processing data + +
+ } + placement={`${hedgehogDirection}-end`} + middleware={[offset(-12)]} + showArrow + visible={!dataProcessingAccepted} + > + { + if (Math.random() < 0.01) { + actor.setOnFire() + } else { + actor.setRandomAnimation() + } + }} + onActorLoaded={(actor) => + setTimeout(() => { + actor.setAnimation('wave') + // Always start out facing right so that the data processing popover is more readable + actor.direction = 'right' + }, 100) } - }} - onActorLoaded={(actor) => setTimeout(() => actor.setAnimation('wave'), 100)} - /> + onPositionChange={(actor) => setHedgehogDirection(actor.direction)} + /> +

{headline}

diff --git a/frontend/src/scenes/max/Max.stories.tsx b/frontend/src/scenes/max/Max.stories.tsx index 73f1ce19a41..d5aa836f7bc 100644 --- a/frontend/src/scenes/max/Max.stories.tsx +++ b/frontend/src/scenes/max/Max.stories.tsx @@ -8,6 +8,7 @@ import { mswDecorator, useStorybookMocks } from '~/mocks/browser' import { chatResponseChunk, failureChunk, generationFailureChunk } from './__mocks__/chatResponse.mocks' import { MaxInstance } from './Max' +import { maxGlobalLogic } from './maxGlobalLogic' import { maxLogic } from './maxLogic' const meta: Meta = { @@ -31,6 +32,12 @@ export default meta const SESSION_ID = 'b1b4b3b4-1b3b-4b3b-1b3b4b3b4b3b' const Template = ({ sessionId: SESSION_ID }: { sessionId: string }): JSX.Element => { + const { acceptDataProcessing } = useActions(maxGlobalLogic) + + useEffect(() => { + acceptDataProcessing() + }, []) + return (
@@ -56,6 +63,11 @@ export const Welcome: StoryFn = () => { ], }, }) + const { acceptDataProcessing } = useActions(maxGlobalLogic) + useEffect(() => { + // We override data processing opt-in to false, so that wee see the welcome screen as a first-time user would + acceptDataProcessing(false) + }, []) return