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

feat: 遷移アニメーションを追加 #29

Merged
merged 4 commits into from
Oct 20, 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
6 changes: 5 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
{
"[javascript][javascriptreact][typescript][typescriptreact][css][scss][html][json][jsonc][yaml]": {
"[javascript][javascriptreact][typescript][typescriptreact][css][scss][postcss][html][json][jsonc][yaml]": {
"editor.defaultFormatter": "biomejs.biome"
},
"editor.codeActionsOnSave": {
"quickFix.biome": "explicit",
"source.organizeImports.biome": "explicit"
},
"tailwindCSS.experimental.classRegex": [
["cva\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"],
["cx\\(([^)]*)\\)", "(?:'|\"|`)([^']*)(?:'|\"|`)"]
Expand Down
17 changes: 16 additions & 1 deletion app/components/Background.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import type { ReactNode } from "react";
import { useId } from "react";
import { useEffect, useId, useRef } from "react";

import { cva } from "class-variance-authority";
import { useReducedMotion } from "~/hooks/useMedia";
import { cn } from "~/libs/utils";
import { useTheme } from "./Theme";

Expand Down Expand Up @@ -35,12 +36,26 @@ export function Background({
}: BackgroundProps): ReactNode {
const id = useId();
const theme = useTheme();
const isReducedMotion = useReducedMotion();

const svgRef = useRef<SVGSVGElement>(null);
useEffect(() => {
const $svg = svgRef.current;
if (!$svg) return;

if (isReducedMotion) {
$svg.pauseAnimations();
} else {
$svg.unpauseAnimations();
}
}, [isReducedMotion]);

return (
<svg
xmlns="http://www.w3.org/2000/svg"
role="presentation"
className={cn("-z-50 absolute inset-0 h-full w-full", className)}
ref={svgRef}
{...props}
>
<defs>
Expand Down
4 changes: 3 additions & 1 deletion app/components/BottomNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,9 @@ export function BottomNav({ path, className }: BottomNavProps): ReactNode {
link.href === path && "-translate-y-1 -rotate-2",
)}
>
<Link to={link.href}>{link.label}</Link>
<Link to={link.href} viewTransition>
{link.label}
</Link>
</NavigationMenu.Link>
</NavigationMenu.Item>
))}
Expand Down
22 changes: 22 additions & 0 deletions app/hooks/useMedia.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { useSyncExternalStore } from "react";

export function useMedia(query: string, defaultState: boolean): boolean {
return useSyncExternalStore(
(callback) => {
const media = window.matchMedia(query);

media.addEventListener("change", callback);
return () => {
media.removeEventListener("change", callback);
};
},
() => {
return window.matchMedia(query).matches;
},
() => defaultState,
);
}

export function useReducedMotion(): boolean {
return useMedia("(prefers-reduced-motion: reduce)", false);
}
6 changes: 5 additions & 1 deletion app/routes/_auth.edit.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import type { ReactNode } from "react";

export default function Page(): ReactNode {
return <h1>キャラ編集</h1>;
return (
<main style={{ viewTransitionName: "main" }}>
<h1>キャラ編集</h1>
</main>
);
}
6 changes: 5 additions & 1 deletion app/routes/_auth.guide.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import type { ReactNode } from "react";

export default function Page(): ReactNode {
return <h1>遊び方</h1>;
return (
<main style={{ viewTransitionName: "main" }}>
<h1>遊び方</h1>
</main>
);
}
2 changes: 1 addition & 1 deletion app/routes/_auth.play.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export default function Page() {

if (!session) return null;
return (
<div className="p-4 font-sans">
<div className="p-4 font-sans" style={{ viewTransitionName: "main" }}>
<h1 className="text-3xl">QR code</h1>
<ul className="mt-4 list-disc space-y-2 pl-6">
<QRCode url={session.user.id} size={512} />
Expand Down
5 changes: 4 additions & 1 deletion app/routes/_index/route.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ export default function Page() {
};

return (
<main className="grid h-dvh w-dvw grid-rows-2">
<main
className="grid h-dvh w-dvw grid-rows-2"
style={{ viewTransitionName: "main" }}
>
<h1 className="p-4 text-center text-4xl">Game</h1>
<div className="mx-auto flex max-w-96 flex-col gap-2 p-4">
{myProfile ? (
Expand Down
28 changes: 28 additions & 0 deletions app/tailwind.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,31 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

/** 「視差効果を減らす」が有効な場合に、アニメーションやトランジションを無効化する */
@media (prefers-reduced-motion: reduce) {
html:focus-within {
scroll-behavior: auto;
}
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}

::view-transition-group(*),
::view-transition-old(*),
::view-transition-new(*) {
animation: none !important;
}
}

::view-transition-old(root) {
animation: none;
}
::view-transition-new(root) {
animation: none;
}