Skip to content

fix <details> in blog posts #335

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 3 commits into from
Oct 11, 2024
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
108 changes: 50 additions & 58 deletions apps/svelte.dev/content/blog/2023-08-31-view-transitions.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,32 +76,28 @@ With that, every navigation that occurs will trigger a view transition. You can

<video src="https://sveltejs.github.io/assets/video/vt-demo-1.mp4" controls muted playsinline></video>

<details>
<summary>How the code works</summary>

This code may look a bit intimidating – if you're curious, I can break it down line-by-line, but for now it’s enough to know that adding it will allow you to interact with the view transitions API during navigation.

As mentioned above, the `onNavigate` callback will run immediately before the new page is rendered after a navigation. Inside the callback, we check if `document.startViewTransition` exists. If it doesn’t (i.e. the browser doesn’t support it), we exit early.

We then return a promise to delay completing the navigation until the view transition has started. We use a [promise constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/Promise) so that we can control when the promise resolves.

```js
// @errors: 1108
return new Promise((resolve) => {
document.startViewTransition(async () => {
resolve();
await navigation.complete;
});
});
```

Inside the promise constructor, we start the view transition. Inside the view transition callback we resolve the promise we just returned, which indicates to SvelteKit that it should finish the navigation. It’s important that the navigation waits to finish until _after_ we start the view transition – the browser needs to snapshot the old state so it can transition to the new state.

Finally, inside the view transition callback we wait for SvelteKit to finish the navigation by awaiting `navigation.complete`. Once `navigation.complete` resolves, the new page has been loaded into the DOM and the browser can animate between the two states.

It’s a bit of a mouthful, but by not abstracting it we allow you to interact with the view transition directly and make any customizations you require.

</details>
> [!DETAILS] How the code works
> This code may look a bit intimidating – if you're curious, I can break it down line-by-line, but for now it’s enough to know that adding it will allow you to interact with the view transitions API during navigation.
>
> As mentioned above, the `onNavigate` callback will run immediately before the new page is rendered after a navigation. Inside the callback, we check if `document.startViewTransition` exists. If it doesn’t (i.e. the browser doesn’t support it), we exit early.
>
> We then return a promise to delay completing the navigation until the view transition has started. We use a [promise constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/Promise) so that we can control when the promise resolves.
>
> ```js
> // @errors: 1108
> return new Promise((resolve) => {
> document.startViewTransition(async () => {
> resolve();
> await navigation.complete;
> });
> });
> ```
>
> Inside the promise constructor, we start the view transition. Inside the view transition callback we resolve the promise we just returned, which indicates to SvelteKit that it should finish the navigation. It’s important that the navigation waits to finish until > _after_ we start the view transition – the browser needs to snapshot the old state so it can transition to the new state.
>
> Finally, inside the view transition callback we wait for SvelteKit to finish the navigation by awaiting `navigation.complete`. Once `navigation.complete` resolves, the new page has been loaded into the DOM and the browser can animate between the two states.
>
> It’s a bit of a mouthful, but by not abstracting it we allow you to interact with the view transition directly and make any customizations you require.

## Customizing the transition with CSS

Expand Down Expand Up @@ -163,38 +159,34 @@ Now, the header will not transition in and out on navigation, but the rest of th

<video src="https://sveltejs.github.io/assets/video/vt-demo-2.mp4" controls muted playsinline></video>

<details>
<summary>Fixing the types</summary>

Since `startViewTransition` is not supported by all browsers, your IDE may not know that it exists. To make the errors go away and get the correct typings, add the following to your `app.d.ts`:

```ts
declare global {
// preserve any customizations you have here
namespace App {
// interface Error {}
// interface Locals {}
// interface PageData {}
// interface Platform {}
}

// add these lines
interface ViewTransition {
updateCallbackDone: Promise<void>;
ready: Promise<void>;
finished: Promise<void>;
skipTransition: () => void;
}

interface Document {
startViewTransition(updateCallback: () => Promise<void>): ViewTransition;
}
}

export {};
```

</details>
> [!DETAILS] Fixing the types
> Since `startViewTransition` is not supported by all browsers, your IDE may not know that it exists. To make the errors go away and get the correct typings, add the following to your `app.d.ts`:
>
> ```ts
> declare global {
> // preserve any customizations you have here
> namespace App {
> // interface Error {}
> // interface Locals {}
> // interface PageData {}
> // interface Platform {}
> }
>
> // add these lines
> interface ViewTransition {
> updateCallbackDone: Promise<void>;
> ready: Promise<void>;
> finished: Promise<void>;
> skipTransition: () => void;
> }
>
> interface Document {
> startViewTransition(updateCallback: () => Promise<void>): ViewTransition;
> }
> }
>
> export {};
> ```

## Transitioning individual elements

Expand Down
11 changes: 6 additions & 5 deletions packages/site-kit/src/lib/components/Text.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,9 @@
}
}

details.legacy {
details {
position: relative;

&::before,
&::after {
content: '';
Expand Down Expand Up @@ -487,16 +489,15 @@
align-items: center;
height: 3rem;
color: var(--sk-text-4);
font-family: var(--sk-font-ui);
font-style: normal;
font-size: var(--sk-font-size-ui-small);
font-size: var(--sk-font-size-body-small);
user-select: none;

&:hover {
color: var(--sk-text-3);
}

&::after {
.legacy &::after {
position: absolute;
display: flex;
align-items: center;
Expand All @@ -516,7 +517,7 @@
& > summary {
margin-bottom: 1.4rem;

&::after {
.legacy &::after {
content: 'hide all';
}
}
Expand Down
7 changes: 7 additions & 0 deletions packages/site-kit/src/lib/markdown/renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,13 @@ export async function render_content_markdown(
content = `<details class="legacy"><summary>Legacy mode</summary>${content.replace('[!LEGACY]', '')}</details>`;
}

if (content.includes('[!DETAILS]')) {
const regex = /\[!DETAILS\] (.+)/;
const match = regex.exec(content)!;
content = `<details><summary>${match[1]}</summary>${content.replace(regex, '')}</details>`;
return `<blockquote class="note">${content}</blockquote>`;
}

if (content.includes('[!NOTE]')) {
return `<blockquote class="note">${content.replace('[!NOTE]', '')}</blockquote>`;
}
Expand Down
Loading