mirror of
https://github.com/documenso/documenso.git
synced 2026-07-24 00:43:40 +10:00
c07eeba178
Consolidate the personal, team and organisation settings surfaces behind a single system so every page shares one width, one navigation implementation and one copy standard. - add shared SettingsNav (aria-current active state, exact matching for the team General route, non-interactive section labels) and delete the four divergent nav implementations it replaces - constrain the settings content column to max-w-3xl in all three layouts and strip the per-page max-w-2xl/max-w-xl wrappers so forms and tables render identically - rewrite SettingsHeader subtitles to remove "Here you can" / "On this page" filler, normalize title casing and punctuation, and translate the hardcoded team general header - align the billing header with SettingsHeader typography and drop redundant fieldset width constraints in the document/email preference forms - fix the wrong team group success toast, team email meta title, misnamed page exports, untranslated Manage label and Create Team casing mismatch - update manage-organisation e2e assertions for the corrected copy
63 lines
1.8 KiB
TypeScript
63 lines
1.8 KiB
TypeScript
import { cn } from '@documenso/ui/lib/utils';
|
|
import { Button } from '@documenso/ui/primitives/button';
|
|
import type { LucideIcon } from 'lucide-react';
|
|
import { NavLink } from 'react-router';
|
|
|
|
export type SettingsNavRoute = {
|
|
path: string;
|
|
label: string;
|
|
icon?: LucideIcon;
|
|
/**
|
|
* Renders the route as a non-interactive group label, only visible on desktop.
|
|
*/
|
|
isSectionLabel?: boolean;
|
|
/**
|
|
* Indents the route under the preceding section label on desktop.
|
|
*/
|
|
isSubNav?: boolean;
|
|
/**
|
|
* Only mark the route as active on an exact path match.
|
|
*/
|
|
end?: boolean;
|
|
};
|
|
|
|
export type SettingsNavProps = {
|
|
routes: SettingsNavRoute[];
|
|
className?: string;
|
|
};
|
|
|
|
export const SettingsNav = ({ routes, className }: SettingsNavProps) => {
|
|
return (
|
|
<nav
|
|
className={cn(
|
|
'flex flex-wrap items-center justify-start gap-x-2 gap-y-4 md:w-full md:flex-col md:items-start md:gap-y-2',
|
|
className,
|
|
)}
|
|
>
|
|
{routes.map((route) =>
|
|
route.isSectionLabel ? (
|
|
<div
|
|
key={`${route.path}-${route.label}`}
|
|
className="flex h-10 w-full items-center px-4 font-medium text-sm max-md:hidden"
|
|
>
|
|
{route.icon && <route.icon className="mr-2 h-5 w-5" />}
|
|
{route.label}
|
|
</div>
|
|
) : (
|
|
<NavLink
|
|
key={`${route.path}-${route.label}`}
|
|
to={route.path}
|
|
end={route.end}
|
|
className={cn('group justify-start md:w-full', route.isSubNav && 'md:pl-8')}
|
|
>
|
|
<Button variant="ghost" className="w-full justify-start group-aria-[current]:bg-secondary">
|
|
{route.icon && <route.icon className="mr-2 h-5 w-5" />}
|
|
{route.label}
|
|
</Button>
|
|
</NavLink>
|
|
),
|
|
)}
|
|
</nav>
|
|
);
|
|
};
|