Skip to content
Open
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
29 changes: 29 additions & 0 deletions app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -339,3 +339,32 @@ pre[class*="language-"] {
pre[class*="language-"] {
color: var(--prism-text) !important;
}

/* Performance optimization utilities */
@layer utilities {
.contain-layout {
contain: layout;
}

.contain-paint {
contain: paint;
}

.contain-strict {
contain: strict;
}

.contain-content {
contain: content;
}

.gpu-accelerated {
transform: translateZ(0);
will-change: transform;
}

.optimize-animation {
contain: layout paint;
will-change: transform, opacity;
}
}
1 change: 1 addition & 0 deletions bun.lock

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

13 changes: 4 additions & 9 deletions components/docs/search/search-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -239,14 +239,14 @@ export function SearchModal({ isOpen, onClose, triggerRef }: SearchModalProps) {
<FocusTrap>
<motion.div
animate={{ opacity: 1 }}
className="fixed inset-0 z-[100] flex items-start justify-center overflow-y-auto overscroll-contain bg-black/70 p-0 pt-0 backdrop-blur-md md:p-4 md:pt-[10vh] md:backdrop-blur-sm"
className="fixed inset-0 z-[100] flex items-start justify-center overflow-y-auto overscroll-contain bg-black/80 p-0 pt-0 md:p-4 md:pt-[10vh]"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The change from backdrop-blur-md to bg-black/80 is a good optimization, as backdrop-blur can be computationally intensive. This aligns with the PR's goal of replacing GPU-expensive backdrop-blur with higher opacity backgrounds for better performance.

exit={{ opacity: 0 }}
initial={{ opacity: 0 }}
transition={{ duration: prefersReducedMotion ? 0 : 0.2 }}
>
<motion.div
animate={{ opacity: 1, scale: 1, y: 0 }}
className="relative h-full w-full md:h-auto md:max-w-2xl"
className="optimize-animation relative h-full w-full md:h-auto md:max-w-2xl"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Adding the optimize-animation class is an excellent move. This class leverages contain: layout paint and will-change: transform, opacity to hint to the browser that this element will be animated, allowing for better GPU acceleration and isolation of rendering layers. This directly contributes to smoother animations.

exit={{
opacity: 0,
scale: prefersReducedMotion ? 1 : 0.95,
Expand All @@ -265,23 +265,18 @@ export function SearchModal({ isOpen, onClose, triggerRef }: SearchModalProps) {
}}
>
{/* Modal Container with Enhanced Glassmorphism */}
<div className="flex h-full flex-col overflow-hidden rounded-none border-0 bg-white/98 shadow-2xl backdrop-blur-2xl md:h-auto md:rounded-2xl md:border md:border-gray-200/60 dark:bg-gray-900/98 dark:md:border-gray-700/60">
<div className="flex h-full flex-col overflow-hidden rounded-none border-0 bg-white shadow-2xl md:h-auto md:rounded-2xl md:border md:border-gray-200/60 dark:bg-gray-900 dark:md:border-gray-700/60">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Removing backdrop-blur-2xl and adjusting the background opacity (bg-white/98 to bg-white, dark:bg-gray-900/98 to dark:bg-gray-900) is a solid performance improvement. backdrop-blur can be a significant performance bottleneck, especially on lower-end devices, so this change helps ensure smoother rendering.

{/* Search Input Section with Enhanced Gradient */}
<div className="relative border-gray-200 border-b bg-gradient-to-r from-gray-50/80 to-white/80 dark:border-gray-700 dark:from-gray-800/80 dark:to-gray-900/80">
<div className="flex items-center gap-3 px-5 py-4">
{/* Search Icon with Animation */}
<motion.div
animate={{
opacity: isLoading ? [0.5, 1, 0.5] : 1,
scale: searchIconScale,
}}
className={isLoading ? "animate-pulse" : ""}
style={{ transformOrigin: "center" }}
transition={{
opacity: {
duration: prefersReducedMotion ? 0 : 1.1,
repeat: isLoading ? Number.POSITIVE_INFINITY : 0,
ease: "easeInOut",
},
scale: { duration: prefersReducedMotion ? 0 : 0.25 },
}}
Comment on lines 275 to 281
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Replacing the Framer Motion opacity animation with className={isLoading ? "animate-pulse" : ""} for the search icon is a good optimization. CSS animations like animate-pulse are often more performant for simple effects as they can be offloaded to the GPU more effectively than JavaScript-driven animations, reducing main thread work. This aligns with the PR description's goal to simplify the search modal loading animation.

>
Expand Down
14 changes: 13 additions & 1 deletion components/docs/sidebar/sidebar-wrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,19 @@ const SidebarWrapper: FC<SidebarWrapperProps> = ({ sidebarStructure }) => {

lenisRef.current = lenis;

// Throttle RAF to 120Hz (8.33ms per frame) for optimal performance
const targetFPS = 120;
const frameTime = 1000 / targetFPS;
let lastTime = 0;

function raf(time: number) {
// Skip frame if not enough time has passed
if (time - lastTime < frameTime) {
requestAnimationFrame(raf);
return;
}

lastTime = time;
Comment on lines +35 to +47
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The implementation of RAF throttling to 120Hz is a critical performance improvement. By ensuring that lenis.raf is only called when enough time has passed for a new frame at the target FPS, you prevent unnecessary work and align the animation loop with the display's refresh rate, leading to a much smoother experience, especially on high refresh rate monitors.

lenis.raf(time);
requestAnimationFrame(raf);
}
Expand Down Expand Up @@ -64,7 +76,7 @@ const SidebarWrapper: FC<SidebarWrapperProps> = ({ sidebarStructure }) => {
<div className="sticky top-32 flex h-[calc(100vh-8rem)] flex-col gap-4">
<SearchTrigger onClick={() => setIsSearchOpen(true)} />
<div
className="scrollbar-hide relative flex min-h-0 flex-1 flex-col overflow-auto overscroll-contain rounded-xl border border-gray-200 bg-white/90 shadow-lg backdrop-blur-md transition-shadow hover:shadow-xl dark:border-gray-800 dark:bg-gray-900/60"
className="scrollbar-hide relative flex min-h-0 flex-1 flex-col overflow-auto overscroll-contain rounded-xl border border-gray-200 bg-white/95 shadow-lg backdrop-blur-sm transition-shadow hover:shadow-xl dark:border-gray-800 dark:bg-gray-900/90"
ref={sidebarRef}
>
<DocSidebar sidebarStructure={sidebarStructure} />
Expand Down
3 changes: 1 addition & 2 deletions components/docs/view/animations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,10 @@ export const containerVariants: Variants = {
};

export const itemVariants: Variants = {
hidden: { y: 20, opacity: 0, filter: "blur(4px)" },
hidden: { y: 20, opacity: 0 },
visible: {
y: 0,
opacity: 1,
filter: "blur(0px)",
transition: {
Comment on lines +12 to 16
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Removing filter: blur() from the itemVariants is a significant performance win. CSS filter properties, especially blur, are known to be very expensive for the GPU and can cause considerable jank during animations. This change directly addresses the PR's goal of eliminating such performance bottlenecks.

type: "spring",
stiffness: 200,
Expand Down
5 changes: 3 additions & 2 deletions components/hero/navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,8 @@ export default function Navbar() {
const handleScroll = () => {
if (!ticking) {
window.requestAnimationFrame(() => {
setScrolled(window.scrollY > 20);
const isScrolled = window.scrollY > 20;
setScrolled((prev) => (prev === isScrolled ? prev : isScrolled));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Optimizing the setScrolled state update with setScrolled((prev) => (prev === isScrolled ? prev : isScrolled)) is a good practice. This prevents unnecessary re-renders of the Navbar component when the scroll state (whether it's scrolled past 20px or not) hasn't actually changed, improving overall component efficiency.

ticking = false;
});
ticking = true;
Expand Down Expand Up @@ -210,7 +211,7 @@ export default function Navbar() {
aria-label="Main navigation"
className={`fixed inset-x-0 top-0 z-50 border-transparent border-b transition-all duration-300 ${
scrolled || isMenuOpen
? "border-gray-200/50 bg-white/80 backdrop-blur-xl dark:border-white/5 dark:bg-[#0a0a0a]/80"
? "border-gray-200/50 bg-white/95 backdrop-blur-sm dark:border-white/5 dark:bg-[#0a0a0a]/95"
Comment on lines 213 to +214
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The reduction of backdrop-blur-xl to backdrop-blur-sm and the increase in background opacity (bg-white/80 to bg-white/95, dark:bg-[#0a0a0a]/80 to dark:bg-[#0a0a0a]/95) is a positive change for performance. This directly addresses the PR's objective to reduce the impact of expensive backdrop-blur effects, leading to a smoother user interface.

: "bg-white/0 dark:bg-black/0"
}`}
initial="hidden"
Expand Down
Loading