Skip to content
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

Mt/link types #16

Merged
merged 2 commits into from
Dec 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
5 changes: 5 additions & 0 deletions .changeset/gold-oranges-switch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@vtbag/turn-signal': minor
---

link-types: assign view transition types directly to the links that trigger navigation!
21 changes: 17 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,31 @@ The @vtbag website can be found at https://vtbag.dev/

## !!! News !!!

Transition types and direction attributes are now also determined on the old page!
The Turn-Signal learned a new trick! With the new `link-types` script, you can assign view transition types directly to the links that trigger navigation. This means you can create different view transition animations for the same page, based on the link that takes you there! Simply use `data-vtbag-link-types` attributes to set transition types and use them in you CSS to guard your animation rules.

But that's not all: `link-types` lets you specify different transition types for history back navigation too!

Check out the [image viewer tech demo](https://vtbag.dev/viewwe-demo/) for a hands-on example and the docs at [vtbag.dev/tools/turn-signal](https://vtbag.dev/tools/turn-signal#link-types).

Happy animating! 🎉


For details see the [CHANGELOG](https://github.com/vtbag/turn-signal/blob/main/CHANGELOG.md) and the [documentation](https://vtbag.dev/tools/turn-signal/).



### What happened before?

> Transition types and direction attributes are now also determined on the old page!

For details see the [CHANGELOG](https://github.com/vtbag/turn-signal/blob/main/CHANGELOG.md) and the [documentation](https://vtbag.dev/tools/turn-signal/).

## What is it?

Turn-Signal is a lightweight script that enhances cross-document view transitions by detecting the direction of browser navigation. It enables developers to create smooth, responsive transitions that adjust based on forward or backward navigation, delivering a more intuitive user experience.
Turn-Signal is a lightweight script that enhances *browser-native* *cross-document* **view transitions** by detecting the **direction** of browser **navigation**. It enables developers to create smooth, responsive transitions that adjust based on forward or backward navigation, delivering a more intuitive user experience.

When your pages slide to the left on forward navigation, let them slide to the right when the users goes back in the browser's history.

The script automatically detects the traversal direction and sets `backward`, `neither` or `forward` view transition types accordingly. You can also instruct the script to set data attributes on the `<html>` element.
The script automatically detects the traversal direction and sets `backward`, `same` or `forward` view transition types accordingly. You can also instruct the script to set data attributes on the `<html>` element.

If your site has the concept of a _previous_ and _next_ page, the Turn-Signal can automatically generate directional transitions for you.

Expand Down
2 changes: 1 addition & 1 deletion bin/bundle
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ else
OPTS="--minify"
(cd lib && rm *.js.map) >> /dev/null 2>&1
fi
npx esbuild src/index.ts src/forced-traversal.ts --bundle $OPTS --target=ESnext --outdir=lib
npx esbuild src/index.ts src/forced-traversal.ts src/link-types.ts --bundle $OPTS --target=ESnext --outdir=lib

tsc
7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,14 @@
"lib/index.js",
"lib/index.d.ts",
"lib/forced-traversal.js",
"lib/forced-traversal.d.ts"
"lib/forced-traversal.d.ts",
"lib/link-types.js",
"lib/link-types.d.ts"
],
"exports": {
".": "./lib/index.js",
"./forced-traversal": "./lib/forced-traversal.js"
"./forced-traversal": "./lib/forced-traversal.js",
"./link-types": "./lib/link-types.js"
},
"scripts": {
"dev": "bin/bundle dev",
Expand Down
4 changes: 2 additions & 2 deletions src/dom-view-transisions-level2.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ declare global {
}

interface NavigationActivation {
entry: NavigationEntry;
from: NavigationEntry;
entry: NavigationHistoryEntry;
from: NavigationHistoryEntry;
navigationType: string;
}
interface AnimationEffect {
Expand Down
10 changes: 5 additions & 5 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
const currentScript = document.currentScript;

function direction(e: PageSwapEvent | PageRevealEvent) {
const activation = e.type === 'pageswap' ? (e as PageSwapEvent).activation : navigation?.activation;
const activation =
e.type === 'pageswap' ? (e as PageSwapEvent).activation : navigation?.activation;
if (e.viewTransition && activation) {
const pages = allPages();
let hereIdx = 1,
Expand All @@ -11,9 +12,9 @@ function direction(e: PageSwapEvent | PageRevealEvent) {
fromIdx = activation.from?.index;
} else {
if (pages.length) {
const index = (url: string) => pages.indexOf(new URL(url).pathname);
hereIdx = index(activation.entry?.url);
fromIdx = index(activation.from?.url);
const index = (url: string) => pages.indexOf(new URL(url, location.href).pathname);
hereIdx = index(activation.entry?.url ?? '');
fromIdx = index(activation.from?.url ?? '');
if (hereIdx === -1 || fromIdx === -1) {
hereIdx = 1;
fromIdx = 0;
Expand Down Expand Up @@ -75,4 +76,3 @@ function allPages() {

'onpagereveal' in window && addEventListener('pagereveal', direction);
'onpageswap' in window && addEventListener('pageswap', direction);

45 changes: 45 additions & 0 deletions src/link-types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { direction, activation } from './navigation';

let anchor: Element | null = null;

addEventListener('DOMContentLoaded', () => {
document.addEventListener('click', (event) => {
const target = event.composedPath()[0];
anchor = target instanceof Element ? target.closest('a, area') : null;
anchor = anchor?.hasAttribute('data-vtbag-link-types') ? anchor : null;
});
});

addEventListener('pageswap', (event) => {
if (!event.viewTransition) return;
const lastAnchor = anchor;
anchor = null;
let types = history.state?.vtbagTypes ?? '';
if (activation(event).navigationType === 'traverse' && direction(event) === 'backward') return;
if (lastAnchor) {
types = lastAnchor.getAttribute('data-vtbag-link-types') ?? '';
console.log('s-types :>> ', types);
setViewTransitionTypes(types);
}
sessionStorage?.setItem('vtbag-link-types', types.split(/\s*\/\s*/, 1)[0]);
sessionStorage
?.getItem('vtbag-link-types')
?.split(/\s+/)
.forEach((type) => event.viewTransition?.types?.add(type));
console.log('x', ...event.viewTransition?.types);
});

addEventListener('pagereveal', (event) => {
if (!event.viewTransition) return;
let types = sessionStorage?.getItem('vtbag-link-types') ?? '';
if (activation().navigationType === 'traverse' && direction() === 'backward') {
types = history.state?.vtbagTypes ?? '';
types.includes('/') && (types = types.split(/\s*\/\s*/, 2)[1]);
}
types.split(/\s+/).forEach((type) => event.viewTransition?.types?.add(type));
console.log('r-types :>> ', [...event.viewTransition?.types]);
});

export function setViewTransitionTypes(types: string) {
history.replaceState({ ...history.state, vtbagTypes: types }, '');
}
11 changes: 11 additions & 0 deletions src/navigation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export const activation = (e?: PageSwapEvent | PageRevealEvent) =>
e && 'activation' in e ? (e as PageSwapEvent).activation : window.navigation.activation;

export function direction(e?: PageSwapEvent | PageRevealEvent) {
const act = activation(e);
return act?.from.index > act?.entry.index
? 'backward'
: act.entry.index === act.from.index
? 'same'
: 'forward';
}
Loading