Skip to content

New book open animation. - #31

Merged
clates merged 1 commit into
mainfrom
feat/explainadd
Dec 28, 2025
Merged

New book open animation.#31
clates merged 1 commit into
mainfrom
feat/explainadd

Conversation

@clates

@clates clates commented Dec 28, 2025

Copy link
Copy Markdown
Owner

No description provided.

@clates
clates requested a review from Copilot December 28, 2025 05:09
@vercel

vercel Bot commented Dec 28, 2025

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
lfl-booktracker Ready Ready Preview, Comment Dec 28, 2025 5:10am

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces an animated book-opening component to display tracking codes in a more engaging way. The implementation replaces a simple text display with a 3D book animation that opens to reveal instructions written in handwriting font, complete with confetti effects.

Key Changes:

  • Added new BookStickerInstruction component with 3D book flip animation and typewriter effects
  • Integrated framer-motion for animations and canvas-confetti for celebration effects
  • Added Caveat font for handwriting-style text
  • Replaced static tracking code display in the add-sighting flow

Reviewed changes

Copilot reviewed 6 out of 9 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
components/book-sticker-instruction.tsx New animated component with 3D book open effect, typewriter animation, and confetti
components/add-sighting-drawer.tsx Integrated the new book instruction component
app/showcase/book-instruction/page.tsx Added showcase page for testing the animation
app/layout.tsx Added Caveat font for handwriting style
tailwind.config.ts Added handwriting font family configuration
package.json Added framer-motion, canvas-confetti, and type definitions
yarn.lock Dependency lock file updates for new packages

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

)}

{/* Cover Texture Overlay */}
<div className="absolute inset-0 bg-[url('https://www.transparenttextures.com/patterns/leather.png')] opacity-30 mix-blend-multiply" />

Copilot AI Dec 28, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using an external texture URL from transparenttextures.com creates a dependency on a third-party service. If this service goes down, the texture will fail to load. Consider hosting the texture locally or inlining it as a data URI for better reliability.

Suggested change
<div className="absolute inset-0 bg-[url('https://www.transparenttextures.com/patterns/leather.png')] opacity-30 mix-blend-multiply" />
<div className="absolute inset-0 bg-[radial-gradient(circle_at_20%_20%,rgba(0,0,0,0.15),transparent_50%),radial-gradient(circle_at_80%_80%,rgba(0,0,0,0.2),transparent_55%)] opacity-30 mix-blend-multiply" />

Copilot uses AI. Check for mistakes.
<img
src={coverUrl}
alt="Book Cover"
className="w-full h-full opacity-90 mix-blend-overlay"

Copilot AI Dec 28, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The coverUrl is used directly in an img src without validation. Consider adding error handling for failed image loads (e.g., using the onError event) to prevent broken image displays and provide a better user experience.

Suggested change
className="w-full h-full opacity-90 mix-blend-overlay"
className="w-full h-full opacity-90 mix-blend-overlay"
onError={(e) => {
e.currentTarget.style.display = "none"
}}

Copilot uses AI. Check for mistakes.
{coverUrl ? (
<img
src={coverUrl}
alt="Book Cover"

Copilot AI Dec 28, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing alt text for the book cover image. The alt attribute should provide meaningful description of the book cover for accessibility purposes, not just "Book Cover". Consider using the book title or description if available.

Suggested change
alt="Book Cover"
alt="Illustrated book cover"

Copilot uses AI. Check for mistakes.
Comment on lines +241 to +253
<div className="absolute -right-8 top-1/2 -translate-y-1/2 opacity-0 group-hover/code:opacity-100 transition-opacity">
<Button
variant="ghost"
size="icon"
className="h-8 w-8 text-amber-700 hover:text-amber-900 hover:bg-amber-100/50"
>
{copied ? (
<Check className="h-4 w-4" />
) : (
<Copy className="h-4 w-4" />
)}
</Button>
</div>

Copilot AI Dec 28, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The copy button and code text are only accessible via hover (group-hover/code). This creates accessibility issues for keyboard-only users and touch device users who cannot hover. Consider making the copy button always visible or providing an alternative interaction method.

Copilot uses AI. Check for mistakes.
{/* The component under test */}
<BookStickerInstruction
code={code}
coverUrl="http://books.google.com/books/content?id=B1hSG45JCX4C&printsec=frontcover&img=1&zoom=1&source=gbs_api"

Copilot AI Dec 28, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The hardcoded cover URL in the showcase may break if the Google Books API removes or changes this image. Consider using a locally hosted sample image or making this more robust by documenting that it's for demonstration purposes only.

Copilot uses AI. Check for mistakes.
type: "spring",
damping: 12,
stiffness: 100,
} as any, // Cast to any to bypass strict variant typing issues with spring

Copilot AI Dec 28, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The as any type assertions used here to bypass TypeScript's strict variant typing are not ideal. Consider using proper type definitions or defining a more specific type for the transition object. This pattern appears twice (lines 46 and 55) and can hide potential type errors.

Copilot uses AI. Check for mistakes.
Comment on lines +131 to +132
// Fallback cover if none provided
const finalCoverUrl = coverUrl || "/images/placeholder-cover.jpg"

Copilot AI Dec 28, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fallback image URL /images/placeholder-cover.jpg may not exist. Consider either ensuring this asset exists in the public directory, or handling the case where no cover is provided more gracefully (e.g., showing a generic placeholder component).

Suggested change
// Fallback cover if none provided
const finalCoverUrl = coverUrl || "/images/placeholder-cover.jpg"
// Fallback cover if none provided: use an inline SVG data URL so it always exists
const placeholderCoverSvg =
'data:image/svg+xml;utf8,' +
encodeURIComponent(
`<svg xmlns="http://www.w3.org/2000/svg" width="400" height="600" viewBox="0 0 400 600">
<defs>
<linearGradient id="grad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#f5f5f4"/>
<stop offset="100%" stop-color="#e7e5e4"/>
</linearGradient>
</defs>
<rect width="400" height="600" fill="url(#grad)" rx="24" ry="24"/>
<rect x="36" y="60" width="328" height="36" fill="#a8a29e" opacity="0.35" rx="6"/>
<rect x="36" y="116" width="328" height="20" fill="#a8a29e" opacity="0.2" rx="4"/>
<rect x="36" y="146" width="260" height="20" fill="#a8a29e" opacity="0.2" rx="4"/>
<rect x="36" y="176" width="220" height="20" fill="#a8a29e" opacity="0.2" rx="4"/>
<rect x="36" y="230" width="328" height="260" fill="#d6d3d1" opacity="0.35" rx="12"/>
<text x="50%" y="520" text-anchor="middle" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif" font-size="20" fill="#78716c">
Book cover
</text>
</svg>`
)
const finalCoverUrl = coverUrl || placeholderCoverSvg

Copilot uses AI. Check for mistakes.

export default function BookInstructionShowcasePage() {
const [code, setCode] = useState("ABCD-1234")
const [key, setKey] = useState(0)

Copilot AI Dec 28, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused variable key.

Copilot uses AI. Check for mistakes.

import { useState, useEffect } from "react"
import { Check, Copy } from "lucide-react"
import { motion, AnimatePresence } from "framer-motion"

Copilot AI Dec 28, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused import AnimatePresence.

Suggested change
import { motion, AnimatePresence } from "framer-motion"
import { motion } from "framer-motion"

Copilot uses AI. Check for mistakes.
Comment on lines +131 to +133
// Fallback cover if none provided
const finalCoverUrl = coverUrl || "/images/placeholder-cover.jpg"

Copilot AI Dec 28, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused variable finalCoverUrl.

Suggested change
// Fallback cover if none provided
const finalCoverUrl = coverUrl || "/images/placeholder-cover.jpg"

Copilot uses AI. Check for mistakes.
@clates
clates merged commit 00e7815 into main Dec 28, 2025
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants