Skip to content

Layout resets #1061

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Apr 17, 2021
Merged
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
5 changes: 5 additions & 0 deletions .changeset/modern-donkeys-invite.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sveltejs/kit': patch
---

Implement layout resets
8 changes: 7 additions & 1 deletion documentation/docs/02-layouts.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ To create a layout component that applies to every page, make a file called `src
<slot></slot>
```

...but we can add whatever markup, styles and behaviour we want. For example, let's add a nav bar:
...but we can add whatever markup, styles and behaviour we want. The only requirement is that the component includes a `<slot>` for the page content. For example, let's add a nav bar:

```html
<!-- src/routes/$layout.svelte -->
Expand Down Expand Up @@ -62,6 +62,12 @@ We can create a layout that only applies to pages below `/settings` (while inher
<slot></slot>
```

### Resets

To reset the layout stack, create a `$layout.reset.svelte` file instead of a `$layout.svelte` file. For example, if you want your `/admin/*` pages to _not_ inherit the root layout, create a file called `src/routes/admin/$layout.reset.svelte`.

Layout resets are otherwise identical to normal layout components.

### Error pages

If a page fails to load (see [Loading](#loading)), SvelteKit will render an error page. You can customise this page by creating `$error.svelte` components alongside your layout and page components.
Expand Down
3 changes: 0 additions & 3 deletions packages/kit/src/core/build/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -340,9 +340,6 @@ async function build_server(
const metadata_lookup = ${s(metadata_lookup)};

async function load_component(file) {
if (!module_lookup[file]) {
console.log({ file });
}
return {
module: await module_lookup[file](),
...metadata_lookup[file]
Expand Down
10 changes: 8 additions & 2 deletions packages/kit/src/core/create_manifest_data/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -140,18 +140,24 @@ export default function create_manifest_data({ config, output, cwd = process.cwd
params.push(...item.parts.filter((p) => p.dynamic).map((p) => p.content));

if (item.is_dir) {
const layout_reset = find_layout('$layout.reset', item.file);
const layout = find_layout('$layout', item.file);
const error = find_layout('$error', item.file);

if (layout_reset && layout) {
throw new Error(`Cannot have $layout next to $layout.reset: ${layout_reset}`);
}

if (layout_reset) components.push(layout_reset);
if (layout) components.push(layout);
if (error) components.push(error);

walk(
path.join(dir, item.basename),
segments,
params,
layout_stack.concat(layout),
error_stack.concat(error)
layout_reset ? [layout_reset] : layout_stack.concat(layout),
layout_reset ? [error] : error_stack.concat(error)
);
} else if (item.is_page) {
components.push(item.file);
Expand Down
38 changes: 38 additions & 0 deletions packages/kit/src/core/create_manifest_data/index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -357,4 +357,42 @@ test('includes nested error components', () => {
]);
});

test('resets layout', () => {
const { routes } = create('samples/layout-reset');

assert.equal(routes, [
{
type: 'page',
pattern: /^\/$/,
params: [],
path: '/',
a: [layout, 'samples/layout-reset/index.svelte'],
b: [error]
},
{
type: 'page',
pattern: /^\/foo\/?$/,
params: [],
path: '/foo',
a: [
layout,
'samples/layout-reset/foo/$layout.svelte',
'samples/layout-reset/foo/index.svelte'
],
b: [error]
},
{
type: 'page',
pattern: /^\/foo\/bar\/?$/,
params: [],
path: '/foo/bar',
a: [
'samples/layout-reset/foo/bar/$layout.reset.svelte',
'samples/layout-reset/foo/bar/index.svelte'
],
b: ['samples/layout-reset/foo/bar/$error.svelte']
}
]);
});

test.run();
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<h1>Layout reset</h1>
<slot></slot>
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import * as assert from 'uvu/assert';

/** @type {import('../../../../../../types').TestMaker} */
export default function (test) {
test('resets layout', '/nested-layout/reset', async ({ page }) => {
assert.ok(await page.evaluate(() => !document.querySelector('footer')));
assert.ok(await page.evaluate(() => !document.querySelector('p')));
assert.equal(await page.textContent('h1'), 'Layout reset');
assert.equal(await page.textContent('h2'), 'Hello');
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<h2>Hello</h2>