Skip to content

Commit 2c00acc

Browse files
sanne-sanaerosol
andauthored
Update goal settings design (#5886)
* Update goal settings design - Replace the `Add goal` button in goal settings with a dropdown button to directly select the goal type. This way, a modal opens with the correct form for the selected goal type. The tabs in the modal have been removed. - Add a new `pill` component to show the goal type in the table in a more distinct way. The `settings_badge` component is replaced with the `pill` component. The `pill` component that was used in `plan_box.ex` is renamed to `highlight_pill`. - Replaced `Belongs to funnel` text with a funnel icon in the goal settings list. - Some small tweaks like increasing the search bar width, the padding of the table cells, and adding a header to the goal settings list. * Update tests to use the new dropdown component instead of tabs * Replace custom `pending invitation` pill with new pill component * Temporary: bump prima to exercise prima dropdown LV re-render fix * Temporary: Bump prima again * Revert "Temporary: Bump prima again" This reverts commit 024b34a. * Revert "Temporary: bump prima to exercise prima dropdown LV re-render fix" This reverts commit a6eabb7. * Update prima * Replace `Add goal` button with dropdown button in goal settings empty state * Update test to check both empty and non-empty states of the add goal dropdown * Remove pb-14 from feature gate --------- Co-authored-by: Adam Rutkowski <hq@mtod.org>
1 parent f2bc96d commit 2c00acc

File tree

12 files changed

+326
-268
lines changed

12 files changed

+326
-268
lines changed

lib/plausible_web/components/billing/plan_box.ex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ defmodule PlausibleWeb.Components.Billing.PlanBox do
3939
]}>
4040
{String.capitalize(to_string(@kind))}
4141
</h3>
42-
<.pill :if={@highlight} text={@highlight} />
42+
<.highlight_pill :if={@highlight} text={@highlight} />
4343
</div>
4444
<div>
4545
<div class={@price_container_class}>
@@ -95,7 +95,7 @@ defmodule PlausibleWeb.Components.Billing.PlanBox do
9595
"""
9696
end
9797

98-
defp pill(assigns) do
98+
defp highlight_pill(assigns) do
9999
~H"""
100100
<div class="flex items-center justify-between gap-x-4">
101101
<p

lib/plausible_web/components/generic.ex

Lines changed: 44 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -522,7 +522,7 @@ defmodule PlausibleWeb.Components.Generic do
522522
current_team={@current_team}
523523
site={@site}
524524
>
525-
<div class="p-6 pb-14">
525+
<div class="p-6">
526526
{render_slot(@inner_block)}
527527
</div>
528528
</PlausibleWeb.Components.Billing.feature_gate>
@@ -793,7 +793,7 @@ defmodule PlausibleWeb.Components.Generic do
793793
<td
794794
class={[
795795
@height,
796-
"text-sm px-6 py-3 first:pl-0 last:pr-0 whitespace-nowrap",
796+
"text-sm px-6 py-4 first:pl-0 last:pr-0 whitespace-nowrap",
797797
@truncate && "truncate",
798798
@max_width,
799799
@actions && "flex text-right justify-end",
@@ -1027,18 +1027,23 @@ defmodule PlausibleWeb.Components.Generic do
10271027

10281028
def filter_bar(assigns) do
10291029
~H"""
1030-
<div class="flex items-center justify-between" x-data>
1031-
<div :if={@filtering_enabled?} class="relative rounded-md flex">
1032-
<form id="filter-form" phx-change="filter" phx-submit="filter" class="flex items-center">
1033-
<div class="text-gray-800 inline-flex items-center">
1030+
<div class="flex items-center justify-between gap-2" x-data>
1031+
<div :if={@filtering_enabled?} class="relative rounded-md flex flex-grow-1 w-full">
1032+
<form
1033+
id="filter-form"
1034+
phx-change="filter"
1035+
phx-submit="filter"
1036+
class="flex items-center w-full"
1037+
>
1038+
<div class="text-gray-800 inline-flex items-center w-full">
10341039
<div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
10351040
<Heroicons.magnifying_glass class="feather mr-1 dark:text-gray-300" />
10361041
</div>
10371042
<input
10381043
type="text"
10391044
name="filter-text"
10401045
id="filter-text"
1041-
class="w-full max-w-64 pl-8 text-sm dark:bg-gray-750 dark:text-gray-300 focus:ring-indigo-500 focus:border-indigo-500 block border-gray-300 dark:border-gray-750 rounded-md dark:placeholder:text-gray-400 focus:outline-none focus:ring-3 focus:ring-indigo-500/20 dark:focus:ring-indigo-500/25 focus:border-indigo-500"
1046+
class="w-full max-w-80 pl-8 text-sm dark:bg-gray-750 dark:text-gray-300 focus:ring-indigo-500 focus:border-indigo-500 block border-gray-300 dark:border-gray-750 rounded-md dark:placeholder:text-gray-400 focus:outline-none focus:ring-3 focus:ring-indigo-500/20 dark:focus:ring-indigo-500/25 focus:border-indigo-500"
10421047
placeholder="Press / to search"
10431048
x-ref="filter_text"
10441049
phx-debounce={200}
@@ -1140,13 +1145,41 @@ defmodule PlausibleWeb.Components.Generic do
11401145
"""
11411146
end
11421147

1143-
def settings_badge(%{type: :new} = assigns) do
1148+
attr(:class, :string, default: "")
1149+
attr(:color, :atom, default: :gray, values: [:gray, :indigo, :yellow, :green])
1150+
attr(:rest, :global)
1151+
slot(:inner_block, required: true)
1152+
1153+
def pill(assigns) do
1154+
assigns = assign(assigns, :color_classes, get_pill_color_classes(assigns.color))
1155+
11441156
~H"""
1145-
<span class="inline-block ml-2 bg-indigo-100 text-indigo-600 text-xs font-semibold py-1 px-2 rounded-md">
1146-
NEW 🔥
1157+
<span
1158+
class={[
1159+
"inline-flex items-center text-xs font-medium py-1 px-2 rounded-md",
1160+
@color_classes,
1161+
@class
1162+
]}
1163+
{@rest}
1164+
>
1165+
{render_slot(@inner_block)}
11471166
</span>
11481167
"""
11491168
end
11501169

1151-
def settings_badge(assigns), do: ~H""
1170+
defp get_pill_color_classes(:gray) do
1171+
"bg-gray-100 text-gray-800 dark:bg-gray-750 dark:text-gray-200"
1172+
end
1173+
1174+
defp get_pill_color_classes(:indigo) do
1175+
"bg-indigo-100/60 text-indigo-600 dark:bg-indigo-900/50 dark:text-indigo-300"
1176+
end
1177+
1178+
defp get_pill_color_classes(:yellow) do
1179+
"bg-yellow-100/80 text-yellow-800 dark:bg-yellow-900/40 dark:text-yellow-300"
1180+
end
1181+
1182+
defp get_pill_color_classes(:green) do
1183+
"bg-green-100/70 text-green-800 dark:bg-green-900/40 dark:text-green-300"
1184+
end
11521185
end

lib/plausible_web/components/layout.ex

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,9 @@ defmodule PlausibleWeb.Components.Layout do
140140
class="size-5 mr-2"
141141
/>
142142
{@text}
143-
<PlausibleWeb.Components.Generic.settings_badge type={@badge} />
143+
<PlausibleWeb.Components.Generic.pill :if={@badge == :new} color={:indigo} class="ml-2">
144+
NEW 🔥
145+
</PlausibleWeb.Components.Generic.pill>
144146
<Heroicons.chevron_down
145147
:if={is_nil(@value)}
146148
class="h-3 w-3 ml-2 text-gray-400 dark:text-gray-500"

lib/plausible_web/components/prima_dropdown.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ defmodule PlausibleWeb.Components.PrimaDropdown do
3333
<Dropdown.dropdown_item
3434
as={@as}
3535
disabled={@disabled}
36-
class="group/item z-50 flex items-center gap-x-2 min-w-max rounded-md px-4 py-2 text-gray-700 text-sm dark:text-gray-300 data-focus:bg-gray-100 dark:data-focus:bg-gray-700 data-focus:text-gray-900 dark:data-focus:text-gray-100"
36+
class="group/item z-50 flex items-center gap-x-2 min-w-max w-full rounded-md pl-3 pr-5 py-2 text-gray-700 text-sm dark:text-gray-300 data-focus:bg-gray-100 dark:data-focus:bg-gray-700 data-focus:text-gray-900 dark:data-focus:text-gray-100"
3737
{@rest}
3838
>
3939
{render_slot(@inner_block)}

lib/plausible_web/live/goal_settings.ex

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ defmodule PlausibleWeb.Live.GoalSettings do
4343
domain: domain,
4444
displayed_goals: socket.assigns.all_goals,
4545
filter_text: "",
46-
form_goal: nil
46+
form_goal: nil,
47+
goal_type: nil
4748
)}
4849
end
4950

@@ -88,6 +89,7 @@ defmodule PlausibleWeb.Live.GoalSettings do
8889
site_team={@site_team}
8990
existing_goals={@all_goals}
9091
goal={@form_goal}
92+
goal_type={@goal_type}
9193
on_save_goal={
9294
fn goal, socket ->
9395
send(self(), {:goal_added, goal})
@@ -137,8 +139,12 @@ defmodule PlausibleWeb.Live.GoalSettings do
137139
{:noreply, socket}
138140
end
139141

140-
def handle_event("add-goal", _, socket) do
141-
socket = socket |> assign(form_goal: nil) |> Modal.open("goals-form-modal")
142+
def handle_event("add-goal", %{"goal-type" => goal_type}, socket) do
143+
socket =
144+
socket
145+
|> assign(form_goal: nil, goal_type: goal_type)
146+
|> Modal.open("goals-form-modal")
147+
142148
{:noreply, socket}
143149
end
144150

@@ -181,7 +187,8 @@ defmodule PlausibleWeb.Live.GoalSettings do
181187
event_name_options:
182188
Enum.reject(socket.assigns.event_name_options, &(&1 == goal.event_name)),
183189
displayed_goals: all_goals,
184-
form_goal: nil
190+
form_goal: nil,
191+
goal_type: nil
185192
)
186193
|> put_live_flash(:success, "Goal saved successfully")
187194

lib/plausible_web/live/goal_settings/form.ex

Lines changed: 26 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,15 @@ defmodule PlausibleWeb.Live.GoalSettings.Form do
1919
|> Plausible.Goal.changeset()
2020
|> to_form()
2121

22-
selected_tab =
23-
case assigns.goal do
24-
%{page_path: p, scroll_threshold: s} when not is_nil(p) and s > -1 -> "scroll"
25-
%{page_path: p} when not is_nil(p) -> "pageviews"
26-
_goal_or_nil -> "custom_events"
22+
form_type =
23+
if assigns.goal do
24+
case assigns.goal do
25+
%{page_path: p, scroll_threshold: s} when not is_nil(p) and s > -1 -> "scroll"
26+
%{page_path: p} when not is_nil(p) -> "pageviews"
27+
_ -> "custom_events"
28+
end
29+
else
30+
assigns[:goal_type] || "custom_events"
2731
end
2832

2933
socket =
@@ -37,14 +41,14 @@ defmodule PlausibleWeb.Live.GoalSettings.Form do
3741
current_user: assigns.current_user,
3842
site_team: assigns.site_team,
3943
domain: assigns.domain,
40-
selected_tab: selected_tab,
41-
tab_sequence_id: 0,
44+
form_type: form_type,
4245
site: site,
4346
has_access_to_revenue_goals?: has_access_to_revenue_goals?,
4447
existing_goals: assigns.existing_goals,
4548
on_save_goal: assigns.on_save_goal,
4649
on_autoconfigure: assigns.on_autoconfigure,
47-
goal: assigns.goal
50+
goal: assigns.goal,
51+
goal_type: assigns[:goal_type]
4852
)
4953

5054
{:ok, socket}
@@ -68,7 +72,7 @@ defmodule PlausibleWeb.Live.GoalSettings.Form do
6872
<.title>Edit goal for {@domain}</.title>
6973
7074
<.custom_event_fields
71-
:if={@selected_tab == "custom_events"}
75+
:if={@form_type == "custom_events"}
7276
f={f}
7377
suffix={@context_unique_id}
7478
current_user={@current_user}
@@ -80,14 +84,14 @@ defmodule PlausibleWeb.Live.GoalSettings.Form do
8084
has_access_to_revenue_goals?={@has_access_to_revenue_goals?}
8185
/>
8286
<.pageview_fields
83-
:if={@selected_tab == "pageviews"}
87+
:if={@form_type == "pageviews"}
8488
f={f}
8589
goal={@goal}
8690
suffix={@context_unique_id}
8791
site={@site}
8892
/>
8993
<.scroll_fields
90-
:if={@selected_tab == "scroll"}
94+
:if={@form_type == "scroll"}
9195
f={f}
9296
goal={@goal}
9397
suffix={@context_unique_id}
@@ -103,58 +107,41 @@ defmodule PlausibleWeb.Live.GoalSettings.Form do
103107

104108
def create_form(assigns) do
105109
~H"""
106-
<.form
107-
:let={f}
108-
x-data="{ tabSelectionInProgress: false }"
109-
for={@form}
110-
phx-submit="save-goal"
111-
phx-target={@myself}
112-
>
110+
<.form :let={f} for={@form} phx-submit="save-goal" phx-target={@myself}>
113111
<.title>
114112
Add goal for {Plausible.Sites.display_name(@site)}
115113
</.title>
116114
117-
<.tabs current_user={@current_user} site={@site} selected_tab={@selected_tab} myself={@myself} />
118-
119115
<.custom_event_fields
120-
:if={@selected_tab == "custom_events"}
121-
x-show="!tabSelectionInProgress"
116+
:if={@form_type == "custom_events"}
122117
f={f}
123-
suffix={suffix(@context_unique_id, @tab_sequence_id)}
118+
suffix={@context_unique_id}
124119
current_user={@current_user}
125120
site_team={@site_team}
126121
site={@site}
127122
existing_goals={@existing_goals}
128123
goal_options={@event_name_options}
129124
has_access_to_revenue_goals?={@has_access_to_revenue_goals?}
130-
x-init="tabSelectionInProgress = false"
131125
/>
132126
<.pageview_fields
133-
:if={@selected_tab == "pageviews"}
134-
x-show="!tabSelectionInProgress"
127+
:if={@form_type == "pageviews"}
135128
f={f}
136-
suffix={suffix(@context_unique_id, @tab_sequence_id)}
129+
suffix={@context_unique_id}
137130
site={@site}
138-
x-init="tabSelectionInProgress = false"
139131
/>
140132
<.scroll_fields
141-
:if={@selected_tab == "scroll"}
142-
x-show="!tabSelectionInProgress"
133+
:if={@form_type == "scroll"}
143134
f={f}
144-
suffix={suffix(@context_unique_id, @tab_sequence_id)}
135+
suffix={@context_unique_id}
145136
site={@site}
146-
x-init="tabSelectionInProgress = false"
147137
/>
148138
149-
<div x-show="!tabSelectionInProgress">
150-
<.button type="submit" class="w-full">
151-
Add goal
152-
</.button>
153-
</div>
139+
<.button type="submit" class="w-full">
140+
Add goal
141+
</.button>
154142
155143
<button
156-
:if={@selected_tab == "custom_events" && @event_name_options_count > 0}
157-
x-show="!tabSelectionInProgress"
144+
:if={@form_type == "custom_events" && @event_name_options_count > 0}
158145
class="mt-4 text-sm hover:underline text-indigo-600 dark:text-indigo-400 text-left"
159146
phx-click="autoconfigure"
160147
phx-target={@myself}
@@ -441,73 +428,6 @@ defmodule PlausibleWeb.Live.GoalSettings.Form do
441428
"""
442429
end
443430

444-
def tabs(assigns) do
445-
~H"""
446-
<div class="text-sm mt-6 font-medium dark:text-gray-100">Goal trigger</div>
447-
<div class="my-2 p-1 text-sm w-full flex gap-1 overflow-hidden rounded-lg border border-gray-300 dark:border-gray-700">
448-
<.tab
449-
id="event-tab"
450-
tab_value="custom_events"
451-
selected?={@selected_tab == "custom_events"}
452-
myself={@myself}
453-
>
454-
Custom event
455-
</.tab>
456-
<.tab
457-
id="pageview-tab"
458-
tab_value="pageviews"
459-
selected?={@selected_tab == "pageviews"}
460-
myself={@myself}
461-
>
462-
Pageview
463-
</.tab>
464-
<.tab
465-
id="scroll-tab"
466-
tab_value="scroll"
467-
selected?={@selected_tab == "scroll"}
468-
myself={@myself}
469-
>
470-
Scroll depth
471-
</.tab>
472-
</div>
473-
"""
474-
end
475-
476-
attr(:id, :string, required: true)
477-
attr(:tab_value, :string, required: true)
478-
attr(:selected?, :boolean, required: true)
479-
attr(:myself, :any, required: true)
480-
slot(:inner_block, required: true)
481-
482-
defp tab(assigns) do
483-
~H"""
484-
<a
485-
class={[
486-
"flex-1 text-center py-2 px-3 rounded-md font-medium hover:bg-gray-100 dark:hover:bg-gray-750 transition-colors duration-150",
487-
"cursor-pointer",
488-
@selected? && "bg-gray-150 dark:bg-gray-700 text-gray-800 dark:text-white",
489-
!@selected? && "dark:text-gray-200 text-gray-600 hover:text-gray-800 dark:hover:text-white"
490-
]}
491-
id={@id}
492-
x-on:click={!@selected? && "tabSelectionInProgress = true"}
493-
phx-click="switch-tab"
494-
phx-value-tab={@tab_value}
495-
phx-target={@myself}
496-
>
497-
{render_slot(@inner_block)}
498-
</a>
499-
"""
500-
end
501-
502-
def handle_event("switch-tab", %{"tab" => tab}, socket) do
503-
socket =
504-
socket
505-
|> assign(:selected_tab, tab)
506-
|> update(:tab_sequence_id, &(&1 + 1))
507-
508-
{:noreply, socket}
509-
end
510-
511431
def handle_event("save-goal", %{"goal" => goal_params}, %{assigns: %{goal: nil}} = socket) do
512432
case Plausible.Goals.create(socket.assigns.site, goal_params) do
513433
{:ok, goal} ->
@@ -572,10 +492,6 @@ defmodule PlausibleWeb.Live.GoalSettings.Form do
572492
|> Enum.map(fn name -> {name, name} end)
573493
end
574494

575-
defp suffix(context_unique_id, tab_sequence_id) do
576-
"#{context_unique_id}-tabseq#{tab_sequence_id}"
577-
end
578-
579495
on_ee do
580496
defp currency_option(nil), do: nil
581497

0 commit comments

Comments
 (0)