Skip to content

Commit a47f03b

Browse files
creilly11235claude
authored andcommitted
feat(apollo-vertex): polish shell/sidebar with framer-motion animations and self-contained CSS
Convert sidebar width animation from CSS transitions to framer-motion spring physics matching MRS exactly. Make shell components self-contained by moving collapsible CSS to co-located file, swap hand-rolled buttons for vertex Button component, add asymmetric text fade variants via AnimatePresence, fix z-index stacking in docs preview, fix minimal header logo background, and switch locale loading state from spinner to skeleton. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 4f56369 commit a47f03b

28 files changed

Lines changed: 615 additions & 290 deletions

apps/apollo-vertex/app/patterns/shell/page.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ Use the `variant="minimal"` prop to render a horizontal header layout instead of
1919

2020
## Features
2121

22-
- **Collapsible Sidebar**: Icon-only collapsed mode with smooth CSS transitions, built on the shadcn sidebar primitives
22+
- **Collapsible Sidebar**: Icon-only collapsed mode with smooth spring animations, built on the shadcn sidebar primitives
2323
- **Sub-Navigation**: Collapsible menu items with nested sub-items that auto-expand when active
2424
- **Collapsed Menu Handling**: Clicking a collapsible item while collapsed expands the sidebar and opens the submenu
2525
- **Custom Logo**: Support for company logos with separate light/dark mode variants

apps/apollo-vertex/locales/en.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@
105105
"turkish": "Turkish",
106106
"type_a_message": "Type a message...",
107107
"user_email_placeholder": "user@company.com",
108+
"user_profile": "Profile and settings",
108109
"view": "View",
109110
"view_customer": "View customer",
110111
"view_payment_details": "View payment details",

apps/apollo-vertex/next-env.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/// <reference types="next" />
22
/// <reference types="next/image-types/global" />
3-
import "./.next/types/routes.d.ts";
3+
import "./.next/dev/types/routes.d.ts";
44

55
// NOTE: This file should not be edited
66
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
Lines changed: 6 additions & 5 deletions
Loading
Lines changed: 6 additions & 12 deletions
Loading

apps/apollo-vertex/registry.json

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,10 @@
496496
{
497497
"path": "registry/collapsible/collapsible.tsx",
498498
"type": "registry:ui"
499+
},
500+
{
501+
"path": "registry/collapsible/collapsible.css",
502+
"type": "registry:ui"
499503
}
500504
]
501505
},
@@ -937,14 +941,15 @@
937941
"@tanstack/react-query",
938942
"@tanstack/react-router",
939943
"pkce-challenge",
940-
"sonner"
944+
"sonner",
945+
"framer-motion"
941946
],
942947
"registryDependencies": [
943948
"button",
944949
"tooltip",
945950
"avatar",
946951
"dropdown-menu",
947-
"spinner",
952+
"skeleton",
948953
"sidebar",
949954
"collapsible"
950955
],
@@ -993,10 +998,6 @@
993998
"path": "registry/shell/shell-text.tsx",
994999
"type": "registry:ui"
9951000
},
996-
{
997-
"path": "registry/shell/shell-theme-toggle.tsx",
998-
"type": "registry:ui"
999-
},
10001001
{
10011002
"path": "registry/shell/shell-theme-provider.tsx",
10021003
"type": "registry:ui"
@@ -1024,6 +1025,10 @@
10241025
{
10251026
"path": "registry/shell/shell-user-profile-menu-items.tsx",
10261027
"type": "registry:ui"
1028+
},
1029+
{
1030+
"path": "registry/shell/shell-animations.ts",
1031+
"type": "registry:ui"
10271032
}
10281033
]
10291034
},
@@ -1108,6 +1113,7 @@
11081113
"dependencies": [
11091114
"@radix-ui/react-slot",
11101115
"class-variance-authority",
1116+
"framer-motion",
11111117
"lucide-react",
11121118
"react-i18next"
11131119
],
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
@keyframes collapsible-down {
2+
from {
3+
height: 0;
4+
}
5+
to {
6+
height: var(--radix-collapsible-content-height);
7+
}
8+
}
9+
10+
@keyframes collapsible-up {
11+
from {
12+
height: var(--radix-collapsible-content-height);
13+
}
14+
to {
15+
height: 0;
16+
}
17+
}
18+
19+
@utility animate-collapsible-down {
20+
animation: collapsible-down 0.2s cubic-bezier(0.4, 0, 0.2, 1);
21+
}
22+
23+
@utility animate-collapsible-up {
24+
animation: collapsible-up 0.2s cubic-bezier(0.4, 0, 0.2, 1);
25+
}

apps/apollo-vertex/registry/collapsible/collapsible.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
"use client";
22

33
import * as CollapsiblePrimitive from "@radix-ui/react-collapsible";
4+
import { cn } from "@/lib/utils";
5+
import "./collapsible.css";
46

57
function Collapsible({
68
...props
@@ -20,11 +22,16 @@ function CollapsibleTrigger({
2022
}
2123

2224
function CollapsibleContent({
25+
className,
2326
...props
2427
}: React.ComponentProps<typeof CollapsiblePrimitive.CollapsibleContent>) {
2528
return (
2629
<CollapsiblePrimitive.CollapsibleContent
2730
data-slot="collapsible-content"
31+
className={cn(
32+
"overflow-hidden transition-all duration-200 data-[state=closed]:animate-collapsible-up data-[state=open]:animate-collapsible-down",
33+
className,
34+
)}
2835
{...props}
2936
/>
3037
);
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
export const sidebarSpring = {
2+
type: "spring",
3+
stiffness: 400,
4+
damping: 30,
5+
mass: 0.5,
6+
} as const;
7+
8+
export const fastFadeTransition = {
9+
duration: 0.15,
10+
ease: [0.25, 0.46, 0.45, 0.94],
11+
} as const;
12+
13+
export const textFadeVariants = {
14+
initial: { opacity: 0, x: -10 },
15+
animate: { opacity: 1, x: 0 },
16+
exit: { opacity: 0 },
17+
};
18+
19+
export const iconHoverScale = {
20+
scale: 1.05,
21+
transition: { duration: 0.2 },
22+
};
23+
24+
export const scaleVariants = {
25+
initial: { opacity: 0, scale: 0.8 },
26+
animate: { opacity: 1, scale: 1 },
27+
exit: { opacity: 0, scale: 0.8 },
28+
};
29+
30+
export const edgeFadeVariants = {
31+
initial: { opacity: 0, scaleX: 0 },
32+
animate: { opacity: 1, scaleX: 1 },
33+
exit: { opacity: 0, scaleX: 0 },
34+
};

apps/apollo-vertex/registry/shell/shell-company-logo.tsx

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,34 @@ interface CompanyLogoIconProps {
88

99
export const CompanyLogoIcon = ({ companyLogo }: CompanyLogoIconProps) => {
1010
if (!companyLogo) {
11-
return <Box className="w-5 h-5 text-sidebar-foreground" />;
11+
return <Box className="w-4 h-4 text-white" />;
1212
}
1313

14+
// Non-custom logos (e.g. UiPath) have the background baked into the SVG —
15+
// render them full-size so they fill the container. Custom logos are small
16+
// marks displayed over a CSS background.
17+
const sizeClass = companyLogo.isCustom
18+
? "w-4 h-auto"
19+
: "h-8 w-8 object-contain";
20+
1421
return (
1522
<>
1623
<img
1724
src={companyLogo.url}
1825
alt={companyLogo.alt}
19-
className={cn(
20-
"h-8 w-8 object-contain",
21-
companyLogo.darkUrl ? "dark:hidden" : "",
22-
)}
26+
className={cn(sizeClass, companyLogo.darkUrl && "dark:hidden")}
27+
onError={(e) => {
28+
e.currentTarget.style.display = "none";
29+
}}
2330
/>
2431
{companyLogo.darkUrl && (
2532
<img
2633
src={companyLogo.darkUrl}
2734
alt={companyLogo.alt}
28-
className="h-8 w-8 object-contain hidden dark:block"
35+
className={cn(sizeClass, "hidden dark:block")}
36+
onError={(e) => {
37+
e.currentTarget.style.display = "none";
38+
}}
2939
/>
3040
)}
3141
</>

0 commit comments

Comments
 (0)