Centralize page layout sizing

This commit is contained in:
SimpleTest 2026-07-22 05:58:20 +03:00
parent 0880b25e73
commit 81b64deced
27 changed files with 120 additions and 51 deletions

View File

@ -105,6 +105,10 @@
/* This file is for your main application CSS */ /* This file is for your main application CSS */
html {
scrollbar-gutter: stable;
}
.skip-link { .skip-link {
position: fixed; position: fixed;
z-index: 100; z-index: 100;

View File

@ -266,7 +266,7 @@ defmodule WhoNeedHelpWeb.CoreComponents do
~H""" ~H"""
<div class="fieldset mb-2"> <div class="fieldset mb-2">
<label for={@id}> <label for={@id} class="block min-w-0 max-w-full">
<input <input
type="hidden" type="hidden"
name={@name} name={@name}
@ -274,16 +274,17 @@ defmodule WhoNeedHelpWeb.CoreComponents do
disabled={@rest[:disabled]} disabled={@rest[:disabled]}
form={@rest[:form]} form={@rest[:form]}
/> />
<span class="label"> <span class="label flex w-full min-w-0 max-w-full items-start justify-start gap-2 whitespace-normal">
<input <input
type="checkbox" type="checkbox"
id={@id} id={@id}
name={@name} name={@name}
value="true" value="true"
checked={@checked} checked={@checked}
class={@class || "checkbox checkbox-sm"} class={[@class || "checkbox checkbox-sm", "shrink-0"]}
{@rest} {@rest}
/>{@label} />
<span class="min-w-0 break-words">{@label}</span>
</span> </span>
</label> </label>
<.error :for={msg <- @errors}>{msg}</.error> <.error :for={msg <- @errors}>{msg}</.error>

View File

@ -31,6 +31,16 @@ defmodule WhoNeedHelpWeb.Layouts do
default: nil, default: nil,
doc: "the current [scope](https://phoenix.hexdocs.pm/scopes.html)" doc: "the current [scope](https://phoenix.hexdocs.pm/scopes.html)"
attr :page_width, :atom,
default: :wide,
values: [:wide, :form, :reading, :medium, :compact, :narrow, :auth],
doc: "the centralized content width used inside the stable application grid"
attr :page_align, :atom,
default: :start,
values: [:start, :center],
doc: "whether constrained content follows the application grid or is centered"
slot :inner_block, required: true slot :inner_block, required: true
def app(assigns) do def app(assigns) do
@ -136,9 +146,15 @@ defmodule WhoNeedHelpWeb.Layouts do
</header> </header>
<main id="main-content" tabindex="-1" class="px-4 py-8 outline-none sm:px-6 lg:px-8"> <main id="main-content" tabindex="-1" class="px-4 py-8 outline-none sm:px-6 lg:px-8">
<div class="mx-auto max-w-7xl space-y-4"> <div class="mx-auto w-full max-w-7xl">
<div class={[
"w-full space-y-4",
page_width_class(@page_width),
@page_align == :center && "mx-auto"
]}>
{render_slot(@inner_block)} {render_slot(@inner_block)}
</div> </div>
</div>
</main> </main>
<footer class="border-t border-base-300 px-4 py-6 text-center text-xs text-base-content/70"> <footer class="border-t border-base-300 px-4 py-6 text-center text-xs text-base-content/70">
@ -159,6 +175,14 @@ defmodule WhoNeedHelpWeb.Layouts do
""" """
end end
defp page_width_class(:wide), do: "max-w-none"
defp page_width_class(:form), do: "max-w-5xl"
defp page_width_class(:reading), do: "max-w-4xl"
defp page_width_class(:medium), do: "max-w-3xl"
defp page_width_class(:compact), do: "max-w-2xl"
defp page_width_class(:narrow), do: "max-w-xl"
defp page_width_class(:auth), do: "max-w-sm"
attr :current_scope, :map, default: nil attr :current_scope, :map, default: nil
attr :link_class, :string, default: "btn btn-ghost btn-sm" attr :link_class, :string, default: "btn btn-ghost btn-sm"

View File

@ -1,5 +1,5 @@
<Layouts.app flash={@flash} current_scope={@current_scope}> <Layouts.app flash={@flash} current_scope={@current_scope} page_width={:compact}>
<div class="mx-auto max-w-2xl"> <div>
<div class="text-sm font-semibold text-error">{gettext("CONTENT REMOVAL")}</div> <div class="text-sm font-semibold text-error">{gettext("CONTENT REMOVAL")}</div>
<h1 class="mt-2 text-4xl font-black">{gettext("Report illegal or harmful content")}</h1> <h1 class="mt-2 text-4xl font-black">{gettext("Report illegal or harmful content")}</h1>
<p class="mt-3 text-base-content/65"> <p class="mt-3 text-base-content/65">

View File

@ -1,5 +1,10 @@
<Layouts.app flash={@flash} current_scope={@current_scope}> <Layouts.app
<div class="mx-auto max-w-xl text-center"> flash={@flash}
current_scope={@current_scope}
page_width={:narrow}
page_align={:center}
>
<div class="text-center">
<div class="text-sm font-semibold text-success">{gettext("NOTICE RECEIVED")}</div> <div class="text-sm font-semibold text-success">{gettext("NOTICE RECEIVED")}</div>
<h1 class="mt-2 text-4xl font-black"> <h1 class="mt-2 text-4xl font-black">
{gettext("Your reference is %{reference}", reference: @reference)} {gettext("Your reference is %{reference}", reference: @reference)}

View File

@ -1,5 +1,5 @@
<Layouts.app flash={@flash} current_scope={@current_scope}> <Layouts.app flash={@flash} current_scope={@current_scope} page_width={:compact}>
<div class="mx-auto max-w-2xl"> <div>
<div class="flex flex-wrap items-center gap-2"> <div class="flex flex-wrap items-center gap-2">
<span class="badge badge-outline">{@notice.reference}</span> <span class="badge badge-outline">{@notice.reference}</span>
<span class={[ <span class={[

View File

@ -1,5 +1,5 @@
<Layouts.app flash={@flash} current_scope={@current_scope}> <Layouts.app flash={@flash} current_scope={@current_scope} page_width={:compact}>
<div class="mx-auto max-w-2xl"> <div>
<div class="text-sm font-semibold text-error">{gettext("TAKE IT DOWN")}</div> <div class="text-sm font-semibold text-error">{gettext("TAKE IT DOWN")}</div>
<h1 class="mt-2 text-4xl font-black"> <h1 class="mt-2 text-4xl font-black">
{gettext("Request removal of intimate visual material")} {gettext("Request removal of intimate visual material")}

View File

@ -1,5 +1,5 @@
<Layouts.app flash={@flash} current_scope={@current_scope}> <Layouts.app flash={@flash} current_scope={@current_scope} page_width={:medium}>
<div class="mx-auto max-w-3xl"> <div>
<div class="text-sm font-semibold text-success">OPENAI BUILD WEEK</div> <div class="text-sm font-semibold text-success">OPENAI BUILD WEEK</div>
<h1 class="mt-2 text-4xl font-black">{gettext("Build feedback")}</h1> <h1 class="mt-2 text-4xl font-black">{gettext("Build feedback")}</h1>
<p class="mt-4 text-base-content/65"> <p class="mt-4 text-base-content/65">

View File

@ -1,5 +1,10 @@
<Layouts.app flash={@flash} current_scope={@current_scope}> <Layouts.app
<div class="mx-auto max-w-md space-y-5"> flash={@flash}
current_scope={@current_scope}
page_width={:narrow}
page_align={:center}
>
<div class="space-y-5">
<div class="text-center"> <div class="text-center">
<.header> <.header>
{gettext("Continue with Google")} {gettext("Continue with Google")}

View File

@ -1,5 +1,5 @@
<Layouts.app flash={@flash} current_scope={@current_scope}> <Layouts.app flash={@flash} current_scope={@current_scope} page_width={:reading}>
<article class="mx-auto max-w-4xl"> <article>
<div class="text-sm font-semibold text-brand">WHO NEED HELP</div> <div class="text-sm font-semibold text-brand">WHO NEED HELP</div>
<h1 class="mt-2 text-4xl font-black">Privacy Policy</h1> <h1 class="mt-2 text-4xl font-black">Privacy Policy</h1>
<p class="mt-3 text-sm text-base-content/60">Effective: 21 July 2026</p> <p class="mt-3 text-sm text-base-content/60">Effective: 21 July 2026</p>

View File

@ -1,5 +1,5 @@
<Layouts.app flash={@flash} current_scope={@current_scope}> <Layouts.app flash={@flash} current_scope={@current_scope} page_width={:reading}>
<article class="mx-auto max-w-4xl"> <article>
<div class="text-sm font-semibold text-warning"> <div class="text-sm font-semibold text-warning">
{gettext("READ BEFORE USING THE SERVICE")} {gettext("READ BEFORE USING THE SERVICE")}
</div> </div>

View File

@ -1,5 +1,5 @@
<Layouts.app flash={@flash} current_scope={@current_scope}> <Layouts.app flash={@flash} current_scope={@current_scope} page_width={:reading}>
<article class="mx-auto max-w-4xl"> <article>
<div class="text-sm font-semibold text-brand">WHO NEED HELP</div> <div class="text-sm font-semibold text-brand">WHO NEED HELP</div>
<h1 class="mt-2 text-4xl font-black">Terms of Service</h1> <h1 class="mt-2 text-4xl font-black">Terms of Service</h1>
<p class="mt-3 text-sm text-base-content/60">Effective: 21 July 2026</p> <p class="mt-3 text-sm text-base-content/60">Effective: 21 July 2026</p>

View File

@ -1,5 +1,5 @@
<Layouts.app flash={@flash} current_scope={@current_scope}> <Layouts.app flash={@flash} current_scope={@current_scope} page_width={:compact}>
<div class="mx-auto max-w-2xl"> <div>
<div class="text-sm font-semibold text-error">{gettext("ACCOUNT AND DATA")}</div> <div class="text-sm font-semibold text-error">{gettext("ACCOUNT AND DATA")}</div>
<h1 class="mt-2 text-4xl font-black">{gettext("Request account deletion")}</h1> <h1 class="mt-2 text-4xl font-black">{gettext("Request account deletion")}</h1>
<p class="mt-3 text-base-content/65"> <p class="mt-3 text-base-content/65">

View File

@ -1,5 +1,5 @@
<Layouts.app flash={@flash} current_scope={@current_scope}> <Layouts.app flash={@flash} current_scope={@current_scope} page_width={:reading}>
<div class="mx-auto max-w-4xl"> <div>
<div class="flex flex-wrap items-center justify-between gap-3"> <div class="flex flex-wrap items-center justify-between gap-3">
<div> <div>
<div class="text-sm font-semibold text-primary">{gettext("SUPPORT")}</div> <div class="text-sm font-semibold text-primary">{gettext("SUPPORT")}</div>

View File

@ -1,5 +1,5 @@
<Layouts.app flash={@flash} current_scope={@current_scope}> <Layouts.app flash={@flash} current_scope={@current_scope} page_width={:compact}>
<div class="mx-auto max-w-2xl"> <div>
<div class="text-sm font-semibold text-primary">{gettext("SUPPORT")}</div> <div class="text-sm font-semibold text-primary">{gettext("SUPPORT")}</div>
<h1 class="mt-2 text-4xl font-black">{gettext("Contact Who Need Help")}</h1> <h1 class="mt-2 text-4xl font-black">{gettext("Contact Who Need Help")}</h1>
<p class="mt-3 text-base-content/65"> <p class="mt-3 text-base-content/65">

View File

@ -1,5 +1,10 @@
<Layouts.app flash={@flash} current_scope={@current_scope}> <Layouts.app
<div class="mx-auto max-w-xl text-center"> flash={@flash}
current_scope={@current_scope}
page_width={:narrow}
page_align={:center}
>
<div class="text-center">
<div class="text-sm font-semibold text-success">{gettext("REQUEST RECEIVED")}</div> <div class="text-sm font-semibold text-success">{gettext("REQUEST RECEIVED")}</div>
<h1 class="mt-2 text-4xl font-black">{gettext("Check your email")}</h1> <h1 class="mt-2 text-4xl font-black">{gettext("Check your email")}</h1>
<p class="mt-4 text-base-content/65"> <p class="mt-4 text-base-content/65">

View File

@ -1,5 +1,5 @@
<Layouts.app flash={@flash} current_scope={@current_scope}> <Layouts.app flash={@flash} current_scope={@current_scope} page_width={:compact}>
<div class="mx-auto max-w-2xl"> <div>
<div class="flex flex-wrap items-center gap-2"> <div class="flex flex-wrap items-center gap-2">
<span class="badge badge-outline">{@request.reference}</span> <span class="badge badge-outline">{@request.reference}</span>
<span class="badge badge-primary">{status_label(@request.status)}</span> <span class="badge badge-primary">{status_label(@request.status)}</span>

View File

@ -1,5 +1,10 @@
<Layouts.app flash={@flash} current_scope={@current_scope}> <Layouts.app
<div class="mx-auto max-w-sm space-y-5"> flash={@flash}
current_scope={@current_scope}
page_width={:auth}
page_align={:center}
>
<div class="space-y-5">
<div class="text-center"> <div class="text-center">
<.header> <.header>
{gettext("Register for an account")} {gettext("Register for an account")}

View File

@ -1,5 +1,10 @@
<Layouts.app flash={@flash} current_scope={@current_scope}> <Layouts.app
<div class="mx-auto max-w-xl space-y-6"> flash={@flash}
current_scope={@current_scope}
page_width={:narrow}
page_align={:center}
>
<div class="space-y-6">
<div class="text-center"> <div class="text-center">
<.header> <.header>
{if @email_flow == "register", {if @email_flow == "register",

View File

@ -1,5 +1,10 @@
<Layouts.app flash={@flash} current_scope={@current_scope}> <Layouts.app
<div class="mx-auto max-w-sm space-y-4"> flash={@flash}
current_scope={@current_scope}
page_width={:auth}
page_align={:center}
>
<div class="space-y-4">
<div class="text-center"> <div class="text-center">
<.header> <.header>
<p>{gettext("Log in")}</p> <p>{gettext("Log in")}</p>

View File

@ -1,5 +1,10 @@
<Layouts.app flash={@flash} current_scope={@current_scope}> <Layouts.app
<div class="mx-auto max-w-md text-center"> flash={@flash}
current_scope={@current_scope}
page_width={:narrow}
page_align={:center}
>
<div class="text-center">
<.header> <.header>
{gettext("Confirm email change")} {gettext("Confirm email change")}
<:subtitle>{gettext("Confirm the new email address for your account.")}</:subtitle> <:subtitle>{gettext("Confirm the new email address for your account.")}</:subtitle>

View File

@ -1,4 +1,4 @@
<Layouts.app flash={@flash} current_scope={@current_scope}> <Layouts.app flash={@flash} current_scope={@current_scope} page_width={:reading}>
<div class="text-center"> <div class="text-center">
<.header> <.header>
{gettext("Account Settings")} {gettext("Account Settings")}

View File

@ -112,8 +112,8 @@ defmodule WhoNeedHelpWeb.ActivityLive.New do
@impl true @impl true
def render(assigns) do def render(assigns) do
~H""" ~H"""
<Layouts.app flash={@flash} current_scope={@current_scope}> <Layouts.app flash={@flash} current_scope={@current_scope} page_width={:form}>
<div class="mx-auto max-w-3xl"> <div>
<.link navigate={~p"/activities"} class="btn btn-ghost btn-sm mb-4"> <.link navigate={~p"/activities"} class="btn btn-ghost btn-sm mb-4">
{gettext("← Back to activities")} {gettext("← Back to activities")}
</.link> </.link>

View File

@ -32,11 +32,11 @@ defmodule WhoNeedHelpWeb.LeaderboardLive do
@impl true @impl true
def render(assigns) do def render(assigns) do
~H""" ~H"""
<Layouts.app flash={@flash} current_scope={@current_scope}> <Layouts.app flash={@flash} current_scope={@current_scope} page_width={:reading}>
<.link navigate={~p"/requests"} class="btn btn-ghost btn-sm"> <.link navigate={~p"/requests"} class="btn btn-ghost btn-sm">
{gettext("← Requests")} {gettext("← Requests")}
</.link> </.link>
<div class="mt-5 max-w-4xl"> <div class="mt-5">
<div class="text-sm font-semibold text-success">{gettext("COMMUNITY TRUST")}</div> <div class="text-sm font-semibold text-success">{gettext("COMMUNITY TRUST")}</div>
<h1 class="mt-1 text-4xl font-black tracking-tight"> <h1 class="mt-1 text-4xl font-black tracking-tight">
{gettext("Helpers leaderboard")} {gettext("Helpers leaderboard")}

View File

@ -137,8 +137,8 @@ defmodule WhoNeedHelpWeb.ProfileLive do
@impl true @impl true
def render(assigns) do def render(assigns) do
~H""" ~H"""
<Layouts.app flash={@flash} current_scope={@current_scope}> <Layouts.app flash={@flash} current_scope={@current_scope} page_width={:reading}>
<div class="mx-auto max-w-4xl"> <div>
<h1 class="text-4xl font-black">{gettext("Your profile")}</h1> <h1 class="text-4xl font-black">{gettext("Your profile")}</h1>
<div class="mt-6 grid gap-6 md:grid-cols-[1fr_.75fr]"> <div class="mt-6 grid gap-6 md:grid-cols-[1fr_.75fr]">
<.form <.form

View File

@ -182,8 +182,8 @@ defmodule WhoNeedHelpWeb.RequestLive.New do
@impl true @impl true
def render(assigns) do def render(assigns) do
~H""" ~H"""
<Layouts.app flash={@flash} current_scope={@current_scope}> <Layouts.app flash={@flash} current_scope={@current_scope} page_width={:form}>
<div class="mx-auto max-w-3xl"> <div>
<.link navigate={~p"/requests"} class="btn btn-ghost btn-sm mb-4"> <.link navigate={~p"/requests"} class="btn btn-ghost btn-sm mb-4">
{gettext("← Back to requests")} {gettext("← Back to requests")}
</.link> </.link>

View File

@ -270,6 +270,11 @@ defmodule WhoNeedHelpWeb.MutualAidLiveTest do
test "new request form uses separate local date and time controls", %{conn: conn} do test "new request form uses separate local date and time controls", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/requests/new") {:ok, view, _html} = live(conn, ~p"/requests/new")
assert has_element?(
view,
"#main-content > div.max-w-7xl > div.max-w-5xl:not(.mx-auto)"
)
assert has_element?(view, "#help_request_expires_at[type='hidden']") assert has_element?(view, "#help_request_expires_at[type='hidden']")
assert has_element?(view, "#help_request_expires_at-date[type='date']") assert has_element?(view, "#help_request_expires_at-date[type='date']")
assert has_element?(view, "#help_request_expires_at-time[type='time']") assert has_element?(view, "#help_request_expires_at-time[type='time']")