diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..8af8493 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,16 @@ +# Flows examples + +This directory contains examples of flows that can be used as a starting point for your own Flows implementation. + +## Examples + +- [React Next.js](./react-nextjs) - A simple example of how to use Flows with React and Next.js. +- [JavaScript](./javascript) - A simple example of how to use Flows with vanilla JavaScript. + +## Reporting Issues + +We actively encourage our community to raise issues and provide feedback. If you find an issue, please let us know by raising an issue in the repository. + +An issue can be raised by clicking the 'Issues' tab at the top of the repository, followed by the Green 'New issue' button. + +When submitting an issue, please thoroughly and concisely describe the problem you are experiencing so that we may easily understand and resolve the issue in a timely manner. diff --git a/examples/javascript/.gitignore b/examples/javascript/.gitignore new file mode 100644 index 0000000..ea12ad6 --- /dev/null +++ b/examples/javascript/.gitignore @@ -0,0 +1,3 @@ +pnpm-lock.yaml +package-lock.json +yarn.lock \ No newline at end of file diff --git a/examples/javascript/arrow.svg b/examples/javascript/arrow.svg new file mode 100644 index 0000000..91635fb --- /dev/null +++ b/examples/javascript/arrow.svg @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/examples/javascript/favicon.ico b/examples/javascript/favicon.ico new file mode 100644 index 0000000..9f96992 Binary files /dev/null and b/examples/javascript/favicon.ico differ diff --git a/examples/javascript/index.html b/examples/javascript/index.html new file mode 100644 index 0000000..c09ab77 --- /dev/null +++ b/examples/javascript/index.html @@ -0,0 +1,233 @@ + + + + + + + Flows - JavaScript example + + + + + + + + + +
+
+
+
+

Flows JavaScript example

+

+ Get started at  + + flows.sh + +

+
+ +
+
+
+
+ + +
+
+
+ + +
+
+

Your files

+
+
+ FunnyCat.jpg +
+
+ ImportantDoc.pdf +
+
+ CoolVideo.mp4 +
+
+ DankMeme.png +
+
+
+
+
+ +
+ diff --git a/examples/javascript/logo.svg b/examples/javascript/logo.svg new file mode 100644 index 0000000..6f66e11 --- /dev/null +++ b/examples/javascript/logo.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/vanilla-js/package.json b/examples/javascript/package.json similarity index 77% rename from examples/vanilla-js/package.json rename to examples/javascript/package.json index 8f519a7..cae86c9 100644 --- a/examples/vanilla-js/package.json +++ b/examples/javascript/package.json @@ -1,5 +1,5 @@ { - "name": "vanilla-js-example", + "name": "javascript-example", "version": "0.1.0", "private": true, "scripts": { diff --git a/examples/javascript/styles.css b/examples/javascript/styles.css new file mode 100644 index 0000000..b323f2a --- /dev/null +++ b/examples/javascript/styles.css @@ -0,0 +1,293 @@ +* { + box-sizing: border-box; + padding: 0; + margin: 0; + + --bg-default: #fff; + --bg-muted: #fafafa; + --bg-hover: #f5f5f5; + --bg-primary: #ec6441; + --bg-primary-hover: #d44121; + + --fg-default: #181818; + --fg-muted: #525252; + --fg-on-primary: #fff; + + --border-default: #e2e2e2; + + --shadow-l1: 0px 2px 2px rgba(0, 0, 0, 0.04), 0px 0px 1px rgba(0, 0, 0, 0.08); + --shadow-l2: 4px 8px 10.1px -2.5px rgba(10, 10, 10, 0.08), + 1.7px 3.3px 4.2px -1.7px rgba(10, 10, 10, 0.09), 0.7px 1.4px 1.8px -0.8px rgba(10, 10, 10, 0.1), + 0px 0.5px 1.5px 0px rgba(10, 10, 10, 0.2); +} + +html, +body { + font-family: + system-ui, + -apple-system, + BlinkMacSystemFont, + "Segoe UI", + Roboto, + Oxygen, + Ubuntu, + Cantarell, + "Open Sans", + "Helvetica Neue", + sans-serif; + max-width: 100vw; + height: 100%; + overflow-x: hidden; + font-size: 10px; + background-color: var(--bg-muted); + color: var(--fg-default); +} + +main { + display: flex; + flex-direction: column; + gap: 16px; + justify-content: space-between; + + height: 100%; + + background-image: radial-gradient(#e2e2e2 1px, transparent 0); + background-size: 16px 16px; +} + +.callout p { + color: var(--fg-muted); +} + +h1 { + font-size: 2rem; + line-height: 2.6rem; +} + +h2 { + font-size: 1.6rem; + line-height: 2.2rem; +} + +p { + font-size: 1.4rem; + line-height: 2rem; +} + +.header { + padding: 4rem; + background-color: var(--bg-default); + border-bottom: 1px solid var(--border-default); +} + +.header-inner-wrap { + display: flex; + justify-content: space-between; + align-items: center; + + max-width: 96rem; + margin: 0 auto; +} + +.link { + color: var(--fg-default); + text-decoration: none; + font-weight: 600; +} + +.link:hover { + text-decoration: underline; +} + +button { + padding: 1rem 2rem; + border: none; + border-radius: 8px; + background-color: var(--bg-primary); + color: var(--fg-on-primary); + font-size: 1.4rem; + font-weight: 600; + cursor: pointer; +} + +button:hover { + background-color: var(--bg-primary-hover); +} + +.btn-secondary { + background-color: var(--bg-muted); + color: var(--fg-default); + border: 1px solid var(--border-default); +} + +.btn-secondary:hover { + background-color: var(--bg-hover); +} + +.main-wrapper { + display: flex; + flex-direction: column; + max-width: 96rem; + max-height: 48rem; + width: 100%; + margin: 0 auto; + padding: 2.4rem; +} + +.footer { + padding: 4rem; + background-color: var(--bg-default); + border-top: 1px solid var(--border-default); +} + +.footer-inner-wrap { + display: flex; + gap: 1.6rem; + + max-width: 96rem; + margin: 0 auto; +} + +.footer-link { + display: flex; + flex-direction: column; + gap: 0.8rem; + padding: 1.6rem; + width: 100%; + + border: 1px solid var(--border-default); + border-radius: 8px; + cursor: pointer; + transition: all 120ms ease-in-out; + + text-decoration: none; + color: var(--fg-default); +} + +.footer-link:hover { + text-decoration: none; + + box-shadow: var(--shadow-l2); +} + +.footer-link-text { + color: var(--fg-muted); +} + +.footer-heading { + display: flex; + align-items: center; +} + +.footer-heading::after { + content: ""; + background-image: url("/arrow.svg"); + width: 1.6rem; + height: 1.6rem; + display: inline-flex; + margin-left: 0.4rem; + transition: all 120ms ease-in-out; +} + +.footer-link:hover .footer-heading::after { + margin-left: 0.8rem; +} + +.app-wrapper { + display: flex; + flex-direction: column; + + background-color: var(--bg-default); + border: 1px solid var(--border-default); + border-radius: 8px; + box-shadow: var(--shadow-l2); +} + +.app-header { + display: flex; + justify-content: space-between; + align-items: center; + + padding: 1.6rem; + border-bottom: 1px solid var(--border-default); +} + +.app-logo { + font-size: 1.6rem; + font-weight: 600; +} + +.app-content { + padding: 1.6rem; +} + +.app-files { + display: flex; + flex-direction: column; + + border: 1px solid var(--border-default); + border-radius: 8px; + overflow: hidden; +} + +.app-file-item { + display: flex; + justify-content: space-between; + align-items: center; + + padding: 1.6rem; + border-bottom: 1px solid var(--border-default); + + font-size: 1.4rem; + font-weight: 600; + cursor: pointer; +} + +.app-file-item:last-child { + border-bottom: none; +} + +.app-file-item:hover { + background-color: var(--bg-hover); +} + +.app-list-title { + margin-bottom: 0.8rem; +} + +.flows-launch-wrapper { + display: flex; + justify-content: center; + margin-bottom: 2.4rem; + gap: 1.6rem; + + padding: 1.6rem; + border: 1px solid var(--border-default); + border-radius: 8px; + background-color: var(--bg-muted); +} + +@media (max-width: 768px) { + .header-inner-wrap { + flex-direction: column-reverse; + gap: 1.6rem; + } + + .footer-inner-wrap { + flex-direction: column; + gap: 1.6rem; + } + + .logo { + display: none; + } + .header { + padding: 2.4rem; + } + .footer { + padding: 2.4rem; + } + .callout { + width: 100%; + } +} diff --git a/examples/react-nextjs/.gitignore b/examples/react-nextjs/.gitignore index 1d268ac..32dc05f 100644 --- a/examples/react-nextjs/.gitignore +++ b/examples/react-nextjs/.gitignore @@ -34,6 +34,6 @@ yarn-error.log* *.tsbuildinfo next-env.d.ts -# This makes it easier to release new version -# without having to update the lockfile everytime -pnpm-lock.yaml \ No newline at end of file +pnpm-lock.yaml +package-lock.json +yarn.lock \ No newline at end of file diff --git a/examples/react-nextjs/app/(local)/about/page.tsx b/examples/react-nextjs/app/(local)/about/page.tsx deleted file mode 100644 index 1343ab4..0000000 --- a/examples/react-nextjs/app/(local)/about/page.tsx +++ /dev/null @@ -1,20 +0,0 @@ -export default function About() { - return ( -
-

About

-

Flow2

-
-
- Text -
-
- -
-

About Flow

-

- Lorem ipsum dolor sit amet consectetur adipisicing elit. Accusamus blanditiis et - necessitatibus, voluptate nihil repellendus ducimus atque maxime corrupti cumque. -

-
- ); -} diff --git a/examples/react-nextjs/app/(local)/home/page.tsx b/examples/react-nextjs/app/(local)/home/page.tsx deleted file mode 100644 index 36bdbbc..0000000 --- a/examples/react-nextjs/app/(local)/home/page.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import { redirect } from "next/navigation"; - -export default function Home() { - return redirect("/"); -} diff --git a/examples/react-nextjs/app/(local)/layout.tsx b/examples/react-nextjs/app/(local)/layout.tsx deleted file mode 100644 index c010ec4..0000000 --- a/examples/react-nextjs/app/(local)/layout.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import { LocalFlows } from "@/components/LocalFlows"; -import { ReactNode } from "react"; - -type Props = { - children?: ReactNode; -}; - -export default function LocalLayout({ children }: Props) { - return ( - <> - {children} - - - ); -} diff --git a/examples/react-nextjs/app/(local)/page.tsx b/examples/react-nextjs/app/(local)/page.tsx deleted file mode 100644 index 923bc1a..0000000 --- a/examples/react-nextjs/app/(local)/page.tsx +++ /dev/null @@ -1,29 +0,0 @@ -export default function Home() { - return ( -
-

Home

-

Flow 1

- -
-

Flow 2

- -
-

Flow 3

- - - -
-
- Variant A text -
-
-
- Variant B text -
-
-
- This is final step -
-
- ); -} diff --git a/examples/react-nextjs/app/cloud/layout.tsx b/examples/react-nextjs/app/cloud/layout.tsx deleted file mode 100644 index 07356ea..0000000 --- a/examples/react-nextjs/app/cloud/layout.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import { CloudFlows } from "@/components/CloudFlows"; -import { ReactNode } from "react"; - -type Props = { - children?: ReactNode; -}; - -export default function CloudLayout({ children }: Props) { - return ( - <> - {children} - - - ); -} diff --git a/examples/react-nextjs/app/cloud/page.tsx b/examples/react-nextjs/app/cloud/page.tsx deleted file mode 100644 index 39eaa98..0000000 --- a/examples/react-nextjs/app/cloud/page.tsx +++ /dev/null @@ -1,12 +0,0 @@ -export default function CloudPage() { - return ( - <> -

- Cloud -

-

Flow 1 - basic flow

- -
- - ); -} diff --git a/examples/react-nextjs/app/favicon.ico b/examples/react-nextjs/app/favicon.ico index 718d6fe..9f96992 100644 Binary files a/examples/react-nextjs/app/favicon.ico and b/examples/react-nextjs/app/favicon.ico differ diff --git a/examples/react-nextjs/app/globals.css b/examples/react-nextjs/app/globals.css index fc42ebb..3e0e266 100644 --- a/examples/react-nextjs/app/globals.css +++ b/examples/react-nextjs/app/globals.css @@ -2,19 +2,280 @@ box-sizing: border-box; padding: 0; margin: 0; + + --bg-default: #fff; + --bg-muted: #fafafa; + --bg-hover: #f5f5f5; + --bg-primary: #ec6441; + --bg-primary-hover: #d44121; + + --fg-default: #181818; + --fg-muted: #525252; + --fg-on-primary: #fff; + + --border-default: #e2e2e2; + + --shadow-l1: 0px 2px 2px rgba(0, 0, 0, 0.04), 0px 0px 1px rgba(0, 0, 0, 0.08); + --shadow-l2: 4px 8px 10.1px -2.5px rgba(10, 10, 10, 0.08), + 1.7px 3.3px 4.2px -1.7px rgba(10, 10, 10, 0.09), 0.7px 1.4px 1.8px -0.8px rgba(10, 10, 10, 0.1), + 0px 0.5px 1.5px 0px rgba(10, 10, 10, 0.2); } html, body { max-width: 100vw; + height: 100%; overflow-x: hidden; + font-size: 10px; + background-color: var(--bg-muted); + color: var(--fg-default); } -header, main { - padding: 16px 16px; + display: flex; + flex-direction: column; + gap: 16px; + justify-content: space-between; + + height: 100%; + + background-image: radial-gradient(#e2e2e2 1px, transparent 0); + background-size: 16px 16px; +} + +.callout p { + color: var(--fg-muted); +} + +h1 { + font-size: 2rem; + line-height: 2.6rem; +} + +h2 { + font-size: 1.6rem; + line-height: 2.2rem; +} + +p { + font-size: 1.4rem; + line-height: 2rem; +} + +.header { + padding: 4rem; + background-color: var(--bg-default); + border-bottom: 1px solid var(--border-default); +} + +.header-inner-wrap { + display: flex; + justify-content: space-between; + align-items: center; + + max-width: 96rem; + margin: 0 auto; +} + +.link { + color: var(--fg-default); + text-decoration: none; + font-weight: 600; } -header ul { - padding-left: 16px; +.link:hover { + text-decoration: underline; +} + +button { + padding: 1rem 2rem; + border: none; + border-radius: 8px; + background-color: var(--bg-primary); + color: var(--fg-on-primary); + font-size: 1.4rem; + font-weight: 600; + cursor: pointer; +} + +button:hover { + background-color: var(--bg-primary-hover); +} + +.btn-secondary { + background-color: var(--bg-muted); + color: var(--fg-default); + border: 1px solid var(--border-default); +} + +.btn-secondary:hover { + background-color: var(--bg-hover); +} + +.main-wrapper { + display: flex; + flex-direction: column; + max-width: 96rem; + max-height: 48rem; + width: 100%; + margin: 0 auto; + padding: 2.4rem; +} + +.footer { + padding: 4rem; + background-color: var(--bg-default); + border-top: 1px solid var(--border-default); +} + +.footer-inner-wrap { + display: flex; + gap: 1.6rem; + + max-width: 96rem; + margin: 0 auto; +} + +.footer-link { + display: flex; + flex-direction: column; + gap: 0.8rem; + padding: 1.6rem; + width: 100%; + + border: 1px solid var(--border-default); + border-radius: 8px; + cursor: pointer; + transition: all 120ms ease-in-out; + + text-decoration: none; + color: var(--fg-default); +} + +.footer-link:hover { + text-decoration: none; + + box-shadow: var(--shadow-l2); +} + +.footer-link-text { + color: var(--fg-muted); +} + +.footer-heading { + display: flex; + align-items: center; +} + +.footer-heading::after { + content: ""; + background-image: url("/arrow.svg"); + width: 1.6rem; + height: 1.6rem; + display: inline-flex; + margin-left: 0.4rem; + transition: all 120ms ease-in-out; +} + +.footer-link:hover .footer-heading::after { + margin-left: 0.8rem; +} + +.app-wrapper { + display: flex; + flex-direction: column; + + background-color: var(--bg-default); + border: 1px solid var(--border-default); + border-radius: 8px; + box-shadow: var(--shadow-l2); +} + +.app-header { + display: flex; + justify-content: space-between; + align-items: center; + + padding: 1.6rem; + border-bottom: 1px solid var(--border-default); +} + +.app-logo { + font-size: 1.6rem; + font-weight: 600; +} + +.app-content { + padding: 1.6rem; +} + +.app-files { + display: flex; + flex-direction: column; + + border: 1px solid var(--border-default); + border-radius: 8px; + overflow: hidden; +} + +.app-file-item { + display: flex; + justify-content: space-between; + align-items: center; + + padding: 1.6rem; + border-bottom: 1px solid var(--border-default); + + font-size: 1.4rem; + font-weight: 600; + cursor: pointer; +} + +.app-file-item:last-child { + border-bottom: none; +} + +.app-file-item:hover { + background-color: var(--bg-hover); +} + +.app-list-title { + margin-bottom: 0.8rem; +} + +.flows-launch-wrapper { + display: flex; + justify-content: center; + margin-bottom: 2.4rem; + gap: 1.6rem; + + padding: 1.6rem; + border: 1px solid var(--border-default); + border-radius: 8px; + background-color: var(--bg-muted); +} + +@media (max-width: 768px) { + .header-inner-wrap { + flex-direction: column-reverse; + gap: 1.6rem; + } + + .footer-inner-wrap { + flex-direction: column; + gap: 1.6rem; + } + + .logo { + display: none; + } + .header { + padding: 2.4rem; + } + .footer { + padding: 2.4rem; + } + .callout { + width: 100%; + } } diff --git a/examples/react-nextjs/app/layout.tsx b/examples/react-nextjs/app/layout.tsx index 16eed46..d112444 100644 --- a/examples/react-nextjs/app/layout.tsx +++ b/examples/react-nextjs/app/layout.tsx @@ -1,38 +1,22 @@ +import { Flows } from "@/components/flows"; import "./globals.css"; import type { Metadata } from "next"; import { Inter } from "next/font/google"; -import Link from "next/link"; const inter = Inter({ subsets: ["latin"] }); export const metadata: Metadata = { - title: "Create Next App", - description: "Generated by create next app", + title: "Flows - React Next.js example", + description: + "Flows lets you build any onboarding you want. Guide users, increase feature adoption, and improve revenue.", }; export default function RootLayout({ children }: { children: React.ReactNode }) { return ( -
-

Vanilla JS example - Flows JS

- -
{children} + ); diff --git a/examples/react-nextjs/app/page.tsx b/examples/react-nextjs/app/page.tsx new file mode 100644 index 0000000..447e911 --- /dev/null +++ b/examples/react-nextjs/app/page.tsx @@ -0,0 +1,99 @@ +export default function HomePage() { + return ( +
+
+
+
+

Flows React Next.js example

+

+ Get started at  + + flows.sh + +

+
+ + FlowsJS + +
+
+
+
+ + +
+
+
+

DropCrate

+ +
+
+

Your files

+
+
+ FunnyCat.jpg +
+
+ ImportantDoc.pdf +
+
+ CoolVideo.mp4 +
+
+ DankMeme.png +
+
+
+
+
+
+ +
+
+ ); +} diff --git a/examples/react-nextjs/components/CloudFlows.tsx b/examples/react-nextjs/components/CloudFlows.tsx deleted file mode 100644 index 47f78fa..0000000 --- a/examples/react-nextjs/components/CloudFlows.tsx +++ /dev/null @@ -1,38 +0,0 @@ -"use client"; - -import { useEffect } from "react"; -import { init } from "@flows/js/cloud"; -import "@flows/js/flows.css"; - -export const CloudFlows = () => { - useEffect(() => { - init({ - customApiUrl: "https://api.stage.flows-cloud.com", - // customApiUrl: "http://localhost:3005", - projectId: "993b3bc3-ebce-4a3e-ba8e-44ca62e3fc9e", - userProperties: { - email: "bob@gmail.com", - role: "admin", - }, - flows: [ - { - id: "vanilla-demo-flow-1", - element: "#start-flow-1", - steps: [ - { - element: "#start-flow-1", - title: "Welcome to FlowsJS!", - body: "This is a demo of FlowsJS. Click the button below to continue.", - }, - { - title: "This is a modal", - body: "This is a modal. It is an useful way to show larger amounts of information with detailed descriptions. For smaller amounts of information, you can use a tooltip. Click the button below to continue.", - }, - ], - }, - ], - }); - }, []); - - return null; -}; diff --git a/examples/react-nextjs/components/LocalFlows.tsx b/examples/react-nextjs/components/LocalFlows.tsx deleted file mode 100644 index 955fd0e..0000000 --- a/examples/react-nextjs/components/LocalFlows.tsx +++ /dev/null @@ -1,98 +0,0 @@ -"use client"; - -import { useEffect } from "react"; -import { init } from "@flows/js"; -import "@flows/js/flows.css"; - -export const LocalFlows = () => { - useEffect(() => { - init({ - flows: [ - { - id: "vanilla-demo-flow-1", - element: "#start-flow-1", - steps: [ - { - element: "#start-flow-1", - title: "Hey!", - body: "This is a demo of FlowsJS.
Click the button below to continue.", - placement: "right-start", - }, - ], - }, - { - id: "vanilla-demo-flow-2", - element: "#start-flow-2", - steps: [ - { - element: "#start-flow-2", - title: "Hello from Flow 2!", - }, - { - element: ".flow-2-text", - title: "This is a text element", - }, - { - wait: { - element: "#continue-flow-2", - }, - }, - { - element: "#continue-flow-2", - title: "This is the last step", - }, - ], - }, - { - id: "vanilla-demo-flow-3", - element: "#start-flow-3", - steps: [ - { - element: "#start-flow-3", - title: "Hello from Flow 3!", - }, - { - wait: [ - { element: "#flow-3-A", action: 0 }, - { element: "#flow-3-B", action: 1 }, - ], - }, - [ - [{ element: ".flow-3-A-text", title: "You selected variant A" }], - [{ element: ".flow-3-B-text", title: "You selected variant B" }], - ], - { element: ".flow-3-final", title: "Goodbye" }, - ], - }, - { - id: "vanilla-about-flow", - frequency: "every-time", - steps: [ - { - element: ".lorem-ipsum-paragraph", - title: "This is a paragraph", - body: "This paragraph doesn't make sense.", - hideNext: true, - wait: { - element: ".home-nav-link", - }, - }, - { - wait: { - location: "/", - }, - }, - { - title: "This is a paragraph", - body: "This paragraph doesn't make sense.", - element: "#start-flow-1", - }, - ], - location: "/about", - }, - ], - }); - }, []); - - return null; -}; diff --git a/examples/react-nextjs/components/flows.tsx b/examples/react-nextjs/components/flows.tsx new file mode 100644 index 0000000..91b1fa2 --- /dev/null +++ b/examples/react-nextjs/components/flows.tsx @@ -0,0 +1,128 @@ +"use client"; + +import { useEffect } from "react"; +import { init } from "@flows/js"; + +export const Flows = () => { + useEffect(() => { + init({ + projectId: "e7d8eb63-7670-4da1-b0e0-d2d3331d108b", + flows: [ + { + id: "local-flow", + clickElement: "#start-local", + frequency: "every-time", + steps: [ + { + title: "Welcome to Flows!", + body: "This is a demo of a local flow loaded from the codebase. Flows offer cloud flows as well, which can be updated without needing code changes.", + }, + { + title: "This is a tooltip", + body: "It can have an overlay...", + targetElement: "#file1", + overlay: true, + }, + { + title: "...or not", + body: "You can customize the tooltip to your liking.", + targetElement: "#file1", + }, + { + title: "You can also wait for a click", + body: "Just like this! Click the button to continue.", + targetElement: "#upload", + overlay: true, + wait: { + clickElement: "#upload", + }, + hideNext: true, + }, + { + title: "Or you can branch out with forks", + body: "Click on one of the files to continue.", + targetElement: ".app-files", + overlay: true, + wait: [ + { + clickElement: "#file1", + targetBranch: 0, + }, + { + clickElement: "#file2", + targetBranch: 1, + }, + { + clickElement: "#file3", + targetBranch: 2, + }, + { + clickElement: "#file4", + targetBranch: 3, + }, + ], + hideNext: true, + }, + [ + [ + { + title: "You clicked on FunnyCat.jpg", + body: "With forks, you can create multiple branches to tailor the onboarding to user actions.", + targetElement: "#file1", + overlay: true, + }, + ], + [ + { + title: "You clicked on ImportantDoc.pdf", + body: "With forks, you can create multiple branches to tailor the onboarding to user actions.", + targetElement: "#file2", + overlay: true, + }, + ], + [ + { + title: "You clicked on CoolVideo.mp4", + body: "With forks, you can create multiple branches to tailor the onboarding to user actions.", + targetElement: "#file3", + overlay: true, + }, + ], + [ + { + title: "You clicked on DankMeme.png", + body: "With forks, you can create multiple branches to tailor the onboarding to user actions.", + targetElement: "#file4", + overlay: true, + }, + ], + ], + { + title: "That was the basics of Flows!", + body: "You can create complex onboarding flows with Flows or a simple tour. If you liked what you saw, sign up and start creating your own flows.", + hideNext: true, + hidePrev: true, + footerActions: { + center: [ + { + label: "Learn more", + external: true, + href: "https://flows.sh/docs", + variant: "secondary", + }, + { + label: "Sign up", + external: true, + href: "https://app.flows.sh/signup", + }, + ], + }, + }, + ], + }, + ], + }); + }, []); + + return null; +}; diff --git a/examples/react-nextjs/package.json b/examples/react-nextjs/package.json index f0ac21b..1702ba6 100644 --- a/examples/react-nextjs/package.json +++ b/examples/react-nextjs/package.json @@ -10,7 +10,7 @@ }, "dependencies": { "@flows/js": "latest", - "next": "14.0.3", + "next": "14.1.0", "react": "18.2.0", "react-dom": "18.2.0" }, diff --git a/examples/react-nextjs/public/arrow.svg b/examples/react-nextjs/public/arrow.svg new file mode 100644 index 0000000..91635fb --- /dev/null +++ b/examples/react-nextjs/public/arrow.svg @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/examples/react-nextjs/public/logo.svg b/examples/react-nextjs/public/logo.svg new file mode 100644 index 0000000..6f66e11 --- /dev/null +++ b/examples/react-nextjs/public/logo.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/react-nextjs/public/next.svg b/examples/react-nextjs/public/next.svg deleted file mode 100644 index 5174b28..0000000 --- a/examples/react-nextjs/public/next.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/examples/react-nextjs/public/vercel.svg b/examples/react-nextjs/public/vercel.svg deleted file mode 100644 index d2f8422..0000000 --- a/examples/react-nextjs/public/vercel.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/examples/vanilla-js/.gitignore b/examples/vanilla-js/.gitignore deleted file mode 100644 index eeeb7be..0000000 --- a/examples/vanilla-js/.gitignore +++ /dev/null @@ -1 +0,0 @@ -pnpm-lock.yaml \ No newline at end of file diff --git a/examples/vanilla-js/cloud/index.html b/examples/vanilla-js/cloud/index.html deleted file mode 100644 index 38e98cf..0000000 --- a/examples/vanilla-js/cloud/index.html +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - Cloud - - - - - - - - -

Vanilla JS example - Flows JS

-

Flow 1 - basic flow

- -
-

Flow 2 - wait flow

- -
-
- Text -
-
- -
- - diff --git a/examples/vanilla-js/cloud/index.js b/examples/vanilla-js/cloud/index.js deleted file mode 100644 index 856e253..0000000 --- a/examples/vanilla-js/cloud/index.js +++ /dev/null @@ -1,32 +0,0 @@ -window.FlowsJS?.init({ - projectId: "216a2d2d-f4e2-44ae-b7e7-84399780294f", - userId: "rbnd-test-user", - flows: [ - { - id: "vanilla-demo-flow-2", - element: "#start-flow-2", - steps: [ - { - element: "#start-flow-2", - title: "Hello from Flow 2!", - body: "In this demo you can see how to point to elements and how to wait for actions.", - }, - { - element: ".flow-2-text", - title: "This is a text element", - body: "The tooltip is pointing to a text element with a class flow-2-text. To continue after this step click on the Continue button below the text.", - }, - { - wait: { - element: "#continue-flow-2", - }, - }, - { - element: "#continue-flow-2", - title: "This is the last step", - body: "This step waited for you to click on the Continue button below the text.", - }, - ], - }, - ], -}); diff --git a/examples/vanilla-js/index.html b/examples/vanilla-js/index.html deleted file mode 100644 index d71e2b7..0000000 --- a/examples/vanilla-js/index.html +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - Vanilla JS example - Flows JS - - - - - - - - - -
-

Vanilla JS example - Flows JS

-

Flow 1 - basic flow

- -
-

Flow 2 - wait flow

- -
-
- Text -
-
- -
-

Flow 3 - conditional steps

- - - -
-
- Variant A text -
-
-
- Variant B text -
-
-
- This is final step -
-
-

Flow 4 - conditional steps with forms

- -
-
- - -
-
-

Flow 5 - waiting on form input

- -
- -
- -
- -
-
-

Flow 6 - conditional steps from tooltip

- -
-
- Variant A text -
-
-
- Variant B text -
-
- - diff --git a/examples/vanilla-js/index.js b/examples/vanilla-js/index.js deleted file mode 100644 index 3d72b82..0000000 --- a/examples/vanilla-js/index.js +++ /dev/null @@ -1,180 +0,0 @@ -window.FlowsJS?.init({ - projectId: "vanilla-demo", - flows: [ - { - id: "vanilla-demo-flow-1", - element: "#start-flow-1", - steps: [ - { - element: "#start-flow-1", - title: "Welcome to FlowsJS!", - body: "This is a demo of FlowsJS. Click the button below to continue.", - }, - { - title: "This is a modal", - body: "This is a modal. It is an useful way to show larger amounts of information with detailed descriptions. For smaller amounts of information, you can use a tooltip. Click the button below to continue.", - }, - ], - }, - { - id: "vanilla-demo-flow-2", - element: "#start-flow-2", - steps: [ - { - element: "#start-flow-2", - title: "Hello from Flow 2!", - body: "In this demo you can see how to point to elements and how to wait for actions.", - }, - { - element: ".flow-2-text", - title: "This is a text element", - body: "The tooltip is pointing to a text element with a class flow-2-text. To continue after this step click on the Continue button below the text.", - }, - { - wait: { - element: "#continue-flow-2", - }, - }, - { - element: "#continue-flow-2", - title: "This is the last step", - body: "This step waited for you to click on the Continue button below the text.", - }, - ], - }, - { - id: "vanilla-demo-flow-3", - element: "#start-flow-3", - steps: [ - { - element: "#start-flow-3", - title: "Hello from Flow 3!", - body: "In this demo you can see how to define conditional steps. To continue after this step click on Variant A or Variant B.", - }, - { - wait: [ - { element: "#flow-3-A", action: 0 }, - { element: "#flow-3-B", action: 1 }, - ], - }, - [ - [ - { - element: ".flow-3-A-text", - title: "You selected variant A", - body: "This is variant A", - }, - ], - [ - { - element: ".flow-3-B-text", - title: "You selected variant B", - body: "This is variant B", - }, - ], - ], - { - element: ".flow-3-final", - title: "Goodbye", - body: "This step is shared with both variants", - }, - ], - }, - { - id: "vanilla-demo-flow-4", - element: "#start-flow-4", - steps: [ - { - element: "#start-flow-4", - title: "Hello from Flow 4!", - body: "In this demo you can see how to define conditional steps based on form values. To continue after this step select Option 1 or Option 2 in the select bellow.", - }, - { - wait: [ - { - form: { - element: ".flow-4-form", - values: [{ element: ".flow-4-select", value: "1" }], - }, - action: 0, - }, - { - form: { - element: ".flow-4-form", - values: [{ element: ".flow-4-select", value: "2" }], - }, - action: 1, - }, - ], - }, - [ - [ - { - element: ".flow-4-form button", - title: "You selected Option 1", - body: "This is Option 1", - }, - ], - [ - { - element: ".flow-4-form button", - title: "You selected Option 2", - body: "This is Option 2", - }, - ], - ], - ], - }, - { - id: "vanilla-demo-flow-5", - element: "#start-flow-5", - steps: [ - { - element: "#start-flow-5", - title: "Hello from Flow 5!", - body: "In this demo you can see how wait for form values to be filled. To continue after this step fill out the form.", - }, - { - wait: { - change: [ - { element: ".flow-5-email", value: /^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/ }, - { element: ".flow-5-password", value: /^......+$/ }, - ], - }, - }, - { - element: ".flow-5-submit", - title: "Thanks for filling out the values, now you can proceed to submit.", - }, - ], - }, - { - id: "vanilla-demo-flow-6", - element: "#start-flow-6", - steps: [ - { - element: "#start-flow-6", - title: "Hello from Flow 6!", - body: "Lorem ipsum dolor sit amet consectetur adipisicing elit. Dicta iure quae soluta quam, eius ullam placeat nobis harum fugiat excepturi?", - hideNext: true, - footerActions: { - right: [ - { text: "Variant A", action: 0 }, - { text: "Variant B", action: 1 }, - ], - }, - }, - [ - [{ element: ".flow-6-A-text", title: "You selected variant A" }], - [{ element: ".flow-6-B-text", title: "You selected variant B" }], - ], - ], - }, - ], - tracking: console.log, -}); -window.FlowsJS?.identifyUser("vanilla@flows.sh"); - -document.addEventListener("submit", (e) => { - e.preventDefault(); -}); diff --git a/workspaces/js/css/vars.css b/workspaces/js/css/vars.css index d3d1e39..6d52b17 100644 --- a/workspaces/js/css/vars.css +++ b/workspaces/js/css/vars.css @@ -61,7 +61,7 @@ --flows-bg-hover: #262626; --flows-bg-primary: #e46a49; --flows-bg-primary-hover: #d35131; - --flows-bg-overlay: rgba(0, 0, 0, 0.4); + --flows-bg-overlay: rgba(0, 0, 0, 0.6); --flows-fg-default: #fafafa; --flows-fg-onPrimary: #181818; diff --git a/workspaces/js/package.json b/workspaces/js/package.json index 5e1e9c3..1440999 100644 --- a/workspaces/js/package.json +++ b/workspaces/js/package.json @@ -11,7 +11,6 @@ "popover", "overlay", "users", - "vanilla-js", "saas", "onboarding", "tour",