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 client/components/app-sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ export function AppSidebar() {
<p className="text-sm font-medium text-[#E8E8E8] truncate">John Doe</p>
<p className="text-xs text-[#888888] truncate">client@apax.institutional</p>
</div>
<button className="p-1.5 rounded-md hover:bg-[#1A1A1A] text-[#888888] hover:text-[#E8E8E8] transition-colors">
<button className="p-1.5 rounded-md hover:bg-[#1A1A1A] text-[#888888] hover:text-[#E8E8E8] transition-colors" title='sign-out'>
<SignOut className="h-4 w-4" />
</button>
</div>
Expand Down
21 changes: 15 additions & 6 deletions client/components/dashboard-layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,19 @@ import { Bell, Search } from 'lucide-react'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { useAPAXStore } from '@/lib/store'
import { AnimatePresence } from "framer-motion"
import { MotionWrapper } from "@/components/shared/MotionWrapper"
import { usePathname } from "next/navigation"

interface DashboardLayoutProps {
children: React.ReactNode
}

export function DashboardLayout({ children }: DashboardLayoutProps) {
const { metalPrices } = useAPAXStore()

export function DashboardLayout({ children}: DashboardLayoutProps) {
const { metalPrices, activeView } = useAPAXStore()
const pathname = usePathname()
//animation key now reacts to store changes automatically
const animationKey = activeView ? `view-${activeView}` : pathname
return (
<SidebarProvider>
<AppSidebar />
Expand Down Expand Up @@ -75,9 +80,13 @@ export function DashboardLayout({ children }: DashboardLayoutProps) {
</header>

{/* Main Content Area */}
<div className="flex-1 p-4 md:p-6 min-w-0">
{children}
</div>
<main className="flex-1 p-4 md:p-6 min-w-0">
<AnimatePresence mode="wait" initial={true}>
<MotionWrapper key={animationKey} stagger={true} className="w-full max-w-7xl mx-auto">
{children}
</MotionWrapper>
</AnimatePresence>
</main>
</SidebarInset>
</SidebarProvider>
)
Expand Down
67 changes: 67 additions & 0 deletions client/components/shared/MotionWrapper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
'use client';

import React from 'react';
import { motion, HTMLMotionProps, Variants } from 'framer-motion';

interface MotionWrapperProps extends HTMLMotionProps<'div'> {
children: React.ReactNode;
delay?: number;
stagger?: boolean; // prop for orchestration
}

const variants: Variants = {
initial: { opacity: 0, y: 20 },
animate: (delay: number) => ({
opacity: 1,
y: 0,
transition: {
delay,
duration: 0.4,
ease: [0.25, 0.1, 0.25, 1],
// if this is a container, stagger the children
staggerChildren: 0.05,
delayChildren: delay,
}
}),
exit: {
opacity: 0,
y: -20,
transition: { duration: 0.2 }
}
};

// item variant for children so they can inherit the stagger
export const childVariants: Variants = {
initial: { opacity: 0, y: 20 },
animate: {
opacity: 1,
y: 0,
transition: { duration: 0.4, ease: [0.25, 0.1, 0.25, 1] }
}
};

export const MotionWrapper = ({
children,
delay = 0,
stagger = false,
className,
...props
}: MotionWrapperProps) => {
return (
<motion.div
variants={variants}
initial="initial"
animate="animate"
exit="exit"
custom={delay}
className={className}
{...props}
>
{stagger
? React.Children.map(children, (child) => (
<motion.div variants={childVariants}>{child}</motion.div>
))
: children}
</motion.div>
);
};
2 changes: 1 addition & 1 deletion client/components/views/dashboard-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { ShariaCertificationHub } from '@/components/sharia-certification-hub'

export function DashboardView() {
return (
<div className="space-y-4 md:space-y-6 stagger-in max-w-7xl mx-auto overflow-hidden">
<div className="space-y-4 md:space-y-6 max-w-7xl mx-auto overflow-hidden">
{/* Live Ledger Ticker */}
<div className="w-full bg-[#1A1A1A]/50 border-y border-[#2A2A2A] overflow-hidden py-1.5 relative">
<div className="flex animate-ticker whitespace-nowrap gap-12 items-center">
Expand Down
4 changes: 2 additions & 2 deletions client/components/views/por-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ export function PorView() {
}

return (
<div className="space-y-6 stagger-in">
<div className="space-y-6 ">
{/* Page Header */}
<div className="flex items-center justify-between">
<div>
<h1 className="text-2xl font-serif font-bold text-[#E8E8E8] stagger-in">
<h1 className="text-2xl font-serif font-bold text-[#E8E8E8] ">
Proof of Reserve Monitor
</h1>
<p className="text-sm text-[#888888] mt-1">
Expand Down
1 change: 1 addition & 0 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"cmdk": "1.0.4",
"date-fns": "4.1.0",
"embla-carousel-react": "8.5.1",
"framer-motion": "^12.31.0",
"immer": "latest",
"lucide-react": "^0.454.0",
"next": "16.1.6",
Expand Down
38 changes: 38 additions & 0 deletions client/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.