Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(funnels): funnel stepper #4345

Open
wants to merge 29 commits into
base: feat-web-funnel
Choose a base branch
from
Open

Conversation

ilasw
Copy link
Contributor

@ilasw ilasw commented Apr 4, 2025

Changes

  • Added Stepper - story
  • Moved background wrapper from steps to stepper
  • Added event tracking hook
  • Added navigation hook
  • Updated shared components adding tracking attributes

Events

Did you introduce any new tracking events?

Experiment

Did you introduce any new experiments?

Manual Testing

Caution

Please make sure existing components are not breaking/affected by this PR

Jira ticket

MI-851

Preview domain

https://mi-851-funnel-stepper.preview.app.daily.dev

Copy link

vercel bot commented Apr 4, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Updated (UTC)
daily-webapp ❌ Failed (Inspect) Apr 9, 2025 8:42am
1 Skipped Deployment
Name Status Preview Updated (UTC)
storybook ⬜️ Ignored (Inspect) Apr 9, 2025 8:42am

@ilasw ilasw changed the base branch from main to feat-web-funnel April 4, 2025 17:21
Comment on lines -16 to -22
<QueryClientProvider client={queryClient}>
<ProgressiveEnhancementContextProvider>
<AppSubscriptionContextProvider>
{children}
</AppSubscriptionContextProvider>
</ProgressiveEnhancementContextProvider>
</QueryClientProvider>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need the LogContext

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where? because it's already inside one of these no?
Afraid this might give some edge-case issue where context wrong order now.

Copy link
Contributor

@rebelchris rebelchris left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, lots of useEffects which worry me a bit, but hard to evaluate from a review.

@@ -72,8 +72,9 @@ const FormInputCheckbox = ({
aria-checked={isSelected}
aria-label={item.label}
className={classNames(isVertical ? 'typo-subhead' : 'typo-body')}
pressed={isSelected}
data-track-click
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this actually? not familiar with it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added a onClickCapture on stepper level, that send events on each element that has this data-track-click

Comment on lines +19 to +22
const handleScroll = () => {
setScrollPosition(window.scrollY);
onScroll?.();
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe if this is useCallback you don't need the exhaustive deps below?

const searchParams = useSearchParams();
const pathname = usePathname();
const [stepTimerStart, setStepTimerStart] = useState<number>(0);
const [position, setPosition] = useAtom(funnelPositionAtom);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess we need atoms to reshare between things here?
Don't we already have exposes context for funnels specifically?

cx="98"
cy="98"
r="90"
className="stroke-overlay-primary-pepper"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the right color it's solid non themed one?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't know, this comes from @AmarTrebinjac component, just removed the bg wrapper

Comment on lines -16 to -22
<QueryClientProvider client={queryClient}>
<ProgressiveEnhancementContextProvider>
<AppSubscriptionContextProvider>
{children}
</AppSubscriptionContextProvider>
</ProgressiveEnhancementContextProvider>
</QueryClientProvider>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where? because it's already inside one of these no?
Afraid this might give some edge-case issue where context wrong order now.

y: number;
}

export const useWindowScroll = (
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd do this hook differently. I'd create a ref for the callback and this callback would call the onScroll with the window.scrollY value. We don't really need state

const [position, setPosition] = useAtom(funnelPositionAtom);
const [history, dispatchHistory] = useAtom(funnelPositionHistoryAtom);

const chapters: Chapters = useMemo(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure that this is how we do the chapters on the backend. we'll need to check

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is how the Header component's props is shaped, just passing to it

globalThis?.removeEventListener?.('scroll', handleScroll);
};
},
// eslint-disable-next-line react-hooks/exhaustive-deps
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this needed?

type: FunnelStepTransitionType;
}) => void;

interface USeFunnelTrackingProps {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Double capitalization

return map;
}, [funnel]);

const step: NonChapterStep = useMemo(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is non chapter step?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Each step in funnel can be chapter or actual step. This is for every non chapter one

const from = step.id;
const timeDuration = Date.now() - stepTimerStart;

if (!stepMap[to]?.position) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it mean we finished the funnel?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or that the editor have put a non existing step as target 👀

@@ -0,0 +1,177 @@
import { useMemo, useState, useEffect, useCallback } from 'react';
Copy link
Member

@idoshamun idoshamun Apr 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need some more comments here to make it maintainable or breakdown to smaller pieces even within the same file

details: {
target_type:
trackedElement.tagName.toLowerCase() as keyof HTMLElementTagNameMap,
...(trackedElement.id ? { target_id: trackedElement.id } : {}),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we gonna preload all steps, we should consider maybe we need to send something else other than id. Because then we'll have duplicate ids

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we track if a step has been interacted with twice? Maybe just add a check for already completed steps?

});

const trackOnHoverCapture: TrackOnMouseCapture = trackOnMouseCapture({
selector: '[data-track-hover]',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think every element that should be tracked for hover will be tracked for click. should we track the same selector for both?

details: {
target_type: event.type,
target_id: event.to,
event_duration: event.timeDuration,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was supposed to be outside of extra, but i'll update the excel

Suggested change
event_duration: event.timeDuration,
duration: event.timeDuration,

// todo: implement resume funnel event

return () => {
trackFunnelEvent({ name: FunnelEventName.LeaveFunnel });
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be triggered only when the user didn't finish the funnel

@@ -32,12 +31,39 @@ const variantToClassName: Record<FunnelBackgroundVariant, string> = {
[FunnelBackgroundVariant.Hourglass]: 'bg-gradient-funnel-hourglass',
};

const getVariantFromStep = (step: NonChapterStep): FunnelBackgroundVariant => {
if (!step) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When are we not on a step ?

{funnel.steps.map((chapter: FunnelStepChapter) => (
<Fragment key={chapter?.id}>
{chapter?.steps?.map((funnelStep: NonChapterStep) => (
<div
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this div needed?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants