Browse Source

fix(ui): unify PageHeader with Flutter AppBar specs (56px toolbar, safeArea, sticky blur)

master
Alireza 13 hours ago
parent
commit
dd0424e5a1
  1. 4
      src/app/candidate-contact/candidate-contact-client.tsx
  2. 4
      src/app/finding-match/finding-match-client.tsx
  3. 18
      src/app/new-match/new-match-client.tsx
  4. 4
      src/app/request-accepted/request-accepted-client.tsx
  5. 4
      src/app/request-sent/request-sent-client.tsx
  6. 82
      src/components/Componentes/page-header.tsx

4
src/app/candidate-contact/candidate-contact-client.tsx

@ -130,7 +130,7 @@ export default function CandidateContactClient() {
/> />
) : null} ) : null}
<main className="-mx-[17px] flex min-h-screen flex-col px-[23px] pt-[max(12px,calc(var(--safe-top)+4px))] pb-[calc(20px+var(--safe-bottom))]">
<main className="-mx-[17px] flex min-h-screen flex-col px-[23px] pb-[calc(20px+var(--safe-bottom))]">
<PageHeader <PageHeader
className="-mx-[6px]" className="-mx-[6px]"
profile={profile} profile={profile}
@ -353,7 +353,7 @@ export default function CandidateContactClient() {
/> />
) : null} ) : null}
<main className="-mx-[17px] flex min-h-screen flex-col px-[17px] pt-[max(12px,calc(var(--safe-top)+4px))] pb-36">
<main className="-mx-[17px] flex min-h-screen flex-col px-[17px] pb-36">
<PageHeader profile={profile} /> <PageHeader profile={profile} />
<section className="flex flex-1 items-center justify-center"> <section className="flex flex-1 items-center justify-center">

4
src/app/finding-match/finding-match-client.tsx

@ -87,9 +87,9 @@ export default function FindingMatchClient() {
<main <main
style={{ paddingBottom: "calc(100px + var(--safe-bottom))" }} style={{ paddingBottom: "calc(100px + var(--safe-bottom))" }}
className="-mx-[17px] flex min-h-screen flex-col px-[23px] pt-[max(12px,calc(var(--safe-top)+4px))] text-center"
className="-mx-[17px] flex min-h-screen flex-col px-[23px] text-center"
> >
<PageHeader className="-mx-[6px]" />
<PageHeader />
<section className="mt-20 flex flex-1 flex-col items-center"> <section className="mt-20 flex flex-1 flex-col items-center">
<div className="relative h-[124px] w-[130px]" aria-hidden="true"> <div className="relative h-[124px] w-[130px]" aria-hidden="true">

18
src/app/new-match/new-match-client.tsx

@ -636,14 +636,7 @@ export default function NewMatchClient() {
<main <main
className="-mx-[17px] flex min-h-dvh flex-col px-[18px] text-center" className="-mx-[17px] flex min-h-dvh flex-col px-[18px] text-center"
> >
<div
style={{
paddingTop: `${Math.max(12, top + 4)}px`,
}}
className="sticky top-0 z-30 -mx-[18px] px-[18px] pb-2 bg-[#F7F1F0]/90 backdrop-blur-md"
>
<PageHeader profile={profile} />
</div>
<PageHeader profile={profile} />
<div <div
style={{ style={{
@ -725,14 +718,7 @@ export default function NewMatchClient() {
<main <main
className="-mx-[17px] flex min-h-dvh flex-col px-[18px] text-center" className="-mx-[17px] flex min-h-dvh flex-col px-[18px] text-center"
> >
<div
style={{
paddingTop: `${Math.max(12, top + 4)}px`,
}}
className="sticky top-0 z-30 -mx-[18px] px-[18px] pb-2 bg-[#F7F1F0]/90 backdrop-blur-md"
>
<PageHeader profile={profile} />
</div>
<PageHeader profile={profile} />
<div <div
style={{ style={{

4
src/app/request-accepted/request-accepted-client.tsx

@ -538,8 +538,8 @@ export default function RequestAcceptedClient() {
/> />
) : null} ) : null}
<main className="-mx-[17px] flex min-h-screen flex-col px-[23px] pt-[max(12px,calc(var(--safe-top)+4px))] pb-[calc(20px+var(--safe-bottom))] text-center">
<PageHeader className="-mx-[6px]" profile={profile} />
<main className="-mx-[17px] flex min-h-screen flex-col px-[23px] pb-[calc(20px+var(--safe-bottom))] text-center">
<PageHeader profile={profile} />
<div className="flex flex-1 flex-col justify-between gap-6 pt-4"> <div className="flex flex-1 flex-col justify-between gap-6 pt-4">
<section className="flex flex-col items-center"> <section className="flex flex-col items-center">

4
src/app/request-sent/request-sent-client.tsx

@ -88,9 +88,9 @@ export default function RequestSentClient() {
<main <main
style={{ paddingBottom: "calc(40px + var(--safe-bottom))" }} style={{ paddingBottom: "calc(40px + var(--safe-bottom))" }}
className="-mx-[17px] flex min-h-screen flex-col px-[23px] pt-[max(12px,calc(var(--safe-top)+4px))] text-center"
className="-mx-[17px] flex min-h-screen flex-col px-[23px] text-center"
> >
<PageHeader className="-mx-[6px]" profile={profile} />
<PageHeader profile={profile} />
<div className="flex flex-1 flex-col justify-between gap-16 pt-8"> <div className="flex flex-1 flex-col justify-between gap-16 pt-8">
<section className="flex flex-col items-center"> <section className="flex flex-col items-center">

82
src/components/Componentes/page-header.tsx

@ -22,14 +22,26 @@ type PageHeaderProps = {
*/ */
enableProfileQuery?: boolean; enableProfileQuery?: boolean;
profile?: any; profile?: any;
/**
* Whether the header is sticky at the top during scroll (matching Flutter AppBar).
* Defaults to true.
*/
sticky?: boolean;
}; };
/**
* Standard AppBar for Marriage WebApp matching Flutter's Scaffold.appBar:
* - Toolbar Height: 56px (Flutter Material kToolbarHeight)
* - Top Safe Area: max(12px, var(--safe-top) + 4px)
* - Sticky at top during body scroll with frosted blur backdrop
*/
export function PageHeader({ export function PageHeader({
className, className,
leftButton, leftButton,
rightButton, rightButton,
enableProfileQuery = true, enableProfileQuery = true,
profile: profileProp, profile: profileProp,
sticky = true,
}: PageHeaderProps) { }: PageHeaderProps) {
const { dictionary: t } = useI18n(); const { dictionary: t } = useI18n();
@ -57,51 +69,61 @@ export function PageHeader({
return ( return (
<header <header
className={["flex items-center justify-between pb-3", className]
style={{
paddingTop: "max(12px, calc(var(--safe-top) + 4px))",
}}
className={[
sticky
? "sticky top-0 z-30 -mx-[17px] px-[17px] bg-[#F7F1F0]/90 backdrop-blur-md"
: "relative z-30 -mx-[17px] px-[17px]",
className,
]
.filter(Boolean) .filter(Boolean)
.join(" ")} .join(" ")}
> >
{leftButton?.className?.includes("hidden") ? (
<div className="size-10 shrink-0" />
) : (
<NavigationButton icon="back" profile={profile} {...leftButton} />
)}
<h1 className="font-faminela text-[20px] font-normal text-foreground">
{t["Habib Marriage"]}
</h1>
<div className="flex h-[56px] items-center justify-between">
{leftButton?.className?.includes("hidden") ? (
<div className="size-10 shrink-0" />
) : (
<NavigationButton icon="back" profile={profile} {...leftButton} />
)}
{isCustomRightButton ? (
<NavigationButton
icon={iconFromProp || "support"}
profile={profile}
{...(iconFromProp === "support" ? { iconLabel: t["Support"] } : {})}
{...rightButtonRest}
/>
) : isMale ? (
<div className="flex items-center gap-2">
<h1 className="font-faminela text-[20px] font-normal text-[#171717] leading-none select-none">
{t["Habib Marriage"]}
</h1>
{isCustomRightButton ? (
<NavigationButton <NavigationButton
icon="subscription"
icon={iconFromProp || "support"}
profile={profile} profile={profile}
iconLabel={t["Subscription Status"] || "Subscription"}
{...(iconFromProp === "support" ? { iconLabel: t["Support"] } : {})}
{...rightButtonRest}
/> />
) : isMale ? (
<div className="flex items-center gap-2">
<NavigationButton
icon="subscription"
profile={profile}
iconLabel={t["Subscription Status"] || "Subscription"}
/>
<NavigationButton
icon="support"
profile={profile}
iconLabel={t["Support"]}
{...rightButtonRest}
/>
</div>
) : (
<NavigationButton <NavigationButton
icon="support" icon="support"
profile={profile} profile={profile}
iconLabel={t["Support"]} iconLabel={t["Support"]}
{...rightButtonRest} {...rightButtonRest}
/> />
</div>
) : (
<NavigationButton
icon="support"
profile={profile}
iconLabel={t["Support"]}
{...rightButtonRest}
/>
)}
)}
</div>
</header> </header>
); );
} }
export default PageHeader; export default PageHeader;
Loading…
Cancel
Save