Skip to content

Commit

Permalink
Feature/sticky note animation (#114)
Browse files Browse the repository at this point in the history
* update: added stickers to apply button anchor

* feature: animated sticky notes

* update: on scroll view animation

* fix: remove stickers

* update: animation timing adjustments and decoupling

* fix: adjusted tape

* fix: tape timing adjustment

* fix: animation triggers once

* fix: removed sticker assets and imports

* fix: removed sticker components

* fix: media queries for resource card width

* fix: tape timing adjustment

* feat: pin animation

* update: mentor sticky note animation
  • Loading branch information
tyleryy committed Nov 4, 2023
1 parent e8d3048 commit e8e15a8
Show file tree
Hide file tree
Showing 10 changed files with 213 additions and 57 deletions.
17 changes: 14 additions & 3 deletions apps/site/src/app/(home)/sections/Intro/Intro.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

.intro {
@include bootstrap.padding(10rem 0.5rem);
margin-left: 10px;
margin-right: 10px;

background-image: url("~src/assets/images/index-card-mobile.svg");
background-size: cover;
Expand All @@ -27,10 +29,19 @@

.pin {
position: absolute;
top: 0;
left: 50%;
transform: translate(-75%, -50%);
top: -12%;
left: 45%;
width: auto;

@include bootstrap.media-breakpoint-down(xl) {
left: 45%;
}
@include bootstrap.media-breakpoint-down(lg) {
left: 40%;
}
@include bootstrap.media-breakpoint-down(md) {
left: 35%;
}
}

.hackDoodle {
Expand Down
20 changes: 18 additions & 2 deletions apps/site/src/app/(home)/sections/Intro/Intro.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import Image from "next/image";
import Container from "react-bootstrap/Container";

import { motion, cubicBezier } from "framer-motion";
import pin from "@/assets/images/index-card-pin.svg";
import hackDoodle from "@/assets/images/hack-doodle.png";

Expand All @@ -12,9 +13,24 @@ const Intro = () => {
return (
<Container as="section">
<div className={styles.intro}>
<Image
<motion.img
initial={{
opacity: 0,
y: -10,
x: -10,
}}
viewport={{ once: true }}
whileInView={{
opacity: 1,
y: 0,
x: 0,
transition: {
duration: 0.65,
ease: cubicBezier(0.64, 0, 0.78, 0),
},
}}
className={styles.pin}
src={pin}
src={pin.src}
width="100"
height="100"
alt="Index card pin"
Expand Down
2 changes: 1 addition & 1 deletion apps/site/src/app/(home)/sections/Landing/ApplyButton.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Button from "react-bootstrap/Button";
import StickerPosition from "@/components/Sticker/StickerPosition";
import { HackSticker, HeartSticker } from "@/components/Sticker/Stickers";
import { HeartSticker } from "@/components/Sticker/Stickers";

import styles from "./ApplyButton.module.scss";

Expand Down
60 changes: 46 additions & 14 deletions apps/site/src/app/(home)/sections/Mentor/Mentor.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"use client";

import { motion, cubicBezier, Variants } from "framer-motion";
import Image from "next/image";
import Col from "react-bootstrap/Col";
import Container from "react-bootstrap/Container";
Expand All @@ -11,6 +11,26 @@ import styles from "./Mentor.module.scss";

const MENTOR_APP_URL = "/mentor";

const variant: Variants = {
initial: {
scale: 1.1,
opacity: 0,
rotateX: 20,
translateY: 30,
},
animate: {
scale: 1,
rotateX: 0,
opacity: 1,
translateY: 0,
transition: {
duration: 0.85,
staggerChildren: 0.1,
ease: cubicBezier(0.33, 1, 0.68, 1),
},
},
};

const Mentor = () => {
const mentorHeader = (
<h2 className="mb-3 text-start">Interested in becoming a mentor?</h2>
Expand All @@ -35,20 +55,32 @@ const Mentor = () => {

return (
<Container as="section">
<div className="position-relative my-5">
<Col lg={5} className={styles.applySticky}>
<Image src={tape} alt="post-it tape" className={styles.tape} />
<div className={styles.applyStickyContent}>
{mentorHeader}
<motion.div
variants={variant}
initial="initial"
whileInView="animate"
className="position-relative my-5"
>
<motion.div variants={variant}>
<Col lg={5} className={styles.applySticky}>
<motion.img
variants={variant}
src={tape.src}
alt="post-it tape"
className={styles.tape}
/>
<div className={styles.applyStickyContent}>
{mentorHeader}
{mentorDescription}
</div>
{applyLink}
</Col>
<Col className={styles.descSticky + " text-center"}>
{mentorDescription}
</div>
{applyLink}
</Col>
<Col className={styles.descSticky + " text-center"}>
{mentorDescription}
{applyLink}
</Col>
</div>
{applyLink}
</Col>
</motion.div>
</motion.div>
</Container>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ const HackSticker: React.FC<StickerProps> = (props) => (
<BaseSticker
imageSrc={HackLogo.src}
alt="Hack at UCI sticker"
height={200}
width={200}
height={150}
width={150}
{...lightShake}
{...props}
/>
Expand Down
2 changes: 0 additions & 2 deletions apps/site/src/components/Sticker/Stickers/index.ts

This file was deleted.

30 changes: 30 additions & 0 deletions apps/site/src/components/Sticker/Stickers/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import type React from "react";
import type { StickerProps } from "./stickerProps";
import HackLogo from "@/assets/icons/hack.png";
import HeartEmoji from "@/assets/images/heart_emoji.png";
import BaseSticker from "../BaseSticker";
import { fastShake, lightShake } from "@/components/animation";

export const HackSticker: React.FC<StickerProps> = (props) => {
return (
<BaseSticker
imageSrc={HackLogo.src}
alt="Hack at UCI sticker"
height={150}
width={150}
{...lightShake}
{...props}
/>
);
};

export const HeartSticker: React.FC<StickerProps> = (props) => (
<BaseSticker
imageSrc={HeartEmoji.src}
alt="heart emoji sticker"
height={150}
width={150}
{...fastShake}
{...props}
/>
);
2 changes: 2 additions & 0 deletions apps/site/src/lib/styles/globals.scss
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ $container-padding: 8rem;
.background {
background-image: url("~@/assets/background/anteater-head-tiling.gif");
background-size: 464px; // half size for 2x scaling
overflow-x: hidden;
max-width: 100%;
}

.accordion {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,22 @@
position: relative;
padding: 1rem 0;
box-shadow: 0 6px 5px -2px rgba(gray, 0.5);
@media screen and (max-width: 400px) {
width: 300px;
}
}

.tape {
background-image: url("~@/assets/images/tape.svg");
width: 238px;
height: 60px;
position: absolute;
top: -12.5%;
top: 3%;
left: 15%;
z-index: 10;
@media screen and (max-width: 400px) {
left: 10%;
}
}

.container {
Expand Down
123 changes: 91 additions & 32 deletions apps/site/src/views/Resources/components/ResourceCard/ResourceCard.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"use client";
import Image from "next/image";

import { Variants, motion, AnimatePresence, cubicBezier } from "framer-motion";
import openNewWindow from "@/assets/icons/open-new-window.svg";
import styles from "./ResourceCard.module.scss";

Expand All @@ -16,6 +17,27 @@ interface ResourceCardProps {
stickyNoteColor: string;
}

const variant: Variants = {
initial: {
scale: 1.1,
opacity: 0,
rotateX: 20,
translateY: 30,
},
animate: {
scale: 1,
rotateX: 0,
opacity: 1,
translateY: 0,
transition: {
duration: 0.85,
staggerChildren: 0.1,
staggerDirection: -1,
ease: cubicBezier(0.33, 1, 0.68, 1),
},
},
};

export default function ResourceCard({
title,
description,
Expand All @@ -24,38 +46,75 @@ export default function ResourceCard({
stickyNoteColor,
}: ResourceCardProps) {
return (
<div
className={styles.group}
style={{
backgroundColor: `${stickyNoteColor}`,
}}
>
<div className={styles.container + " text-center px-3"}>
<div className={styles.tape}></div>
{stickerSrc && <img src={stickerSrc} alt="Resource logo" width="100" />}
<h3>{title}</h3>
{description}
</div>

{links.map(({ text, link }) => (
<a
key={link}
href={link}
target="_blank"
rel="noopener noreferrer"
className={styles.tag}
<AnimatePresence mode="wait">
<motion.div style={{ position: "relative" }}>
<motion.div
initial={{
scale: 1.1,
opacity: 0,
rotateX: 15,
}}
viewport={{ once: true }}
whileInView={{
scale: 1,
rotateX: 0,
opacity: 1,
transition: {
delay: 0.1,
duration: 0.65,
ease: cubicBezier(0.64, 0, 0.78, 0),
},
}}
className={styles.tape}
></motion.div>
<motion.div
variants={variant}
initial="initial"
whileInView="animate"
viewport={{ once: true }}
className={styles.group}
style={{
backgroundColor: `${stickyNoteColor}`,
}}
>
{text}
<div className="d-inline ms-1 vertical-align-middle">
<Image
src={openNewWindow}
width="20"
height="20"
alt="Open link in new window"
/>
<div className={styles.container + " text-center px-3"}>
{stickerSrc && (
<motion.img
src={stickerSrc}
alt="Resource logo"
width="100"
variants={variant}
/>
)}
<h3>{title}</h3>
{description}
</div>
</a>
))}
</div>

{links.map(({ text, link }) => (
<motion.a
key={link}
href={link}
target="_blank"
rel="noopener noreferrer"
className={styles.tag}
variants={variant}
>
{text}
<motion.div
className="d-inline ms-1 vertical-align-middle"
variants={variant}
>
<Image
src={openNewWindow}
width="20"
height="20"
alt="Open link in new window"
/>
</motion.div>
</motion.a>
))}
</motion.div>
</motion.div>
</AnimatePresence>
);
}

0 comments on commit e8e15a8

Please sign in to comment.