diff --git a/components/elements/CodeBlock.tsx b/components/elements/CodeBlock.tsx
index c438befc..b957118e 100644
--- a/components/elements/CodeBlock.tsx
+++ b/components/elements/CodeBlock.tsx
@@ -24,18 +24,20 @@ function cargo(Prism: any) {
SyntaxHighlighter.registerLanguage('cargo', cargo)
interface Props {
+ readonly id?: string
readonly language: string
readonly code: string
readonly showLineNumbers?: boolean
readonly className?: string
readonly copyBtn?: boolean
+ readonly style?: React.CSSProperties
}
-export default function CodeBlock({ code, language, showLineNumbers, className, copyBtn }: Props) {
+export default function CodeBlock({ id, code, language, showLineNumbers, className, copyBtn, style }: Props) {
useWindowSize()
return (
-
+
{copyBtn && }
diff --git a/components/sections/Home/LaunchSystem/LaunchSystemStep1.tsx b/components/sections/Home/LaunchSystem/LaunchSystemStep1.tsx
index 9e6053bb..5a39a10b 100644
--- a/components/sections/Home/LaunchSystem/LaunchSystemStep1.tsx
+++ b/components/sections/Home/LaunchSystem/LaunchSystemStep1.tsx
@@ -2,7 +2,7 @@ import Xarrow from 'react-xarrows'
import Step1Top from '../Step1Top'
import Step1Left from '../Step1Left'
import Step1Right from '../Step1Right'
-import Step1Bottom from '../Step1Bottom'
+import Step1Bottom from './Step1Bottom'
import RocketColor1 from '../RocketColor1'
export default function LaunchSystemStep1() {
@@ -61,7 +61,7 @@ export default function LaunchSystemStep1() {
-
+
diff --git a/components/sections/Home/LaunchSystem/LaunchSystemStep2.tsx b/components/sections/Home/LaunchSystem/LaunchSystemStep2.tsx
index ac9c46d9..8ab10086 100644
--- a/components/sections/Home/LaunchSystem/LaunchSystemStep2.tsx
+++ b/components/sections/Home/LaunchSystem/LaunchSystemStep2.tsx
@@ -3,7 +3,7 @@ import RocketColor2 from '../RocketColor2'
import Step2Top from '../Step2Top'
import Step2Left from '../Step2Left'
import Step2Right from '../Step2Right'
-import Step2Bottom from '../Step2Bottom'
+import Step2Bottom from './Step2Bottom'
export default function LaunchSystemStep2() {
return (
diff --git a/components/sections/Home/LaunchSystem/Step1Bottom.tsx b/components/sections/Home/LaunchSystem/Step1Bottom.tsx
new file mode 100644
index 00000000..5c3ccbfa
--- /dev/null
+++ b/components/sections/Home/LaunchSystem/Step1Bottom.tsx
@@ -0,0 +1,165 @@
+import { Splide, SplideSlide, SplideTrack } from '@splidejs/react-splide'
+import clsx from 'clsx'
+import { CodeBlock } from 'components/elements'
+import { trackEvent } from 'lib/posthog'
+import { FC, useState } from 'react'
+
+type SelectedItem = 'hello-world' | 'using-db' | 'using-secrets'
+
+interface Step2BottomProps {
+ id?: string
+ className?: string
+ style?: React.CSSProperties
+}
+
+const Step2Bottom: FC = ({ id, className, style }) => {
+ const [selectedItem, setSelectedItem] = useState('hello-world')
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+export default Step2Bottom
+
+const HELLO_WORLD = `
+use rocket::{get, routes};
+
+#[get("/")]
+fn index() -> &'static str {
+ "Hello, world!"
+}
+
+#[shuttle_runtime::main]
+async fn main() -> shuttle_rocket::ShuttleRocket {
+ let rocket = rocket::build().mount("/", routes![index]);
+
+ Ok(rocket.into())
+}
+`.trim()
+
+const USING_DB = `
+use axum::{routing::get, Router};
+
+async fn hello_world() -> &'static str {
+ "Hello, world!"
+}
+
+#[shuttle_runtime::main]
+async fn main() -> shuttle_axum::ShuttleAxum {
+ let router = Router::new().route("/", get(hello_world));
+
+ Ok(router.into())
+}
+
+`.trim()
+
+const USING_SECRETS = `
+use actix_web::{get, web::ServiceConfig};
+use shuttle_actix_web::ShuttleActixWeb;
+
+#[get("/")]
+async fn hello_world() -> &'static str {
+ "Hello World!"
+}
+
+#[shuttle_runtime::main]
+async fn main() -> ShuttleActixWeb {
+ let config = move |cfg: &mut ServiceConfig| {
+ cfg.service(hello_world);
+ };
+
+ Ok(config.into())
+}
+`.trim()
diff --git a/components/sections/Home/LaunchSystem/Step2Bottom.tsx b/components/sections/Home/LaunchSystem/Step2Bottom.tsx
new file mode 100644
index 00000000..c41fc943
--- /dev/null
+++ b/components/sections/Home/LaunchSystem/Step2Bottom.tsx
@@ -0,0 +1,179 @@
+import { Splide, SplideSlide, SplideTrack } from '@splidejs/react-splide'
+import clsx from 'clsx'
+import { CodeBlock } from 'components/elements'
+import { trackEvent } from 'lib/posthog'
+import { FC, useState } from 'react'
+
+type SelectedItem = 'hello-world' | 'using-db' | 'using-secrets'
+
+interface Step2BottomProps {
+ id?: string
+ className?: string
+ style?: React.CSSProperties
+}
+
+const Step2Bottom: FC = ({ id, className, style }) => {
+ const [selectedItem, setSelectedItem] = useState('hello-world')
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+export default Step2Bottom
+
+const HELLO_WORLD = `
+use axum::{routing::get, Router};
+
+async fn hello_world() -> &'static str {
+ "Hello, world!"
+}
+
+#[shuttle_runtime::main]
+async fn main() -> shuttle_axum::ShuttleAxum {
+ let router = Router::new().route("/", get(hello_world));
+
+ Ok(router.into())
+}
+`.trim()
+
+const USING_DB = `
+use sqlx::PgPool;
+mod router;
+mod routes;
+
+
+#[shuttle_runtime::main]
+async fn main(#[shuttle_shared_db::Postgres] pool: PgPool) -> shuttle_axum::ShuttleAxum {
+ sqlx::migrate!()
+ .run(&pool)
+ .await
+ .expect("Failed to run migrations");
+
+ let router = router::init_router(pool);
+
+ Ok(router.into())
+}
+`.trim()
+
+const USING_SECRETS = `
+use axum::{extract::State, routing::get, Router};
+use qdrant_client::Qdrant;
+use std::sync::Arc;
+
+struct AppState {
+ qdrant: Qdrant,
+}
+
+async fn list_collections(State(state): State>) -> String {
+ format!("{:?}\n", state.qdrant.list_collections().await)
+}
+
+#[shuttle_runtime::main]
+async fn main(
+ #[shuttle_qdrant::Qdrant(cloud_url = "{secrets.CLOUD_URL}", api_key = "{secrets.API_KEY}")]
+ qdrant: Qdrant,
+) -> shuttle_axum::ShuttleAxum {
+ let state = Arc::new(AppState { qdrant });
+
+ let router = Router::new()
+ .route("/", get(list_collections))
+ .with_state(state);
+
+ Ok(router.into())
+}
+`.trim()
diff --git a/components/sections/Home/LaunchSystem/index.tsx b/components/sections/Home/LaunchSystem/index.tsx
index 0a9ebadc..5d4bae11 100644
--- a/components/sections/Home/LaunchSystem/index.tsx
+++ b/components/sections/Home/LaunchSystem/index.tsx
@@ -1,16 +1,16 @@
'use client'
-import { motion, useMotionValueEvent, useScroll } from 'framer-motion'
+import { distance, motion, useMotionValueEvent, useScroll, useVelocity } from 'framer-motion'
import LaunchSystemStep1 from './LaunchSystemStep1'
import LaunchSystemStep2 from './LaunchSystemStep2'
import LaunchSystemStep3 from './LaunchSystemStep3'
import LaunchSystemStep4 from './LaunchSystemStep4'
-import { useRef, useState } from 'react'
+import { use, useRef, useState } from 'react'
import Step1Top from '../Step1Top'
import Step1Left from '../Step1Left'
import Step1Right from '../Step1Right'
-import Step1Bottom from '../Step1Bottom'
+import Step1Bottom from './Step1Bottom'
import RocketColor1 from '../RocketColor1'
import RocketColor2 from '../RocketColor2'
import RocketColor3 from '../RocketColor3'
@@ -21,7 +21,7 @@ import Step2Left from '../Step2Left'
import Step3Left from '../Step3Left'
import Step2Right from '../Step2Right'
import Step3Right from '../Step3Right'
-import Step2Bottom from '../Step2Bottom'
+import Step2Bottom from './Step2Bottom'
export default function LaunchSystem() {
const css = `
@@ -35,8 +35,88 @@ export default function LaunchSystem() {
const ref = useRef(null)
const { scrollYProgress } = useScroll({ target: ref })
const [scrollPosition, setScrollPosition] = useState(0)
+ const [scrollVelocity, setScrollVelocity] = useState(0)
+ const [scrollingToNext, setScrollingToNext] = useState(false)
- useMotionValueEvent(scrollYProgress, 'change', setScrollPosition)
+ useMotionValueEvent(scrollYProgress, 'change', (position) => {
+ let distanceToNextCheckpoint = 0
+ let distanceToPrevCheckpoint = 0
+
+ if (scrollPosition < 0.37) {
+ distanceToNextCheckpoint = 0.37 - scrollPosition
+ } else if (scrollPosition < 0.6) {
+ distanceToNextCheckpoint = 0.6 - scrollPosition
+ } else if (scrollPosition < 1) {
+ distanceToNextCheckpoint = 1 - scrollPosition
+ }
+
+ if (scrollPosition >= 0.99) {
+ distanceToPrevCheckpoint = scrollPosition - 0.6
+ } else if (scrollPosition >= 0.59) {
+ distanceToPrevCheckpoint = scrollPosition - 0.37
+ } else if (scrollPosition >= 0.36) {
+ distanceToPrevCheckpoint = scrollPosition
+ }
+ const prevCheckpoint = scrollPosition - distanceToPrevCheckpoint
+ const nextCheckpoint = scrollPosition + distanceToNextCheckpoint
+
+ if (scrollVelocity > 0.25 && position >= 0.01 && scrollPosition <= 1.01 && !scrollingToNext) {
+ if (scrollPosition >= 1) {
+ // Scroll to the very end of the section
+
+ setScrollingToNext(false)
+
+ // @ts-ignore
+ const endOfSection = ref.current.scrollHeight
+ window.scrollTo({ top: endOfSection, behavior: 'smooth' })
+ return
+ }
+
+ const interval = setInterval(() => {
+ setScrollingToNext(true)
+ setScrollPosition((prev) => {
+ if (prev > nextCheckpoint) {
+ clearInterval(interval)
+ setScrollingToNext(false)
+ return nextCheckpoint
+ }
+ return prev + 0.02
+ })
+ }, 50)
+ }
+
+ // Same for opposite
+ else if (scrollVelocity < -0.25 && position >= 0.01 && scrollPosition <= 1.01 && !scrollingToNext) {
+ if (scrollPosition <= 0.02) {
+ // Scroll to the very end of the section
+
+ setScrollingToNext(false)
+
+ // @ts-ignore
+ const startOfSection = ref.current.getBoundingClientRect().top
+ window.scrollTo({ top: startOfSection, behavior: 'smooth' })
+ return
+ }
+
+ const interval = setInterval(() => {
+ setScrollingToNext(true)
+ setScrollPosition((prev) => {
+ if (prev < prevCheckpoint) {
+ clearInterval(interval)
+ setScrollingToNext(false)
+ return prevCheckpoint
+ }
+
+ return prev - 0.02
+ })
+ }, 50)
+ }
+ })
+
+ const scrollYVelocity = useVelocity(scrollYProgress)
+ useMotionValueEvent(scrollYVelocity, 'change', setScrollVelocity)
+
+ // console.log(scrollVelocity, scrollPosition)
// Change opacity based on section
const changeOpacity = (
@@ -245,17 +325,18 @@ export default function LaunchSystem() {
>
2
? changeOpacity(2, scrollPosition, 1, 0, 0.2)
: changeOpacity(1, scrollPosition, 0, 1, 0.2),
+ visibility: scrollPosition * 4 > 1.2 ? 'visible' : 'collapse',
}}
/>
@@ -300,11 +381,6 @@ export default function LaunchSystem() {
-
- {/* {currentSection === 1 && }
- {currentSection === 2 && }
- {currentSection === 3 && }
- {currentSection === 4 && } */}
>
)
diff --git a/components/sections/Home/Step1Bottom.tsx b/components/sections/Home/Step1Bottom.tsx
deleted file mode 100644
index 0c1dba41..00000000
--- a/components/sections/Home/Step1Bottom.tsx
+++ /dev/null
@@ -1,108 +0,0 @@
-import clsx from 'clsx'
-
-export default function Step1Bottom({
- className,
- id,
- style,
-}: {
- className?: string
- id: string
- style?: React.SVGAttributes['style']
-}) {
- return (
-
- )
-}
diff --git a/components/sections/Home/Step2Bottom.tsx b/components/sections/Home/Step2Bottom.tsx
deleted file mode 100644
index 21023224..00000000
--- a/components/sections/Home/Step2Bottom.tsx
+++ /dev/null
@@ -1,109 +0,0 @@
-import clsx from 'clsx'
-import React from 'react'
-
-export default function Step2Bottom({
- className,
- id,
- style,
-}: {
- className?: string
- id?: string
- style?: React.SVGAttributes['style']
-}) {
- return (
-
- )
-}