Skip to content

Commit

Permalink
feat(funnels): Show conversion rates in funnel step legends (#11933)
Browse files Browse the repository at this point in the history
* feat(funnels): Show conversion rates in funnel step legends

* Make `StepLegend` height dynamic
  • Loading branch information
Twixes authored Sep 23, 2022
1 parent c629bc9 commit efe92f7
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 24 deletions.
3 changes: 3 additions & 0 deletions frontend/src/scenes/funnels/FunnelBarChart.scss
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
}
}
> td {
// Sneaky hack to make height: 100% work in .StepLegend. The wonders of CSS - there's NO other way!
height: 1px;
padding: 0.75rem 0;
}
}
Expand Down Expand Up @@ -147,6 +149,7 @@
.StepLegend {
border-left: 1px solid var(--border);
white-space: nowrap;
height: 100%;
> .LemonRow {
min-height: 1.5rem;
padding: 0 0.5rem;
Expand Down
71 changes: 47 additions & 24 deletions frontend/src/scenes/funnels/FunnelBarChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { Lettermark, LettermarkColor } from 'lib/components/Lettermark/Lettermar
import { EntityFilterInfo } from 'lib/components/EntityFilterInfo'
import { getActionFilterFromFunnelStep } from 'scenes/insights/views/Funnels/funnelStepTableUtils'
import { IconSchedule, IconTrendingFlat, IconTrendingFlatDown } from 'lib/components/icons'
import { humanFriendlyDuration, percentage, pluralize } from 'lib/utils'
import { capitalizeFirstLetter, humanFriendlyDuration, percentage, pluralize } from 'lib/utils'
import { ValueInspectorButton } from './ValueInspectorButton'
import clsx from 'clsx'
import { useScrollable } from 'lib/hooks/useScrollable'
Expand Down Expand Up @@ -49,6 +49,7 @@ function StepBar({ step, stepIndex, series }: StepBarProps): JSX.Element {
return (
<div
className="StepBar"
/* eslint-disable-next-line react/forbid-dom-props */
style={
{
'--series-color': getSeriesColor(series.order ?? 0),
Expand Down Expand Up @@ -118,6 +119,23 @@ function StepLegend({ step, stepIndex, showTime, showPersonsModal }: StepLegendP
aggregationTargetLabel.plural
)

const convertedCountPresentationWithPercentage = (
<>
{convertedCountPresentation}{' '}
<span title="Rate of conversion from initial step" className="text-muted">
({percentage(step.conversionRates.fromBasisStep, 2)})
</span>
</>
)
const droppedOffCountPresentationWithPercentage = (
<>
{droppedOffCountPresentation}{' '}
<span title="Rate of drop-off from previous step" className="text-muted">
({percentage(1 - step.conversionRates.fromPrevious, 2)})
</span>
</>
)

return (
<div className="StepLegend">
<LemonRow
Expand All @@ -132,40 +150,44 @@ function StepLegend({ step, stepIndex, showTime, showPersonsModal }: StepLegendP
icon={<IconTrendingFlat />}
status="success"
style={{ color: 'unset' }} // Prevent status color from affecting text
title="Users who converted in this step"
title={`${capitalizeFirstLetter(aggregationTargetLabel.plural)} who completed this step`}
>
{showPersonsModal ? (
<ValueInspectorButton
onClick={() => openPersonsModalForStep({ step, stepIndex, converted: true })}
style={{ padding: 0 }}
>
{convertedCountPresentation}
{convertedCountPresentationWithPercentage}
</ValueInspectorButton>
) : (
convertedCountPresentation
convertedCountPresentationWithPercentage
)}
</LemonRow>
<LemonRow
icon={<IconTrendingFlatDown />}
status="danger"
style={{ color: 'unset' }} // Prevent status color from affecting text
title="Users who dropped of at this step"
>
{showPersonsModal && stepIndex ? (
<ValueInspectorButton
onClick={() => openPersonsModalForStep({ step, stepIndex, converted: false })}
style={{ padding: 0 }}
{stepIndex > 0 && (
<>
<LemonRow
icon={<IconTrendingFlatDown />}
status="danger"
style={{ color: 'unset' }} // Prevent status color from affecting text
title={`${capitalizeFirstLetter(aggregationTargetLabel.plural)} who didn't complete this step`}
>
{droppedOffCountPresentation}
</ValueInspectorButton>
) : (
droppedOffCountPresentation
)}
</LemonRow>
{showTime && (
<LemonRow icon={<IconSchedule />} title="Median time of conversion from previous step">
{humanFriendlyDuration(step.median_conversion_time, 3) || '–'}
</LemonRow>
{showPersonsModal && stepIndex ? (
<ValueInspectorButton
onClick={() => openPersonsModalForStep({ step, stepIndex, converted: false })}
style={{ padding: 0 }}
>
{droppedOffCountPresentationWithPercentage}
</ValueInspectorButton>
) : (
droppedOffCountPresentationWithPercentage
)}
</LemonRow>
{showTime && (
<LemonRow icon={<IconSchedule />} title="Median time of conversion from previous step">
{humanFriendlyDuration(step.median_conversion_time, 3) || '–'}
</LemonRow>
)}
</>
)}
</div>
)
Expand Down Expand Up @@ -217,6 +239,7 @@ export function FunnelBarChart({ showPersonsModal = true }: ChartParams): JSX.El

return (
<table
/* eslint-disable-next-line react/forbid-dom-props */
style={
{
'--bar-width': `${barWidthPx}px`,
Expand Down

0 comments on commit efe92f7

Please sign in to comment.