Update UI elements and refine billing schema
Several changes were made to improve UI consistency across various components. Styling updates and enhancements were applied to elements including but not limited to, the SiteHeader, SiteNavigationItem, and ModeToggle components. Additionally, a refinement was made to the billing schema to enforce only having one per-seat and one flat line item per plan.
This commit is contained in:
@@ -63,26 +63,24 @@ function SuspendedPersonalAccountDropdown(props: { user: User | null }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function AuthButtons() {
|
function AuthButtons() {
|
||||||
|
const textClassName =
|
||||||
|
'text-gray-600 hover:text-current dark:text-gray-400 dark:hover:text-white';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={'flex space-x-2'}>
|
<div className={'flex space-x-2'}>
|
||||||
<div className={'hidden space-x-0.5 md:flex'}>
|
<div className={'hidden space-x-0.5 md:flex'}>
|
||||||
<ModeToggle />
|
<ModeToggle className={textClassName} />
|
||||||
|
|
||||||
<Link href={pathsConfig.auth.signIn}>
|
<Link href={pathsConfig.auth.signIn}>
|
||||||
<Button variant={'link'}>
|
<Button variant={'ghost'} className={textClassName}>
|
||||||
<Trans i18nKey={'auth:signIn'} />
|
<Trans i18nKey={'auth:signIn'} />
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Link href={pathsConfig.auth.signUp}>
|
<Link href={pathsConfig.auth.signUp}>
|
||||||
<Button
|
<Button variant={'default'}>
|
||||||
variant={'ghost'}
|
<Trans i18nKey={'auth:signUp'} />
|
||||||
className={
|
|
||||||
'border border-primary hover:bg-primary hover:text-primary-foreground'
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Trans i18nKey={'auth:getStarted'} />
|
|
||||||
<ChevronRight className={'h-4'} />
|
<ChevronRight className={'h-4'} />
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ export function SiteHeader(props: { user?: User | null }) {
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={
|
className={
|
||||||
'sticky top-0 z-10 w-full bg-background/80 shadow-sm backdrop-blur-md dark:bg-background/50 dark:shadow-primary/20'
|
'sticky top-0 z-10 w-full bg-background/80 shadow-sm backdrop-blur-md dark:bg-background/50 dark:shadow-primary/10'
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<div className={'px-4 lg:px-8'}>
|
<div className={'px-4 lg:px-8'}>
|
||||||
|
|||||||
@@ -10,9 +10,10 @@ const getClassName = (path: string, currentPathName: string) => {
|
|||||||
const isActive = isRouteActive(path, currentPathName);
|
const isActive = isRouteActive(path, currentPathName);
|
||||||
|
|
||||||
return cn(
|
return cn(
|
||||||
`text-sm font-medium px-2.5 py-2 border rounded-lg border-transparent transition-colors`,
|
`text-sm font-medium px-2.5 py-2 border rounded-lg border-transparent transition-colors duration-200`,
|
||||||
{
|
{
|
||||||
'hover:border-border': !isActive,
|
'hover:border-border active:dark:bg-secondary active:bg-gray-50 dark:text-gray-400 text-gray-600 hover:text-current dark:hover:text-white':
|
||||||
|
!isActive,
|
||||||
'dark:bg-secondary bg-gray-50': isActive,
|
'dark:bg-secondary bg-gray-50': isActive,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -80,7 +80,19 @@ export const PlanSchema = z
|
|||||||
})
|
})
|
||||||
.min(1),
|
.min(1),
|
||||||
interval: BillingIntervalSchema.optional(),
|
interval: BillingIntervalSchema.optional(),
|
||||||
lineItems: z.array(LineItemSchema),
|
lineItems: z.array(LineItemSchema).refine(
|
||||||
|
(schema) => {
|
||||||
|
const types = schema.map((item) => item.type);
|
||||||
|
const perSeat = types.filter((type) => type === 'per-seat').length;
|
||||||
|
const flat = types.filter((type) => type === 'flat').length;
|
||||||
|
|
||||||
|
return perSeat <= 1 && flat <= 1;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: 'Plans can only have one per-seat and one flat line item',
|
||||||
|
path: ['lineItems'],
|
||||||
|
},
|
||||||
|
),
|
||||||
trialDays: z
|
trialDays: z
|
||||||
.number({
|
.number({
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import { Trans } from './trans';
|
|||||||
|
|
||||||
const MODES = ['light', 'dark', 'system'];
|
const MODES = ['light', 'dark', 'system'];
|
||||||
|
|
||||||
export function ModeToggle() {
|
export function ModeToggle(props: { className?: string }) {
|
||||||
const { setTheme, theme } = useTheme();
|
const { setTheme, theme } = useTheme();
|
||||||
|
|
||||||
const Items = useMemo(() => {
|
const Items = useMemo(() => {
|
||||||
@@ -51,9 +51,9 @@ export function ModeToggle() {
|
|||||||
return (
|
return (
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger asChild>
|
<DropdownMenuTrigger asChild>
|
||||||
<Button variant="ghost" size="icon" className="rounded-full">
|
<Button variant="ghost" size="icon" className={props.className}>
|
||||||
<Sun className="h-[1rem] w-[1rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
|
<Sun className="h-[0.9rem] w-[0.9rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
|
||||||
<Moon className="absolute h-[1rem] w-[1rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
|
<Moon className="absolute h-[0.9rem] w-[0.9rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
|
||||||
<span className="sr-only">Toggle theme</span>
|
<span className="sr-only">Toggle theme</span>
|
||||||
</Button>
|
</Button>
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
|
|||||||
Reference in New Issue
Block a user