Skip to content

Latest commit

 

History

History
215 lines (150 loc) · 6.79 KB

+Page.mdx

File metadata and controls

215 lines (150 loc) · 6.79 KB

import { Link, RepoLink } from '@brillout/docpress' import { UiFrameworkVikeExtension, ImplementedBy } from '../../components'

Layout setting

What are layouts? Pages can have different layouts: for example, if admin panel pages (/admin/product/@id and /admin/user/@id) have a sidebar while marketing pages (/ and /about-us) have a sticky header instead. The admin pages can share the same <Layout> component that includes the sidebar, while the marketing pages can share the <Layout> component that includes the sticky header.

The Layout setting wraps your Page component with another component (the layout component).

<Layout>   ⟸ component defined by the setting "Layout"
  <Page /> ⟸ component defined by the setting "Page"
</Layout>

You can apply a layout as default to all pages:

// /pages/+Layout.js

// This layout component is the default layout
export { Layout }

// ...

See also: .

You can then override the default layout on a page-by-page basis:

// pages/product/@id/+Layout.js

// This layout component overrides the default layout and
// applies to the product page /product/@id
export { Layout }

// ...

You can also define a layout for a group of pages:

// /pages/admin/+Layout.js

/* This layout applies only to admin pages (/pages/admin/**) such as:
   URL                     FILESYSTEM
   /admin                  /pages/admin/+Page.js
   /admin/user/@id         /pages/admin/user/@id/+Page.js
   /admin/product/@id      /pages/admin/product/@id/+Page.js
*/
export { Layout }

// ...

See also <Wrapper> which also wraps <Page>, but for different use cases.

Examples

React / Vue / Solid

Nested Layouts

What are nested layouts? A nested layout is, essentially, when a page has a route with multiple parameters. For example /product/@id/@view:

URL                        id            view
=====================      ====          =======
/product/1337              1337          null
/product/1337/pricing      1337          pricing
/product/42/reviews        42            reviews
/product/42/pricing                   /product/42/reviews
+------------------+                  +-----------------+
| Product          |                  | Product         |
| +--------------+ |                  | +-------------+ |
| | Pricing      | |  +------------>  | | Reviews     | |
| |              | |                  | |             | |
| +--------------+ |                  | +-------------+ |
+------------------+                  +-----------------+

If your nested layout isn't associated with a URL (in other words the pricing page and the reviews page share the same URL /product/42), then you can simply use a stateful component instead of the following.

You can implement a nested layout by using a route with multiple parameters:

// /pages/product/+route.js

export default '/product/@id/@view'

You can also use a Route Function for full programmatic flexibility, see this example.

To ensure @view matches a list of pre-defined values, you can use a guard() hook with throw render(404):

// /pages/product/+guard.js

import { render } from 'vike/abort'

export function guard(pageContext) {
  const { view } = pageContext.routeParams
  if (!['reviews', 'pricing'].includes(view)) {
    throw render(404)
  }
}

You can then use pageContext.routeParams.view to implement the nested layout:

// /pages/product/+Page.js

export { Page }

import { usePageContext } from 'vike-react/usePageContext' // or 'vike-vue' / 'vike-solid'

function Page() {
  const pageContext = usePageContext()
  const nestedLayout = (() => {
    const { view } = pageContext.routeParams
    if (view === 'reviews') return <Reviews />
    if (view === 'pricing') return <Pricing />
  })()
  return <>
     {/* ... */}
       {/* Somewhere deep */ }
       { nestedLayout }
     {/* ... */}
  </>
}

Finally, make sure to use <a href="/product/42/reviews" keep-scroll-position /> (and navigate('/product/42/reviews', { keepScrollPosition: true })) to avoid the browser to scroll to the top.

Once #1459 - Nested Routes is implemented, Vike will automatically preserve the scroll position.

Examples:

Without Vike extension

The following is for users that don't use a .

The simple way

A simple way to implement layouts is to manually wrap your <Page> components:

// /pages/index/+Page.js

export { Page }

import { LayoutDefault } from '../layouts/LayoutDefault'

function Page() {
  return <>
    <LayoutDefault>
      {/* ... */}
    </LayoutDefault>
  </>
}
// /pages/admin/+Page.js

export { Page }

import { LayoutDashboard } from '../layouts/LayoutDashboard'

function Page() {
  return <>
    <LayoutDashboard>
      {/* ... */}
    </LayoutDashboard>
  </>
}

With a custom setting

In case you don't use a , you can implement the Layout setting yourself by using meta.

Examples:

Nested Layout

See .

For smooth nested layout navigation, we recommend using Client Routing. (Using Server Routing leads to full page reloads upon nested layout navigation which usually isn't an acceptable UX.)

See also