Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 29 additions & 10 deletions apps/web/app/(ee)/partners.dub.co/(onboarding)/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import Toolbar from "@/ui/layout/toolbar/toolbar";
import { Grid, Wordmark } from "@dub/ui";
import { CircleQuestion, Grid, Wordmark } from "@dub/ui";
import { cn } from "@dub/utils";
import { SignedInHint } from "app/app.dub.co/(onboarding)/signed-in-hint";
import Link from "next/link";
Expand Down Expand Up @@ -48,10 +47,14 @@ export default function PartnerOnboardingLayout({
))}
</div>

<div className="relative flex min-h-[100dvh] min-h-screen w-full flex-col items-center justify-between">
<div className="grow basis-0">
<div className="pt-4">
<Link href="https://dub.co/home" target="_blank" className="block">
<div className="relative flex min-h-[100dvh] min-h-screen w-full flex-col items-center overflow-hidden md:justify-between">
<div className="w-full px-4 md:grow md:basis-0 md:px-0">
<div className="flex justify-center pt-4">
<Link
href="https://dub.co/home"
target="_blank"
className="block w-fit"
>
<Wordmark className="h-8" />
<div className="text-center text-sm font-semibold text-black/80">
Partners
Expand All @@ -60,14 +63,30 @@ export default function PartnerOnboardingLayout({
</div>
</div>

<div className="w-full py-16">{children}</div>
<div className="w-full flex-1 overflow-y-auto md:flex-none md:overflow-visible">
<div className="w-full pt-8 pb-8 sm:pb-4 md:py-16 px-5 md:px-0">{children}</div>
</div>

<div className="w-full md:hidden">
<SignedInHint />
</div>

{/* Empty div to center main content */}
<div className="grow basis-0" />
<div className="hidden md:block md:grow md:basis-0" />
</div>

<div className="hidden md:block">
<SignedInHint />
</div>

<Toolbar show={["help"]} />
<SignedInHint />
<a
href="https://dub.co/contact/support"
target="_blank"
className="fixed bottom-0 right-0 z-40 m-5 hidden h-8 w-8 shrink-0 items-center justify-center rounded-lg border border-neutral-200 bg-white text-neutral-700 shadow-sm transition-colors hover:bg-neutral-100 md:flex"
aria-label="Help"
>
<CircleQuestion className="size-5" strokeWidth={2} />
</a>
</>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ export function OnboardingForm({
render={({ field }) => (
<FileUpload
accept="images"
className="mt-1.5 size-20 rounded-full border border-neutral-300"
className="mt-1.5 size-20 shrink-0 rounded-full border border-neutral-300 transition-[border-color,box-shadow] focus-within:border-neutral-500 focus-within:ring-1 focus-within:ring-neutral-500"
iconClassName="size-5"
previewClassName="size-20 rounded-full"
variant="plain"
Expand All @@ -162,11 +162,11 @@ export function OnboardingForm({
)}
/>
<div>
<p className="text-xs text-neutral-500">
Square image recommended, up to 2 MB.
<p className="text-xs font-medium text-neutral-600">
Visible to programs and helps with approvals
</p>
<p className="mt-0.5 text-xs font-medium text-neutral-500">
Adding an image can improve your approval rates.
<p className="mt-0.5 text-xs text-neutral-500">
Max 2 MB
</p>
</div>
</div>
Expand Down Expand Up @@ -218,7 +218,7 @@ export function OnboardingForm({

<label>
<span className="text-sm font-medium text-neutral-800">
Description
About you
<span className="font-normal text-neutral-500"> (optional)</span>
</span>
<div>
Expand All @@ -229,7 +229,7 @@ export function OnboardingForm({
? "border-red-300 pr-10 text-red-900 placeholder-red-300 focus:border-red-500 focus:ring-red-500"
: "border-neutral-300 text-neutral-900 placeholder-neutral-400 focus:border-neutral-500 focus:ring-neutral-500",
)}
placeholder="Tell us about the kind of content you create – e.g. tech, travel, fashion, etc."
placeholder="Share who you are, what you do, and who your audience is."
maxLength={MAX_PARTNER_DESCRIPTION_LENGTH}
minRows={3}
onKeyDown={handleKeyDown}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import { OnboardingForm } from "./onboarding-form";

export default function PartnerOnboarding() {
return (
<div className="mx-auto flex w-full max-w-[480px] flex-col items-center md:mt-4">
<h1 className="animate-slide-up-fade text-lg font-medium [--offset:8px] [animation-delay:250ms] [animation-duration:1s] [animation-fill-mode:both]">
<div className="mx-auto flex w-full max-w-[430px] flex-col items-center md:mt-4">
<h1 className="animate-slide-up-fade text-center text-xl font-semibold [--offset:8px] [animation-delay:250ms] [animation-duration:1s] [animation-fill-mode:both]">
Create your partner profile
</h1>
<div className="animate-slide-up-fade w-full rounded-xl p-8 [--offset:10px] [animation-delay:500ms] [animation-duration:1s] [animation-fill-mode:both]">
<div className="animate-slide-up-fade w-full [--offset:10px] [animation-delay:500ms] [animation-duration:1s] [animation-fill-mode:both]">
<Suspense fallback={<OnboardingForm />}>
<OnboardingFormRSC />
</Suspense>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ import { Suspense } from "react";

export default function OnboardingVerificationPage() {
return (
<div className="relative mx-auto my-10 flex w-full max-w-[640px] flex-col items-center px-4 text-center sm:px-6 md:mt-6">
<h1 className="animate-slide-up-fade text-content-emphasis text-xl font-semibold [--offset:8px] [animation-delay:250ms] [animation-duration:1s] [animation-fill-mode:both]">
<div className="relative mx-auto flex w-full max-w-[600px] flex-col items-center text-center md:mt-6">
<h1 className="animate-slide-up-fade text-content-emphasis text-xl text-center font-semibold [--offset:8px] [animation-delay:250ms] [animation-duration:1s] [animation-fill-mode:both]">
Connect payouts
</h1>
<p className="animate-slide-up-fade mt-1 text-base font-medium text-neutral-500 [--offset:8px] [animation-delay:250ms] [animation-duration:1s] [animation-fill-mode:both]">
<p className="animate-slide-up-fade mt-1 text-center text-base text-neutral-500 [--offset:8px] [animation-delay:250ms] [animation-duration:1s] [animation-fill-mode:both]">
Connect your preferred payout method to receive payments.
</p>
<div className="animate-slide-up-fade relative mt-12 w-full [--offset:10px] [animation-delay:500ms] [animation-duration:1s] [animation-fill-mode:both]">
<div className="animate-slide-up-fade relative mt-10 w-full [--offset:10px] [animation-delay:500ms] [animation-duration:1s] [animation-fill-mode:both]">
<Suspense fallback={<PayoutSkeleton />}>
<PayoutRSC />
</Suspense>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,22 @@ import { OnboardingPlatformsPageClient } from "./page-client";

export default function OnboardingPlatformsPage() {
return (
<div className="relative mx-auto w-full max-w-[416px] text-center md:mt-4">
<h1 className="animate-slide-up-fade text-lg font-medium [--offset:8px] [animation-delay:250ms] [animation-duration:1s] [animation-fill-mode:both]">
<div className="mx-auto flex w-full max-w-[430px] flex-col text-center md:mt-4">
<h1 className="animate-slide-up-fade text-center text-xl font-semibold [--offset:8px] [animation-delay:250ms] [animation-duration:1s] [animation-fill-mode:both]">
Your social and web platforms
</h1>

<p className="animate-slide-up-fade text-content-subtle mt-1 text-sm [animation-delay:500ms] [animation-duration:1s] [animation-fill-mode:both]">
<p className="animate-slide-up-fade text-content-subtle mt-1 text-base [animation-delay:500ms] [animation-duration:1s] [animation-fill-mode:both]">
Verifying your social and web platforms will improve your reputation
score and rank you higher in our partner network.
</p>

<div className="animate-slide-up-fade mt-8 grid gap-4 [animation-delay:750ms] [animation-duration:1s] [animation-fill-mode:both]">
<Suspense fallback={<PartnerPlatformsForm partner={null} />}>
<OnboardingPlatformsFormRSC />
</Suspense>
<div className="animate-slide-up-fade w-full rounded-xl py-8 [animation-delay:750ms] [animation-duration:1s] [animation-fill-mode:both]">
<div className="grid gap-4">
<Suspense fallback={<PartnerPlatformsForm partner={null} />}>
<OnboardingPlatformsFormRSC />
</Suspense>
</div>
</div>
</div>
);
Expand Down
15 changes: 12 additions & 3 deletions apps/web/app/app.dub.co/(onboarding)/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
import Toolbar from "@/ui/layout/toolbar/toolbar";
import { CircleQuestion } from "@dub/ui";
import { PropsWithChildren } from "react";
import { SignedInHint } from "./signed-in-hint";

export default function Layout({ children }: PropsWithChildren) {
return (
<>
{children}
<Toolbar show={["help"]} />
<SignedInHint />
<div className="hidden md:block">
<SignedInHint />
</div>
<a
href="https://dub.co/contact/support"
target="_blank"
className="fixed bottom-0 right-0 z-40 m-5 hidden h-8 w-8 shrink-0 items-center justify-center rounded-lg border border-neutral-200 bg-white text-neutral-700 shadow-sm transition-colors hover:bg-neutral-100 md:flex"
aria-label="Help"
>
<CircleQuestion className="size-5" strokeWidth={2} />
</a>
</>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export function DefaultDomainSelector() {

return (
<>
<div className="animate-fade-in mx-auto grid w-full max-w-[312px] gap-4 sm:max-w-[600px] sm:grid-cols-2">
<div className="animate-fade-in mx-auto grid w-full gap-4 sm:max-w-[600px] sm:grid-cols-2">
<DomainOption
step="domain/custom"
icon="https://assets.dub.co/icons/domain-sign.webp"
Expand Down
21 changes: 15 additions & 6 deletions apps/web/app/app.dub.co/(onboarding)/onboarding/(steps)/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Grid, Wordmark } from "@dub/ui";
import { cn } from "@dub/utils";
import { SignedInHint } from "app/app.dub.co/(onboarding)/signed-in-hint";
import Link from "next/link";
import { PropsWithChildren } from "react";

Expand Down Expand Up @@ -43,19 +44,27 @@ export default function Layout({ children }: PropsWithChildren) {
))}
</div>

<div className="relative flex min-h-[100dvh] min-h-screen w-full flex-col items-center justify-between">
<div className="grow basis-0">
<div className="pt-4">
<div className="relative flex min-h-[100dvh] min-h-screen w-full flex-col items-center overflow-hidden md:justify-between">
<div className="w-full px-4 pt-4 md:grow md:basis-0 md:px-0">
<div className="flex justify-center pt-4">
<Link href="https://dub.co/home" target="_blank" className="block">
<Wordmark className="h-8" />
</Link>
</div>
</div>

<div className="w-full py-16">{children}</div>
<div className="w-full flex-1 overflow-y-auto md:flex-none md:overflow-visible">
<div className="w-full px-5 pb-8 pt-8 sm:pb-4 md:px-0 md:py-16">
{children}
</div>
</div>

<div className="w-full md:hidden">
<SignedInHint />
</div>

{/* Empty div to center main content */}
<div className="grow basis-0" />
{/* Empty div to center main content on desktop */}
<div className="hidden md:block md:grow md:basis-0" />
</div>
</>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,40 +33,48 @@ export function PlanSelector({ product }: { product: OnboardingProduct }) {
: [PRO_PLAN, BUSINESS_PLAN, ADVANCED_PLAN];

const [period, setPeriod] = useState<"monthly" | "yearly">("monthly");
const [mobilePlanIndex, setMobilePlanIndex] = useState(0);
const [mobilePlanIndex, setMobilePlanIndex] = useState(() => {
const defaultPlanName = product === "partners" ? "Advanced" : "Business";
return Math.max(
0,
plans.findIndex((plan) => plan.name === defaultPlanName),
);
});

return (
<div className="overflow-hidden [container-type:inline-size]">
<div
className={cn(
"mx-auto grid max-w-[calc(var(--cols)*342px)] grid-cols-[repeat(var(--cols),1fr)]",
<div className="[container-type:inline-size]">
<div className="overflow-hidden max-md:rounded-lg">
<div
className={cn(
"mx-auto grid max-w-[calc(var(--cols)*342px)] grid-cols-[repeat(var(--cols),1fr)]",

// Mobile
"max-lg:w-[calc(var(--cols)*100cqw+(var(--cols)-1)*32px)] max-lg:max-w-none max-lg:translate-x-[calc(-1*var(--index)*(100cqw+32px))] max-lg:gap-x-8 max-lg:transition-transform",
)}
style={
{
"--cols": plans.length,
"--index": mobilePlanIndex,
} as CSSProperties
}
>
{plans.map((plan) => {
const features = PRICING_PLAN_MAIN_FEATURES[product][plan.name] || [];
// Mobile
"max-md:w-[calc(var(--cols)*100cqw+(var(--cols)-1)*32px)] max-md:max-w-none max-md:translate-x-[calc(-1*var(--index)*(100cqw+32px))] max-md:gap-x-8 max-md:transition-transform",
)}
style={
{
"--cols": plans.length,
"--index": mobilePlanIndex,
} as CSSProperties
}
>
{plans.map((plan) => {
const features = PRICING_PLAN_MAIN_FEATURES[product][plan.name] || [];

return (
<div
key={plan.name}
className={cn(
"flex flex-col border-y border-l border-neutral-200 bg-white first:rounded-l-lg last:rounded-r-lg last:border-r",
product === "links" &&
plan.name === "Business" &&
"bg-gradient-to-b from-orange-50 to-40%",
product === "partners" &&
plan.name === "Advanced" &&
"bg-gradient-to-b from-violet-50 to-40%",
)}
>
return (
<div
key={plan.name}
className={cn(
"flex flex-col border-y border-l border-neutral-200 bg-white first:rounded-l-lg last:rounded-r-lg last:border-r",
"max-md:overflow-hidden max-md:rounded-lg max-md:border-0 max-md:ring-1 max-md:ring-inset max-md:ring-neutral-200",
product === "links" &&
plan.name === "Business" &&
"bg-gradient-to-b from-orange-50 to-40%",
product === "partners" &&
plan.name === "Advanced" &&
"bg-gradient-to-b from-violet-50 to-40%",
)}
>
<div className="flex grow flex-col gap-6 p-5 pb-3">
<div>
<div className="flex items-center gap-2">
Expand Down Expand Up @@ -151,7 +159,7 @@ export function PlanSelector({ product }: { product: OnboardingProduct }) {
<div className="flex gap-2">
<button
type="button"
className="h-full w-fit rounded-lg bg-neutral-100 px-2.5 transition-colors duration-75 hover:bg-neutral-200/80 enabled:active:bg-neutral-200 disabled:opacity-30 lg:hidden"
className="h-full w-fit rounded-lg bg-neutral-100 px-2.5 transition-colors duration-75 hover:bg-neutral-200/80 enabled:active:bg-neutral-200 disabled:opacity-30 md:hidden"
disabled={mobilePlanIndex === 0}
onClick={() => setMobilePlanIndex(mobilePlanIndex - 1)}
>
Expand All @@ -178,7 +186,7 @@ export function PlanSelector({ product }: { product: OnboardingProduct }) {
)}
<button
type="button"
className="h-full w-fit rounded-lg bg-neutral-100 px-2.5 transition-colors duration-75 hover:bg-neutral-200/80 active:bg-neutral-200 disabled:opacity-30 lg:hidden"
className="h-full w-fit rounded-lg bg-neutral-100 px-2.5 transition-colors duration-75 hover:bg-neutral-200/80 active:bg-neutral-200 disabled:opacity-30 md:hidden"
disabled={mobilePlanIndex >= plans.length - 1}
onClick={() => setMobilePlanIndex(mobilePlanIndex + 1)}
>
Expand Down Expand Up @@ -286,9 +294,10 @@ export function PlanSelector({ product }: { product: OnboardingProduct }) {
</div>
</div>
)}
</div>
);
})}
</div>
);
})}
</div>
</div>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,6 @@ import { ReactNode } from "react";
import { useOnboardingProgress } from "../../use-onboarding-progress";

const products = {
links: {
image: "https://assets.dub.co/icons/link.webp",
title: "Dub Links",
href: "https://dub.co/links",
description:
"[Short links](https://dub.co/help/category/link-management), [QR codes](https://dub.co/help/article/custom-qr-codes), [real-time analytics](https://dub.co/help/article/dub-analytics), and [conversion tracking](https://dub.co/docs/conversions/quickstart).",
paidPlanRequired: false,
},
partners: {
image: "https://assets.dub.co/icons/trophy.webp",
title: "Dub Partners",
Expand All @@ -23,11 +15,19 @@ const products = {
"Modern [affiliate programs](https://dub.co/partners) with [global payouts](https://dub.co/help/article/partner-payouts) and [accurate attribution](https://dub.co/help/article/program-analytics).",
paidPlanRequired: true,
},
links: {
image: "https://assets.dub.co/icons/link.webp",
title: "Dub Links",
href: "https://dub.co/links",
description:
"[Short links](https://dub.co/help/category/link-management), [QR codes](https://dub.co/help/article/custom-qr-codes), [real-time analytics](https://dub.co/help/article/dub-analytics), and [conversion tracking](https://dub.co/docs/conversions/quickstart).",
paidPlanRequired: false,
},
};

export function ProductSelector() {
return (
<div className="animate-fade-in mx-auto grid w-full max-w-[312px] gap-4 sm:max-w-[600px] sm:grid-cols-2">
<div className="animate-fade-in mx-auto grid w-full gap-4 sm:max-w-[600px] sm:grid-cols-2">
{Object.entries(products).map(([key, product]) => (
<ProductOption
key={key}
Expand Down
Loading
Loading