Repository navigation
feat(max): showcase capabilities - #32556
Conversation
There was a problem hiding this comment.
PR Summary
This PR enhances Max AI's user interface by replacing random suggestions with a structured, categorized menu system to better showcase its capabilities.
- Added
maxQuestionSuggestionsLogic.tsxwith predefined categories (SQL, Product Analytics, Docs, etc.) and their specific suggestions - Implemented two-level navigation in
QuestionSuggestions.tsxwith category selection and detailed suggestions - Added new animation effects in
QuestionSuggestions.scssfor staggered suggestion appearance - Enhanced focus management in
maxLogic.tsxwith newfocusCounterreducer andfocusInputaction - Added
ThreadWithOpenedSuggestionsstory to test the new suggestion system
8 file(s) reviewed, 8 comment(s)
Edit PR Review Bot Settings | Greptile
📸 UI snapshots have been updated12 snapshot changes in total. 0 added, 12 modified, 0 deleted:
Triggered by this commit. |
kappa90
left a comment
There was a problem hiding this comment.
Beautiful. Just left some minor UX comments.
I also noticed that the suggestions are center-aligned, I think it makes sense to always aligns them to the left (like in ChatGPT).
| disabledReason={!dataProcessingAccepted ? 'Please accept OpenAI processing data' : undefined} | ||
| center | ||
| > | ||
| Let's get started with me learning about your project! |
There was a problem hiding this comment.
I think we still need this button to trigger the onboarding manually.
There was a problem hiding this comment.
Shouldn't the onboarding be triggered when any of the product analytics suggestions are clicked?
There was a problem hiding this comment.
There was a button to also run it directly, but yeah you're right, now that we have direct product analytics suggestions, we can keep it this way.
| ) | ||
| } | ||
|
|
||
| function useClickOutside<T extends HTMLElement>( |
There was a problem hiding this comment.
Still on a fan of this. I think on ChatGPT it works well because there's lots of space around the suggestions, but Max lives in a tiny sidebar, so clicking "outside" is kinda difficult.
There was a problem hiding this comment.
This experience should be more obvious and easier with the UI. You typically expect to be able to click anywhere to close an autocomplete.
| onClick={() => { | ||
| // If it's a product-based skill, open the URL first | ||
| if (group.url && !router.values.currentLocation.pathname.includes(group.url)) { | ||
| router.actions.push(group.url) |
There was a problem hiding this comment.
There's an edge case where this is slightly annoying: you're editing an insight, click by mistake on a suggestion, you get the alert: "You have unsaved changes", and you click yes by mistake because you're not reading the alert text like 90% of the people out there (including me) 😄 There's no way to solve it, it's just that one wouldn't necessarily expect Max's suggestions to also redirect to a different page (although it makes sense).
There was a problem hiding this comment.
Product-based flows will solve it👀 It's probably fine for now unless you think otherwise.
| label: 'What are the top referring domains?', | ||
| }, | ||
| { | ||
| label: 'Calculate a conversion rate for <events or features>', |
There was a problem hiding this comment.
This is slightly difficult to understand, specifically the "or features" part, since there is no "feature" concept within PostHog (yet). Maybe we can just write "Calculate a conversion rate for..." and it prefills the input, like you did.
| tooltip: 'Max can generate insights from natural language and tweak existing ones.', | ||
| }, | ||
| { | ||
| label: 'Docs', |
There was a problem hiding this comment.
I wonder if we can "suggest" to Max that it should always answers these by searching the docs. It could be an additional field in askMax, which forces the Root to use a specific tool. This also applies to the insight questions.
There was a problem hiding this comment.
Those questions are prompted in a way that should always trigger their flows. Did you experience a situation when it hadn't triggered a flow?
There was a problem hiding this comment.
I didn't, I was just wondering if it would make sense to add some "guardrails".
| icon: <IconPlug />, | ||
| suggestions: [ | ||
| { | ||
| label: 'How can I set up the session replay in <a framework or language>', |
38e25de to
81c73b6
Compare
📸 UI snapshots have been updated14 snapshot changes in total. 0 added, 14 modified, 0 deleted: Caution Detected flapping snapshotsThese snapshots have auto-updated more than once since the last human commit:
The flippy-flappies are deadly and must be fixed ASAP. They're productivity killers.
Triggered by this commit. |
|
@Twixes are the snapshots above actually flapping? It looks like they're generated for the first time. |
|
Size Change: 0 B Total Size: 3.72 MB ℹ️ View Unchanged
|
| label: 'How can I set up the session replay in a framework or language', | ||
| content: 'How can I set up the session replay in ', |
There was a problem hiding this comment.
To bump up Em's point, I think the suggestions will be more intuitive the other way, and we can probably standardize this so that it's not needed to have label and content separate.
We can keep just label in this format:
How can I set up the session replay in <framework or language>? or Write an SQL query to …
This way we can handle angled brackets <> and the ellipsis … as markup in terms of the resulting content:
- angled brackets
<>– the opening bracket<, and everything after it, is stripped, so the content automatically becomes justHow can I set up the session replay in - ellipsis
…– just gets removed, so onlyWrite an SQL query toremains
There was a problem hiding this comment.
It seemed to me like overkill for the hardcoded suggestions. Nevertheless, it's implemented now👍
| return scrollableEl | ||
| } | ||
|
|
||
| export const QUESTION_SUGGESTIONS_DATA: readonly SuggestionGroup[] = [ |
There was a problem hiding this comment.
I had the idea to use verbs instead to signify things to do, but it seems to wordy after trying:

Real polish suggestions though:
- let's add an ellipsis after "Ask Max…"
- Let's use sentence case in accordance with our style, which applies even to product names, i.e. "Product analytics" rather than "Product Analytics"
- To me, it'd be slightly more intuitive to still put "Product analytics" first, since that's the broadest use case for Max.
- "Set up" is vague, "SDK setup" would be clearer. I'd put it second to last
- "Docs" feel like they should be at the end, since they're the the least in-product of these items, if that makes sense
| icon: <IconHogQL />, | ||
| suggestions: [ | ||
| { | ||
| label: 'Generate an SQL query to', |
There was a problem hiding this comment.
Slightly friendlier wording: "Write an SQL query to …"
| }, | ||
| ], | ||
| url: urls.sqlEditor(), | ||
| tooltip: 'Max can generate SQL queries using your PostHog data and the data warehouse.', |
There was a problem hiding this comment.
| tooltip: 'Max can generate SQL queries using your PostHog data and the data warehouse.', | |
| tooltip: 'Max can generate SQL queries for your PostHog data, both analytics and the data warehouse.', |
| label: 'How can I capture an exception?', | ||
| }, | ||
| ], | ||
| tooltip: 'Max can help you find the right documentation pieces.', |
There was a problem hiding this comment.
"pieces" is slightly odd
| tooltip: 'Max can help you find the right documentation pieces.', | |
| tooltip: 'Max has access to PostHog docs and can help you get the most out of PostHog.', |
| suggestionGroups: [ | ||
| () => [], // Kea selector typing hint | ||
| (): readonly SuggestionGroup[] => QUESTION_SUGGESTIONS_DATA, | ||
| ], |
There was a problem hiding this comment.
Hmm, doesn't look like we need this to be a selector
| (index, groups): SuggestionGroup | undefined => { | ||
| if (index === null) { | ||
| return undefined | ||
| } |
There was a problem hiding this comment.
Nit: I always find null to be a clearer indication of an intended lack of result than undefined.
| {activeSuggestionGroup && !isFloating && ( | ||
| <ToggleGroup | ||
| type="single" | ||
| className="absolute inset-x-2 top-full grid auto-rows-auto p-1 border-x border-b rounded-b backdrop-blur-sm bg-[var(--glass-bg-3000)] z-10" |
There was a problem hiding this comment.
For visual harmony, we need to round with -lg, because we're wrapping a collection of elements that are each rounded with the base radius – this looks slightly off:
| className="absolute inset-x-2 top-full grid auto-rows-auto p-1 border-x border-b rounded-b backdrop-blur-sm bg-[var(--glass-bg-3000)] z-10" | |
| className="absolute inset-x-2 top-full grid auto-rows-auto p-1 border-x border-b rounded-lg-b backdrop-blur-sm bg-[var(--glass-bg-3000)] z-10" |
| @keyframes QuestionSuggestion__slide-in-fade-down { | ||
| from { | ||
| opacity: 0; | ||
| transform: translateY(-0.5rem); | ||
| } | ||
|
|
||
| to { | ||
| opacity: 1; | ||
| transform: translateY(0); | ||
| } | ||
| } |
There was a problem hiding this comment.
I would propose a CSSTransition instead, as currently we only have an entry animation, but jarringly exit is just abrupt disappearance

Problem
One of the pieces of feedback we frequently get is that it is not clear what Max can and cannot do. Let's replace random suggestions with a hardcoded list of suggestions where Max excels.
Changes
Demo
Mobile
Did you write or update any docs for this change?
How did you test this code?
Manual testing & a new story