diff --git a/apps/web/src/assets/plans-footer.svg b/apps/web/src/assets/plans-footer.svg
new file mode 100644
index 000000000..6c71ab718
--- /dev/null
+++ b/apps/web/src/assets/plans-footer.svg
@@ -0,0 +1,128 @@
+
diff --git a/apps/web/src/common/theme.ts b/apps/web/src/common/theme.ts
index 786d5eb03..d1f41abba 100644
--- a/apps/web/src/common/theme.ts
+++ b/apps/web/src/common/theme.ts
@@ -60,7 +60,7 @@ export const THEME_LIGHT: any = {
paragraph: "#858585",
background: "#F7F7F7",
border: "#EFEFEF",
- heading: "#4B4B4B",
+ heading: "#6F6F6F",
icon: "#666666",
separator: "#E8E8E8",
placeholder: "#999999",
diff --git a/apps/web/src/components/icons/index.tsx b/apps/web/src/components/icons/index.tsx
index 4762430bc..efb8eca87 100644
--- a/apps/web/src/components/icons/index.tsx
+++ b/apps/web/src/components/icons/index.tsx
@@ -226,7 +226,6 @@ import {
mdiHistory,
mdiArrowCollapseRight,
mdiNoteEditOutline,
- mdiArrowUp,
mdiInbox,
mdiConsoleLine,
mdiSpellcheck,
@@ -260,6 +259,12 @@ import BoxArrowDownIcon from "@notesnook/icons/box-arrow-down.svg?react";
import DownloadIcon from "@notesnook/icons/download-simple.svg?react";
import FloppyDiskIcon from "@notesnook/icons/floppy-disk.svg?react";
import CheckSvg from "@notesnook/icons/check.svg?react";
+import ShieldCheckSvg from "@notesnook/icons/shield-check.svg?react";
+import CalendarBlankSvg from "@notesnook/icons/calendar-blank.svg?react";
+import ProhibitSvg from "@notesnook/icons/prohibit.svg?react";
+import HandCoinsSvg from "@notesnook/icons/hand-coins.svg?react";
+import ArrowUpSvg from "@notesnook/icons/arrow-up.svg?react";
+import LightningSvg from "@notesnook/icons/lightning.svg?react";
type MDIIconWrapperProps = {
title?: string;
@@ -625,7 +630,6 @@ export const SessionHistory = createIcon(mdiHistory);
export const ColorRemove = createIcon(mdiCloseCircleOutline);
export const ExpandSidebar = createIcon(mdiArrowCollapseRight);
export const HamburgerMenu = createIcon(mdiMenu);
-export const ArrowUp = createIcon(mdiArrowUp);
export const Inbox = createIcon(mdiInbox);
export const SpellCheck = createIcon(mdiSpellcheck);
export const ClearTrash = createIcon(mdiDeleteSweepOutline);
@@ -654,3 +658,9 @@ export const Copy = createSvgIcon(CopyIcon);
export const BoxArrowDown = createSvgIcon(BoxArrowDownIcon);
export const Download = createSvgIcon(DownloadIcon);
export const FloppyDisk = createSvgIcon(FloppyDiskIcon);
+export const ShieldCheck = createSvgIcon(ShieldCheckSvg);
+export const CalendarBlank = createSvgIcon(CalendarBlankSvg);
+export const Prohibit = createSvgIcon(ProhibitSvg);
+export const HandCoins = createSvgIcon(HandCoinsSvg);
+export const ArrowUp = createSvgIcon(ArrowUpSvg);
+export const Lightning = createSvgIcon(LightningSvg);
diff --git a/apps/web/src/dialogs/buy-dialog/plan-list.tsx b/apps/web/src/dialogs/buy-dialog/plan-list.tsx
index 08dd968d7..b249fa003 100644
--- a/apps/web/src/dialogs/buy-dialog/plan-list.tsx
+++ b/apps/web/src/dialogs/buy-dialog/plan-list.tsx
@@ -25,7 +25,12 @@ import {
FileDoc,
Picture,
CheckSvgIcon,
- ArrowRightSvgIcon
+ ArrowRightSvgIcon,
+ ShieldCheck,
+ CaretDown,
+ CalendarBlank,
+ Prohibit,
+ HandCoins
} from "../../components/icons";
import { Plan } from "./types";
import { PERIOD_METADATA, PLAN_METADATA, usePlans } from "./plans";
@@ -52,6 +57,8 @@ import Accordion from "../../components/accordion";
import { useStore as useUserStore } from "../../stores/user-store";
import { getCurrencySymbol } from "../../common/currencies";
import Star from "../../assets/star.svg";
+import { DialogManager } from "../../common/dialog-manager";
+import Dialog from "../../components/dialog";
const PLAN_CARD_FEATURES = [
getFeature("storage"),
@@ -200,208 +207,274 @@ export function PlansList(props: PlansListProps) {
))}
-
- {isLoading ? (
-
- ) : (
- plans
- .filter(
- (p) =>
- p.plan !== SubscriptionPlan.EDUCATION &&
- p.period === selectedPeriod
- )
- .map((plan) => {
- const metadata = PLAN_METADATA[plan.plan];
- const isRecommended = recommendedPlan === plan.plan;
- return (
-
+
+
+ {isLoading ? (
+
+ ) : (
+ plans
+ .filter(
+ (p) =>
+ p.plan !== SubscriptionPlan.EDUCATION &&
+ p.period === selectedPeriod
+ )
+ .map((plan) => {
+ const metadata = PLAN_METADATA[plan.plan];
+ const isRecommended = recommendedPlan === plan.plan;
+ return (
-
- {metadata.title}
-
- {isRecommended && (
-
-
- Recommended
-
-
- )}
-
-
- {metadata.subtitle}
-
-
-
- {plan.recurring ? (
-
- ) : (
-
- )}
-
-
- {PLAN_CARD_FEATURES.map((feature, index) => {
- const caption =
- feature.availability[planToAvailability(plan.plan)]
- .caption;
- return (
-
+ {metadata.title}
+
+ {isRecommended && (
-
-
-
- {feature.title}
-
-
-
+ Recommended
- {index < PLAN_CARD_FEATURES.length - 1 && (
-
+
+ {metadata.subtitle}
+
+
+
+ {plan.recurring ? (
+
+ ) : (
+
+ )}
+
+
+ {PLAN_CARD_FEATURES.map((feature, index) => {
+ const caption =
+ feature.availability[planToAvailability(plan.plan)]
+ .caption;
+ return (
+
+
- )}
-
- );
- })}
+ >
+
+
+
+ {feature.title}
+
+
+
+
+
+
+ {index < PLAN_CARD_FEATURES.length - 1 && (
+
+ )}
+
+ );
+ })}
+
+ {selectedPlan === plan.id ? (
+
+
+ You are on this plan.
+
+ ) : (
+
+ )}
- {selectedPlan === plan.id ? (
-
-
- You are on this plan.
-
- ) : (
-
- )}
-
- );
- })
- )}
-
-
- {/* */}
- {/* Cancel anytime. {PERIOD_METADATA[selectedPeriod].refundDays}-day */}
- {/* money-back guarantee. */}
- {/* */}
- {/* */}
+ );
+ })
+ )}
+
+
+
+
+
+
+
+
+ Cancel anytime
+
+
+ 14-day money back guarantee
+
+
+
+
+
+
>
);
}
@@ -621,7 +694,7 @@ function RecurringPricing(props: PricingProps) {
}}
>
{" "}
- /Month
+ / Month
)}
@@ -1216,3 +1289,122 @@ function toMonthlyPrice(price: number, period: Period) {
? (price / (12 * 5)).toFixed(2)
: (price / 12).toFixed(2);
}
+
+const CancelInfoDialog = DialogManager.register(function CancelInfoDialog(
+ props
+) {
+ return (
+
+ );
+});
+
+type CancelInfoCardProps = {
+ icon: React.ComponentType<{ size: number; color?: string }>;
+ title: string;
+ description: string;
+};
+
+function CancelInfoCard(props: CancelInfoCardProps) {
+ const Icon = props.icon;
+
+ return (
+
+
+
+
+
+
+
+ {props.title}
+
+
+ {props.description}
+
+
+
+
+ );
+}
diff --git a/apps/web/src/views/plans.tsx b/apps/web/src/views/plans.tsx
index fd017b6b7..063d59648 100644
--- a/apps/web/src/views/plans.tsx
+++ b/apps/web/src/views/plans.tsx
@@ -28,11 +28,13 @@ import {
import { FlexScrollContainer } from "../components/scroll-container";
import { Flex, Text, Button, Image, Box } from "@notesnook/ui";
import { useStore as useUserStore } from "../stores/user-store";
+import { useStore as useThemeStore } from "../stores/theme-store";
import { useEffect } from "react";
import { getQueryParams, hardNavigate } from "../navigation";
import { isUserSubscribed } from "../hooks/use-is-user-premium";
-import { ChevronLeft } from "../components/icons";
+import { ArrowUp, ChevronLeft, Lightning } from "../components/icons";
import Star from "../assets/star.svg";
+import PlansFooter from "../assets/plans-footer.svg";
function Plans() {
const user = useUserStore((store) => store.user);
@@ -173,12 +175,236 @@ function Plans() {
+
);
}
+
+function PlansCTA() {
+ const colorScheme = useThemeStore((store) => store.colorScheme);
+ const darkTheme = useThemeStore((store) => store.darkTheme);
+ const lightTheme = useThemeStore((store) => store.lightTheme);
+ const inverseBackground =
+ colorScheme === "dark"
+ ? lightTheme.scopes.base.primary.background
+ : darkTheme.scopes.base.primary.background;
+ const inverseHeading =
+ colorScheme === "dark"
+ ? lightTheme.scopes.base.primary.heading
+ : darkTheme.scopes.base.primary.heading;
+ const inverseParagraph =
+ colorScheme === "dark"
+ ? lightTheme.scopes.base.primary.paragraph
+ : darkTheme.scopes.base.primary.paragraph;
+ const inverseBackgroundSecondary =
+ colorScheme === "dark"
+ ? lightTheme.scopes.base.secondary.background
+ : darkTheme.scopes.base.secondary.background;
+ const inverseAccentForeground =
+ colorScheme === "dark"
+ ? lightTheme.scopes.base.primary.accentForeground
+ : darkTheme.scopes.base.primary.accentForeground;
+ const inverseBorder =
+ colorScheme === "dark"
+ ? lightTheme.scopes.base.primary.border
+ : darkTheme.scopes.base.primary.border;
+ const inverseParagraphSecondary =
+ colorScheme === "dark"
+ ? lightTheme.scopes.base.secondary.paragraph
+ : darkTheme.scopes.base.secondary.paragraph;
+
+ return (
+ <>
+
+
+
+
+
+
+ UNLOCK THE FULL POWER OF NOTESNOOK
+
+
+
+
+
+ Your notes deserve more than basic storage
+
+
+ Unlock encrypted syncing, larger storage, premium productivity
+ features, and everything you need to write with confidence.
+
+
+
+
+
+
+
+
+
+
+ ©
+
+
+ 2026 Streetwriters (Private) Ltd.
+
+
+
+
+ Privacy policy
+
+
+ Terms of service
+
+
+
+
+ >
+ );
+}
+
export default Plans;
function openURL(url: string) {
diff --git a/packages/icons/svgs/arrow-up.svg b/packages/icons/svgs/arrow-up.svg
new file mode 100644
index 000000000..d87088a63
--- /dev/null
+++ b/packages/icons/svgs/arrow-up.svg
@@ -0,0 +1,5 @@
+
diff --git a/packages/icons/svgs/calendar-blank.svg b/packages/icons/svgs/calendar-blank.svg
new file mode 100644
index 000000000..210cff1e3
--- /dev/null
+++ b/packages/icons/svgs/calendar-blank.svg
@@ -0,0 +1,3 @@
+
diff --git a/packages/icons/svgs/hand-coins.svg b/packages/icons/svgs/hand-coins.svg
new file mode 100644
index 000000000..552f16caa
--- /dev/null
+++ b/packages/icons/svgs/hand-coins.svg
@@ -0,0 +1,3 @@
+
diff --git a/packages/icons/svgs/lightning.svg b/packages/icons/svgs/lightning.svg
new file mode 100644
index 000000000..da780ded7
--- /dev/null
+++ b/packages/icons/svgs/lightning.svg
@@ -0,0 +1,5 @@
+
diff --git a/packages/icons/svgs/prohibit.svg b/packages/icons/svgs/prohibit.svg
new file mode 100644
index 000000000..a2247f643
--- /dev/null
+++ b/packages/icons/svgs/prohibit.svg
@@ -0,0 +1,3 @@
+
diff --git a/packages/icons/svgs/shield-check.svg b/packages/icons/svgs/shield-check.svg
index a10b58b1b..cac4ed6dc 100644
--- a/packages/icons/svgs/shield-check.svg
+++ b/packages/icons/svgs/shield-check.svg
@@ -1,3 +1,3 @@
diff --git a/packages/theme/src/theme/index.ts b/packages/theme/src/theme/index.ts
index 720d27fc9..f615de19b 100644
--- a/packages/theme/src/theme/index.ts
+++ b/packages/theme/src/theme/index.ts
@@ -42,6 +42,7 @@ export type Theme = {
spacing11: number;
spacing12: number;
spacing13: number;
+ spacing14: number;
};
sizes: { full: "100%"; half: "50%" };
radii: {
@@ -89,6 +90,7 @@ export class ThemeFactory {
spacing11: 40,
spacing12: 45,
spacing13: 50,
+ spacing14: 80,
auto: "auto"
}),
sizes: { full: "100%", half: "50%" },