View transition api and solid start

Has anybody gotten view transition api working reliably with solid router? I tried following code but it doesnt work always for some reason.
const VtApi: ParentComponent = (props) => {
const transition = (fnStartingTheSynchronousTransition) => {
// In case the API is not yet supported
if (!document.startViewTransition) {
return fnStartingTheSynchronousTransition();
}

// Transition the changes in the DOM
const transition = document.startViewTransition(
fnStartingTheSynchronousTransition,
);
};

useBeforeLeave((e) => {
// Stop the inmediate navigation and DOM change
if (!e.defaultPrevented) {
e.preventDefault();

// Perform the action that triggers a DOM change synchronously
transition(() => {
e.retry(true);
});
}
});

return <>{props.children}</>;
};

export default VtApi;
const VtApi: ParentComponent = (props) => {
const transition = (fnStartingTheSynchronousTransition) => {
// In case the API is not yet supported
if (!document.startViewTransition) {
return fnStartingTheSynchronousTransition();
}

// Transition the changes in the DOM
const transition = document.startViewTransition(
fnStartingTheSynchronousTransition,
);
};

useBeforeLeave((e) => {
// Stop the inmediate navigation and DOM change
if (!e.defaultPrevented) {
e.preventDefault();

// Perform the action that triggers a DOM change synchronously
transition(() => {
e.retry(true);
});
}
});

return <>{props.children}</>;
};

export default VtApi;
7 Replies
apollo79
apollo792mo ago
Do you know when exactly it doesn't work? My implementation looks similar and it works fine
Massukka
Massukka2mo ago
It works like 70% of the time on routing. I have no idea on what situations it fails.
apollo79
apollo792mo ago
import type { ParentComponent } from "solid-js";
import { type RouteSectionProps, useBeforeLeave } from "@solidjs/router";

import "./view-transition.css";
export const ViewTransition: ParentComponent<RouteSectionProps> = (props) => {
  let isTransitionNavigate = false;

  useBeforeLeave((event) => {
    if (document.startViewTransition) {

      // if this is not already the second navigation,
      // which happens after the view-transition was initialized from inside this component
      if (!isTransitionNavigate) {
        const isBackNavigation = Number.isInteger(event.to) && (event.to as number) < 0;

        event.preventDefault();

        isTransitionNavigate = true;

        if (isBackNavigation) {
          document.documentElement.classList.add("back-navigation");
        const transition = document.startViewTransition(() => {
          event.retry();
        });

        transition.finished.finally(() => {
          isTransitionNavigate = false;
          document.documentElement.classList.remove("back-navigation");
        });
      }
    }
  });

  return <>{props.children}</>;
};
import type { ParentComponent } from "solid-js";
import { type RouteSectionProps, useBeforeLeave } from "@solidjs/router";

import "./view-transition.css";
export const ViewTransition: ParentComponent<RouteSectionProps> = (props) => {
  let isTransitionNavigate = false;

  useBeforeLeave((event) => {
    if (document.startViewTransition) {

      // if this is not already the second navigation,
      // which happens after the view-transition was initialized from inside this component
      if (!isTransitionNavigate) {
        const isBackNavigation = Number.isInteger(event.to) && (event.to as number) < 0;

        event.preventDefault();

        isTransitionNavigate = true;

        if (isBackNavigation) {
          document.documentElement.classList.add("back-navigation");
        const transition = document.startViewTransition(() => {
          event.retry();
        });

        transition.finished.finally(() => {
          isTransitionNavigate = false;
          document.documentElement.classList.remove("back-navigation");
        });
      }
    }
  });

  return <>{props.children}</>;
};
This is my solution and it works... I am not at my computer rn so can't really dig deeper
Massukka
Massukka2mo ago
Thanks a lot. With your code it works pretty much always.
Luka
Luka2mo ago
Oohh I would like to use this too! Where do I place this code? In app.tsx as a comp?
Massukka
Massukka2mo ago
I wrapped props.children with this component in app.tsx. Desktop works for the most part but i am still having issues with mobile browsers
Luka
Luka2mo ago
Thanks man!!