<html lang="en">
<head></head>
<body>

<form id="mainForm" method="post" action="https://stackblitz.com/run" target="_self">
<input type="hidden" name="project[files][.gitignore]" value="node_modules
.DS_Store
dist
dist-ssr
*.local
">
<input type="hidden" name="project[files][README.md]" value="# TanStack Router - Scroll Restoration Example

An example demonstrating scroll position restoration.

- [TanStack Router Docs](https://tanstack.com/router)

## Start a new project based on this example

To start a new project based on this example, run:

```sh
npx gitpick TanStack/router/tree/main/examples/react/scroll-restoration scroll-restoration
```

## Getting Started

Install dependencies:

```sh
pnpm install
```

Start the development server:

```sh
pnpm dev
```

## Build

Build for production:

```sh
pnpm build
```

## About This Example

This example demonstrates:

- Scroll position restoration
- Browser back/forward scroll behavior
- Custom scroll restoration logic
- User experience optimization
">
<input type="hidden" name="project[files][index.html]" value="&lt;!doctype html&gt;
&lt;html lang=&quot;en&quot;&gt;
  &lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot; /&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot; /&gt;
    &lt;title&gt;Vite App&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;div id=&quot;app&quot;&gt;&lt;/div&gt;
    &lt;script type=&quot;module&quot; src=&quot;/src/main.tsx&quot;&gt;&lt;/script&gt;
  &lt;/body&gt;
&lt;/html&gt;
">
<input type="hidden" name="project[files][package.json]" value="{
  &quot;name&quot;: &quot;tanstack-router-react-example-scroll-restoration&quot;,
  &quot;private&quot;: true,
  &quot;type&quot;: &quot;module&quot;,
  &quot;scripts&quot;: {
    &quot;dev&quot;: &quot;vite --port 3000&quot;,
    &quot;build&quot;: &quot;vite build &amp;&amp; tsc --noEmit&quot;,
    &quot;preview&quot;: &quot;vite preview&quot;,
    &quot;start&quot;: &quot;vite&quot;
  },
  &quot;dependencies&quot;: {
    &quot;@tailwindcss/vite&quot;: &quot;^4.2.2&quot;,
    &quot;@tanstack/react-router&quot;: &quot;https://pkg.pr.new/TanStack/router/@tanstack/react-router@9b77320&quot;,
    &quot;@tanstack/react-router-devtools&quot;: &quot;https://pkg.pr.new/TanStack/router/@tanstack/react-router-devtools@9b77320&quot;,
    &quot;@tanstack/react-virtual&quot;: &quot;^3.13.0&quot;,
    &quot;react&quot;: &quot;^19.0.0&quot;,
    &quot;react-dom&quot;: &quot;^19.0.0&quot;,
    &quot;tailwindcss&quot;: &quot;^4.2.2&quot;
  },
  &quot;devDependencies&quot;: {
    &quot;@types/react&quot;: &quot;^19.0.8&quot;,
    &quot;@types/react-dom&quot;: &quot;^19.0.3&quot;,
    &quot;@vitejs/plugin-react&quot;: &quot;^6.0.1&quot;,
    &quot;@typescript/native&quot;: &quot;npm:typescript@^7.0.2&quot;,
    &quot;typescript&quot;: &quot;npm:@typescript/typescript6@^6.0.2&quot;,
    &quot;vite&quot;: &quot;^8.0.14&quot;
  }
}">
<input type="hidden" name="project[files][tsconfig.json]" value="{
  &quot;compilerOptions&quot;: {
    &quot;strict&quot;: true,
    &quot;esModuleInterop&quot;: true,
    &quot;jsx&quot;: &quot;react-jsx&quot;,
    &quot;target&quot;: &quot;ESNext&quot;,
    &quot;moduleResolution&quot;: &quot;Bundler&quot;,
    &quot;lib&quot;: [&quot;DOM&quot;, &quot;DOM.Iterable&quot;, &quot;ES2022&quot;],
    &quot;skipLibCheck&quot;: true
  }
}
">
<input type="hidden" name="project[files][vite.config.js]" value="import { defineConfig } from &#39;vite&#39;
import react from &#39;@vitejs/plugin-react&#39;
import tailwindcss from &#39;@tailwindcss/vite&#39;

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [tailwindcss(), react()],
})
">
<input type="hidden" name="project[files][.vscode/settings.json]" value="{
  &quot;files.watcherExclude&quot;: {
    &quot;**/routeTree.gen.ts&quot;: true
  },
  &quot;search.exclude&quot;: {
    &quot;**/routeTree.gen.ts&quot;: true
  },
  &quot;files.readonlyInclude&quot;: {
    &quot;**/routeTree.gen.ts&quot;: true
  }
}
">
<input type="hidden" name="project[files][src/main.tsx]" value="import React, { StrictMode } from &#39;react&#39;
import ReactDOM from &#39;react-dom/client&#39;
import {
  Link,
  Outlet,
  RouterProvider,
  createRootRoute,
  createRoute,
  createRouter,
  useElementScrollRestoration,
} from &#39;@tanstack/react-router&#39;
import { TanStackRouterDevtools } from &#39;@tanstack/react-router-devtools&#39;
import { useVirtualizer } from &#39;@tanstack/react-virtual&#39;
import &#39;./styles.css&#39;

const rootRoute = createRootRoute({
  component: RootComponent,
})

function RootComponent() {
  return (
    &lt;&gt;
      &lt;div className=&quot;p-2 flex gap-2 sticky top-0 border-b bg-gray-100 dark:bg-gray-900&quot;&gt;
        &lt;Link to=&quot;/&quot; className=&quot;[&amp;.active]:font-bold&quot;&gt;
          Home
        &lt;/Link&gt;{&#39; &#39;}
        &lt;Link to=&quot;/about&quot; className=&quot;[&amp;.active]:font-bold&quot;&gt;
          About
        &lt;/Link&gt;
        &lt;Link to=&quot;/about&quot; resetScroll={false}&gt;
          About (No Reset)
        &lt;/Link&gt;
        &lt;Link to=&quot;/by-element&quot; className=&quot;[&amp;.active]:font-bold&quot;&gt;
          By-Element
        &lt;/Link&gt;
      &lt;/div&gt;
      &lt;Outlet /&gt;
      &lt;TanStackRouterDevtools /&gt;
    &lt;/&gt;
  )
}

const indexRoute = createRoute({
  getParentRoute: () =&gt; rootRoute,
  path: &#39;/&#39;,
  loader: () =&gt; new Promise&lt;void&gt;((r) =&gt; setTimeout(r, 500)),
  component: IndexComponent,
})

function IndexComponent() {
  return (
    &lt;div className=&quot;p-2&quot;&gt;
      &lt;h3&gt;Welcome Home!&lt;/h3&gt;
      &lt;div className=&quot;space-y-2&quot;&gt;
        {Array.from({ length: 50 }).map((_, i) =&gt; (
          &lt;div
            key={i}
            className=&quot;h-[100px] p-2 rounded-lg bg-gray-200 dark:bg-gray-800 border&quot;
          &gt;
            Home Item {i + 1}
          &lt;/div&gt;
        ))}
      &lt;/div&gt;
    &lt;/div&gt;
  )
}

const aboutRoute = createRoute({
  getParentRoute: () =&gt; rootRoute,
  path: &#39;/about&#39;,
  loader: () =&gt; new Promise&lt;void&gt;((r) =&gt; setTimeout(r, 500)),
  component: AboutComponent,
})

function AboutComponent() {
  return (
    &lt;div className=&quot;p-2&quot;&gt;
      &lt;div&gt;Hello from About!&lt;/div&gt;
      &lt;div className=&quot;space-y-2&quot;&gt;
        {Array.from({ length: 50 }).map((_, i) =&gt; (
          &lt;div
            key={i}
            className=&quot;h-[100px] p-2 rounded-lg bg-gray-200 dark:bg-gray-800 border&quot;
          &gt;
            About Item {i + 1}
          &lt;/div&gt;
        ))}
      &lt;/div&gt;
    &lt;/div&gt;
  )
}

const byElementRoute = createRoute({
  getParentRoute: () =&gt; rootRoute,
  path: &#39;/by-element&#39;,
  loader: () =&gt; new Promise&lt;void&gt;((r) =&gt; setTimeout(r, 500)),
  component: ByElementComponent,
})

function ByElementComponent() {
  // We need a unique ID for manual scroll restoration on a specific element
  // It should be as unique as possible for this element across your app
  const scrollRestorationId = &#39;myVirtualizedContent&#39;

  // We use that ID to get the scroll entry for this element
  const scrollEntry = useElementScrollRestoration({
    id: scrollRestorationId,
  })

  // Let&#39;s use TanStack Virtual to virtualize some content!
  const virtualizerParentRef = React.useRef&lt;HTMLDivElement&gt;(null)
  const virtualizer = useVirtualizer({
    count: 10000,
    getScrollElement: () =&gt; virtualizerParentRef.current,
    estimateSize: () =&gt; 100,
    // We pass the scrollY from the scroll restoration entry to the virtualizer
    // as the initial offset
    initialOffset: scrollEntry?.scrollY,
  })

  return (
    &lt;div className=&quot;p-2 h-[calc(100vh-41px)] flex flex-col&quot;&gt;
      &lt;div&gt;Hello from By-Element!&lt;/div&gt;
      &lt;div className=&quot;h-full min-h-0 flex gap-4&quot;&gt;
        &lt;div className=&quot;border rounded-lg p-2 overflow-auto flex-1 space-y-2&quot;&gt;
          {Array.from({ length: 50 }).map((_, i) =&gt; (
            &lt;div
              key={i}
              className=&quot;h-[100px] p-2 rounded-lg bg-gray-200 dark:bg-gray-800 border&quot;
            &gt;
              About Item {i + 1}
            &lt;/div&gt;
          ))}
        &lt;/div&gt;
        &lt;div className=&quot;flex-1 overflow-auto flex flex-col gap-4&quot;&gt;
          {Array.from({ length: 2 }).map((_, i) =&gt; (
            &lt;div key={i} className=&quot;flex-1 border rounded-lg p-2 overflow-auto&quot;&gt;
              &lt;div className=&quot;space-y-2&quot;&gt;
                {Array.from({ length: 50 }).map((_, i) =&gt; (
                  &lt;div
                    key={i}
                    className=&quot;h-[100px] p-2 rounded-lg bg-gray-200 dark:bg-gray-800 border&quot;
                  &gt;
                    About Item {i + 1}
                  &lt;/div&gt;
                ))}
              &lt;/div&gt;
            &lt;/div&gt;
          ))}
          &lt;div className=&quot;flex-1 flex flex-col min-h-0&quot;&gt;
            &lt;div className=&quot;font-bold&quot;&gt;Virtualized&lt;/div&gt;
            &lt;div
              ref={virtualizerParentRef}
              // We pass the scroll restoration ID to the element
              // as a custom attribute that will get picked up by the
              // scroll restoration watcher
              data-scroll-restoration-id={scrollRestorationId}
              className=&quot;flex-1 border rounded-lg overflow-auto relative&quot;
            &gt;
              &lt;div
                style={{
                  height: `${virtualizer.getTotalSize()}px`,
                }}
              &gt;
                {virtualizer.getVirtualItems().map((item) =&gt; (
                  &lt;div
                    key={item.index}
                    className=&quot;absolute p-2 pb-0 w-full&quot;
                    style={{
                      height: item.size,
                      top: item.start,
                    }}
                  &gt;
                    &lt;div className=&quot;p-2 rounded-lg bg-gray-200 dark:bg-gray-800 border h-full&quot;&gt;
                      Virtualized Item {item.index + 1}
                    &lt;/div&gt;
                  &lt;/div&gt;
                ))}
              &lt;/div&gt;
            &lt;/div&gt;
          &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  )
}

const routeTree = rootRoute.addChildren([
  indexRoute,
  aboutRoute,
  byElementRoute,
])

const router = createRouter({
  routeTree,
  defaultPreload: &#39;intent&#39;,
  scrollRestoration: true,
})

declare module &#39;@tanstack/react-router&#39; {
  interface Register {
    router: typeof router
  }
}

const rootElement = document.getElementById(&#39;app&#39;)!
if (!rootElement.innerHTML) {
  const root = ReactDOM.createRoot(rootElement)
  root.render(
    &lt;StrictMode&gt;
      &lt;RouterProvider router={router} /&gt;
    &lt;/StrictMode&gt;,
  )
}
">
<input type="hidden" name="project[files][src/styles.css]" value="@import &#39;tailwindcss&#39; source(&#39;../&#39;);

@layer base {
  *,
  ::after,
  ::before,
  ::backdrop,
  ::file-selector-button {
    border-color: var(--color-gray-200, currentcolor);
  }
}

html {
  color-scheme: light dark;
}
* {
  @apply border-gray-200 dark:border-gray-800;
}
body {
  @apply bg-gray-50 text-gray-950 dark:bg-gray-900 dark:text-gray-200;
}
">
<input type="hidden" name="project[files][src/vite-env.d.ts]" value="/// &lt;reference types=&quot;vite/client&quot; /&gt;
">
<input type="hidden" name="project[files][.devcontainer/devcontainer.json]" value="{
  &quot;image&quot;: &quot;mcr.microsoft.com/devcontainers/typescript-node:24&quot;
}
">
<input type="hidden" name="project[description]" value="generated by https://pkg.pr.new">
<input type="hidden" name="project[template]" value="node">
<input type="hidden" name="project[title]" value="tanstack-router-react-example-scroll-restoration">
</form>
<script>document.getElementById("mainForm").submit();</script>

</body></html>