chore: bump version to 3.1.1 in package.json; refactor mobile navigation components and improve layout structure (#472)

- Updated version to 3.1.1 in package.json.
- Refactored mobile navigation components to enhance structure and usability.
- Adjusted layout components to improve responsiveness and visual consistency.
- Introduced shared mobile navigation components for better code reuse.
This commit is contained in:
Giancarlo Buomprisco
2026-03-31 21:24:37 +08:00
committed by GitHub
parent 6268d1bab0
commit c837d4f592
17 changed files with 270 additions and 260 deletions

View File

@@ -22,13 +22,15 @@ export function HomeAccountSelector(props: {
}>; }>;
userId: string; userId: string;
collapsed?: boolean;
}) { }) {
const router = useRouter(); const router = useRouter();
const context = useContext(SidebarContext); const context = useContext(SidebarContext);
const collapsed = props.collapsed ?? !context?.open;
return ( return (
<AccountSelector <AccountSelector
collapsed={!context?.open} collapsed={collapsed}
accounts={props.accounts} accounts={props.accounts}
features={features} features={features}
userId={props.userId} userId={props.userId}

View File

@@ -39,7 +39,9 @@ export function HomeMenuNavigation(props: { workspace: UserWorkspace }) {
return ( return (
<div className={'flex w-full flex-1 justify-between'}> <div className={'flex w-full flex-1 justify-between'}>
<div className={'flex items-center space-x-8'}> <div className={'flex items-center space-x-8'}>
<AppLogo /> <div>
<AppLogo />
</div>
<BorderedNavigationMenu> <BorderedNavigationMenu>
{routes.map((route) => ( {routes.map((route) => (
@@ -54,7 +56,9 @@ export function HomeMenuNavigation(props: { workspace: UserWorkspace }) {
</If> </If>
<If condition={featuresFlagConfig.enableTeamAccounts}> <If condition={featuresFlagConfig.enableTeamAccounts}>
<HomeAccountSelector userId={user.id} accounts={accounts} /> <div>
<HomeAccountSelector userId={user.id} accounts={accounts} />
</div>
</If> </If>
<div> <div>

View File

@@ -1,15 +1,12 @@
'use client'; 'use client';
import Link from 'next/link'; import { Menu } from 'lucide-react';
import { LogOut, Menu } from 'lucide-react';
import { useSignOut } from '@kit/supabase/hooks/use-sign-out'; import { useSignOut } from '@kit/supabase/hooks/use-sign-out';
import { import {
DropdownMenu, DropdownMenu,
DropdownMenuContent, DropdownMenuContent,
DropdownMenuGroup, DropdownMenuGroup,
DropdownMenuItem,
DropdownMenuLabel, DropdownMenuLabel,
DropdownMenuSeparator, DropdownMenuSeparator,
DropdownMenuTrigger, DropdownMenuTrigger,
@@ -17,6 +14,10 @@ import {
import { If } from '@kit/ui/if'; import { If } from '@kit/ui/if';
import { Trans } from '@kit/ui/trans'; import { Trans } from '@kit/ui/trans';
import {
MobileNavRouteLinks,
MobileNavSignOutItem,
} from '~/components/mobile-navigation-shared';
import featuresFlagConfig from '~/config/feature-flags.config'; import featuresFlagConfig from '~/config/feature-flags.config';
import { personalAccountNavigationConfig } from '~/config/personal-account-navigation.config'; import { personalAccountNavigationConfig } from '~/config/personal-account-navigation.config';
@@ -27,25 +28,6 @@ import type { UserWorkspace } from '../_lib/server/load-user-workspace';
export function HomeMobileNavigation(props: { workspace: UserWorkspace }) { export function HomeMobileNavigation(props: { workspace: UserWorkspace }) {
const signOut = useSignOut(); const signOut = useSignOut();
const Links = personalAccountNavigationConfig.routes.map((item, index) => {
if ('children' in item) {
return item.children.map((child) => {
return (
<DropdownLink
key={child.path}
Icon={child.Icon}
path={child.path}
label={child.label}
/>
);
});
}
if ('divider' in item) {
return <DropdownMenuSeparator key={index} />;
}
});
return ( return (
<DropdownMenu> <DropdownMenu>
<DropdownMenuTrigger> <DropdownMenuTrigger>
@@ -60,6 +42,7 @@ export function HomeMobileNavigation(props: { workspace: UserWorkspace }) {
</DropdownMenuLabel> </DropdownMenuLabel>
<HomeAccountSelector <HomeAccountSelector
collapsed={false}
userId={props.workspace.user.id} userId={props.workspace.user.id}
accounts={props.workspace.accounts} accounts={props.workspace.accounts}
/> />
@@ -68,57 +51,16 @@ export function HomeMobileNavigation(props: { workspace: UserWorkspace }) {
<DropdownMenuSeparator /> <DropdownMenuSeparator />
</If> </If>
<DropdownMenuGroup>{Links}</DropdownMenuGroup> <DropdownMenuGroup>
<MobileNavRouteLinks
routes={personalAccountNavigationConfig.routes}
/>
</DropdownMenuGroup>
<DropdownMenuSeparator /> <DropdownMenuSeparator />
<SignOutDropdownItem onSignOut={() => signOut.mutateAsync()} /> <MobileNavSignOutItem onSignOut={() => signOut.mutateAsync()} />
</DropdownMenuContent> </DropdownMenuContent>
</DropdownMenu> </DropdownMenu>
); );
} }
function DropdownLink(
props: React.PropsWithChildren<{
path: string;
label: string;
Icon: React.ReactNode;
}>,
) {
return (
<DropdownMenuItem
render={
<Link
href={props.path}
className={'flex h-12 w-full items-center space-x-4'}
>
{props.Icon}
<span>
<Trans i18nKey={props.label} defaults={props.label} />
</span>
</Link>
}
key={props.path}
/>
);
}
function SignOutDropdownItem(
props: React.PropsWithChildren<{
onSignOut: () => unknown;
}>,
) {
return (
<DropdownMenuItem
className={'flex h-12 w-full items-center space-x-4'}
onClick={props.onSignOut}
>
<LogOut className={'h-6'} />
<span>
<Trans i18nKey={'common.signOut'} defaults={'Sign out'} />
</span>
</DropdownMenuItem>
);
}

View File

@@ -1,12 +1,26 @@
import { cookies } from 'next/headers';
import { PageHeader } from '@kit/ui/page'; import { PageHeader } from '@kit/ui/page';
export function HomeLayoutPageHeader( import { personalAccountNavigationConfig } from '~/config/personal-account-navigation.config';
export async function HomeLayoutPageHeader(
props: React.PropsWithChildren<{ props: React.PropsWithChildren<{
title: string | React.ReactNode; title: string | React.ReactNode;
description: string | React.ReactNode; description: string | React.ReactNode;
}>, }>,
) { ) {
const cookieStore = await cookies();
const layoutStyleCookie = cookieStore.get('layout-style')?.value;
const displaySidebarTrigger =
(layoutStyleCookie ?? personalAccountNavigationConfig.style) === 'sidebar';
return ( return (
<PageHeader description={props.description}>{props.children}</PageHeader> <PageHeader
description={props.description}
displaySidebarTrigger={displaySidebarTrigger}
>
{props.children}
</PageHeader>
); );
} }

View File

@@ -109,7 +109,7 @@ class UserBillingService {
planId, planId,
customerId, customerId,
accountId, accountId,
error: message error: message,
}, },
`Checkout session not created due to an error`, `Checkout session not created due to an error`,
); );

View File

@@ -52,7 +52,7 @@ async function SidebarLayout({ children }: React.PropsWithChildren) {
<HomeSidebar workspace={workspace} /> <HomeSidebar workspace={workspace} />
</PageNavigation> </PageNavigation>
<PageMobileNavigation className={'flex items-center justify-between'}> <PageMobileNavigation>
<MobileNavigation workspace={workspace} /> <MobileNavigation workspace={workspace} />
</PageMobileNavigation> </PageMobileNavigation>
@@ -75,7 +75,7 @@ async function HeaderLayout({ children }: React.PropsWithChildren) {
<HomeMenuNavigation workspace={workspace} /> <HomeMenuNavigation workspace={workspace} />
</PageNavigation> </PageNavigation>
<PageMobileNavigation className={'flex items-center justify-between'}> <PageMobileNavigation>
<MobileNavigation workspace={workspace} /> <MobileNavigation workspace={workspace} />
</PageMobileNavigation> </PageMobileNavigation>
@@ -92,7 +92,9 @@ function MobileNavigation({
}) { }) {
return ( return (
<> <>
<AppLogo /> <div>
<AppLogo />
</div>
<HomeMobileNavigation workspace={workspace} /> <HomeMobileNavigation workspace={workspace} />
</> </>

View File

@@ -1,9 +1,11 @@
'use client'; 'use client';
import { useContext } from 'react';
import { useRouter } from 'next/navigation'; import { useRouter } from 'next/navigation';
import { AccountSelector } from '@kit/accounts/account-selector'; import { AccountSelector } from '@kit/accounts/account-selector';
import { useSidebar } from '@kit/ui/sidebar'; import { SidebarContext } from '@kit/ui/sidebar';
import featureFlagsConfig from '~/config/feature-flags.config'; import featureFlagsConfig from '~/config/feature-flags.config';
import pathsConfig from '~/config/paths.config'; import pathsConfig from '~/config/paths.config';
@@ -23,7 +25,7 @@ export function TeamAccountAccountsSelector(params: {
}>; }>;
}) { }) {
const router = useRouter(); const router = useRouter();
const ctx = useSidebar(); const ctx = useContext(SidebarContext);
return ( return (
<AccountSelector <AccountSelector

View File

@@ -1,28 +1,25 @@
'use client'; 'use client';
import Link from 'next/link';
import { useRouter } from 'next/navigation'; import { useRouter } from 'next/navigation';
import { Home, LogOut, Menu } from 'lucide-react'; import { Menu } from 'lucide-react';
import { AccountSelector } from '@kit/accounts/account-selector'; import { AccountSelector } from '@kit/accounts/account-selector';
import { useSignOut } from '@kit/supabase/hooks/use-sign-out'; import { useSignOut } from '@kit/supabase/hooks/use-sign-out';
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
DialogTrigger,
} from '@kit/ui/dialog';
import { import {
DropdownMenu, DropdownMenu,
DropdownMenuContent, DropdownMenuContent,
DropdownMenuItem, DropdownMenuGroup,
DropdownMenuLabel,
DropdownMenuSeparator, DropdownMenuSeparator,
DropdownMenuTrigger, DropdownMenuTrigger,
} from '@kit/ui/dropdown-menu'; } from '@kit/ui/dropdown-menu';
import { Trans } from '@kit/ui/trans'; import { Trans } from '@kit/ui/trans';
import {
MobileNavRouteLinks,
MobileNavSignOutItem,
} from '~/components/mobile-navigation-shared';
import featureFlagsConfig from '~/config/feature-flags.config'; import featureFlagsConfig from '~/config/feature-flags.config';
import pathsConfig from '~/config/paths.config'; import pathsConfig from '~/config/paths.config';
import { getTeamAccountSidebarConfig } from '~/config/team-account-navigation.config'; import { getTeamAccountSidebarConfig } from '~/config/team-account-navigation.config';
@@ -34,7 +31,6 @@ type Accounts = Array<{
}>; }>;
const features = { const features = {
enableTeamAccounts: featureFlagsConfig.enableTeamAccounts,
enableTeamCreation: featureFlagsConfig.enableTeamCreation, enableTeamCreation: featureFlagsConfig.enableTeamCreation,
}; };
@@ -45,128 +41,21 @@ export const TeamAccountLayoutMobileNavigation = (
accounts: Accounts; accounts: Accounts;
}>, }>,
) => { ) => {
const router = useRouter();
const signOut = useSignOut(); const signOut = useSignOut();
const Links = getTeamAccountSidebarConfig(props.account).routes.map(
(item, index) => {
if ('children' in item) {
return item.children.map((child) => {
return (
<DropdownLink
key={child.path}
Icon={child.Icon}
path={child.path}
label={child.label}
/>
);
});
}
if ('divider' in item) {
return <DropdownMenuSeparator key={index} />;
}
},
);
return ( return (
<DropdownMenu> <DropdownMenu>
<DropdownMenuTrigger> <DropdownMenuTrigger>
<Menu className={'h-9'} /> <Menu className={'h-9'} />
</DropdownMenuTrigger> </DropdownMenuTrigger>
<DropdownMenuContent sideOffset={10} className={'w-screen rounded-none'}> <DropdownMenuContent className={'w-screen rounded-none'}>
<TeamAccountsModal <DropdownMenuGroup>
userId={props.userId} <DropdownMenuLabel>
accounts={props.accounts}
account={props.account}
/>
{Links}
<DropdownMenuSeparator />
<SignOutDropdownItem onSignOut={() => signOut.mutateAsync()} />
</DropdownMenuContent>
</DropdownMenu>
);
};
function DropdownLink(
props: React.PropsWithChildren<{
path: string;
label: string;
Icon: React.ReactNode;
}>,
) {
return (
<DropdownMenuItem
render={
<Link
href={props.path}
className={'flex h-12 w-full items-center gap-x-3 px-3'}
>
{props.Icon}
<span>
<Trans i18nKey={props.label} defaults={props.label} />
</span>
</Link>
}
/>
);
}
function SignOutDropdownItem(
props: React.PropsWithChildren<{
onSignOut: () => unknown;
}>,
) {
return (
<DropdownMenuItem
className={'flex h-12 w-full items-center space-x-2'}
onClick={props.onSignOut}
>
<LogOut className={'h-4'} />
<span>
<Trans i18nKey={'common.signOut'} />
</span>
</DropdownMenuItem>
);
}
function TeamAccountsModal(props: {
accounts: Accounts;
userId: string;
account: string;
}) {
const router = useRouter();
return (
<Dialog>
<DialogTrigger
render={
<DropdownMenuItem
className={'flex h-12 w-full items-center space-x-2'}
onSelect={(e) => e.preventDefault()}
>
<Home className={'h-4'} />
<span>
<Trans i18nKey={'common.yourAccounts'} />
</span>
</DropdownMenuItem>
}
/>
<DialogContent>
<DialogHeader>
<DialogTitle>
<Trans i18nKey={'common.yourAccounts'} /> <Trans i18nKey={'common.yourAccounts'} />
</DialogTitle> </DropdownMenuLabel>
</DialogHeader>
<div className={'py-6'}>
<AccountSelector <AccountSelector
className={'w-full max-w-full'} className={'w-full max-w-full'}
userId={props.userId} userId={props.userId}
@@ -185,8 +74,20 @@ function TeamAccountsModal(props: {
router.replace(path); router.replace(path);
}} }}
/> />
</div> </DropdownMenuGroup>
</DialogContent>
</Dialog> <DropdownMenuSeparator />
<DropdownMenuGroup>
<MobileNavRouteLinks
routes={getTeamAccountSidebarConfig(props.account).routes}
/>
</DropdownMenuGroup>
<DropdownMenuSeparator />
<MobileNavSignOutItem onSignOut={() => signOut.mutateAsync()} />
</DropdownMenuContent>
</DropdownMenu>
); );
} };

View File

@@ -1,13 +1,28 @@
import { cookies } from 'next/headers';
import { PageHeader } from '@kit/ui/page'; import { PageHeader } from '@kit/ui/page';
export function TeamAccountLayoutPageHeader( import { getTeamAccountSidebarConfig } from '~/config/team-account-navigation.config';
export async function TeamAccountLayoutPageHeader(
props: React.PropsWithChildren<{ props: React.PropsWithChildren<{
title: string | React.ReactNode; title: string | React.ReactNode;
description: string | React.ReactNode; description: string | React.ReactNode;
account: string; account: string;
}>, }>,
) { ) {
const cookieStore = await cookies();
const layoutStyleCookie = cookieStore.get('layout-style')?.value;
const defaultStyle = getTeamAccountSidebarConfig(props.account).style;
const displaySidebarTrigger =
(layoutStyleCookie ?? defaultStyle) === 'sidebar';
return ( return (
<PageHeader description={props.description}>{props.children}</PageHeader> <PageHeader
description={props.description}
displaySidebarTrigger={displaySidebarTrigger}
>
{props.children}
</PageHeader>
); );
} }

View File

@@ -41,7 +41,9 @@ export function TeamAccountNavigationMenu(props: {
return ( return (
<div className={'flex w-full flex-1 justify-between'}> <div className={'flex w-full flex-1 justify-between'}>
<div className={'flex items-center space-x-8'}> <div className={'flex items-center space-x-8'}>
<AppLogo /> <div>
<AppLogo />
</div>
<BorderedNavigationMenu> <BorderedNavigationMenu>
{routes.map((route) => ( {routes.map((route) => (
@@ -50,20 +52,22 @@ export function TeamAccountNavigationMenu(props: {
</BorderedNavigationMenu> </BorderedNavigationMenu>
</div> </div>
<div className={'flex items-center justify-end space-x-2.5'}> <div className={'flex items-center justify-end space-x-1'}>
<If condition={featureFlagsConfig.enableNotifications}> <If condition={featureFlagsConfig.enableNotifications}>
<TeamAccountNotifications accountId={account.id} userId={user.id} /> <TeamAccountNotifications accountId={account.id} userId={user.id} />
</If> </If>
<TeamAccountAccountsSelector <div>
userId={user.id} <TeamAccountAccountsSelector
selectedAccount={account.slug} userId={user.id}
accounts={accounts.map((account) => ({ selectedAccount={account.slug}
label: account.name, accounts={accounts.map((account) => ({
value: account.slug, label: account.name,
image: account.picture_url, value: account.slug,
}))} image: account.picture_url,
/> }))}
/>
</div>
<div> <div>
<ProfileAccountDropdownContainer <ProfileAccountDropdownContainer

View File

@@ -131,7 +131,7 @@ class TeamBillingService {
logger.error( logger.error(
{ {
...ctx, ...ctx,
error: message error: message,
}, },
`Error creating the checkout session`, `Error creating the checkout session`,
); );

View File

@@ -67,10 +67,10 @@ async function SidebarLayout({
/> />
</PageNavigation> </PageNavigation>
<PageMobileNavigation className={'flex items-center justify-between'}> <PageMobileNavigation>
<AppLogo /> <AppLogo />
<div className={'flex space-x-4'}> <div className={'flex'}>
<TeamAccountLayoutMobileNavigation <TeamAccountLayoutMobileNavigation
userId={data.user.id} userId={data.user.id}
accounts={accounts} accounts={accounts}
@@ -94,6 +94,12 @@ function HeaderLayout({
}>) { }>) {
const data = use(loadTeamWorkspace(account)); const data = use(loadTeamWorkspace(account));
const accounts = data.accounts.map(({ name, slug, picture_url }) => ({
label: name,
value: slug,
image: picture_url,
}));
return ( return (
<TeamAccountWorkspaceContextProvider value={data}> <TeamAccountWorkspaceContextProvider value={data}>
<Page style={'header'}> <Page style={'header'}>
@@ -101,6 +107,20 @@ function HeaderLayout({
<TeamAccountNavigationMenu workspace={data} /> <TeamAccountNavigationMenu workspace={data} />
</PageNavigation> </PageNavigation>
<PageMobileNavigation className={'flex items-center justify-between'}>
<div>
<AppLogo />
</div>
<div>
<TeamAccountLayoutMobileNavigation
userId={data.user.id}
accounts={accounts}
account={account}
/>
</div>
</PageMobileNavigation>
{children} {children}
</Page> </Page>
</TeamAccountWorkspaceContextProvider> </TeamAccountWorkspaceContextProvider>

View File

@@ -0,0 +1,78 @@
'use client';
import Link from 'next/link';
import { LogOut } from 'lucide-react';
import { DropdownMenuItem, DropdownMenuSeparator } from '@kit/ui/dropdown-menu';
import { Trans } from '@kit/ui/trans';
export function MobileNavDropdownLink(
props: React.PropsWithChildren<{
path: string;
label: string;
Icon?: React.ReactNode;
}>,
) {
return (
<DropdownMenuItem
render={
<Link
href={props.path}
className={'flex h-12 w-full items-center space-x-4'}
>
{props.Icon}
<span>
<Trans i18nKey={props.label} defaults={props.label} />
</span>
</Link>
}
/>
);
}
export function MobileNavSignOutItem(props: { onSignOut: () => unknown }) {
return (
<DropdownMenuItem
className={'flex h-12 w-full items-center space-x-4'}
onClick={props.onSignOut}
>
<LogOut className={'h-5'} />
<span>
<Trans i18nKey={'auth.signOut'} defaults={'Sign out'} />
</span>
</DropdownMenuItem>
);
}
export function MobileNavRouteLinks(props: {
routes: Array<
| {
children: Array<{
path: string;
label: string;
Icon?: React.ReactNode;
}>;
}
| { divider: true }
>;
}) {
return props.routes.map((item, index) => {
if ('children' in item) {
return item.children.map((child) => (
<MobileNavDropdownLink
key={child.path}
Icon={child.Icon}
path={child.path}
label={child.label}
/>
));
}
if ('divider' in item) {
return <DropdownMenuSeparator key={index} />;
}
});
}

View File

@@ -1,6 +1,6 @@
{ {
"name": "next-supabase-saas-kit-turbo", "name": "next-supabase-saas-kit-turbo",
"version": "3.1.0", "version": "3.1.1",
"private": true, "private": true,
"author": { "author": {
"name": "MakerKit", "name": "MakerKit",

View File

@@ -4,9 +4,7 @@ const isHostedMode = process.env.STRIPE_UI_MODE === 'hosted_page';
export const StripeClientEnvSchema = z export const StripeClientEnvSchema = z
.object({ .object({
publishableKey: isHostedMode publishableKey: isHostedMode ? z.string().optional() : z.string().min(1),
? z.string().optional()
: z.string().min(1),
}) })
.refine( .refine(
(schema) => { (schema) => {

View File

@@ -1,19 +1,19 @@
import type { Stripe } from "stripe"; import type { Stripe } from 'stripe';
import * as z from "zod"; import * as z from 'zod';
import type { CreateBillingCheckoutSchema } from "@kit/billing/schema"; import type { CreateBillingCheckoutSchema } from '@kit/billing/schema';
/** /**
* @description If set to true, users can start a trial without entering their credit card details * @description If set to true, users can start a trial without entering their credit card details
*/ */
const enableTrialWithoutCreditCard = const enableTrialWithoutCreditCard =
process.env.STRIPE_ENABLE_TRIAL_WITHOUT_CC === "true"; process.env.STRIPE_ENABLE_TRIAL_WITHOUT_CC === 'true';
const UI_MODE_VALUES = ["embedded_page", "hosted_page"] as const; const UI_MODE_VALUES = ['embedded_page', 'hosted_page'] as const;
const uiMode = z const uiMode = z
.enum(UI_MODE_VALUES) .enum(UI_MODE_VALUES)
.default("embedded_page") .default('embedded_page')
.parse(process.env.STRIPE_UI_MODE); .parse(process.env.STRIPE_UI_MODE);
/** /**
@@ -37,9 +37,9 @@ export async function createStripeCheckout(
// docs: https://stripe.com/docs/billing/subscriptions/build-subscription // docs: https://stripe.com/docs/billing/subscriptions/build-subscription
const mode: Stripe.Checkout.SessionCreateParams.Mode = const mode: Stripe.Checkout.SessionCreateParams.Mode =
params.plan.paymentType === "recurring" ? "subscription" : "payment"; params.plan.paymentType === 'recurring' ? 'subscription' : 'payment';
const isSubscription = mode === "subscription"; const isSubscription = mode === 'subscription';
let trialDays: number | null | undefined = params.plan.trialDays; let trialDays: number | null | undefined = params.plan.trialDays;
@@ -53,7 +53,7 @@ export async function createStripeCheckout(
? { ? {
trial_settings: { trial_settings: {
end_behavior: { end_behavior: {
missing_payment_method: "cancel" as const, missing_payment_method: 'cancel' as const,
}, },
}, },
} }
@@ -89,10 +89,10 @@ export async function createStripeCheckout(
const customerCreation = const customerCreation =
isSubscription || customer isSubscription || customer
? ({} as Record<string, string>) ? ({} as Record<string, string>)
: { customer_creation: "always" }; : { customer_creation: 'always' };
const lineItems = params.plan.lineItems.map((item) => { const lineItems = params.plan.lineItems.map((item) => {
if (item.type === "metered") { if (item.type === 'metered') {
return { return {
price: item.id, price: item.id,
}; };
@@ -114,7 +114,7 @@ export async function createStripeCheckout(
const paymentCollectionMethod = const paymentCollectionMethod =
enableTrialWithoutCreditCard && params.plan.trialDays enableTrialWithoutCreditCard && params.plan.trialDays
? { ? {
payment_method_collection: "if_required" as const, payment_method_collection: 'if_required' as const,
} }
: {}; : {};
@@ -138,7 +138,7 @@ function getUrls(params: {
}) { }) {
const url = `${params.returnUrl}?session_id={CHECKOUT_SESSION_ID}`; const url = `${params.returnUrl}?session_id={CHECKOUT_SESSION_ID}`;
if (params.uiMode === "hosted_page") { if (params.uiMode === 'hosted_page') {
return { return {
success_url: url, success_url: url,
cancel_url: params.returnUrl, cancel_url: params.returnUrl,

View File

@@ -60,7 +60,7 @@ export function PageMobileNavigation(
return ( return (
<div <div
className={cn( className={cn(
'flex w-full items-center border-b px-4 py-2 lg:hidden lg:px-0', 'container flex w-full items-center justify-between px-0 py-2 group-data-[slot="sidebar-wrapper"]/sidebar-wrapper:border-b lg:hidden',
props.className, props.className,
)} )}
> >
@@ -73,30 +73,39 @@ function PageWithHeader(props: PageProps) {
const { Navigation, Children, MobileNavigation } = getSlotsFromPage(props); const { Navigation, Children, MobileNavigation } = getSlotsFromPage(props);
return ( return (
<div className={cn('flex h-screen flex-1 flex-col', props.className)}> <div
className={cn(
'bg-background flex min-h-screen flex-1 flex-col',
props.className,
)}
>
<div <div
className={ className={props.contentContainerClassName ?? 'flex flex-1 flex-col'}
props.contentContainerClassName ?? 'flex flex-1 flex-col space-y-4'
}
> >
<div <div
className={cn( className={cn(
'bg-muted/40 dark:border-border dark:shadow-primary/10 flex h-14 items-center justify-between px-4 lg:justify-start lg:shadow-xs', 'bg-background/95 supports-[backdrop-filter]:bg-background/80 border-b',
{ {
'sticky top-0 z-10 backdrop-blur-md': props.sticky ?? true, 'sticky top-0 z-10 backdrop-blur-md': props.sticky ?? true,
}, },
)} )}
> >
<div <div className="container mx-auto flex h-14 w-full items-center">
className={'hidden w-full flex-1 items-center space-x-8 lg:flex'} <div
> className={
{Navigation} 'hidden w-full min-w-0 flex-1 items-center space-x-4 lg:flex lg:px-4'
</div> }
>
{Navigation}
</div>
{MobileNavigation} {MobileNavigation}
</div>
</div> </div>
<div className={'container flex flex-1 flex-col'}>{Children}</div> <div className="container mx-auto flex w-full flex-1 flex-col">
{Children}
</div>
</div> </div>
</div> </div>
); );
@@ -113,7 +122,15 @@ export function PageBody(
} }
export function PageNavigation(props: React.PropsWithChildren) { export function PageNavigation(props: React.PropsWithChildren) {
return <div className={'bg-inherit'}>{props.children}</div>; return (
<div
className={
'flex flex-1 flex-col bg-inherit group-data-[slot="sidebar-wrapper"]/sidebar-wrapper:flex-initial'
}
>
{props.children}
</div>
);
} }
export function PageDescription(props: React.PropsWithChildren) { export function PageDescription(props: React.PropsWithChildren) {
@@ -147,16 +164,25 @@ export function PageHeader({
title, title,
description, description,
className, className,
displaySidebarTrigger = true,
}: React.PropsWithChildren<{ }: React.PropsWithChildren<{
className?: string; className?: string;
title?: string | React.ReactNode; title?: string | React.ReactNode;
description?: string | React.ReactNode; description?: string | React.ReactNode;
displaySidebarTrigger?: boolean;
}>) { }>) {
return ( return (
<div className={cn('flex items-center justify-between py-4', className)}> <div
<div className={'flex flex-col gap-y-2'}> className={cn(
<div className="flex items-center gap-x-2.5"> 'flex flex-col gap-4 py-4 sm:py-5 lg:flex-row lg:items-center lg:justify-between',
<SidebarTrigger className="text-muted-foreground hover:text-secondary-foreground h-4.5 w-4.5 cursor-pointer" /> className,
)}
>
<div className={'flex min-w-0 flex-col gap-y-2'}>
<div className="flex flex-wrap items-center gap-x-2.5 gap-y-1.5">
<If condition={displaySidebarTrigger}>
<SidebarTrigger className="text-muted-foreground hover:text-secondary-foreground h-4.5 w-4.5 cursor-pointer" />
</If>
<If condition={description}> <If condition={description}>
<Separator <Separator
@@ -173,7 +199,9 @@ export function PageHeader({
</If> </If>
</div> </div>
{children} <div className="flex w-full flex-wrap items-center gap-2 lg:w-auto lg:justify-end">
{children}
</div>
</div> </div>
); );
} }