Skip to content

Commit

Permalink
demoe updates
Browse files Browse the repository at this point in the history
  • Loading branch information
martrapp committed Oct 15, 2024
1 parent e9bb56d commit cbbfa94
Show file tree
Hide file tree
Showing 13 changed files with 335 additions and 29 deletions.
2 changes: 1 addition & 1 deletion astro.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export default defineConfig({
integrations: [starlight({
title: '@vtbag',
components: {
Head: "./src/components/Head.astro",
Head: "./src/components/NHead.astro",
PageTitle: "./src/components/PageTitle.astro"
},
plugins: [starlightImageZoom()],
Expand Down
9 changes: 8 additions & 1 deletion src/components/DemoNavigation.astro
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
---
import LeaveDemoLink from "./LeaveDemoLink.astro";
export interface Props {
backlink: string;
prev: string;
next: string;
}
const { backlink, prev, next } = Astro.props;
---
<div class="demonav">{prev && (<a id="prev" href={"javascript:top.sessionStorage.setItem('vtbag-ui-standby','true'),top.location.href='" + prev + "'"}>Prev</a>)}<a id="back" href={"javascript:top.sessionStorage.setItem('vtbag-ui-standby','true'),top.location.href='" + backlink+"'"}>Back to the example list</a>{next && (<a id="next" href={"javascript:top.sessionStorage.setItem('vtbag-ui-standby','true'),top.location.href='" + next +"'"}>Next</a>)}</div>

<div class="demonav">
<LeaveDemoLink href={prev}>Prev</LeaveDemoLink><LeaveDemoLink href={backlink}>
Back to the example list
</LeaveDemoLink><LeaveDemoLink href={next}>Next</LeaveDemoLink>
</div>
<style is:global>
.demonav {
display: flex;
Expand Down
9 changes: 9 additions & 0 deletions src/components/LeaveDemoLink.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
export interface Props {
href: string;
}
const {href} = Astro.props;
---

{href && (<a href={"javascript:top.sessionStorage.setItem('vtbag-ui-standby','true'),top.location.assign('" + href + "')"}><slot/></a>)}

80 changes: 60 additions & 20 deletions src/components/NHead.astro
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,32 @@ import type { Props } from "@astrojs/starlight/props";
import StarlightHead from "@astrojs/starlight/components/Head.astro";
import turnSignal from "@vtbag/turn-signal?url";
import camShaft from "@vtbag/cam-shaft?url";
import "./vtbag-bar.css";
---

<StarlightHead {...Astro.props}><slot /></StarlightHead>
<script is:inline>
["pageswap", "pagereveal"].forEach((event) =>
addEventListener(
event,
(e) =>
e.viewTransition &&
document
.querySelectorAll("h2")
.forEach((h2, idx) => (h2.style.viewTransitionName = `h2-${idx}`))
)
);
</script>

{/* Decent transitions for scrolled down pages */}
<script is:inline src={camShaft}/>
<script is:inline src={camShaft}></script>

{/* Make animation direction based on the order of the pages in the sidebar */}
<script is:inline src={turnSignal} data-selector="nav.sidebar li a" />
<script is:inline src={turnSignal} data-selector="nav.sidebar li a"></script>

{
/* Without further configuration, make headings stand out during view transitions.
Can be used to declaratively add view transition names which open a door to all kinds of funny thing. */
/* Make headings stand out during view transitions. Can be used to declaratively add view transition names which open a door to all kinds of funny thing. */
}
<script is:inline>
["pageswap", "pagereveal"].forEach((eventName) =>
addEventListener(
eventName,
(event) =>
event.viewTransition &&
document
.querySelectorAll("h2, h3")
.forEach((heading, index) => (heading.style.viewTransitionName = `vtbag-h-${index}`))
)
);
</script>

<style is:global>
@view-transition {
Expand All @@ -37,47 +38,86 @@ import camShaft from "@vtbag/cam-shaft?url";
view-transition-name: main;
}
::view-transition-old(main) {
animation: forwardsSwingOut 150ms ease-in-out;
animation: forwardsSwingOut 400ms ease-in-out;
}
::view-transition-new(main) {
animation: forwardsSwingIn 150ms ease-in-out;
animation: forwardsSwingIn 400ms ease-in-out;
}
:active-view-transition-type(backward)::view-transition-old(main) {
animation: backwardsSwingOut 150ms ease-in-out;
animation: backwardsSwingOut 400ms ease-in-out;
}
:active-view-transition-type(backward)::view-transition-new(main) {
animation: backwardsSwingIn 150ms ease-in-out;
animation: backwardsSwingIn 400ms ease-in-out;
}
:active-view-transition-type(same)::view-transition-old(main) {
animation: shake-old 400ms ease-in-out;
}
:active-view-transition-type(same)::view-transition-new(main) {
animation: shake-new 400ms ease-in-out;
}
@keyframes forwardsSwingOut {
0% {
transform: translateX(0);
opacity: 1;
}
100% {
transform: translateX(-100%);
opacity: 0;
}
}
@keyframes forwardsSwingIn {
0% {
transform: translateX(100%);
opacity: 0;
}
100% {
transform: translateX(0);
opacity: 1;
}
}
@keyframes backwardsSwingOut {
0% {
transform: translateX(0);
opacity: 1;
}
100% {
transform: translateX(100%);
opacity: 0;
}
}
@keyframes backwardsSwingIn {
0% {
transform: translateX(-100%);
opacity: 0;
}
100% {
transform: translateX(0);
opacity: 1;
}
}
@keyframes shake-old {
25% {
transform: rotateZ(-2deg);
}
50% {
transform: rotateZ(0deg);
opacity: 0.5;
}
51%, 100% {
opacity: 0;
}
}
@keyframes shake-new {
0%, 49% {
opacity: 0;
}
50% {
transform: rotateZ(0deg);
opacity: 0.5;
}
75% {
transform: rotateZ(2deg);
opacity: 1;
}
}
::view-transition-image-pair(main) {
Expand Down
56 changes: 56 additions & 0 deletions src/components/vtbag-bar.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#vtbag-bar-outer {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 8px;
background-color: var(--sl-color-black);
z-index: 1000;
view-transition-name: vtbag-bar-outer;
}
#vtbag-bar {
background-color: var(--sl-color-accent);
height: 100%;
}
:root.vtbag-bar-old #vtbag-bar-inner {
height: 100%;
width: 25%;
background-color: var(--sl-color-white);
animation: slide 0.5s ease-in-out alternate infinite;
}

:root.vtbag-bar-old :is(#vtbag-bar, #vtbag-bar-inner) {
border-radius: 3pt;
transition: opacity 0.25s 0.25s;

@starting-style {
opacity: 0;
}

}
@keyframes slide {
0% {
transform: translateX(30%);
}
100% {
transform: translateX(75%);
}
}

:root.vtbag-bar-freeze #vtbag-bar {
background-color: red;
}
:root.vtbag-bar-new #vtbag-bar {
background-color: var(--sl-color-white);
}

::view-transition-old(vtbag-bar-outer),
::view-transition-new(vtbag-bar-outer) {
animation: none;
}

:active-view-transition,
:root.vtbag-bar-loading *,
:root.vtbag-bar-loading {
cursor: pointer !important;
}
126 changes: 126 additions & 0 deletions src/components/vtbag-bar.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
document.documentElement.classList.add("vtbag-bar-loading", "vtbag-bar-new");

let timeout:any;
let width = -1;
export function addBar(first:number) {
document.querySelector("#vtbag-bar-outer")?.remove();
console.log("adding");
document.body.insertAdjacentHTML(
"afterbegin",
`<div id="vtbag-bar-outer"><div id="vtbag-bar"><div id="vtbag-bar-inner"/></div></div>`
);
const timing = [
10, 20, 30, 40, 50, 100, 90, 80, 70, 60, 50, 40, 20, 25, 30, 35, 40, 45,
50, 55, 60, 65, 70, 75, 70, 65, 60, 55, 50, 45, 400, 35, 30, 25, 20, 20,
20, 20, 20, 20, 200, 20, 20, 20, 20, 400, 20, 20, 20, 20, 200, 20, 20, 20,
20, 30, 40, 50, 600, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160, 170,
180, 190, 200, 210, 220, 230, 240, 250, 260, 270, 280, 290, 300, 310, 320,
330, 340, 350, 360, 370, 380, 390, 400, 410, 420, 430, 440, 450, 460, 470,
];
timing[-1] = first;
let step = -1;
const f = () => {
width += 1;
console.log("width:", width);
const bar = document.getElementById("vtbag-bar");
if (bar) {
bar.style.width = `${width}%`;
if (timing[step] !== undefined) {
console.log("waiting for", timing[step], "ms");
clearTimeout(timeout);
timeout = setTimeout(f, timing[step++]);
}
sessionStorage.setItem("vtbag-bar", ""+width);
}
};
//f();
return document.getElementById("vtbag-bar");
}

const storedWidth = () => ~~sessionStorage.getItem("vtbag-bar")!;

// @ts-expect-error
navigation.addEventListener("navigate", (e) => {
console.log("event:", "navigate", e);

const back =
e.navigationType === "traverse" &&
// @ts-expect-error
e.destination.index < navigation.currentEntry.index;

if (
!e.downloadRequest &&
e.userInitiated &&
(!e.destination.sameDocument ||
(!back && !e.hashChange) ||
// @ts-expect-error
(back && !new URL(navigation.currentEntry.url).hash))
) {
document.documentElement.classList.add("vtbag-bar-loading", "vtbag-bar-old");
width = -1;
addBar(0);
}
});

addEventListener("DOMContentLoaded", (_e) =>
stop("DOMContentloaded", storedWidth() !== 0)
);

function stop(where: string, extend: boolean) {
console.log("stop", where, extend);
clearTimeout(timeout);
const bar = document.getElementById("vtbag-bar");
if (bar) {
if (extend) {
bar.style.width = "100%";
setTimeout(() => {
document.documentElement.classList.remove(
"vtbag-bar-loading",
"vtbag-bar-freeze",
"vtbag-bar-old",
"vtbag-bar-new"
);
bar.parentElement?.remove();
}, 200);
return;
}
bar.parentElement?.remove();
}
document.documentElement.classList.remove(
"vtbag-bar-loading",
"vtbag-bar-freeze",
"vtbag-bar-old",
"vtbag-bar-new"
);
}

["pageswap", "pagereveal"].forEach((event) =>
addEventListener(event, (e) => {
// @ts-expect-errork
console.log("event:", event, e.viewTransition);
// @ts-expect-error
if (e.viewTransition) {
let bar = document.getElementById("vtbag-bar");
width = storedWidth();
console.log("width :>> ", width);
if (bar) {
// pageswap
if (width < 1) {
stop("pageswap", false);
return;
}
document.documentElement.classList?.add("vtbag-bar-freeze");
width+=30;
addBar(0);
} else {
// pagereveal
if (width < 1) return;
bar = addBar(0);
// @ts-expect-error
e.viewTransition.ready.then(() => stop("ready", true));
}
} else {
stop("no viewTransition", false);
}
})
);
2 changes: 1 addition & 1 deletion src/content/docs/vtbag.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ The third block contains practical tips and tricks for styling view transitions.

@vtbag is all about the View Transition API. Find out [more about this browser API](https://events-3bg.pages.dev/jotter/api/).

The content part of this site is build with [Starlight + View Transitions](https://events-3bg.pages.dev/jotter/starlight/guide/). Thanks to Astro's view transition simulation, you can experience some of the effects on the content pages even with browsers that do not yet offer native support for the View Transition API.
The content part of this site is build with Starlight + browser-native cross-document view transitions. To see the effects you need a browser with [native view transition support](https://events-3bg.pages.dev/jotter/api/test-page/).

The tech demos on this site are independent of Astro. They only use the View Transition API and require browsers with native support for it. Cross document effects need a [level 2 compliant browser](https://events-3bg.pages.dev/jotter/api/test-page/). The [Inspection Chamber](/tools/inspection-chamber/) also requires support for view transitions inside iframes, which might require you to manually set the `chrome://flags/#view-transition-on-navigation-iframe` flag.

Expand Down
6 changes: 3 additions & 3 deletions src/layouts/DemoLayout.astro
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
import DemoNavigation from '@/components/DemoNavigation.astro';
import DemoNavigation from "@/components/DemoNavigation.astro";
export interface Props {
title: string;
backlink: string;
Expand All @@ -26,9 +26,9 @@ const script =
</head>
<body>
<h1>{title}</h1>
<DemoNavigation {prev} {backlink} {next}/>
<DemoNavigation {prev} {backlink} {next} />
<slot />
<div id="vtbag-spacer" style="min-height:100vh"></div>
<DemoNavigation {prev} {backlink} {next}/>
<DemoNavigation {prev} {backlink} {next} />
</body>
</html>
Loading

0 comments on commit cbbfa94

Please sign in to comment.