Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/mail/components/golden.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ export const GoldenTicketModal = () => {
<Dialog open={isOpen} onOpenChange={setIsOpen}>
<DialogTrigger asChild>
<SidebarMenuButton tooltip={'Invite a friend'}>
<Ticket className="relative mr-2.5 h-3 w-3.5" />
<Ticket className="relative mr-2 h-3 w-3.5" />
<p className="mt-0.5 truncate text-[13px]">Invite a friend</p>
</SidebarMenuButton>
</DialogTrigger>
Expand Down
8 changes: 4 additions & 4 deletions apps/mail/components/mail/mail-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ const Draft = memo(({ message }: { message: { id: string } }) => {
'text-md flex items-baseline gap-1 group-hover:opacity-100',
)}
>
<span className={cn('max-w-[20ch] truncate text-sm')}>
<span className={cn('max-w-[25ch] truncate text-sm')}>
{cleanNameDisplay(draft?.to?.[0] || 'noname') || ''}
</span>
</span>
Expand All @@ -144,7 +144,7 @@ const Draft = memo(({ message }: { message: { id: string } }) => {
<div className="flex justify-between">
<p
className={cn(
'mt-1 line-clamp-1 max-w-[50ch] text-sm text-[#8C8C8C] md:max-w-[25ch]',
'mt-1 line-clamp-1 max-w-[50ch] text-sm text-[#8C8C8C] md:max-w-[30ch]',
)}
>
{draft?.subject}
Expand Down Expand Up @@ -608,7 +608,7 @@ const Thread = memo(
{isFolderSent ? (
<span>{highlightText(latestMessage.subject, searchValue.highlight)}</span>
) : (
<span className={cn('max-w-[18ch] truncate text-sm')}>
<span className={cn('truncate text-sm md:max-w-[15ch] xl:max-w-[25ch]')}>
{highlightText(
cleanNameDisplay(latestMessage.sender.name) || '',
searchValue.highlight,
Expand Down Expand Up @@ -657,7 +657,7 @@ const Thread = memo(
) : (
<p
className={cn(
'mt-1 line-clamp-1 max-w-[50ch] text-sm text-[#8C8C8C] md:max-w-[25ch]',
'mt-1 line-clamp-1 max-w-[50ch] text-sm text-[#8C8C8C] md:max-w-[40ch]',
)}
>
{highlightText(latestMessage.subject, searchValue.highlight)}
Expand Down
85 changes: 54 additions & 31 deletions apps/mail/components/mail/mail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ export function MailLayout() {
threadId ? 'md:hidden lg:block' : '',
)}
>
<div className="bg-panelLight dark:bg-panelDark h-screen flex-1 flex-col overflow-y-auto overflow-x-hidden border-[#E7E7E7] shadow-inner md:flex md:h-[calc(100dvh-0.5rem)] md:rounded-2xl md:border md:shadow-sm lg:w-screen lg:max-w-[415px] dark:border-[#252525]">
<div className="bg-panelLight dark:bg-panelDark h-screen flex-1 flex-col overflow-y-auto overflow-x-hidden border-[#E7E7E7] shadow-inner md:flex md:h-[calc(100dvh-0.5rem)] md:rounded-2xl md:border md:shadow-sm lg:w-screen lg:max-w-[415px] xl:max-w-[500px] dark:border-[#252525]">
<div
className={cn(
'sticky top-0 z-[15] flex items-center justify-between gap-1.5 border-b border-[#E7E7E7] p-2 px-[20px] transition-colors md:min-h-14 dark:border-[#252525]',
Expand Down Expand Up @@ -506,8 +506,7 @@ export const Categories = () => {
icon: (
<Lightning
className={cn(
'fill-[#6D6D6D] dark:fill-[#989898]',
category === 'Important' && 'fill-white dark:fill-white',
'fill-white dark:fill-white',
)}
/>
),
Expand All @@ -519,8 +518,7 @@ export const Categories = () => {
icon: (
<Mail
className={cn(
'fill-[#6D6D6D] dark:fill-[#989898]',
category === 'All Mail' && 'fill-white dark:fill-white',
'fill-white dark:fill-white',
)}
/>
),
Expand All @@ -534,8 +532,7 @@ export const Categories = () => {
icon: (
<User
className={cn(
'fill-[#6D6D6D] dark:fill-[#989898]',
category === 'Personal' && 'fill-white dark:fill-white',
'fill-white dark:fill-white',
)}
/>
),
Expand All @@ -547,8 +544,7 @@ export const Categories = () => {
icon: (
<Bell
className={cn(
'fill-[#6D6D6D] dark:fill-[#989898]',
category === 'Updates' && 'fill-white dark:fill-white',
'fill-white dark:fill-white',
)}
/>
),
Expand All @@ -560,8 +556,7 @@ export const Categories = () => {
icon: (
<Tag
className={cn(
'fill-[#6D6D6D] dark:fill-[#989898]',
category === 'Promotions' && 'fill-white dark:fill-white',
'fill-white dark:fill-white',
)}
/>
),
Expand All @@ -573,8 +568,7 @@ export const Categories = () => {
icon: (
<ScanEye
className={cn(
'h-4 w-4 fill-[#6D6D6D] dark:fill-[#989898]',
category === 'Unread' && 'fill-white dark:fill-white',
'h-4 w-4 fill-white dark:fill-white',
)}
/>
),
Expand All @@ -599,7 +593,7 @@ function getCategoryColor(categoryId: string): string {
case 'updates':
return 'bg-[#8B5CF6]';
case 'unread':
return 'bg-[#006FFE]';
return 'bg-[#FF4800]';
default:
return 'bg-base-primary-500';
}
Expand All @@ -624,14 +618,13 @@ function CategorySelect({ isMultiSelectMode }: { isMultiSelectMode: boolean }) {
const primaryCategory = categories[0];
if (!primaryCategory) return null;

const renderCategoryButton = (cat: CategoryType, isOverlay = false) => {
const renderCategoryButton = (cat: CategoryType, isOverlay = false, idx?: number) => {
const isSelected = cat.id === (category || 'Primary');
const bgColor = getCategoryColor(cat.id);

return (
return isSelected ? (
<button
key={cat.id}
ref={isSelected && !isOverlay ? activeTabElementRef : null}
ref={!isOverlay ? activeTabElementRef : null}
onClick={() => {
setCategory(cat.id);
setSearchValue({
Expand All @@ -642,21 +635,47 @@ function CategorySelect({ isMultiSelectMode }: { isMultiSelectMode: boolean }) {
}}
className={cn(
'flex h-8 items-center justify-center gap-1 overflow-hidden rounded-md border transition-all duration-300 ease-out dark:border-none',
isSelected
? cn('flex-1 border-none px-3 text-white', bgColor)
: 'w-8 bg-white hover:bg-gray-100 dark:bg-[#313131] dark:hover:bg-[#313131]/80',
'flex-1 border-none px-3 text-white',
bgColor,
idx === 0 && 'ml-2',
)}
tabIndex={isOverlay ? -1 : undefined}
>
<div className="relative overflow-visible">{cat.icon}</div>
{isSelected && (
<div className="flex items-center justify-center gap-2.5 px-0.5">
<div className="animate-in fade-in-0 slide-in-from-right-4 justify-start text-sm leading-none text-white duration-300">
{cat.name}
</div>
<div className="flex items-center justify-center gap-2.5 px-0.5">
<div className="animate-in fade-in-0 slide-in-from-right-4 justify-start text-sm leading-none text-white duration-300">
{cat.name}
</div>
)}
</div>
</button>
) : (
<Tooltip key={cat.id}>
<TooltipTrigger asChild>
<button
ref={null}
onClick={() => {
setCategory(cat.id);
setSearchValue({
value: cat.searchValue || '',
highlight: searchValue.highlight,
folder: '',
});
}}
className={cn(
'flex h-8 items-center justify-center gap-1 overflow-hidden rounded-md border transition-all duration-300 ease-out dark:border-none',
'w-8',
bgColor,
idx === 0 && 'ml-2',
)}
tabIndex={isOverlay ? -1 : undefined}
>
<div className="relative overflow-visible">{cat.icon}</div>
</button>
</TooltipTrigger>
<TooltipContent side={idx === 0 ? 'top' : undefined} align={idx === 0 ? 'top' : undefined} sideOffset={idx === 0 ? 4 : undefined}>
<span>{cat.name}</span>
</TooltipContent>
</Tooltip>
);
};

Expand Down Expand Up @@ -685,7 +704,7 @@ function CategorySelect({ isMultiSelectMode }: { isMultiSelectMode: boolean }) {
return (
<div className="relative w-full">
<div className="flex w-full items-start justify-start gap-2">
{categories.map((cat) => renderCategoryButton(cat))}
{categories.map((cat, idx) => renderCategoryButton(cat, false, idx))}
</div>

<div
Expand All @@ -694,7 +713,7 @@ function CategorySelect({ isMultiSelectMode }: { isMultiSelectMode: boolean }) {
ref={containerRef}
>
<div className="flex w-full items-start justify-start gap-2">
{categories.map((cat) => renderCategoryButton(cat, true))}
{categories.map((cat, idx) => renderCategoryButton(cat, true, idx))}
</div>
</div>
</div>
Expand Down Expand Up @@ -814,7 +833,9 @@ function MailCategoryTabs({
: 'text-muted-foreground hover:text-foreground hover:bg-muted/50',
)}
>
{category.icon}
<div className="relative overflow-visible">
{category.icon}
</div>
<span className={cn('hidden', !iconsOnly && 'md:inline')}>{category.name}</span>
</button>
</TooltipTrigger>
Expand Down Expand Up @@ -844,7 +865,9 @@ function MailCategoryTabs({
className={cn('flex items-center gap-1.5 rounded-full px-2 text-xs font-medium')}
tabIndex={-1}
>
<p>{category.icon}</p>
<div className="relative overflow-visible">
{category.icon}
</div>
<span className={cn('hidden', !iconsOnly && 'md:inline')}>{category.name}</span>
</button>
</li>
Expand Down
2 changes: 1 addition & 1 deletion apps/mail/components/ui/app-sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ export function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {
className={`mt-auto flex w-full flex-col ${state !== 'collapsed' ? 'px-0 md:px-2' : ''}`}
>
<SidebarContent className="py-0 pt-0">
<div className="px-2">
<div className="sm:px-2">
<GoldenTicketModal />
</div>

Expand Down
43 changes: 17 additions & 26 deletions apps/mail/components/ui/nav-main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -129,25 +129,25 @@ export function NavMain({ items }: NavMainProps) {
const currentFrom = searchParams.get('from');

// Handle settings navigation
// if (item.isSettingsButton) {
// Include current path with category query parameter if present
// const currentPath = category
// ? `${pathname}?category=${encodeURIComponent(category)}`
// : pathname;
// return `${item.url}?from=${encodeURIComponent(currentPath)}`;
// }
if (item.isSettingsButton) {
// Include current path with category query parameter if present
const currentPath = category
? `${pathname}?category=${encodeURIComponent(category)}`
: pathname;
return `${item.url}?from=${encodeURIComponent(currentPath)}`;
}

// Handle back button with redirect protection
// if (item.isBackButton) {
// if (currentFrom) {
// const decodedFrom = decodeURIComponent(currentFrom);
// if (isValidInternalUrl(decodedFrom)) {
// return decodedFrom;
// }
// }
// // Fall back to safe default if URL is missing or invalid
// return '/mail';
// }
if (item.isBackButton) {
if (currentFrom) {
const decodedFrom = decodeURIComponent(currentFrom);
if (isValidInternalUrl(decodedFrom)) {
return decodedFrom;
}
}
// Fall back to safe default if URL is missing or invalid
return '/mail';
}

// Handle settings pages navigation
if (item.isSettingsPage && currentFrom) {
Expand Down Expand Up @@ -504,15 +504,6 @@ function NavItem(item: NavItemProps & { href: string }) {
</SidebarMenuButton>
);

if (item.isBackButton) {
return (
// TODO: Fix back link to go back a step not to /mail/inbox
<Link {...linkProps} href="/mail/inbox">
{buttonContent}
</Link>
);
}

return (
<Collapsible defaultOpen={item.isActive}>
<CollapsibleTrigger asChild>
Expand Down
1 change: 1 addition & 0 deletions apps/mail/config/navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ export const bottomNavItems = [
title: 'navigation.sidebar.settings',
url: '/settings/general',
icon: SettingsGear,
isSettingsButton: true,
},
],
},
Expand Down
2 changes: 0 additions & 2 deletions apps/mail/locales/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
"signedOutSuccess": "Sesión cerrada correctamente",
"signOutError": "Error al cerrar sesión",
"refresh": "Actualizar",
"loading": "Loading...",
"featureNotImplemented": "Esta función aún no está implementada",
"moving": "Moviendo...",
"movedToInbox": "Movido a la bandeja de entrada",
Expand Down Expand Up @@ -116,7 +115,6 @@
},
"mailCategories": {
"primary": "Principal",
"allMail": "All Mail",
"important": "Importante",
"personal": "Personal",
"updates": "Actualizaciones",
Expand Down