`. Further more, the title (and potentially other head elements) can be sent as a prop to the layout component so that it's customizable in all pages.
+This example shows a very common use case when building websites where you need to repeat some sort of layout for all your pages. Our pages are: `home`, `about` and `contact` and they all share the same layout and sidebar.
## Preview
diff --git a/examples/layout-component/components/layout.js b/examples/layout-component/components/layout.js
index a6c43e131175d..3b8d995eb96da 100644
--- a/examples/layout-component/components/layout.js
+++ b/examples/layout-component/components/layout.js
@@ -1,36 +1,13 @@
-import Link from 'next/link'
import Head from 'next/head'
+import styles from './layout.module.css'
-export default function Layout({
- children,
- title = 'This is the default title',
-}) {
+export default function Layout({ children }) {
return (
-
+ <>
-
{title}
-
-
+
Layouts Example
-
-
- {children}
-
-
-
+ {children}
+ >
)
}
diff --git a/examples/layout-component/components/layout.module.css b/examples/layout-component/components/layout.module.css
new file mode 100644
index 0000000000000..e5e0a5c98a3ee
--- /dev/null
+++ b/examples/layout-component/components/layout.module.css
@@ -0,0 +1,9 @@
+.main {
+ display: flex;
+ height: calc(100vh - 64px);
+ background-color: white;
+}
+
+.main > section {
+ padding: 32px;
+}
diff --git a/examples/layout-component/components/sidebar.js b/examples/layout-component/components/sidebar.js
new file mode 100644
index 0000000000000..9253827283085
--- /dev/null
+++ b/examples/layout-component/components/sidebar.js
@@ -0,0 +1,19 @@
+import Link from 'next/link'
+import styles from './sidebar.module.css'
+
+export default function Sidebar() {
+ return (
+
+
+
+ Home
+
+
+ About
+
+
+ Contact
+
+
+ )
+}
diff --git a/examples/layout-component/components/sidebar.module.css b/examples/layout-component/components/sidebar.module.css
new file mode 100644
index 0000000000000..b0c9d9de4161e
--- /dev/null
+++ b/examples/layout-component/components/sidebar.module.css
@@ -0,0 +1,39 @@
+.nav {
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+ width: 250px;
+ background-color: #fafafa;
+ padding: 32px;
+ border-right: 1px solid #eaeaea;
+}
+
+.nav > a {
+ margin: 8px 0;
+ text-decoration: none;
+ background: white;
+ border-radius: 4px;
+ font-size: 14px;
+ padding: 12px 16px;
+ text-transform: uppercase;
+ font-weight: 600;
+ letter-spacing: 0.025em;
+ color: #333;
+ border: 1px solid #eaeaea;
+ transition: all 0.125s ease;
+}
+
+.nav > a:hover {
+ background-color: #eaeaea;
+}
+
+.input {
+ margin: 32px 0;
+ text-decoration: none;
+ background: white;
+ border-radius: 4px;
+ border: 1px solid #eaeaea;
+ font-size: 14px;
+ padding: 8px 16px;
+ height: 28px;
+}
diff --git a/examples/layout-component/global.css b/examples/layout-component/global.css
new file mode 100644
index 0000000000000..350e2d10c0846
--- /dev/null
+++ b/examples/layout-component/global.css
@@ -0,0 +1,12 @@
+#__next {
+ display: flex;
+ flex-direction: column;
+ min-height: 100vh;
+}
+
+body {
+ margin: 0;
+ font-size: 24px;
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica,
+ Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
+}
diff --git a/examples/layout-component/pages/_app.js b/examples/layout-component/pages/_app.js
new file mode 100644
index 0000000000000..279f19e94b0c7
--- /dev/null
+++ b/examples/layout-component/pages/_app.js
@@ -0,0 +1,8 @@
+import '../global.css'
+
+export default function MyApp({ Component, pageProps }) {
+ // Use the layout defined at the page level, if available
+ const getLayout = Component.getLayout || ((page) => page)
+
+ return getLayout( )
+}
diff --git a/examples/layout-component/pages/about.js b/examples/layout-component/pages/about.js
index bc65e34a64d09..1625335992923 100644
--- a/examples/layout-component/pages/about.js
+++ b/examples/layout-component/pages/about.js
@@ -1,9 +1,40 @@
import Layout from '../components/layout'
+import Sidebar from '../components/sidebar'
export default function About() {
return (
-
- About us
-
+
+ Layout Example (About)
+
+ This example adds a property getLayout
to your page,
+ allowing you to return a React component for the layout. This allows you
+ to define the layout on a per-page basis. Since we're returning a
+ function, we can have complex nested layouts if desired.
+
+
+ When navigating between pages, we want to persist page state (input
+ values, scroll position, etc) for a Single-Page Application (SPA)
+ experience.
+
+
+ This layout pattern will allow for state persistence because the React
+ component tree is persisted between page transitions. To preserve state,
+ we need to prevent the React component tree from being discarded between
+ page transitions.
+
+ Try It Out
+
+ To visualize this, try tying in the search input in the{' '}
+ Sidebar
and then changing routes. You'll notice the input
+ state is persisted.
+
+
)
}
+
+About.getLayout = (page) => (
+
+
+ {page}
+
+)
diff --git a/examples/layout-component/pages/contact.js b/examples/layout-component/pages/contact.js
index 1a0559f172b5b..0572f002f78cc 100644
--- a/examples/layout-component/pages/contact.js
+++ b/examples/layout-component/pages/contact.js
@@ -1,9 +1,40 @@
import Layout from '../components/layout'
+import Sidebar from '../components/sidebar'
export default function Contact() {
return (
-
- Contact
-
+
+ Layout Example (Contact)
+
+ This example adds a property getLayout
to your page,
+ allowing you to return a React component for the layout. This allows you
+ to define the layout on a per-page basis. Since we're returning a
+ function, we can have complex nested layouts if desired.
+
+
+ When navigating between pages, we want to persist page state (input
+ values, scroll position, etc) for a Single-Page Application (SPA)
+ experience.
+
+
+ This layout pattern will allow for state persistence because the React
+ component tree is persisted between page transitions. To preserve state,
+ we need to prevent the React component tree from being discarded between
+ page transitions.
+
+ Try It Out
+
+ To visualize this, try tying in the search input in the{' '}
+ Sidebar
and then changing routes. You'll notice the input
+ state is persisted.
+
+
)
}
+
+Contact.getLayout = (page) => (
+
+
+ {page}
+
+)
diff --git a/examples/layout-component/pages/index.js b/examples/layout-component/pages/index.js
index a5814308f9b6f..0c78775767bcd 100644
--- a/examples/layout-component/pages/index.js
+++ b/examples/layout-component/pages/index.js
@@ -1,9 +1,40 @@
import Layout from '../components/layout'
+import Sidebar from '../components/sidebar'
-export default function Home() {
+export default function Index() {
return (
-
- Hello World.
-
+
+ Layout Example (Index)
+
+ This example adds a property getLayout
to your page,
+ allowing you to return a React component for the layout. This allows you
+ to define the layout on a per-page basis. Since we're returning a
+ function, we can have complex nested layouts if desired.
+
+
+ When navigating between pages, we want to persist page state (input
+ values, scroll position, etc) for a Single-Page Application (SPA)
+ experience.
+
+
+ This layout pattern will allow for state persistence because the React
+ component tree is persisted between page transitions. To preserve state,
+ we need to prevent the React component tree from being discarded between
+ page transitions.
+
+ Try It Out
+
+ To visualize this, try tying in the search input in the{' '}
+ Sidebar
and then changing routes. You'll notice the input
+ state is persisted.
+
+
)
}
+
+Index.getLayout = (page) => (
+
+
+ {page}
+
+)