Skip to content

Commit 70f9ad8

Browse files
committed
fix typing for action and move jsdoc to return value
1 parent facb4f5 commit 70f9ad8

File tree

5 files changed

+147
-61
lines changed

5 files changed

+147
-61
lines changed

.changeset/mighty-pigs-kiss.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'sveltekit-view-transition': patch
3+
---
4+
5+
fix typing for action and move jsdoc to return value

README.md

+21-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,27 @@ Simplified `view-transition-api` for Sveltekit.
99

1010
## Before we begin: what is a view transition?
1111

12-
I could go in thousands of details on what `view-transitions` are but what a better way of understanding them that from the words of Jake Archibald, the main mind behind them? Here's a [wonderful article](https://developer.chrome.com/docs/web-platform/view-transitions/) from him that explains what they are and how to use them in Vanilla JS.
12+
Svelte has kinda spoiled us: we have built in animations and transitions so that we can add a little bit of micro-interactions to our websites and apps. Do you need to animate a list reordering? `flip` comes to the rescue. Is a div moving and morphing from one list to another? `crossfade` is your friend. The web platform must have seen how much svelte developers love those kind of things and has provided us with a brand new, fully progressive enhance-able api: **[the view transition API](https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API)**. This api not only allows you to animate between two states of your application regardless of the fact that two elements are actually the same or not (something that before was only possible with third party libraries or very complex code) but allows you to animate elements that are **on different pages**!
13+
14+
SvelteKit provides a way to hook into the navigation to allow the developer to start a view transition before the navigation and they do so with a very low level primitive. Here's how you can enable view transitions in SvelteKit
15+
16+
```ts
17+
onNavigate((navigation) => {
18+
if (!document.startViewTransition) return;
19+
return new Promise((resolve) => {
20+
document.startViewTransition(async () => {
21+
resolve();
22+
await navigation.complete;
23+
});
24+
});
25+
});
26+
```
27+
28+
While not very complex, writing this snippets everywhere you need it can get quite tedious and sometimes based on how the `view-transition-api` works you might need to do other things like add classes or change the style of an element.
29+
30+
`sveltekit-view-transition` aim to ease the experience of writing easy and complex transitions in SvelteKit!
31+
32+
Before going in the details of how this library works and how to make use of it i want to leave here a [wonderful article](https://developer.chrome.com/docs/web-platform/view-transitions/) that explains what they are and how to use them in Vanilla JS from Jake Archibald, the main mind behind them.
1333

1434
## Installation
1535

src/lib/sveltekit-view-transition.ts

+57-57
Original file line numberDiff line numberDiff line change
@@ -96,14 +96,6 @@ function run_all_events<T extends SveltekitViewTransitionEvents>(
9696
}
9797
}
9898

99-
/**
100-
* This function is used to deregister from an event. A function that
101-
* deregister from an event is also returned from the on function.
102-
* @param event the event name you want to deregister from
103-
* @param callback the callback reference you want to deregister
104-
* @param autoWrap by default the off function is wrapped in afterNavigate so that you can
105-
* avoid unnecessarily wrap it every time. If you need to avoid this behavior you can pass false.
106-
*/
10799
function off<T extends SveltekitViewTransitionEvents>(
108100
event: T,
109101
callback: (props: SveltekitViewTransitionEventsMap[T]) => void | Promise<void>,
@@ -142,19 +134,6 @@ function off<T extends SveltekitViewTransitionEvents>(
142134
}
143135
}
144136

145-
/**
146-
* Function used to register a callback run during the onNavigate
147-
* @param event the event name you want to register a callback for
148-
* @param callback The callback you want to run
149-
* @param options The options for the add listener
150-
* @param options.registerDuringTransition if you want to register this callback even if a transition is running (if false
151-
* it will still be registered as soon as the transition finishes)
152-
* @param options.avoidWrapping by default the on function is wrapped in afterNavigate so that you can
153-
* avoid unnecessarily wrap it every time. If you need to avoid this behavior you can pass true.
154-
* @param options.autoClean wether the listener clean automatically after has been applied or it requires manual cleaning.
155-
* it defaults to true
156-
* @returns A function to deregister the callback
157-
*/
158137
function on<T extends SveltekitViewTransitionEvents>(
159138
event: T,
160139
callback: (props: SveltekitViewTransitionEventsMap[T]) => void,
@@ -199,18 +178,6 @@ function on<T extends SveltekitViewTransitionEvents>(
199178
return return_value;
200179
}
201180

202-
/**
203-
* Function to call during component initialization to add a class or a series of classes
204-
* during the navigation. This is useful to run a different types of transition when you are going
205-
* back to a specific page.
206-
*
207-
* The classes will be automatically removed at the end of the transition.
208-
*
209-
* @param to_add either a list of class that will always be applied or a function that returns an array
210-
* of strings. The function will get a navigation props as input to allow you to check the to, from, route id etc.
211-
* @param autoWrap by default the classes function is wrapped in afterNavigate so that you can
212-
* avoid unnecessarily wrap it every time. If you need to avoid this behavior you can pass false.
213-
*/
214181
function classes(
215182
to_add:
216183
| string[]
@@ -249,30 +216,7 @@ function classes(
249216
);
250217
}
251218

252-
/**
253-
* The action to specify a transition name on a specific element. You can use it on an element
254-
* passing a string to directly assign that specific string as view transition name.
255-
*
256-
* If you pass an object instead you can specify a series of options:
257-
*
258-
* - name: required, it's the transition name that will be applied it can be either a string or a function that return a string. The function takes a navigation
259-
* object as input. This is useful if you need to apply different transition names depending on where the navigation is going.
260-
* - classes: either an array of strings or a function that returns an array of string that will be applied
261-
* during the transition. The function will take a navigation object
262-
* - applyImmediately: by default when you specify a transition name it will only be applied when it's actually navigating
263-
* following the suggestion from Jake Archibald himself (the creator of the view transition api) https://twitter.com/jaffathecake/status/1697541871847748098?s=20
264-
* that you should not add transition names to everything but only to the elements involved in the transition. Sometimes tho you want to
265-
* add a transition name immediately (for example when you are coming back from a detail page and you want to animate back an image in the list).
266-
* applyImmediately is either a boolean or a function that take the navigation object (please note that this is the navigation object) from
267-
* the previous page so the `from` will be the page that is navigating to this page and the `to` will be this page) and returns a boolean.
268-
* - shouldApply: as mentioned above this can be either a boolean or a function that takes a navigation object (this time the `from` is
269-
* this page and the `to` is the page you are navigating to) and return a boolean. If the boolean is true the transition name will be applied.
270-
* This is useful when you want to navigate from a list to a detail.
271-
*
272-
* @param node The element to apply the action to
273-
* @param props either a string for a simple view transition name or a set of options
274-
*/
275-
function transition(node: HTMLElement, props: string | TransitionAction) {
219+
function transition(node: HTMLElement | SVGElement, props: string | TransitionAction) {
276220
if (typeof props === 'string') {
277221
node.style.setProperty('view-transition-name', props);
278222
return;
@@ -434,9 +378,65 @@ export function setupViewTransition() {
434378
}
435379

436380
return {
381+
/**
382+
* Function used to register a callback run during the onNavigate
383+
* @param event the event name you want to register a callback for
384+
* @param callback The callback you want to run
385+
* @param options The options for the add listener
386+
* @param options.registerDuringTransition if you want to register this callback even if a transition is running (if false
387+
* it will still be registered as soon as the transition finishes)
388+
* @param options.avoidWrapping by default the on function is wrapped in afterNavigate so that you can
389+
* avoid unnecessarily wrap it every time. If you need to avoid this behavior you can pass true.
390+
* @param options.autoClean wether the listener clean automatically after has been applied or it requires manual cleaning.
391+
* it defaults to true
392+
* @returns A function to deregister the callback
393+
*/
437394
on,
395+
/**
396+
* This function is used to deregister from an event. A function that
397+
* deregister from an event is also returned from the on function.
398+
* @param event the event name you want to deregister from
399+
* @param callback the callback reference you want to deregister
400+
* @param autoWrap by default the off function is wrapped in afterNavigate so that you can
401+
* avoid unnecessarily wrap it every time. If you need to avoid this behavior you can pass false.
402+
*/
438403
off,
404+
/**
405+
* The action to specify a transition name on a specific element. You can use it on an element
406+
* passing a string to directly assign that specific string as view transition name.
407+
*
408+
* If you pass an object instead you can specify a series of options:
409+
*
410+
* - name: required, it's the transition name that will be applied it can be either a string or a function that return a string. The function takes a navigation
411+
* object as input. This is useful if you need to apply different transition names depending on where the navigation is going.
412+
* - classes: either an array of strings or a function that returns an array of string that will be applied
413+
* during the transition. The function will take a navigation object
414+
* - applyImmediately: by default when you specify a transition name it will only be applied when it's actually navigating
415+
* following the suggestion from Jake Archibald himself (the creator of the view transition api) https://twitter.com/jaffathecake/status/1697541871847748098?s=20
416+
* that you should not add transition names to everything but only to the elements involved in the transition. Sometimes tho you want to
417+
* add a transition name immediately (for example when you are coming back from a detail page and you want to animate back an image in the list).
418+
* applyImmediately is either a boolean or a function that take the navigation object (please note that this is the navigation object) from
419+
* the previous page so the `from` will be the page that is navigating to this page and the `to` will be this page) and returns a boolean.
420+
* - shouldApply: as mentioned above this can be either a boolean or a function that takes a navigation object (this time the `from` is
421+
* this page and the `to` is the page you are navigating to) and return a boolean. If the boolean is true the transition name will be applied.
422+
* This is useful when you want to navigate from a list to a detail.
423+
*
424+
* @param node The element to apply the action to
425+
* @param props either a string for a simple view transition name or a set of options
426+
*/
439427
transition,
428+
/**
429+
* Function to call during component initialization to add a class or a series of classes
430+
* during the navigation. This is useful to run a different types of transition when you are going
431+
* back to a specific page.
432+
*
433+
* The classes will be automatically removed at the end of the transition.
434+
*
435+
* @param to_add either a list of class that will always be applied or a function that returns an array
436+
* of strings. The function will get a navigation props as input to allow you to check the to, from, route id etc.
437+
* @param autoWrap by default the classes function is wrapped in afterNavigate so that you can
438+
* avoid unnecessarily wrap it every time. If you need to avoid this behavior you can pass false.
439+
*/
440440
classes,
441441
};
442442
}

src/routes/+page.svelte

+48-1
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,37 @@
6666
<Mouse {clicking} />
6767
</span>
6868
</a>
69+
<p>
70+
<a class="flex items-center gap-2" href="https://twitter.com/paoloricciuti"
71+
><svg
72+
in:receive={{
73+
key: 'github',
74+
}}
75+
out:send={{
76+
key: 'github',
77+
}}
78+
use:transition={'github'}
79+
aria-hidden="true"
80+
viewBox="0 0 16 16"
81+
version="1.1"
82+
class="h-4 w-4"
83+
fill="currentColor"
84+
><path
85+
fill-rule="evenodd"
86+
d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"
87+
></path></svg
88+
> sveltekit-view-transition</a
89+
>
90+
</p>
91+
<p>
92+
Made with 🧡 by <a class="underline" href="https://twitter.com/paoloricciuti"
93+
>paoloricciuti</a
94+
>
95+
</p>
6996
</main>
7097
{:else}
7198
<main class="absolute inset-0">
72-
<header class="bg-slate-800 p-4">
99+
<header class="flex justify-between bg-slate-800 p-4">
73100
<h1
74101
in:receive={{
75102
key: 'title',
@@ -81,6 +108,26 @@
81108
>
82109
<code use:transition={'title'}>`sveltekit-view-transition`</code>
83110
</h1>
111+
<a href="https://twitter.com/paoloricciuti"
112+
><svg
113+
in:receive={{
114+
key: 'github',
115+
}}
116+
out:send={{
117+
key: 'github',
118+
}}
119+
use:transition={'github'}
120+
aria-hidden="true"
121+
viewBox="0 0 16 16"
122+
version="1.1"
123+
class="h-8 w-8"
124+
fill="currentColor"
125+
><path
126+
fill-rule="evenodd"
127+
d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"
128+
></path></svg
129+
></a
130+
>
84131
</header>
85132
<p class="p-5 text-2xl font-bold">Getting started</p>
86133
<p class="px-5">

src/routes/docs/+page.svelte

+16-2
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,23 @@
55
const { transition } = setupViewTransition();
66
</script>
77

8-
<header class="sticky top-0 bg-slate-900 p-4">
8+
<header class="sticky top-0 flex justify-between bg-slate-900 p-4">
99
<h1><code use:transition={'title'} class="text-2xl">`sveltekit-view-transition`</code></h1>
10+
<a href="https://twitter.com/paoloricciuti"
11+
><svg
12+
use:transition={'github'}
13+
aria-hidden="true"
14+
viewBox="0 0 16 16"
15+
version="1.1"
16+
class="h-8 w-8"
17+
fill="currentColor"
18+
><path
19+
fill-rule="evenodd"
20+
d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"
21+
></path></svg
22+
></a
23+
>
1024
</header>
11-
<section class="prose prose-invert prose-h1:hidden m-auto overflow-y-auto p-4">
25+
<section class="prose prose-invert m-auto overflow-y-auto p-4 prose-h1:hidden">
1226
<Readme />
1327
</section>

0 commit comments

Comments
 (0)