diff --git a/apps/webapp/app/components/billing/FreePlanUsage.tsx b/apps/webapp/app/components/billing/FreePlanUsage.tsx new file mode 100644 index 000000000..f81f32944 --- /dev/null +++ b/apps/webapp/app/components/billing/FreePlanUsage.tsx @@ -0,0 +1,39 @@ +import { ArrowUpCircleIcon } from "@heroicons/react/24/outline"; +import { motion, useMotionValue, useTransform } from "framer-motion"; +import { Paragraph } from "../primitives/Paragraph"; +import { Link } from "@remix-run/react"; +import { cn } from "~/utils/cn"; + +export function FreePlanUsage({ to, percentage }: { to: string; percentage: number }) { + const widthProgress = useMotionValue(percentage * 100); + const color = useTransform( + widthProgress, + [0, 74, 75, 95, 100], + ["#22C55E", "#22C55E", "#F59E0B", "#F43F5E", "#F43F5E"] + ); + + return ( +
+
+
+ + Free Plan +
+ + Learn more + +
+
+ +
+
+ ); +} diff --git a/apps/webapp/app/components/navigation/SideMenu.tsx b/apps/webapp/app/components/navigation/SideMenu.tsx index 5b8e6acdb..f01705eeb 100644 --- a/apps/webapp/app/components/navigation/SideMenu.tsx +++ b/apps/webapp/app/components/navigation/SideMenu.tsx @@ -4,12 +4,10 @@ import { ChartBarIcon, EllipsisHorizontalIcon, } from "@heroicons/react/20/solid"; -import { ArrowUpCircleIcon } from "@heroicons/react/24/outline"; import { UserGroupIcon, UserPlusIcon } from "@heroicons/react/24/solid"; -import { Link, useNavigation } from "@remix-run/react"; +import { useNavigation } from "@remix-run/react"; import { IconExclamationCircle } from "@tabler/icons-react"; import { SlackIcon } from "@trigger.dev/companyicons"; -import { motion, useMotionValue, useTransform } from "framer-motion"; import { AnchorHTMLAttributes, Fragment, useEffect, useRef, useState } from "react"; import { useFeatures } from "~/hooks/useFeatures"; import { MatchedOrganization } from "~/hooks/useOrganizations"; @@ -37,6 +35,7 @@ import { Feedback } from "../Feedback"; import { ImpersonationBanner } from "../ImpersonationBanner"; import { LogoIcon } from "../LogoIcon"; import { UserProfilePhoto } from "../UserProfilePhoto"; +import { FreePlanUsage } from "../billing/FreePlanUsage"; import { Button, LinkButton } from "../primitives/Buttons"; import { Icon } from "../primitives/Icon"; import { type IconNames } from "../primitives/NamedIcon"; @@ -222,7 +221,7 @@ export function SideMenu({ user, project, organization, organizations }: SideMen } /> - + @@ -440,37 +439,3 @@ function SideMenuItem({ function MenuCount({ count }: { count: number | string }) { return
{count}
; } - -function FreePlanUsage({ to, percentage }: { to: string; percentage: number }) { - const widthProgress = useMotionValue(percentage * 100); - const color = useTransform( - widthProgress, - [0, 74, 75, 95, 100], - ["#22C55E", "#22C55E", "#F59E0B", "#F43F5E", "#F43F5E"] - ); - - return ( -
-
-
- - Free Plan -
- - Learn more - -
-
- -
-
- ); -} diff --git a/apps/webapp/app/components/stories/FreePlanUsage.stories.tsx b/apps/webapp/app/components/stories/FreePlanUsage.stories.tsx new file mode 100644 index 000000000..e62477ee3 --- /dev/null +++ b/apps/webapp/app/components/stories/FreePlanUsage.stories.tsx @@ -0,0 +1,46 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { FreePlanUsage } from "../billing/FreePlanUsage"; +import { organizationBillingPath } from "~/utils/pathBuilder"; +import { MatchedOrganization } from "~/hooks/useOrganizations"; + +const meta: Meta = { + title: "Billing/FreePlanUsage", + component: FreePlanUsageBar, +}; + +export default meta; + +type Story = StoryObj; + +const mockOrganization: MatchedOrganization = { + id: "mockID", + title: "mockTitle", + slug: "mockSlug", + projects: [ + { id: "mockId1", slug: "mockSlug1", name: "mockName1", jobCount: 1 }, + { id: "mockId2", slug: "mockSlug2", name: "mockName2", jobCount: 2 }, + ], + hasUnconfiguredIntegrations: false, + memberCount: 1, +}; + +export const ProgressBar: Story = { + args: { + organization: mockOrganization, + }, + render: (args) => , +}; + +type FreePlanUsageBarProps = { + organization: MatchedOrganization; +}; + +function FreePlanUsageBar({ organization }: FreePlanUsageBarProps) { + return ( +
+
+ +
+
+ ); +}