diff --git a/components/announcement.js b/components/announcement.js
index 57536346..a34c5e68 100644
--- a/components/announcement.js
+++ b/components/announcement.js
@@ -1,6 +1,7 @@
-import { Card, Text } from 'theme-ui'
+import { Card, Text, Box } from 'theme-ui'
import { keyframes } from '@emotion/react'
import Icon from './icon'
+import Image from 'next/image'
const unfold = keyframes({
from: { transform: 'scaleY(0)' },
@@ -12,6 +13,8 @@ const Announcement = ({
copy,
iconLeft,
iconRight,
+ imgSrc,
+ imgAlt,
color = 'accent',
sx = {},
...props
@@ -48,6 +51,16 @@ const Announcement = ({
sx={{ mr: [2, 3], ml: 2, color, display: ['none', 'block'] }}
/>
)}
+ {imgSrc && (
+
+
+
+ )}
{
+ const prefersReducedMotion = usePrefersReducedMotion()
+ // Fancy lights animation
+ const lightsScrollTrigger = useRef()
+ const lightsAnimated = useRef(false)
+ useEffect(() => {
+ let canceled = false
+
+ const setAtIndex = (i, color) => {
+ if (canceled) return
+
+ // Going outside of React for performance
+ const el = document.getElementById(`pixel-${i}`)
+ if (!el) return
+
+ if (recapPixels[i]) {
+ el.style.background = color
+ el.style.boxShadow = `0 0 10px ${color}`
+ } else {
+ el.style.background = dimBg
+ el.style.boxShadow = 'none'
+ }
+ }
+ const setAll = color => {
+ for (let i = 0; i < recapPixels.length; i++) setAtIndex(i, color)
+ }
+
+ const animate = async () => {
+ if (lightsAnimated.current) return
+ lightsAnimated.current = true
+
+ // Illuminate lights in diagonal lines starting with only top left.
+ for (
+ let curColumn = 0;
+ curColumn < recapWidth + recapHeight;
+ curColumn++
+ ) {
+ for (
+ let offset = curColumn;
+ offset >= Math.max(0, curColumn - recapHeight);
+ offset--
+ ) {
+ const i = curColumn * recapWidth + offset - offset * recapWidth
+ setAtIndex(i, '#ffffff')
+ if (!recapPixels[i]) await sleep(4)
+ if (canceled) return
+ }
+ // await sleep(2); if (canceled) return
+ }
+
+ // Flash the lights twice
+ await sleep(600)
+ if (canceled) return
+
+ setAll(dimBg)
+ await sleep(80)
+ if (canceled) return
+
+ setAll('#aaaaaa')
+ await sleep(20)
+ if (canceled) return
+
+ setAll(dimBg)
+ await sleep(30)
+ if (canceled) return
+
+ setAll('#aaaaaa')
+ await sleep(100)
+ if (canceled) return
+
+ setAll(dimBg)
+ await sleep(200)
+ if (canceled) return
+
+ // Animate rainbow 2-column increments
+ for (let x = 0; x < recapWidth; x++) {
+ const color = `hsl(${(x * 360) / recapWidth}, 100%, 65%)`
+ for (let y = 0; y < recapHeight; y++) {
+ const i = y * recapWidth + x
+ setAtIndex(i, color)
+ }
+ if (x % 2 === 1) await sleep(35)
+ }
+ }
+
+ if (prefersReducedMotion) {
+ if (!lightsAnimated.current) setAll('#ffffff')
+ return () => (canceled = true)
+ } else {
+ const observer = new IntersectionObserver(
+ ([entry]) => {
+ if (entry.isIntersecting) animate()
+ },
+ { threshold: 0.5 }
+ )
+ observer.observe(lightsScrollTrigger.current)
+ return () => {
+ canceled = true
+ observer.disconnect()
+ }
+ }
+ }, [prefersReducedMotion])
+
+ return (
+
+ {recapPixels.map((_, i) => (
+
+ ))}
+
+
+ )
+}
+
+export default Recap
\ No newline at end of file
diff --git a/lib/sleep.js b/lib/sleep.js
new file mode 100644
index 00000000..75200d76
--- /dev/null
+++ b/lib/sleep.js
@@ -0,0 +1,4 @@
+// Beloved classic utility function :3
+const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
+
+export default sleep
\ No newline at end of file
diff --git a/pages/onboard/index.js b/pages/onboard/index.js
index f822df49..5dd5be2f 100644
--- a/pages/onboard/index.js
+++ b/pages/onboard/index.js
@@ -7,8 +7,11 @@ import Footer from '../../components/footer'
import FadeIn from '../../components/fade-in'
import Sparkles from '../../components/sparkles'
import Tilt from '../../components/tilt'
+import Recap from '../../components/onboard/recap'
import usePrefersReducedMotion from '../../lib/use-prefers-reduced-motion'
import { useEffect, useRef, useState } from 'react'
+import sleep from '../../lib/sleep'
+import Announcement from '../../components/announcement'
/**
* @type {import('theme-ui').ThemeUIStyleObject}
@@ -23,135 +26,6 @@ const traceSx = {
const dimBg = '#151515'
-// Beloved classic utility function :3
-const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
-
-// "LET'S RECAP" pixel art (exported from Piskel)
-// Original: https://doggo.ninja/fiK0nk.piskel
-const recapWidth = 71
-const recapHeight = 10
-const recapPixels = [
- 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
- 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
- 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
- 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff,
- 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000,
- 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
- 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
- 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff,
- 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
- 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
- 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000,
- 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
- 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
- 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000,
- 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
- 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000,
- 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
- 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
- 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
- 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
- 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
- 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
- 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
- 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff,
- 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff,
- 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000,
- 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000,
- 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000,
- 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
- 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
- 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
- 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff,
- 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000,
- 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0xffffffff, 0xffffffff
-]
-
const slackLink = '/slack/?event=onboard'
const stickerButtonText = 'Click 4 Stickers'
@@ -255,106 +129,6 @@ const ShipPage = () => {
return () => observer.disconnect()
}, [])
- // Fancy lights animation
- const lightsScrollTrigger = useRef()
- const lightsAnimated = useRef(false)
- useEffect(() => {
- let canceled = false
-
- const setAtIndex = (i, color) => {
- if (canceled) return
-
- // Going outside of React for performance
- const el = document.getElementById(`pixel-${i}`)
- if (!el) return
-
- if (recapPixels[i]) {
- el.style.background = color
- el.style.boxShadow = `0 0 10px ${color}`
- } else {
- el.style.background = dimBg
- el.style.boxShadow = 'none'
- }
- }
- const setAll = color => {
- for (let i = 0; i < recapPixels.length; i++) setAtIndex(i, color)
- }
-
- const animate = async () => {
- if (lightsAnimated.current) return
- lightsAnimated.current = true
-
- // Illuminate lights in diagonal lines starting with only top left.
- for (
- let curColumn = 0;
- curColumn < recapWidth + recapHeight;
- curColumn++
- ) {
- for (
- let offset = curColumn;
- offset >= Math.max(0, curColumn - recapHeight);
- offset--
- ) {
- const i = curColumn * recapWidth + offset - offset * recapWidth
- setAtIndex(i, '#ffffff')
- if (!recapPixels[i]) await sleep(4)
- if (canceled) return
- }
- // await sleep(2); if (canceled) return
- }
-
- // Flash the lights twice
- await sleep(600)
- if (canceled) return
-
- setAll(dimBg)
- await sleep(80)
- if (canceled) return
-
- setAll('#aaaaaa')
- await sleep(20)
- if (canceled) return
-
- setAll(dimBg)
- await sleep(30)
- if (canceled) return
-
- setAll('#aaaaaa')
- await sleep(100)
- if (canceled) return
-
- setAll(dimBg)
- await sleep(200)
- if (canceled) return
-
- // Animate rainbow 2-column increments
- for (let x = 0; x < recapWidth; x++) {
- const color = `hsl(${(x * 360) / recapWidth}, 100%, 65%)`
- for (let y = 0; y < recapHeight; y++) {
- const i = y * recapWidth + x
- setAtIndex(i, color)
- }
- if (x % 2 === 1) await sleep(35)
- }
- }
-
- if (prefersReducedMotion) {
- if (!lightsAnimated.current) setAll('#ffffff')
- return () => (canceled = true)
- } else {
- const observer = new IntersectionObserver(
- ([entry]) => {
- if (entry.isIntersecting) animate()
- },
- { threshold: 0.5 }
- )
- observer.observe(lightsScrollTrigger.current)
- return () => {
- canceled = true
- observer.disconnect()
- }
- }
- }, [prefersReducedMotion])
return (
<>
@@ -425,9 +199,18 @@ const ShipPage = () => {
position: 'relative'
}}
>
+
+
+
{
Let's Recap
-
- {recapPixels.map((_, i) => (
-
- ))}
-
-
+