mirror of
https://github.com/supermemoryai/supermemory.git
synced 2026-08-28 05:25:33 +00:00
more stuff
This commit is contained in:
parent
ebc8c1f60d
commit
593bb2556a
9 changed files with 407 additions and 93 deletions
|
|
@ -11,13 +11,20 @@ import {
|
|||
CardTitle,
|
||||
} from "@ui/components/card"
|
||||
import { Avatar, AvatarFallback, AvatarImage } from "@ui/components/avatar"
|
||||
import { ShareIcon, LoaderIcon } from "lucide-react"
|
||||
import { ShareIcon, LoaderIcon, ArrowRightIcon } from "lucide-react"
|
||||
import Link from "next/link"
|
||||
import { useParams } from "next/navigation"
|
||||
import { useParams, useRouter } from "next/navigation"
|
||||
import { labelVariants } from "@ui/text/label"
|
||||
import { cn } from "@lib/utils"
|
||||
import { headingVariants } from "@ui/text/heading"
|
||||
import { titleVariants } from "@ui/text/title"
|
||||
import { useSession } from "@lib/auth"
|
||||
|
||||
export default function ReferralInvitePage() {
|
||||
const params = useParams()
|
||||
const code = params.code as string
|
||||
const router = useRouter()
|
||||
const session = useSession()
|
||||
|
||||
const {
|
||||
data: referrerData,
|
||||
|
|
@ -48,6 +55,10 @@ export default function ReferralInvitePage() {
|
|||
retry: 1,
|
||||
})
|
||||
|
||||
if (session.data) {
|
||||
router.push("/")
|
||||
}
|
||||
|
||||
const referrer = referrerData?.referrer
|
||||
|
||||
if (isLoading) {
|
||||
|
|
@ -55,7 +66,13 @@ export default function ReferralInvitePage() {
|
|||
<div className="min-h-screen flex items-center justify-center p-4 bg-[#0f1419]">
|
||||
<div className="flex flex-col items-center gap-4">
|
||||
<LoaderIcon className="w-8 h-8 text-orange-500 animate-spin" />
|
||||
<p className="text-white/60">Loading invitation...</p>
|
||||
<p
|
||||
className={cn(
|
||||
labelVariants({ level: 1, weight: "regular", color: "muted" }),
|
||||
)}
|
||||
>
|
||||
Loading invitation...
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
|
@ -64,15 +81,22 @@ export default function ReferralInvitePage() {
|
|||
if (error || !code) {
|
||||
return (
|
||||
<div className="min-h-screen flex items-center justify-center p-4 bg-[#0f1419]">
|
||||
<Card className="max-w-md w-full bg-[#1a1f2a] border-white/10">
|
||||
<Card className="max-w-md w-full bg-sm-shark">
|
||||
<CardHeader className="text-center">
|
||||
<div className="mx-auto mb-4 w-16 h-16 rounded-full bg-red-500/10 flex items-center justify-center">
|
||||
<ShareIcon className="w-8 h-8 text-red-500" />
|
||||
</div>
|
||||
<CardTitle className="text-2xl font-bold text-white">
|
||||
<CardTitle
|
||||
className={cn(titleVariants({ level: 2, weight: "bold" }))}
|
||||
>
|
||||
Invalid Referral Link
|
||||
</CardTitle>
|
||||
<CardDescription className="text-white/60 mt-2">
|
||||
<CardDescription
|
||||
className={cn(
|
||||
labelVariants({ level: 1, weight: "regular", color: "muted" }),
|
||||
"mt-2",
|
||||
)}
|
||||
>
|
||||
{error instanceof Error ? error.message : "Invalid referral code"}
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
|
|
@ -80,10 +104,17 @@ export default function ReferralInvitePage() {
|
|||
<div className="space-y-4">
|
||||
<div className="text-center">
|
||||
<Link
|
||||
className="text-orange-500 hover:text-orange-400 text-sm underline"
|
||||
className={cn(
|
||||
labelVariants({
|
||||
level: 1,
|
||||
weight: "regular",
|
||||
color: "default",
|
||||
}),
|
||||
"underline underline-offset-2 hover:opacity-50 transition-all",
|
||||
)}
|
||||
href="https://supermemory.ai"
|
||||
>
|
||||
Learn more about supermemory
|
||||
Learn more
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -95,7 +126,7 @@ export default function ReferralInvitePage() {
|
|||
|
||||
return (
|
||||
<div className="min-h-screen flex items-center justify-center p-4 bg-[#0f1419]">
|
||||
<Card className="max-w-md w-full bg-[#1a1f2a] border-white/10">
|
||||
<Card className="max-w-md w-full bg-sm-shark">
|
||||
<CardHeader className="text-center">
|
||||
<div className="mx-auto mb-4">
|
||||
<Avatar className="w-20 h-20">
|
||||
|
|
@ -105,10 +136,17 @@ export default function ReferralInvitePage() {
|
|||
</AvatarFallback>
|
||||
</Avatar>
|
||||
</div>
|
||||
<CardTitle className="text-2xl font-bold text-white">
|
||||
<CardTitle
|
||||
className={cn(titleVariants({ level: 2, weight: "bold" }))}
|
||||
>
|
||||
You've been invited!
|
||||
</CardTitle>
|
||||
<CardDescription className="text-white/60 mt-2">
|
||||
<CardDescription
|
||||
className={cn(
|
||||
labelVariants({ level: 1, weight: "regular", color: "muted" }),
|
||||
"mt-2",
|
||||
)}
|
||||
>
|
||||
<span className="text-orange-400 font-semibold">
|
||||
{referrer?.name}
|
||||
</span>{" "}
|
||||
|
|
@ -117,29 +155,66 @@ export default function ReferralInvitePage() {
|
|||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="space-y-4">
|
||||
<div className="bg-[#0f1419] rounded-lg p-4 border border-white/10">
|
||||
<h3 className="text-white font-semibold mb-2">
|
||||
<div
|
||||
className={
|
||||
(cn(
|
||||
headingVariants({
|
||||
level: "h2",
|
||||
weight: "medium",
|
||||
}),
|
||||
),
|
||||
"text-white text-center")
|
||||
}
|
||||
>
|
||||
You and {referrer?.name} both get a free month of{" "}
|
||||
<b>supermemory pro</b>
|
||||
</div>
|
||||
<div className="bg-sm-shark rounded-lg p-4 border border-white/10">
|
||||
<h3
|
||||
className={cn(headingVariants({ level: "h3", weight: "bold" }))}
|
||||
>
|
||||
What is supermemory?
|
||||
</h3>
|
||||
<p className="text-white/70 text-sm leading-relaxed">
|
||||
<p
|
||||
className={cn(
|
||||
labelVariants({
|
||||
level: 1,
|
||||
weight: "regular",
|
||||
color: "muted",
|
||||
}),
|
||||
)}
|
||||
>
|
||||
supermemory is an AI-powered personal knowledge base that helps
|
||||
you store, organize, and interact with all your digital
|
||||
memories.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Link href={`/login?ref=${code}`} className="block">
|
||||
<Button className="w-full bg-orange-500 hover:bg-orange-600 text-white">
|
||||
Get Started
|
||||
</Button>
|
||||
</Link>
|
||||
<Button
|
||||
className={cn(
|
||||
labelVariants({ level: 1, weight: "medium" }),
|
||||
"w-full",
|
||||
)}
|
||||
asChild
|
||||
>
|
||||
<Link href={`/login?ref=${code}`}>
|
||||
Get Started <ArrowRightIcon className="w-4 h-4" />
|
||||
</Link>
|
||||
</Button>
|
||||
|
||||
<div className="text-center">
|
||||
<Link
|
||||
className="text-orange-500 hover:text-orange-400 text-sm underline"
|
||||
className={cn(
|
||||
labelVariants({
|
||||
level: 1,
|
||||
weight: "regular",
|
||||
color: "default",
|
||||
}),
|
||||
"underline underline-offset-2 hover:opacity-50 transition-all",
|
||||
)}
|
||||
href="https://supermemory.ai"
|
||||
>
|
||||
Learn more about supermemory
|
||||
Learn more
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,56 +1,95 @@
|
|||
"use client";
|
||||
"use client"
|
||||
|
||||
import { Button } from "@ui/components/button";
|
||||
import { Button } from "@ui/components/button"
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@ui/components/card";
|
||||
import { ShareIcon } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
} from "@ui/components/card"
|
||||
import { ArrowRightIcon, HeartIcon, ShareIcon } from "lucide-react"
|
||||
import Link from "next/link"
|
||||
import { labelVariants } from "@ui/text/label"
|
||||
import { cn } from "@lib/utils"
|
||||
import { headingVariants } from "@ui/text/heading"
|
||||
import { titleVariants } from "@ui/text/title"
|
||||
|
||||
export default function ReferralHomePage() {
|
||||
return (
|
||||
<div className="min-h-screen flex items-center justify-center p-4 bg-[#0f1419]">
|
||||
<Card className="max-w-md w-full bg-[#1a1f2a] border-white/10">
|
||||
<CardHeader className="text-center">
|
||||
<div className="mx-auto mb-4 w-16 h-16 rounded-full bg-orange-500/10 flex items-center justify-center">
|
||||
<ShareIcon className="w-8 h-8 text-orange-500" />
|
||||
<Card className="max-w-md w-full bg-sm-shark">
|
||||
<CardHeader className="flex flex-col items-center gap-4">
|
||||
<div className="mx-auto size-16 rounded-full bg-black/40 flex items-center justify-center">
|
||||
<HeartIcon className="h-full" />
|
||||
</div>
|
||||
<div className="flex flex-col items-center gap-1">
|
||||
<CardTitle
|
||||
className={cn(titleVariants({ level: 3, weight: "bold" }))}
|
||||
>
|
||||
Missing Referral Code?
|
||||
</CardTitle>
|
||||
<CardDescription
|
||||
className={cn(
|
||||
labelVariants({
|
||||
level: 1,
|
||||
weight: "regular",
|
||||
color: "muted",
|
||||
}),
|
||||
"text-center",
|
||||
)}
|
||||
>
|
||||
It looks like you're missing a referral code. Get one from a
|
||||
friend or join directly!
|
||||
</CardDescription>
|
||||
</div>
|
||||
<CardTitle className="text-2xl font-bold text-white">
|
||||
Missing Referral Code
|
||||
</CardTitle>
|
||||
<CardDescription className="text-white/60 mt-2">
|
||||
It looks like you're missing a referral code. Get one from a friend
|
||||
or join directly!
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="space-y-4">
|
||||
<div className="bg-[#0f1419] rounded-lg p-4 border border-white/10">
|
||||
<h3 className="text-white font-semibold mb-2">
|
||||
What is supermemory?
|
||||
</h3>
|
||||
<p className="text-white/70 text-sm leading-relaxed">
|
||||
supermemory is an AI-powered personal knowledge base that helps
|
||||
you store, organize, and interact with all your digital
|
||||
memories.
|
||||
</p>
|
||||
</div>
|
||||
<CardContent className="flex flex-col gap-4">
|
||||
<div className="bg-sm-shark rounded-lg p-4 border border-white/10">
|
||||
<h3
|
||||
className={cn(headingVariants({ level: "h3", weight: "bold" }))}
|
||||
>
|
||||
What is supermemory?
|
||||
</h3>
|
||||
<p
|
||||
className={cn(
|
||||
labelVariants({ level: 1, weight: "regular", color: "muted" }),
|
||||
)}
|
||||
>
|
||||
supermemory is an AI-powered personal knowledge base that helps
|
||||
you store, organize, and interact with all your digital memories.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="text-center">
|
||||
<Link
|
||||
className="text-orange-500 hover:text-orange-400 text-sm underline"
|
||||
href="https://supermemory.ai"
|
||||
>
|
||||
Learn more about supermemory
|
||||
</Link>
|
||||
</div>
|
||||
<Button
|
||||
className={cn(
|
||||
labelVariants({ level: 1, weight: "medium" }),
|
||||
"w-full",
|
||||
)}
|
||||
asChild
|
||||
>
|
||||
<Link href={"/login"}>
|
||||
Get Started <ArrowRightIcon className="w-4 h-4" />
|
||||
</Link>
|
||||
</Button>
|
||||
|
||||
<div className="text-center">
|
||||
<Link
|
||||
className={cn(
|
||||
labelVariants({
|
||||
level: 1,
|
||||
weight: "regular",
|
||||
color: "default",
|
||||
}),
|
||||
"underline underline-offset-2 hover:opacity-50 transition-all",
|
||||
)}
|
||||
href="https://supermemory.ai"
|
||||
>
|
||||
Learn more
|
||||
</Link>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,6 +47,6 @@ export default async function middleware(request: Request) {
|
|||
|
||||
export const config = {
|
||||
matcher: [
|
||||
"/((?!_next/static|_next/image|images|icon.png|monitoring|opengraph-image.png|ingest|api|login|api/emails).*)",
|
||||
"/((?!_next/static|_next/image|images|icon.png|monitoring|opengraph-image.png|ingest|api|login|api/emails|ref).*)",
|
||||
],
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,63 +1,63 @@
|
|||
import { withSentryConfig } from "@sentry/nextjs";
|
||||
import type { NextConfig } from "next";
|
||||
import { withSentryConfig } from "@sentry/nextjs"
|
||||
import type { NextConfig } from "next"
|
||||
|
||||
const nextConfig: NextConfig = {
|
||||
experimental: {
|
||||
reactCompiler: true,
|
||||
viewTransition: true,
|
||||
},
|
||||
eslint: {
|
||||
ignoreDuringBuilds: true,
|
||||
},
|
||||
poweredByHeader: false,
|
||||
async rewrites() {
|
||||
return [
|
||||
{
|
||||
source: "/ingest/static/:path*",
|
||||
destination: "https://us-assets.i.posthog.com/static/:path*",
|
||||
},
|
||||
{
|
||||
source: "/ingest/:path*",
|
||||
destination: "https://us.i.posthog.com/:path*",
|
||||
},
|
||||
];
|
||||
},
|
||||
skipTrailingSlashRedirect: true,
|
||||
};
|
||||
experimental: {
|
||||
reactCompiler: true,
|
||||
viewTransition: true,
|
||||
},
|
||||
eslint: {
|
||||
ignoreDuringBuilds: true,
|
||||
},
|
||||
poweredByHeader: false,
|
||||
async rewrites() {
|
||||
return [
|
||||
{
|
||||
source: "/ingest/static/:path*",
|
||||
destination: "https://us-assets.i.posthog.com/static/:path*",
|
||||
},
|
||||
{
|
||||
source: "/ingest/:path*",
|
||||
destination: "https://us.i.posthog.com/:path*",
|
||||
},
|
||||
]
|
||||
},
|
||||
skipTrailingSlashRedirect: true,
|
||||
}
|
||||
|
||||
export default withSentryConfig(nextConfig, {
|
||||
// For all available options, see:
|
||||
// For all available options, see:
|
||||
// https://www.npmjs.com/package/@sentry/webpack-plugin#options
|
||||
|
||||
org: "supermemory",
|
||||
|
||||
project: "consumer-app",
|
||||
project: "consumer-app",
|
||||
|
||||
// Only print logs for uploading source maps in CI
|
||||
// Only print logs for uploading source maps in CI
|
||||
silent: !process.env.CI,
|
||||
|
||||
// For all available options, see:
|
||||
// For all available options, see:
|
||||
// https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/
|
||||
|
||||
// Upload a larger set of source maps for prettier stack traces (increases build time)
|
||||
widenClientFileUpload: true,
|
||||
|
||||
// Route browser requests to Sentry through a Next.js rewrite to circumvent ad-blockers.
|
||||
// Route browser requests to Sentry through a Next.js rewrite to circumvent ad-blockers.
|
||||
// This can increase your server load as well as your hosting bill.
|
||||
// Note: Check that the configured route will not match with your Next.js middleware, otherwise reporting of client-
|
||||
// side errors will fail.
|
||||
tunnelRoute: "/monitoring",
|
||||
|
||||
// Automatically tree-shake Sentry logger statements to reduce bundle size
|
||||
// Automatically tree-shake Sentry logger statements to reduce bundle size
|
||||
disableLogger: true,
|
||||
|
||||
// Enables automatic instrumentation of Vercel Cron Monitors. (Does not yet work with App Router route handlers.)
|
||||
// Enables automatic instrumentation of Vercel Cron Monitors. (Does not yet work with App Router route handlers.)
|
||||
// See the following for more information:
|
||||
// https://docs.sentry.io/product/crons/
|
||||
// https://vercel.com/docs/cron-jobs
|
||||
automaticVercelMonitors: true,
|
||||
});
|
||||
})
|
||||
|
||||
import { initOpenNextCloudflareForDev } from "@opennextjs/cloudflare";
|
||||
import { initOpenNextCloudflareForDev } from "@opennextjs/cloudflare"
|
||||
|
||||
initOpenNextCloudflareForDev();
|
||||
initOpenNextCloudflareForDev()
|
||||
|
|
|
|||
3
bun.lock
3
bun.lock
|
|
@ -20,6 +20,7 @@
|
|||
"boxen": "^8.0.1",
|
||||
"cloudflare": "^4.5.0",
|
||||
"compromise": "^14.14.4",
|
||||
"cva": "^1.0.0-beta.4",
|
||||
"dedent": "^1.6.0",
|
||||
"destr": "^2.0.5",
|
||||
"drizzle-orm": "^0.44.3",
|
||||
|
|
@ -2002,6 +2003,8 @@
|
|||
|
||||
"csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
|
||||
|
||||
"cva": ["cva@1.0.0-beta.4", "", { "dependencies": { "clsx": "^2.1.1" }, "peerDependencies": { "typescript": ">= 4.5.5" }, "optionalPeers": ["typescript"] }, "sha512-F/JS9hScapq4DBVQXcK85l9U91M6ePeXoBMSp7vypzShoefUBxjQTo3g3935PUHgQd+IW77DjbPRIxugy4/GCQ=="],
|
||||
|
||||
"cytoscape": ["cytoscape@3.33.1", "", {}, "sha512-iJc4TwyANnOGR1OmWhsS9ayRS3s+XQ185FmuHObThD+5AeJCakAAbWv8KimMTt08xCCLNgneQwFp+JRJOr9qGQ=="],
|
||||
|
||||
"cytoscape-cose-bilkent": ["cytoscape-cose-bilkent@4.1.0", "", { "dependencies": { "cose-base": "^1.0.0" }, "peerDependencies": { "cytoscape": "^3.2.0" } }, "sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ=="],
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
"boxen": "^8.0.1",
|
||||
"cloudflare": "^4.5.0",
|
||||
"compromise": "^14.14.4",
|
||||
"cva": "^1.0.0-beta.4",
|
||||
"dedent": "^1.6.0",
|
||||
"destr": "^2.0.5",
|
||||
"drizzle-orm": "^0.44.3",
|
||||
|
|
|
|||
63
packages/ui/text/heading.tsx
Normal file
63
packages/ui/text/heading.tsx
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
import { Root } from "@radix-ui/react-slot"
|
||||
import { cva, type VariantProps } from "cva"
|
||||
import { cn } from "../../lib/utils"
|
||||
|
||||
export const headingVariants = cva({
|
||||
base: "tracking-[-0.4px]",
|
||||
variants: {
|
||||
level: {
|
||||
h1: "text-sm sm:text-base md:text-lg lg:text-xl leading-[32px]",
|
||||
h2: "text-xs sm:text-sm md:text-base lg:text-lg leading-[30px]",
|
||||
h3: "text-[0.625rem] sm:text-xs md:text-sm lg:text-base leading-[28px]",
|
||||
h4: "text-[0.5rem] sm:text-[0.625rem] md:text-xs lg:text-sm leading-[24px]",
|
||||
},
|
||||
weight: {
|
||||
bold: "font-bold",
|
||||
medium: "font-medium",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
level: "h1",
|
||||
weight: "medium",
|
||||
},
|
||||
})
|
||||
|
||||
export interface HeadingProps
|
||||
extends React.HTMLAttributes<HTMLHeadingElement>,
|
||||
VariantProps<typeof headingVariants> {
|
||||
asChild?: boolean
|
||||
}
|
||||
|
||||
export function Heading({
|
||||
className,
|
||||
level = "h1",
|
||||
weight = "medium",
|
||||
asChild,
|
||||
...props
|
||||
}: HeadingProps) {
|
||||
const Comp = asChild ? Root : level
|
||||
return (
|
||||
<Comp
|
||||
className={cn(headingVariants({ level, weight }), className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
// Export individual variant classes for compatibility
|
||||
export const headingH1Bold = () =>
|
||||
headingVariants({ level: "h1", weight: "bold" })
|
||||
export const headingH1Medium = () =>
|
||||
headingVariants({ level: "h1", weight: "medium" })
|
||||
export const headingH2Bold = () =>
|
||||
headingVariants({ level: "h2", weight: "bold" })
|
||||
export const headingH2Medium = () =>
|
||||
headingVariants({ level: "h2", weight: "medium" })
|
||||
export const headingH3Bold = () =>
|
||||
headingVariants({ level: "h3", weight: "bold" })
|
||||
export const headingH3Medium = () =>
|
||||
headingVariants({ level: "h3", weight: "medium" })
|
||||
export const headingH4Bold = () =>
|
||||
headingVariants({ level: "h4", weight: "bold" })
|
||||
export const headingH4Medium = () =>
|
||||
headingVariants({ level: "h4", weight: "medium" })
|
||||
68
packages/ui/text/label.tsx
Normal file
68
packages/ui/text/label.tsx
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
import { Root } from "@radix-ui/react-slot"
|
||||
import { cva, type VariantProps } from "cva"
|
||||
import { cn } from "../../lib/utils"
|
||||
|
||||
export const labelVariants = cva({
|
||||
base: "tracking-[-0.4px]",
|
||||
variants: {
|
||||
level: {
|
||||
1: "text-[0.875rem] md:text-[1rem] leading-[1.5rem]",
|
||||
2: "text-[0.25rem] sm:text-[0.375rem] md:text-[0.5rem] lg:text-[0.625rem] leading-[18px]",
|
||||
3: "text-[0.125rem] sm:text-[0.25rem] md:text-[0.375rem] lg:text-[0.5rem] leading-[16px] tracking-[-0.2px]",
|
||||
},
|
||||
weight: {
|
||||
medium: "font-medium",
|
||||
regular: "font-normal",
|
||||
},
|
||||
color: {
|
||||
default: "",
|
||||
muted: "text-sm-silver-chalice",
|
||||
},
|
||||
},
|
||||
compoundVariants: [
|
||||
{
|
||||
level: [2, 3],
|
||||
color: "default",
|
||||
class: "text-sm-silver-chalice",
|
||||
},
|
||||
],
|
||||
defaultVariants: {
|
||||
level: 1,
|
||||
weight: "regular",
|
||||
color: "default",
|
||||
},
|
||||
})
|
||||
|
||||
export interface LabelProps
|
||||
extends Omit<React.HTMLAttributes<HTMLParagraphElement>, "color">,
|
||||
VariantProps<typeof labelVariants> {
|
||||
asChild?: boolean
|
||||
}
|
||||
|
||||
export function Label({
|
||||
className,
|
||||
level = 1,
|
||||
weight = "regular",
|
||||
color = "default",
|
||||
asChild,
|
||||
...props
|
||||
}: LabelProps) {
|
||||
const Comp = asChild ? Root : "p"
|
||||
return (
|
||||
<Comp
|
||||
className={cn(labelVariants({ level, weight, color }), className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
// Export individual variant classes for compatibility
|
||||
export const label1Medium = () => labelVariants({ level: 1, weight: "medium" })
|
||||
export const label1Regular = () =>
|
||||
labelVariants({ level: 1, weight: "regular" })
|
||||
export const label2Medium = () => labelVariants({ level: 2, weight: "medium" })
|
||||
export const label2Regular = () =>
|
||||
labelVariants({ level: 2, weight: "regular" })
|
||||
export const label3Medium = () => labelVariants({ level: 3, weight: "medium" })
|
||||
export const label3Regular = () =>
|
||||
labelVariants({ level: 3, weight: "regular" })
|
||||
65
packages/ui/text/title.tsx
Normal file
65
packages/ui/text/title.tsx
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
import { Root } from "@radix-ui/react-slot"
|
||||
import { cva, type VariantProps } from "cva"
|
||||
import { cn } from "../../lib/utils"
|
||||
|
||||
export const titleVariants = cva({
|
||||
base: "tracking-[-0.4px]",
|
||||
variants: {
|
||||
level: {
|
||||
1: "text-xl sm:text-2xl md:text-3xl lg:text-4xl leading-[70px] tracking-[-0.8px]",
|
||||
2: "text-lg sm:text-xl md:text-2xl lg:text-3xl leading-[48px]",
|
||||
3: "text-base sm:text-lg md:text-xl lg:text-2xl leading-[40px]",
|
||||
},
|
||||
weight: {
|
||||
bold: "font-bold",
|
||||
medium: "font-medium",
|
||||
},
|
||||
},
|
||||
compoundVariants: [
|
||||
{
|
||||
level: 2,
|
||||
weight: "medium",
|
||||
class: "leading-[32px] md:leading-[48px]",
|
||||
},
|
||||
],
|
||||
defaultVariants: {
|
||||
level: 1,
|
||||
weight: "medium",
|
||||
},
|
||||
})
|
||||
|
||||
export interface TitleProps
|
||||
extends React.HTMLAttributes<HTMLHeadingElement>,
|
||||
VariantProps<typeof titleVariants> {
|
||||
asChild?: boolean
|
||||
}
|
||||
|
||||
export function Title({
|
||||
className,
|
||||
level = 1,
|
||||
weight = "medium",
|
||||
asChild,
|
||||
...props
|
||||
}: TitleProps) {
|
||||
const levelMap = {
|
||||
1: "h1",
|
||||
2: "h2",
|
||||
3: "h3",
|
||||
} as const
|
||||
|
||||
const Comp = asChild ? Root : levelMap[level]
|
||||
return (
|
||||
<Comp
|
||||
className={cn(titleVariants({ level, weight }), className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
// Export individual variant classes for compatibility
|
||||
export const title1Bold = () => titleVariants({ level: 1, weight: "bold" })
|
||||
export const title1Medium = () => titleVariants({ level: 1, weight: "medium" })
|
||||
export const title2Bold = () => titleVariants({ level: 2, weight: "bold" })
|
||||
export const title2Medium = () => titleVariants({ level: 2, weight: "medium" })
|
||||
export const title3Bold = () => titleVariants({ level: 3, weight: "bold" })
|
||||
export const title3Medium = () => titleVariants({ level: 3, weight: "medium" })
|
||||
Loading…
Add table
Reference in a new issue