Skip to content
Merged

Test #1527

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
13 changes: 1 addition & 12 deletions components/Icon/resolver.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -225,18 +225,7 @@ export const Icons = {
</svg>
),
robot: () => (
<svg
width="21"
height="19"
viewBox="0 0 21 19"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M10.5 0C11.0063 0 11.4919 0.200178 11.8499 0.556497C12.208 0.912816 12.4091 1.39609 12.4091 1.9C12.4091 2.603 12.0273 3.2205 11.4545 3.5435V4.75H12.4091C14.1812 4.75 15.8808 5.45062 17.1339 6.69774C18.3869 7.94486 19.0909 9.63631 19.0909 11.4H20.0455C20.2986 11.4 20.5414 11.5001 20.7204 11.6782C20.8994 11.8564 21 12.098 21 12.35V15.2C21 15.452 20.8994 15.6936 20.7204 15.8718C20.5414 16.0499 20.2986 16.15 20.0455 16.15H19.0909V17.1C19.0909 17.6039 18.8898 18.0872 18.5317 18.4435C18.1737 18.7998 17.6881 19 17.1818 19H3.81818C3.31186 19 2.82627 18.7998 2.46825 18.4435C2.11023 18.0872 1.90909 17.6039 1.90909 17.1V16.15H0.954545C0.701384 16.15 0.458592 16.0499 0.27958 15.8718C0.100568 15.6936 0 15.452 0 15.2V12.35C0 12.098 0.100568 11.8564 0.27958 11.6782C0.458592 11.5001 0.701384 11.4 0.954545 11.4H1.90909C1.90909 9.63631 2.61307 7.94486 3.86615 6.69774C5.11923 5.45062 6.81878 4.75 8.59091 4.75H9.54545V3.5435C8.97273 3.2205 8.59091 2.603 8.59091 1.9C8.59091 1.39609 8.79204 0.912816 9.15007 0.556497C9.50809 0.200178 9.99368 0 10.5 0ZM6.20455 10.45C5.57164 10.45 4.96466 10.7002 4.51713 11.1456C4.0696 11.591 3.81818 12.1951 3.81818 12.825C3.81818 13.4549 4.0696 14.059 4.51713 14.5044C4.96466 14.9498 5.57164 15.2 6.20455 15.2C6.83745 15.2 7.44443 14.9498 7.89196 14.5044C8.33949 14.059 8.59091 13.4549 8.59091 12.825C8.59091 12.1951 8.33949 11.591 7.89196 11.1456C7.44443 10.7002 6.83745 10.45 6.20455 10.45ZM14.7955 10.45C14.1626 10.45 13.5556 10.7002 13.108 11.1456C12.6605 11.591 12.4091 12.1951 12.4091 12.825C12.4091 13.4549 12.6605 14.059 13.108 14.5044C13.5556 14.9498 14.1626 15.2 14.7955 15.2C15.4284 15.2 16.0353 14.9498 16.4829 14.5044C16.9304 14.059 17.1818 13.4549 17.1818 12.825C17.1818 12.1951 16.9304 11.591 16.4829 11.1456C16.0353 10.7002 15.4284 10.45 14.7955 10.45Z"
fill="currentColor"
/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><rect width="18" height="10" x="3" y="11" rx="2"/><circle cx="12" cy="5" r="2"/><path d="M12 7v4"/><line x1="8" x2="8" y1="16" y2="16"/><line x1="16" x2="16" y1="16" y2="16"/></svg>
),
micval: () => (
<svg
Expand Down
29 changes: 23 additions & 6 deletions components/Logo/Logo.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,33 @@
import Image from "next/image";
import { cn } from "@/lib/utils";

const Logo = () => {
const Logo = ({ isExpanded = false }: { isExpanded?: boolean }) => {
return (
<div className="relative flex items-center">
<div className="flex items-center gap-0">
{/* Icon — always visible, never moves */}
<Image
src="/brand-logos/recoup-v2.png"
src="/brand/icon-lightmode.svg"
alt="Recoup Logo"
width={260}
height={260}
width={223}
height={223}
priority
className="w-7 h-7 rounded-lg"
className="w-7 h-7 shrink-0 dark:hidden"
/>
<Image
src="/brand/icon-darkmode.svg"
alt="Recoup Logo"
width={223}
height={223}
priority
className="w-7 h-7 shrink-0 hidden dark:block"
/>
{/* Brand name — fades in/out alongside sidebar */}
<span className={cn(
"font-semibold text-base text-foreground whitespace-nowrap overflow-hidden transition-all duration-200 font-heading",
isExpanded ? "opacity-100 max-w-[150px] ml-2" : "opacity-0 max-w-0 ml-0"
)}>
Recoupable
</span>
</div>
);
};
Expand Down
3 changes: 3 additions & 0 deletions components/Sidebar/AgentsNavItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ import NavButton from "./NavButton";

const AgentsNavItem = ({
isActive,
isExpanded,
onClick,
}: {
isActive: boolean;
isExpanded?: boolean;
onClick: () => void;
}) => {
const { prefetchAgents } = useAgentData();
Expand All @@ -15,6 +17,7 @@ const AgentsNavItem = ({
icon="robot"
label="Agents"
isActive={isActive}
isExpanded={isExpanded}
onClick={onClick}
aria-label="View agents"
onHover={prefetchAgents}
Expand Down
3 changes: 3 additions & 0 deletions components/Sidebar/FanGroupNavItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ import NavButton from "./NavButton";

const FanGroupNavItem = ({
isActive,
isExpanded,
onClick,
}: {
isActive: boolean;
isExpanded?: boolean;
onClick: () => void;
}) => {
const { selectedArtist } = useArtistProvider();
Expand All @@ -19,6 +21,7 @@ const FanGroupNavItem = ({
icon="segments"
label="Fans"
isActive={isActive}
isExpanded={isExpanded}
onClick={onClick}
shouldRender={shouldRender}
/>
Expand Down
3 changes: 3 additions & 0 deletions components/Sidebar/FilesNavItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,19 @@ import NavButton from "./NavButton";

const FilesNavItem = ({
isActive,
isExpanded,
onClick,
}: {
isActive: boolean;
isExpanded?: boolean;
onClick: () => void;
}) => {
return (
<NavButton
icon="files"
label="Files"
isActive={isActive}
isExpanded={isExpanded}
onClick={onClick}
aria-label="View files"
/>
Expand Down
106 changes: 69 additions & 37 deletions components/Sidebar/Menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { usePathname, useRouter } from "next/navigation";
import Link from "next/link";
import { useUserProvider } from "@/providers/UserProvder";
import RecentChats from "../Sidebar/RecentChats";
import UnlockPro from "./UnlockPro";
import UserInfo from "../Sidebar/UserInfo";
import Logo from "../Logo";
import { v4 as uuidV4 } from "uuid";
Expand All @@ -13,8 +12,11 @@ import { RecentChatsSectionSkeleton } from "./RecentChatsSectionSkeleton";
import TasksNavItem from "./TasksNavItem";
import FilesNavItem from "./FilesNavItem";
import { useEffect } from "react";
import { cn } from "@/lib/utils";
import { AnimatePresence, motion } from "framer-motion";
import { SquarePen } from "lucide-react";

const Menu = ({ toggleMenuExpanded }: { toggleMenuExpanded: () => void }) => {
const Menu = ({ isExpanded }: { isExpanded: boolean }) => {
const { push, prefetch } = useRouter();
const pathname = usePathname();
const { email, isPrepared } = useUserProvider();
Expand All @@ -35,54 +37,84 @@ const Menu = ({ toggleMenuExpanded }: { toggleMenuExpanded: () => void }) => {
}, [prefetch]);

return (
<div className="w-full h-screen pt-4 pb-2 px-2.5 hidden md:flex flex-col">
<div className="w-full h-screen pt-3 pb-2 px-2 hidden md:flex flex-col">
{/* Logo */}
<Link
href="/"
className="shrink-0 mb-0 hover:opacity-80 transition-opacity duration-200 w-fit"
className={cn(
"shrink-0 hover:opacity-80 transition-all duration-200",
isExpanded ? "pl-[7px]" : "self-center"
)}
aria-label="Home"
>
<Logo />
<Logo isExpanded={isExpanded} />
</Link>

{/* Navigation Section */}
<div className="flex flex-col gap-3 w-full mt-2">
<Button
variant="outline"
className="rounded-xl w-full"
<div className="flex flex-col gap-0.5 w-full mt-2">
<button
type="button"
className={cn(
"inline-flex items-center h-8 rounded-lg whitespace-nowrap overflow-hidden transition-all duration-200 text-sm font-normal text-foreground hover:bg-muted",
isExpanded ? "w-full justify-start gap-2 px-3" : "w-8 justify-center mx-auto gap-0"
)}
onClick={() => goToItem("chat")}
aria-label={email ? "New Chat" : "Sign In"}
>
{email ? "New Chat" : "Sign In"}
</Button>

<div className="flex flex-col gap-1">
<AgentsNavItem
isActive={isAgents}
onClick={() => goToItem("agents")}
/>
<TasksNavItem isActive={isTasks} onClick={() => goToItem("tasks")} />
<FanGroupNavItem
isActive={isSegments}
onClick={() => goToItem("segments")}
/>
<FilesNavItem isActive={isFiles} onClick={() => goToItem("files")} />
</div>
<div className="w-[21px] flex justify-center items-center shrink-0">
<SquarePen className="size-4" />
</div>
<span className={cn(
"overflow-hidden transition-all duration-200",
isExpanded ? "opacity-100 max-w-[150px]" : "opacity-0 max-w-0"
)}>
{email ? "New Chat" : "Sign In"}
</span>
</button>
<AgentsNavItem
isActive={isAgents}
isExpanded={isExpanded}
onClick={() => goToItem("agents")}
/>
<TasksNavItem
isActive={isTasks}
isExpanded={isExpanded}
onClick={() => goToItem("tasks")}
/>
<FanGroupNavItem
isActive={isSegments}
isExpanded={isExpanded}
onClick={() => goToItem("segments")}
/>
<FilesNavItem
isActive={isFiles}
isExpanded={isExpanded}
onClick={() => goToItem("files")}
/>
</div>

{/* Recent Chats Section */}
<div className="flex flex-col flex-grow min-h-0">
{!email ? (
<RecentChatsSectionSkeleton />
) : (
<RecentChats toggleModal={toggleMenuExpanded} />
{/* Recent Chats & Unlock Pro — smoothly fade in/out */}
<AnimatePresence>
{isExpanded && (
<motion.div
className="flex flex-col flex-grow min-h-0 overflow-hidden"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.15, exit: { duration: 0.05 } }}
>
{!email ? (
<RecentChatsSectionSkeleton />
) : (
<RecentChats toggleModal={() => {}} />
)}
</motion.div>
)}
</AnimatePresence>

{/* Bottom Section */}
<div className="shrink-0 border-t border-border mx-auto space-y-2">
<UnlockPro />
<div className="w-full px-2">
<UserInfo />
</div>
</div>
{/* User Profile — always visible (avatar shows when collapsed) */}
<div className="shrink-0 mt-auto px-0.5 pb-1">
<UserInfo isExpanded={isExpanded} />
</div>
</div>
);
Expand Down
28 changes: 22 additions & 6 deletions components/Sidebar/NavButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ interface NavButtonProps {
icon: IconsType;
label: string;
isActive: boolean;
isExpanded?: boolean;
onClick: () => void;
shouldRender?: boolean;
"aria-label"?: string;
Expand All @@ -17,6 +18,7 @@ const NavButton = ({
icon,
label,
isActive,
isExpanded = true,
onClick,
shouldRender = true,
"aria-label": ariaLabel,
Expand All @@ -29,16 +31,30 @@ const NavButton = ({
return (
<Button
variant="ghost"
size={isExpanded ? "sm" : "icon"}
onClick={onClick}
onMouseEnter={onHover}
className={cn("rounded-xl w-full flex justify-start", {
"bg-muted text-foreground ring-1 ring-border hover:bg-muted": isActive,
"text-foreground hover:bg-muted hover:ring-1 hover:ring-border": !isActive,
})}
aria-label={ariaLabel}
className={cn(
"rounded-lg whitespace-nowrap overflow-hidden transition-all duration-200 h-8 relative text-sm font-normal",
isExpanded ? "w-full flex justify-start gap-2 px-3" : "w-8 mx-auto gap-0",
{
"bg-muted text-foreground hover:bg-muted": isActive,
"text-foreground hover:bg-muted": !isActive,
}
)}
aria-label={ariaLabel || label}
>
{/* Active page accent bar */}
{isActive && isExpanded && (
<div className="absolute left-0 top-1.5 bottom-1.5 w-[3px] rounded-r-full bg-[#345A5D]" />
)}
<MenuItemIcon name={icon} />
{label}
<span className={cn(
"overflow-hidden transition-all duration-200",
isExpanded ? "opacity-100 max-w-[150px]" : "opacity-0 max-w-0"
)}>
{label}
</span>
</Button>
);
};
Expand Down
2 changes: 1 addition & 1 deletion components/Sidebar/RecentChats/ChatItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ const ChatItem = ({

return (
<div
className={`flex gap-2 items-center w-full py-1.5 px-2 rounded-xl transition-all duration-150 relative ${
className={`flex gap-1.5 items-center w-full py-[6px] px-3 rounded-lg transition-all duration-150 relative ${
isSelected
? "bg-primary/20 dark:bg-primary/30 border border-primary/30 dark:border-primary/40"
: isActive
Expand Down
28 changes: 14 additions & 14 deletions components/Sidebar/RecentChats/RecentChats.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,20 +40,20 @@ const RecentChats = ({ toggleModal }: { toggleModal: () => void }) => {

return (
<div className="w-full flex-grow min-h-0 flex flex-col">
<div className="h-[1px] bg-border w-full mt-1 mb-2 md:mt-2 md:mb-3 shrink-0" />

{isSelectionMode ? (
<SelectionModeHeader
selectedCount={selectedChatIds.size}
onCancel={clearSelection}
onDelete={handleBulkDelete}
/>
) : (
<p className="text-xs font-medium text-muted-foreground px-2 shrink-0 mb-2">
Recent Chats
</p>
)}
<div className="overflow-y-auto space-y-1 flex-grow">
<div className="mt-3 mb-1 shrink-0">
{isSelectionMode ? (
<SelectionModeHeader
selectedCount={selectedChatIds.size}
onCancel={clearSelection}
onDelete={handleBulkDelete}
/>
) : (
<p className="text-xs text-muted-foreground px-3">
Chats
</p>
)}
</div>
<div className="overflow-y-auto flex-grow">
{showSkeleton ? (
<RecentChatSkeleton />
) : (
Expand Down
2 changes: 1 addition & 1 deletion components/Sidebar/RecoupablePro.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const RecoupablePro = () => {
return (
<div className="font-sans font-medium text-xs rounded-xl w-full bg-muted text-foreground px-4 py-2.5 text-center border border-border">
<div className="font-sans font-medium text-xs rounded-xl w-full bg-muted text-foreground px-4 py-2.5 text-center border border-border whitespace-nowrap overflow-hidden">
Recoupable Pro: Active
</div>
);
Expand Down
Loading