diff --git a/apps/web/app/activity-demo/Sidebar.tsx b/apps/web/app/activity-demo/Sidebar.tsx new file mode 100644 index 0000000..98453f9 --- /dev/null +++ b/apps/web/app/activity-demo/Sidebar.tsx @@ -0,0 +1,45 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; + +export default function Sidebar() { + const [isExpanded, setIsExpanded] = useState(false); + const [time, setTime] = useState(0); + + useEffect(() => { + // This effect demonstrates that effects are cleaned up while the + // component is inside a hidden boundary (React 19 behavior). + const id = setInterval(() => setTime((t) => t + 1), 1000); + return () => clearInterval(id); + }, []); + + return ( + + ); +} diff --git a/apps/web/app/activity-demo/TabsExample.tsx b/apps/web/app/activity-demo/TabsExample.tsx new file mode 100644 index 0000000..d6a68e9 --- /dev/null +++ b/apps/web/app/activity-demo/TabsExample.tsx @@ -0,0 +1,44 @@ +'use client'; + +import React, { useState } from 'react'; + +export default function TabsExample() { + const [tab, setTab] = useState<'home' | 'contact'>('home'); + + return ( +
+
+ + +
+ +
+ {/* We intentionally do not use conditional mounting here to preserve DOM/state */} +
+

Home

+

This is the home tab content. Switch to Contact and back to see state preserved.

+
+ +
+ +
+
+
+ ); +} + +function Contact() { + const [message, setMessage] = useState(''); + return ( +
+

Contact Us

+