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

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

View File

@@ -1,19 +1,19 @@
import type { Stripe } from "stripe";
import * as z from "zod";
import type { Stripe } from 'stripe';
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
*/
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
.enum(UI_MODE_VALUES)
.default("embedded_page")
.default('embedded_page')
.parse(process.env.STRIPE_UI_MODE);
/**
@@ -37,9 +37,9 @@ export async function createStripeCheckout(
// docs: https://stripe.com/docs/billing/subscriptions/build-subscription
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;
@@ -53,7 +53,7 @@ export async function createStripeCheckout(
? {
trial_settings: {
end_behavior: {
missing_payment_method: "cancel" as const,
missing_payment_method: 'cancel' as const,
},
},
}
@@ -89,10 +89,10 @@ export async function createStripeCheckout(
const customerCreation =
isSubscription || customer
? ({} as Record<string, string>)
: { customer_creation: "always" };
: { customer_creation: 'always' };
const lineItems = params.plan.lineItems.map((item) => {
if (item.type === "metered") {
if (item.type === 'metered') {
return {
price: item.id,
};
@@ -114,7 +114,7 @@ export async function createStripeCheckout(
const paymentCollectionMethod =
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}`;
if (params.uiMode === "hosted_page") {
if (params.uiMode === 'hosted_page') {
return {
success_url: url,
cancel_url: params.returnUrl,

View File

@@ -60,7 +60,7 @@ export function PageMobileNavigation(
return (
<div
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,
)}
>
@@ -73,30 +73,39 @@ function PageWithHeader(props: PageProps) {
const { Navigation, Children, MobileNavigation } = getSlotsFromPage(props);
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
className={
props.contentContainerClassName ?? 'flex flex-1 flex-col space-y-4'
}
className={props.contentContainerClassName ?? 'flex flex-1 flex-col'}
>
<div
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,
},
)}
>
<div
className={'hidden w-full flex-1 items-center space-x-8 lg:flex'}
>
{Navigation}
</div>
<div className="container mx-auto flex h-14 w-full items-center">
<div
className={
'hidden w-full min-w-0 flex-1 items-center space-x-4 lg:flex lg:px-4'
}
>
{Navigation}
</div>
{MobileNavigation}
{MobileNavigation}
</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>
);
@@ -113,7 +122,15 @@ export function PageBody(
}
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) {
@@ -147,16 +164,25 @@ export function PageHeader({
title,
description,
className,
displaySidebarTrigger = true,
}: React.PropsWithChildren<{
className?: string;
title?: string | React.ReactNode;
description?: string | React.ReactNode;
displaySidebarTrigger?: boolean;
}>) {
return (
<div className={cn('flex items-center justify-between py-4', className)}>
<div className={'flex flex-col gap-y-2'}>
<div className="flex items-center gap-x-2.5">
<SidebarTrigger className="text-muted-foreground hover:text-secondary-foreground h-4.5 w-4.5 cursor-pointer" />
<div
className={cn(
'flex flex-col gap-4 py-4 sm:py-5 lg:flex-row lg:items-center lg:justify-between',
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}>
<Separator
@@ -173,7 +199,9 @@ export function PageHeader({
</If>
</div>
{children}
<div className="flex w-full flex-wrap items-center gap-2 lg:w-auto lg:justify-end">
{children}
</div>
</div>
);
}