Make various UI improvements (#5890)

- Fix invite modal z-index issues
- Improve invite modal design
- Add hover state to stats bars on dashboard
- Improve feature gate design
- Improve trial upgrade CTA design
This commit is contained in:
Sanne de Vries 2025-11-18 14:28:09 +01:00 committed by GitHub
parent a2ba1256d2
commit dec382ccd5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 99 additions and 91 deletions

View File

@ -26,7 +26,7 @@ export default function Bar({
return ( return (
<div className="w-full h-full relative" style={style}> <div className="w-full h-full relative" style={style}>
<div <div
className={`absolute top-0 left-0 h-full ${bg || ''}`} className={`absolute top-0 left-0 h-full rounded-sm transition-colors duration-150 ${bg || ''}`}
style={{ width: `${width}%` }} style={{ width: `${width}%` }}
></div> ></div>
{children} {children}

View File

@ -54,7 +54,7 @@ export default function Conversions({ afterFetchData, onGoalFilterClick }) {
path: conversionsRoute.path, path: conversionsRoute.path,
search: (search) => search search: (search) => search
}} }}
color="bg-red-50" color="bg-red-50 group-hover:bg-red-100"
colMinWidth={90} colMinWidth={90}
/> />
) )

View File

@ -138,7 +138,7 @@ export default function Properties({ afterFetchData }) {
search: (search) => search search: (search) => search
}} }}
maybeHideDetails={true} maybeHideDetails={true}
color="bg-red-50" color="bg-red-50 group-hover:bg-red-100"
colMinWidth={90} colMinWidth={90}
/> />
) )

View File

@ -53,7 +53,7 @@ function EntryPages({ afterFetchData }) {
search: (search) => search search: (search) => search
}} }}
getExternalLinkUrl={getExternalLinkUrl} getExternalLinkUrl={getExternalLinkUrl}
color="bg-orange-50" color="bg-orange-50 group-hover:bg-orange-100"
/> />
) )
} }
@ -99,7 +99,7 @@ function ExitPages({ afterFetchData }) {
search: (search) => search search: (search) => search
}} }}
getExternalLinkUrl={getExternalLinkUrl} getExternalLinkUrl={getExternalLinkUrl}
color="bg-orange-50" color="bg-orange-50 group-hover:bg-orange-100"
/> />
) )
} }
@ -141,7 +141,7 @@ function TopPages({ afterFetchData }) {
search: (search) => search search: (search) => search
}} }}
getExternalLinkUrl={getExternalLinkUrl} getExternalLinkUrl={getExternalLinkUrl}
color="bg-orange-50" color="bg-orange-50 group-hover:bg-orange-100"
/> />
) )
} }

View File

@ -247,7 +247,7 @@ export default function ListReport<
return ( return (
<div key={listItem.name} style={{ minHeight: ROW_HEIGHT }}> <div key={listItem.name} style={{ minHeight: ROW_HEIGHT }}>
<div <div
className="flex w-full items-center" className="group flex w-full items-center hover:bg-gray-100/60 dark:hover:bg-gray-850 rounded-sm transition-colors duration-150"
style={{ marginTop: ROW_GAP_HEIGHT }} style={{ marginTop: ROW_GAP_HEIGHT }}
> >
{renderBarFor(listItem)} {renderBarFor(listItem)}
@ -258,7 +258,7 @@ export default function ListReport<
} }
function renderBarFor(listItem: TListItem) { function renderBarFor(listItem: TListItem) {
const lightBackground = color || 'bg-green-50' const lightBackground = color || 'bg-green-50 group-hover:bg-green-100'
const metricToPlot = metrics.find((metric) => metric.meta.plot)?.key const metricToPlot = metrics.find((metric) => metric.meta.plot)?.key
return ( return (
@ -267,7 +267,7 @@ export default function ListReport<
maxWidthDeduction={undefined} maxWidthDeduction={undefined}
count={listItem[metricToPlot]} count={listItem[metricToPlot]}
all={state.list} all={state.list}
bg={`${lightBackground} dark:bg-gray-500/15`} bg={`${lightBackground} dark:bg-gray-500/15 dark:group-hover:bg-gray-500/30`}
plot={metricToPlot} plot={metricToPlot}
> >
<div className="flex justify-start px-2 py-1.5 group text-sm dark:text-gray-300 relative z-9 break-all w-full"> <div className="flex justify-start px-2 py-1.5 group text-sm dark:text-gray-300 relative z-9 break-all w-full">

View File

@ -83,7 +83,7 @@ function AllSources({ afterFetchData }) {
metrics={chooseMetrics()} metrics={chooseMetrics()}
detailsLinkProps={{ path: sourcesRoute.path, search: (search) => search }} detailsLinkProps={{ path: sourcesRoute.path, search: (search) => search }}
renderIcon={renderIcon} renderIcon={renderIcon}
color="bg-blue-50" color="bg-blue-50 group-hover:bg-blue-100"
/> />
) )
} }
@ -122,7 +122,7 @@ function Channels({ onClick, afterFetchData }) {
path: channelsRoute.path, path: channelsRoute.path,
search: (search) => search search: (search) => search
}} }}
color="bg-blue-50" color="bg-blue-50 group-hover:bg-blue-100"
/> />
) )
} }
@ -166,7 +166,7 @@ function UTMSources({ tab, afterFetchData }) {
keyLabel={utmTag.label} keyLabel={utmTag.label}
metrics={chooseMetrics()} metrics={chooseMetrics()}
detailsLinkProps={{ path: route?.path, search: (search) => search }} detailsLinkProps={{ path: route?.path, search: (search) => search }}
color="bg-blue-50" color="bg-blue-50 group-hover:bg-blue-100"
/> />
) )
} }

View File

@ -20,15 +20,24 @@ defmodule PlausibleWeb.Components.Billing do
<div <div
:if={@locked?} :if={@locked?}
id="feature-gate-overlay" id="feature-gate-overlay"
class="absolute backdrop-blur-[6px] bg-white/50 dark:bg-gray-800/50 inset-0 flex justify-center items-center rounded-md" class="absolute backdrop-blur-[8px] bg-white/70 dark:bg-gray-800/50 inset-0 flex justify-center items-center"
> >
<div class="px-6 flex flex-col items-center text-gray-500 dark:text-gray-400"> <div class="px-6 flex flex-col items-center gap-y-3">
<Heroicons.lock_closed solid class="size-8 mb-2" /> <div class="flex-shrink-0 bg-white dark:bg-gray-700 max-w-max rounded-md p-2 border border-gray-200 dark:border-gray-600 text-indigo-500">
<Heroicons.lock_closed solid class="size-6 -mt-px pb-px" />
<span id="lock-notice" class="text-center max-w-sm sm:max-w-md"> </div>
To gain access to this feature, <div class="flex flex-col gap-y-1.5 items-center">
<.upgrade_call_to_action current_role={@current_role} current_team={@current_team} />. <h3 class="font-medium text-gray-900 dark:text-gray-100">
</span> Upgrade to unlock
</h3>
<span
id="lock-notice"
class="max-w-sm sm:max-w-md mb-2 text-sm text-gray-600 dark:text-gray-100/60 leading-normal text-center"
>
To access this feature,
<.upgrade_call_to_action current_role={@current_role} current_team={@current_team} />
</span>
</div>
</div> </div>
</div> </div>
""" """
@ -359,23 +368,25 @@ defmodule PlausibleWeb.Components.Billing do
cond do cond do
not is_nil(assigns.current_role) and assigns.current_role not in [:owner, :billing] -> not is_nil(assigns.current_role) and assigns.current_role not in [:owner, :billing] ->
~H"please reach out to the team owner to upgrade their subscription" ~H"ask your team owner to upgrade their subscription."
upgrade_assistance_required? -> upgrade_assistance_required? ->
~H""" ~H"""
please contact <a href="mailto:hello@plausible.io" class="underline">hello@plausible.io</a> contact
to upgrade your subscription <.styled_link href="mailto:hello@plausible.io" class="font-medium">
hello@plausible.io
</.styled_link>
to upgrade your subscription.
""" """
true -> true ->
~H""" ~H"""
please <.styled_link
<.link class="inline-block font-medium"
class="underline inline-block"
href={Routes.billing_path(PlausibleWeb.Endpoint, :choose_plan)} href={Routes.billing_path(PlausibleWeb.Endpoint, :choose_plan)}
> >
upgrade your subscription upgrade your subscription.
</.link> </.styled_link>
""" """
end end
end end

View File

@ -30,6 +30,8 @@ defmodule PlausibleWeb.Components.Generic do
"bg-indigo-600 text-white hover:bg-indigo-700 focus-visible:outline-indigo-600 disabled:bg-indigo-400/60 disabled:dark:bg-indigo-600/30 disabled:dark:text-white/35", "bg-indigo-600 text-white hover:bg-indigo-700 focus-visible:outline-indigo-600 disabled:bg-indigo-400/60 disabled:dark:bg-indigo-600/30 disabled:dark:text-white/35",
"secondary" => "secondary" =>
"border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-700 text-gray-800 dark:text-gray-100 hover:text-gray-900 hover:shadow-sm dark:hover:bg-gray-600 dark:hover:text-white disabled:text-gray-700/40 disabled:hover:shadow-none dark:disabled:text-gray-500 dark:disabled:bg-gray-800 dark:disabled:border-gray-800", "border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-700 text-gray-800 dark:text-gray-100 hover:text-gray-900 hover:shadow-sm dark:hover:bg-gray-600 dark:hover:text-white disabled:text-gray-700/40 disabled:hover:shadow-none dark:disabled:text-gray-500 dark:disabled:bg-gray-800 dark:disabled:border-gray-800",
"yellow" =>
"bg-yellow-600/90 text-white hover:bg-yellow-600 focus-visible:outline-yellow-600 disabled:bg-yellow-400/60 disabled:dark:bg-yellow-600/30 disabled:dark:text-white/35",
"danger" => "danger" =>
"border border-gray-300 dark:border-gray-800 text-red-600 bg-white dark:bg-gray-800 hover:text-red-700 hover:shadow-sm dark:hover:text-red-400 dark:text-red-500 active:text-red-800 disabled:text-red-700/40 disabled:hover:shadow-none dark:disabled:text-red-500/35 dark:disabled:bg-gray-800" "border border-gray-300 dark:border-gray-800 text-red-600 bg-white dark:bg-gray-800 hover:text-red-700 hover:shadow-sm dark:hover:text-red-400 dark:text-red-500 active:text-red-800 disabled:text-red-700/40 disabled:hover:shadow-none dark:disabled:text-red-500/35 dark:disabled:bg-gray-800"
} }
@ -95,7 +97,7 @@ defmodule PlausibleWeb.Components.Generic do
theme_class = theme_class =
if assigns.disabled do if assigns.disabled do
"bg-gray-400 text-white transition-colors duration-150 dark:text-white dark:text-gray-400 dark:bg-gray-700 cursor-not-allowed" "bg-gray-400 text-white transition-all duration-150 dark:text-white dark:text-gray-400 dark:bg-gray-700 cursor-not-allowed"
else else
@button_themes[assigns.theme] @button_themes[assigns.theme]
end end
@ -515,7 +517,7 @@ defmodule PlausibleWeb.Components.Generic do
current_role={@current_role} current_role={@current_role}
current_team={@current_team} current_team={@current_team}
> >
<div class="p-6"> <div class="p-6 pb-14">
{render_slot(@inner_block)} {render_slot(@inner_block)}
</div> </div>
</PlausibleWeb.Components.Billing.feature_gate> </PlausibleWeb.Components.Billing.feature_gate>

View File

@ -12,11 +12,11 @@ defmodule PlausibleWeb.Live.Components.PrimaModal do
<Modal.modal_overlay <Modal.modal_overlay
transition_enter={{"ease-out duration-300", "opacity-0", "opacity-100"}} transition_enter={{"ease-out duration-300", "opacity-0", "opacity-100"}}
transition_leave={{"ease-in duration-200", "opacity-100", "opacity-0"}} transition_leave={{"ease-in duration-200", "opacity-100", "opacity-0"}}
class="fixed inset-0 bg-gray-500/75 dark:bg-gray-800/75" class="fixed inset-0 z-[9999] bg-gray-500/75 dark:bg-gray-800/75"
/> />
<div class="fixed inset-0 w-screen overflow-y-auto"> <div class="fixed inset-0 z-[9999] w-screen overflow-y-auto sm:pt-[10vmin]">
<div class="flex min-h-full items-end justify-center p-4 sm:items-center sm:p-0"> <div class="flex min-h-full items-end justify-center p-4 sm:items-start sm:p-0">
<Modal.modal_panel <Modal.modal_panel
id={@id <> "-panel"} id={@id <> "-panel"}
class="relative overflow-hidden rounded-lg bg-white dark:bg-gray-900 text-left shadow-xl sm:w-full sm:max-w-lg" class="relative overflow-hidden rounded-lg bg-white dark:bg-gray-900 text-left shadow-xl sm:w-full sm:max-w-lg"
@ -41,7 +41,7 @@ defmodule PlausibleWeb.Live.Components.PrimaModal do
def modal_title(assigns) do def modal_title(assigns) do
~H""" ~H"""
<Modal.modal_title as={&h2/1}> <Modal.modal_title as={&h2/1} class="text-lg font-semibold text-gray-900 dark:text-gray-100">
{render_slot(@inner_block)} {render_slot(@inner_block)}
</Modal.modal_title> </Modal.modal_title>
""" """

View File

@ -656,38 +656,31 @@ defmodule PlausibleWeb.Live.Sites do
def invitation_modal(assigns) do def invitation_modal(assigns) do
~H""" ~H"""
<PlausibleWeb.Live.Components.PrimaModal.modal id={@id}> <PlausibleWeb.Live.Components.PrimaModal.modal id={@id}>
<div class="bg-white dark:bg-gray-850 px-4 pt-5 pb-4 sm:p-6 sm:pb-4"> <div class="p-5 pb-3 sm:p-6 sm:pb-3">
<div class="hidden sm:block absolute top-0 right-0 pt-4 pr-4"> <div class="hidden sm:block absolute top-0 right-0 pt-4 pr-4">
<button <button
phx-click={Prima.Modal.close()} phx-click={Prima.Modal.close()}
class="bg-white dark:bg-gray-800 rounded-md text-gray-400 dark:text-gray-500 hover:text-gray-500 dark:hover:text-gray-400 focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-indigo-500" class="text-gray-400 dark:text-gray-500 hover:text-gray-500 dark:hover:text-gray-400"
> >
<span class="sr-only">Close</span> <span class="sr-only">Close</span>
<Heroicons.x_mark class="size-6" /> <Heroicons.x_mark class="size-6" />
</button> </button>
</div> </div>
<div class="sm:flex sm:items-start"> <div class="flex flex-col gap-y-4 text-center sm:text-left">
<div class="mx-auto shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-green-100 sm:mx-0 sm:h-10 sm:w-10"> <PlausibleWeb.Live.Components.PrimaModal.modal_title>
<Heroicons.user_group class="size-6" /> You're invited to {@site.domain}
</div> </PlausibleWeb.Live.Components.PrimaModal.modal_title>
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left"> <div>
<PlausibleWeb.Live.Components.PrimaModal.modal_title> <p class="text-sm text-gray-600 dark:text-gray-400 text-pretty">
Invitation for {@site.domain} You've been added as <b class="capitalize">{@invitation.invitation.role}</b>
</PlausibleWeb.Live.Components.PrimaModal.modal_title> to the {@site.domain} analytics dashboard.
<div class="mt-2"> <%= if !(Map.get(@invitation, :exceeded_limits) || Map.get(@invitation, :no_plan)) &&
<p class="text-sm text-gray-500 dark:text-gray-200"> @invitation.invitation.role == :owner do %>
You've been invited to the {@site.domain} analytics dashboard as <b class="capitalize">{@invitation.invitation.role}</b>.
</p>
<div
:if={
!(Map.get(@invitation, :exceeded_limits) || Map.get(@invitation, :no_plan)) &&
@invitation.invitation.role == :owner
}
class="mt-2 text-sm text-gray-500 dark:text-gray-200"
>
If you accept the ownership transfer, you will be responsible for billing going forward. If you accept the ownership transfer, you will be responsible for billing going forward.
</div> <% else %>
</div> Welcome aboard!
<% end %>
</p>
</div> </div>
</div> </div>
<.notice <.notice
@ -730,30 +723,30 @@ defmodule PlausibleWeb.Live.Sites do
You are unable to accept the ownership of this site because your account does not have a subscription. To become the owner of this site, you should upgrade to a suitable plan. You are unable to accept the ownership of this site because your account does not have a subscription. To become the owner of this site, you should upgrade to a suitable plan.
</.notice> </.notice>
</div> </div>
<div class="bg-gray-50 dark:bg-gray-850 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse"> <div class="flex flex-col sm:flex-row-reverse gap-3 p-5 sm:p-6">
<.button <.button
:if={!(Map.get(@invitation, :exceeded_limits) || Map.get(@invitation, :no_plan))} :if={!(Map.get(@invitation, :exceeded_limits) || Map.get(@invitation, :no_plan))}
mt?={false} mt?={false}
class="sm:ml-3 w-full sm:w-auto sm:text-sm" class="w-full sm:w-auto sm:text-sm"
data-method="post" data-method="post"
data-csrf={Plug.CSRFProtection.get_csrf_token()} data-csrf={Plug.CSRFProtection.get_csrf_token()}
data-to={"/sites/invitations/#{@invitation.invitation.invitation_id}/accept"} data-to={"/sites/invitations/#{@invitation.invitation.invitation_id}/accept"}
data-autofocus data-autofocus
> >
Accept &amp; Continue Accept and continue
</.button> </.button>
<.button_link <.button_link
:if={Map.get(@invitation, :exceeded_limits) || Map.get(@invitation, :no_plan)} :if={Map.get(@invitation, :exceeded_limits) || Map.get(@invitation, :no_plan)}
mt?={false} mt?={false}
href={Routes.billing_path(PlausibleWeb.Endpoint, :choose_plan)} href={Routes.billing_path(PlausibleWeb.Endpoint, :choose_plan)}
class="sm:ml-3 w-full sm:w-auto sm:text-sm" class="w-full sm:w-auto sm:text-sm"
data-autofocus data-autofocus
> >
Upgrade Upgrade
</.button_link> </.button_link>
<.button_link <.button_link
mt?={false} mt?={false}
class="w-full sm:w-auto mr-2 sm:text-sm mt-2 sm:mt-0" class="w-full sm:w-auto sm:text-sm"
href="#" href="#"
theme="secondary" theme="secondary"
data-method="post" data-method="post"

View File

@ -47,12 +47,19 @@
:if={ee?() and Plausible.Teams.on_trial?(@conn.assigns[:current_team])} :if={ee?() and Plausible.Teams.on_trial?(@conn.assigns[:current_team])}
class="hidden sm:block" class="hidden sm:block"
> >
<.styled_link <div class="flex items-center p-1 rounded-lg bg-yellow-100 dark:bg-yellow-600/35 overflow-hidden">
class="flex items-center h-[40px] px-3 py-2 text-sm text-yellow-700 hover:text-yellow-800 dark:text-yellow-500 dark:hover:text-yellow-500 font-medium rounded-md bg-yellow-100 dark:bg-yellow-800/40 dark:hover:bg-yellow-800/50 transition-colors duration-150" <span class="px-3 text-sm font-medium text-gray-900 dark:text-gray-100">
href={Routes.settings_path(@conn, :subscription)} {trial_notification(@conn.assigns[:current_team])}
> </span>
{trial_notification(@conn.assigns[:current_team])} <.button_link
</.styled_link> href={Routes.settings_path(@conn, :subscription)}
theme="yellow"
mt?={false}
class="!px-3 !py-2"
>
Upgrade
</.button_link>
</div>
</li> </li>
<li class="w-full sm:w-auto"> <li class="w-full sm:w-auto">
<.dropdown> <.dropdown>

View File

@ -17,10 +17,9 @@ defmodule PlausibleWeb.Components.BillingTest do
} }
|> render_feature_gate() |> render_feature_gate()
assert class_of_element(html, "#feature-gate-inner-block-container") =~ assert element_exists?(html, "#feature-gate-inner-block-container")
"pointer-events-none" assert element_exists?(html, "#feature-gate-overlay")
assert text_of_element(html, "#feature-gate-overlay") =~ "Upgrade to unlock"
assert class_of_element(html, "#feature-gate-overlay") =~ "backdrop-blur"
end end
test "renders a blur overlay for a teamless account" do test "renders a blur overlay for a teamless account" do
@ -32,10 +31,9 @@ defmodule PlausibleWeb.Components.BillingTest do
} }
|> render_feature_gate() |> render_feature_gate()
assert class_of_element(html, "#feature-gate-inner-block-container") =~ assert element_exists?(html, "#feature-gate-inner-block-container")
"pointer-events-none" assert element_exists?(html, "#feature-gate-overlay")
assert text_of_element(html, "#feature-gate-overlay") =~ "Upgrade to unlock"
assert class_of_element(html, "#feature-gate-overlay") =~ "backdrop-blur"
end end
test "does not render a blur overlay if feature access is granted", %{user: user} do test "does not render a blur overlay if feature access is granted", %{user: user} do
@ -47,9 +45,7 @@ defmodule PlausibleWeb.Components.BillingTest do
} }
|> render_feature_gate() |> render_feature_gate()
refute class_of_element(html, "#feature-gate-inner-block-container") =~ assert element_exists?(html, "#feature-gate-inner-block-container")
"pointer-events-none"
refute element_exists?(html, "#feature-gate-overlay") refute element_exists?(html, "#feature-gate-overlay")
end end
@ -89,7 +85,7 @@ defmodule PlausibleWeb.Components.BillingTest do
} }
|> render_feature_gate() |> render_feature_gate()
assert text_of_element(html, "#lock-notice") =~ "reach out to the team owner" assert text_of_element(html, "#lock-notice") =~ "ask your team owner"
end end
end end

View File

@ -50,7 +50,7 @@ defmodule PlausibleWeb.Components.Billing.NoticeTest do
) )
assert rendered =~ "This team is limited to 10 users" assert rendered =~ "This team is limited to 10 users"
assert rendered =~ "please reach out to the team owner to upgrade their subscription" assert rendered =~ "ask your team owner to upgrade their subscription"
end end
@tag :ee_only @tag :ee_only

View File

@ -21,7 +21,7 @@ defmodule PlausibleWeb.Live.FunnelSettingsTest do
conn = get(conn, "/#{site.domain}/settings/funnels") conn = get(conn, "/#{site.domain}/settings/funnels")
resp = conn |> html_response(200) resp = conn |> html_response(200)
assert text(resp) =~ "please upgrade your subscription" assert text(resp) =~ "upgrade your subscription"
end end
test "lists funnels for the site and renders help link", %{conn: conn, site: site} do test "lists funnels for the site and renders help link", %{conn: conn, site: site} do
@ -33,7 +33,7 @@ defmodule PlausibleWeb.Live.FunnelSettingsTest do
assert resp =~ "From blog to signup" assert resp =~ "From blog to signup"
assert resp =~ "From signup to blog" assert resp =~ "From signup to blog"
refute resp =~ "Your account does not have access" refute resp =~ "Your account does not have access"
refute resp =~ "please upgrade your subscription" refute resp =~ "upgrade your subscription"
assert element_exists?(resp, "a[href=\"https://plausible.io/docs/funnel-analysis\"]") assert element_exists?(resp, "a[href=\"https://plausible.io/docs/funnel-analysis\"]")
end end

View File

@ -21,7 +21,7 @@ defmodule PlausibleWeb.Live.PropsSettingsTest do
|> html_response(200) |> html_response(200)
|> text_of_element("#lock-notice") |> text_of_element("#lock-notice")
assert lock_notice =~ "please upgrade your subscription" assert lock_notice =~ "upgrade your subscription"
end end
@tag :ee_only @tag :ee_only
@ -38,7 +38,7 @@ defmodule PlausibleWeb.Live.PropsSettingsTest do
|> html_response(200) |> html_response(200)
|> text_of_element("#lock-notice") |> text_of_element("#lock-notice")
refute lock_notice =~ "please upgrade your subscription" refute lock_notice =~ "upgrade your subscription"
end end
test "lists props for the site and renders links", %{conn: conn, site: site} do test "lists props for the site and renders links", %{conn: conn, site: site} do
@ -56,7 +56,7 @@ defmodule PlausibleWeb.Live.PropsSettingsTest do
assert resp =~ "amount" assert resp =~ "amount"
assert resp =~ "logged_in" assert resp =~ "logged_in"
assert resp =~ "is_customer" assert resp =~ "is_customer"
refute resp =~ "please upgrade your subscription" refute resp =~ "upgrade your subscription"
end end
test "lists props with disallow actions", %{conn: conn, site: site} do test "lists props with disallow actions", %{conn: conn, site: site} do
@ -133,7 +133,7 @@ defmodule PlausibleWeb.Live.PropsSettingsTest do
assert resp =~ "amount" assert resp =~ "amount"
assert resp =~ "logged_in" assert resp =~ "logged_in"
assert resp =~ "is_customer" assert resp =~ "is_customer"
refute resp =~ "please upgrade your subscription" refute resp =~ "upgrade your subscription"
end end
test "if no props are allowed, a proper info is displayed", %{ test "if no props are allowed, a proper info is displayed", %{

View File

@ -93,10 +93,9 @@ defmodule PlausibleWeb.Live.TeamSetupTest do
{:ok, _lv, html} = live(conn, @url) {:ok, _lv, html} = live(conn, @url)
assert class_of_element(html, "#feature-gate-inner-block-container") =~ assert element_exists?(html, "#feature-gate-inner-block-container")
"pointer-events-none" assert element_exists?(html, "#feature-gate-overlay")
assert text_of_element(html, "#feature-gate-overlay") =~ "Upgrade to unlock"
assert class_of_element(html, "#feature-gate-overlay") =~ "backdrop-blur-[6px]"
end end
end end