Skip to content

Commit 3398dd5

Browse files
committed
Improve upgrade call to action styles and content
- Improve `Upgrade` CTA in list and turn it into a link - Improve `Upgrade` CTA tooltip copy to make it more clear what happens with locked goals on the dashboard - Add disabled (faded) styling to icon button and toggle switch - Move disabled styling to toggle only in goal form - Add `link_class` attribute to `upgrade_call_to_action` component in order to override link color when displayed inside tooltip - Add `Business` pill to goal form to make it more obvious that the feature is locked, and make it a link to the billing page - Improve prop styling inside tooltip in goal list to make it more readable and ensure truncation when prop is long
1 parent f86872f commit 3398dd5

File tree

4 files changed

+109
-85
lines changed

4 files changed

+109
-85
lines changed

lib/plausible_web/components/billing/billing.ex

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ defmodule PlausibleWeb.Components.Billing do
1111
attr :current_user, Plausible.Auth.User, required: true
1212
attr :current_team, :any, required: true
1313
attr :locked?, :boolean, required: true
14+
attr :link_class, :string, default: ""
1415
slot :inner_block, required: true
1516

1617
def feature_gate(assigns) do
@@ -36,7 +37,7 @@ defmodule PlausibleWeb.Components.Billing do
3637
class="max-w-sm sm:max-w-md mb-2 text-sm text-gray-600 dark:text-gray-100/60 leading-normal text-center"
3738
>
3839
To access this feature,
39-
<.upgrade_call_to_action current_user={@current_user} current_team={@current_team} />
40+
<.upgrade_call_to_action current_user={@current_user} current_team={@current_team} link_class={@link_class} />
4041
</span>
4142
</div>
4243
</div>
@@ -357,6 +358,8 @@ defmodule PlausibleWeb.Components.Billing do
357358

358359
defp change_plan_or_upgrade_text(_subscription), do: "Change plan"
359360

361+
attr :link_class, :string, default: ""
362+
360363
def upgrade_call_to_action(assigns) do
361364
user = assigns.current_user
362365
site = assigns[:site]
@@ -389,7 +392,7 @@ defmodule PlausibleWeb.Components.Billing do
389392
upgrade_assistance_required? ->
390393
~H"""
391394
contact
392-
<.styled_link href="mailto:hello@plausible.io" class="font-medium">
395+
<.styled_link href="mailto:hello@plausible.io" class={"font-medium " <> @link_class}>
393396
hello@plausible.io
394397
</.styled_link>
395398
to upgrade your subscription.
@@ -398,7 +401,7 @@ defmodule PlausibleWeb.Components.Billing do
398401
true ->
399402
~H"""
400403
<.styled_link
401-
class="inline-block font-medium"
404+
class={"inline-block font-medium " <> @link_class}
402405
href={Routes.billing_path(PlausibleWeb.Endpoint, :choose_plan)}
403406
>
404407
upgrade your subscription.

lib/plausible_web/components/generic.ex

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,8 @@ defmodule PlausibleWeb.Components.Generic do
488488
:if={@server_mode?}
489489
class={[
490490
"relative inline-flex h-6 w-11 shrink-0 rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-hidden focus:ring-2 focus:ring-indigo-600 focus:ring-offset-2",
491-
if(@checked, do: "bg-indigo-600", else: "dark:bg-gray-600 bg-gray-200")
491+
if(@checked, do: "bg-indigo-600", else: "dark:bg-gray-600 bg-gray-200"),
492+
if(@disabled, do: "opacity-50")
492493
]}
493494
>
494495
<span
@@ -501,7 +502,10 @@ defmodule PlausibleWeb.Components.Generic do
501502
</span>
502503
<span
503504
:if={!@server_mode?}
504-
class="relative inline-flex h-6 w-11 shrink-0 rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-hidden focus:ring-2 focus:ring-indigo-600 focus:ring-offset-2"
505+
class={[
506+
"relative inline-flex h-6 w-11 shrink-0 rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-hidden focus:ring-2 focus:ring-indigo-600 focus:ring-offset-2",
507+
if(@disabled, do: "opacity-50")
508+
]}
505509
x-bind:class={"#{@js_active_var} ? 'bg-indigo-600' : 'dark:bg-gray-600 bg-gray-200'"}
506510
>
507511
<span
@@ -646,7 +650,7 @@ defmodule PlausibleWeb.Components.Generic do
646650
"top-0",
647651
"-translate-y-full",
648652
"z-[1000]",
649-
"sm:max-w-72",
653+
"sm:max-w-64",
650654
"w-max"
651655
]
652656

@@ -684,7 +688,7 @@ defmodule PlausibleWeb.Components.Generic do
684688
x-transition:leave-start="opacity-100"
685689
x-transition:leave-end="opacity-0"
686690
>
687-
<div class="bg-gray-800 text-white rounded-sm px-2.5 py-1.5 text-xs font-medium">
691+
<div class="bg-gray-800 text-white rounded-sm px-2.5 py-1.5 text-xs font-medium whitespace-normal">
688692
{render_slot(@tooltip_content)}
689693
</div>
690694
</div>
@@ -1035,6 +1039,7 @@ defmodule PlausibleWeb.Components.Generic do
10351039
"dark:group-hover/button:" <> text.dark_hover,
10361040
"transition-colors",
10371041
"duration-150",
1042+
"group-disabled/button:opacity-50",
10381043
assigns.icon_class
10391044
]
10401045

@@ -1251,7 +1256,7 @@ defmodule PlausibleWeb.Components.Generic do
12511256
~H"""
12521257
<span
12531258
class={[
1254-
"inline-flex items-center text-xs font-medium py-1 px-2 rounded-md",
1259+
"inline-flex items-center text-xs font-medium py-[3px] px-[7px] rounded-md",
12551260
@color_classes,
12561261
@class
12571262
]}

lib/plausible_web/live/goal_settings/form.ex

Lines changed: 45 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -526,26 +526,30 @@ defmodule PlausibleWeb.Live.GoalSettings.Form do
526526

527527
def custom_property_section(assigns) do
528528
~H"""
529-
<.tooltip enabled?={not @has_access_to_props?}>
530-
<:tooltip_content>
531-
<div class="text-xs">
532-
To get access to this feature
529+
<div class="mt-6 mb-2 flex items-center justify-between">
530+
<div class="flex items-center gap-2">
531+
<span class="text-sm/6 font-medium text-gray-900 dark:text-gray-100">
532+
{if @use_custom_props, do: "Custom properties", else: "Add custom property"}
533+
</span>
534+
<.link
535+
:if={not @has_access_to_props? and not @use_custom_props}
536+
href={Routes.billing_path(PlausibleWeb.Endpoint, :choose_plan)}
537+
class="inline-block"
538+
>
539+
<.pill color={:indigo}>
540+
Business
541+
</.pill>
542+
</.link>
543+
</div>
544+
<.tooltip enabled?={not @has_access_to_props?} centered?={true}>
545+
<:tooltip_content>
546+
To get access to this feature,
533547
<PlausibleWeb.Components.Billing.upgrade_call_to_action
534548
current_user={@current_user}
535549
current_team={@site_team}
550+
link_class="!inline !text-indigo-400 hover:!text-indigo-300"
536551
/>
537-
</div>
538-
</:tooltip_content>
539-
<div class="mt-6 mb-2 flex items-center justify-between">
540-
<span class={[
541-
"text-sm/6 font-medium",
542-
if(@has_access_to_props?,
543-
do: "text-gray-900 dark:text-gray-100",
544-
else: "text-gray-500 dark:text-gray-400"
545-
)
546-
]}>
547-
{if @use_custom_props, do: "Custom properties", else: "Add custom property"}
548-
</span>
552+
</:tooltip_content>
549553
<.toggle_switch
550554
id="add-custom-property"
551555
id_suffix={@suffix}
@@ -554,8 +558,8 @@ defmodule PlausibleWeb.Live.GoalSettings.Form do
554558
phx-target={@myself}
555559
disabled={not @has_access_to_props?}
556560
/>
557-
</div>
558-
</.tooltip>
561+
</.tooltip>
562+
</div>
559563
560564
<.error :for={msg <- Enum.map(@f[:custom_props].errors, &translate_error/1)}>
561565
{msg}
@@ -709,34 +713,39 @@ defmodule PlausibleWeb.Live.GoalSettings.Form do
709713

710714
defp revenue_toggle(assigns) do
711715
~H"""
712-
<.tooltip enabled?={not @has_access_to_revenue_goals?}>
713-
<:tooltip_content>
714-
<div class="text-xs">
715-
To get access to this feature
716+
717+
<div class="flex items-center justify-between">
718+
<div class="flex items-center gap-2">
719+
<span class="text-sm/6 font-medium text-gray-900 dark:text-gray-100">
720+
Enable revenue tracking
721+
</span>
722+
<.link
723+
:if={not @has_access_to_revenue_goals?}
724+
href={Routes.billing_path(PlausibleWeb.Endpoint, :choose_plan)}
725+
class="inline-block"
726+
>
727+
<.pill color={:indigo}>
728+
Business
729+
</.pill>
730+
</.link>
731+
</div>
732+
<.tooltip enabled?={not @has_access_to_revenue_goals?} centered?={true}>
733+
<:tooltip_content>
734+
To get access to this feature,
716735
<PlausibleWeb.Components.Billing.upgrade_call_to_action
717736
current_user={@current_user}
718737
current_team={@site_team}
738+
link_class="!inline !text-indigo-400 hover:!text-indigo-300"
719739
/>
720-
</div>
721-
</:tooltip_content>
722-
<div class="flex items-center justify-between">
723-
<span class={[
724-
"text-sm/6 font-medium",
725-
if(@has_access_to_revenue_goals?,
726-
do: "text-gray-900 dark:text-gray-100",
727-
else: "text-gray-500 dark:text-gray-400"
728-
)
729-
]}>
730-
Enable revenue tracking
731-
</span>
740+
</:tooltip_content>
732741
<PlausibleWeb.Components.Generic.toggle_switch
733742
id="enable-revenue-tracking"
734743
id_suffix={@suffix}
735744
js_active_var="active"
736745
disabled={not @has_access_to_revenue_goals?}
737746
/>
738-
</div>
739-
</.tooltip>
747+
</.tooltip>
748+
</div>
740749
"""
741750
end
742751

lib/plausible_web/live/goal_settings/list.ex

Lines changed: 48 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -73,57 +73,26 @@ defmodule PlausibleWeb.Live.GoalSettings.List do
7373
<% has_unavailable_revenue? = not @revenue_goals_enabled? and not is_nil(goal.currency) %>
7474
<% has_unavailable_props? =
7575
not @props_available? and Plausible.Goal.has_custom_props?(goal) %>
76+
<.goal_name_with_icons goal={goal} />
7677
<%= if has_unavailable_revenue? or has_unavailable_props? do %>
77-
<div class="truncate">{goal}</div>
78-
<.tooltip>
78+
<.tooltip centered?={true}>
7979
<:tooltip_content>
8080
<p class="text-xs">
8181
<%= if has_unavailable_revenue? do %>
82-
Revenue Goals act like regular custom<br />
83-
events without a Business subscription<br />
82+
Revenue goals appear as regular goals on the dashboard. Upgrade to Business to see revenue data.
8483
<% else %>
85-
Custom Properties on Goals require<br /> a Business subscription<br />
84+
Upgrade to Business to show goals with custom properties on the dashboard.
8685
<% end %>
8786
</p>
8887
</:tooltip_content>
89-
<span class="w-max flex items-center text-gray-500 italic text-sm">
90-
<Heroicons.lock_closed solid class="size-4 mr-1" /> Upgrade Required
91-
</span>
88+
<.styled_link
89+
class="w-max flex items-center text-sm"
90+
href={Routes.billing_path(PlausibleWeb.Endpoint, :choose_plan)}
91+
>
92+
<Heroicons.lock_closed class="size-3.5 mr-1 stroke-2" /> Upgrade
93+
</.styled_link>
9294
</.tooltip>
9395
<% else %>
94-
<div class="font-medium text-sm flex items-center gap-1.5">
95-
<span class="truncate">{goal}</span>
96-
<.tooltip :if={not Enum.empty?(goal.funnels)} centered?={true}>
97-
<:tooltip_content>
98-
Belongs to funnel
99-
</:tooltip_content>
100-
<Heroicons.funnel class="size-3.5 mt-px stroke-2 flex-shrink-0" />
101-
</.tooltip>
102-
<.tooltip :if={Plausible.Goal.has_custom_props?(goal)} centered?={true}>
103-
<:tooltip_content>
104-
<div class="text-xs">
105-
<div :for={{key, value} <- goal.custom_props}>
106-
{key} is {value}
107-
</div>
108-
</div>
109-
</:tooltip_content>
110-
<svg
111-
xmlns="http://www.w3.org/2000/svg"
112-
viewBox="0 0 20 20"
113-
class="size-3.5 mt-px flex-shrink-0"
114-
>
115-
<circle fill="currentColor" cx="7.25" cy="7.25" r="1.25" />
116-
<path
117-
fill="none"
118-
stroke="currentColor"
119-
stroke-linecap="round"
120-
stroke-linejoin="round"
121-
stroke-width="2"
122-
d="M4 3h5.172a2 2 0 0 1 1.414.586l5.536 5.536a3 3 0 0 1 0 4.243l-2.757 2.757a3 3 0 0 1-4.243 0l-5.536-5.536A2 2 0 0 1 3 9.172V4a1 1 0 0 1 1-1Z"
123-
/>
124-
</svg>
125-
</.tooltip>
126-
</div>
12796
<div class="truncate">
12897
<.goal_description goal={goal} />
12998
</div>
@@ -294,6 +263,44 @@ defmodule PlausibleWeb.Live.GoalSettings.List do
294263
end
295264
end
296265

266+
defp goal_name_with_icons(assigns) do
267+
~H"""
268+
<div class="font-medium text-sm flex items-center gap-1.5">
269+
<span class="truncate">{@goal}</span>
270+
<.tooltip :if={not Enum.empty?(@goal.funnels)} centered?={true}>
271+
<:tooltip_content>
272+
Belongs to funnel
273+
</:tooltip_content>
274+
<Heroicons.funnel class="size-3.5 mt-px stroke-2 flex-shrink-0" />
275+
</.tooltip>
276+
<.tooltip :if={Plausible.Goal.has_custom_props?(@goal)} centered?={true}>
277+
<:tooltip_content>
278+
<div class="-mx-1 flex flex-col gap-1 text-xs">
279+
<div class="truncate" :for={{key, value} <- @goal.custom_props}>
280+
<span class="bg-white/20 px-1 py-0.5 rounded-sm">{key}</span> is <span class="bg-white/20 px-1 py-0.5 rounded-sm">{value}</span>
281+
</div>
282+
</div>
283+
</:tooltip_content>
284+
<svg
285+
xmlns="http://www.w3.org/2000/svg"
286+
viewBox="0 0 20 20"
287+
class="size-3.5 mt-px flex-shrink-0"
288+
>
289+
<circle fill="currentColor" cx="7.25" cy="7.25" r="1.25" />
290+
<path
291+
fill="none"
292+
stroke="currentColor"
293+
stroke-linecap="round"
294+
stroke-linejoin="round"
295+
stroke-width="2"
296+
d="M4 3h5.172a2 2 0 0 1 1.414.586l5.536 5.536a3 3 0 0 1 0 4.243l-2.757 2.757a3 3 0 0 1-4.243 0l-5.536-5.536A2 2 0 0 1 3 9.172V4a1 1 0 0 1 1-1Z"
297+
/>
298+
</svg>
299+
</.tooltip>
300+
</div>
301+
"""
302+
end
303+
297304
defp goal_editable?(goal, revenue_goals_enabled?, props_available?) do
298305
revenue_ok? = not is_nil(goal.currency) or revenue_goals_enabled?
299306
props_ok? = not Plausible.Goal.has_custom_props?(goal) or props_available?

0 commit comments

Comments
 (0)