Skip to content
Merged
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
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ pnpm registry:build # registry only

See [CONTRIBUTING.md](./CONTRIBUTING.md).

## Sponsors

Analytics by [OpenPanel](https://openpanel.dev/open-source?utm_source=justinlevine.me).

## License

[MIT](./LICENSE)
9 changes: 2 additions & 7 deletions apps/docs/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export const metadata: Metadata = {
},
}

import Script from "next/script"
import { Analytics } from "@/components/analytics"

export default function RootLayout({
children,
Expand Down Expand Up @@ -118,12 +118,7 @@ export default function RootLayout({
>
<head />
<body className="antialiased">
<Script
id="umami-analytics"
src="https://cloud.umami.is/script.js"
data-website-id="1577ed14-ed62-48d4-a679-1e96a0f4ae54"
strategy="afterInteractive"
/>
<Analytics />
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
Expand Down
61 changes: 56 additions & 5 deletions apps/docs/app/sponsor/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { Metadata } from "next"
import Image from "next/image"
import Link from "next/link"
import { Heart, ExternalLink, Star, Plus } from "lucide-react"
import type { ReactNode } from "react"
import { JalcoLogo } from "@/components/icons/jalco-logo"
import { ThemeSwitcher } from "@/components/docs/theme-switcher"
import { GitHubStarsButton } from "@/registry/github-stars-button/github-stars-button"
Expand Down Expand Up @@ -46,11 +47,57 @@ async function getStargazers(): Promise<Stargazer[]> {
return pages.filter((s) => s.login !== "jal-co")
}

const tiers = [
function OpenPanelLogo({ className }: { className?: string }) {
return (
<svg viewBox="55 28 210 42" fill="currentColor" aria-hidden="true" className={className}>
<path d="M104.374 36.542a5.173 5.173 0 1 0-10.347 0V60.42a5.174 5.174 0 1 0 10.347 0zM120.293 36.542a5.174 5.174 0 1 0-10.347 0v7.163a5.173 5.173 0 1 0 10.347 0z"></path>
<path d="M74.212 31C66.362 31 60 37.363 60 45.212v5.808c0 7.85 6.363 14.212 14.212 14.212 7.85 0 14.212-6.363 14.212-14.212v-5.808c0-7.85-6.363-14.212-14.212-14.212m.026 8.36a5.174 5.174 0 0 0-5.174 5.174v7.163a5.174 5.174 0 1 0 10.348 0v-7.163a5.174 5.174 0 0 0-5.174-5.174" fillRule="evenodd" clipRule="evenodd"></path>
<path d="M146 57.384q-2.472 0-4.248-1.056-1.776-1.08-2.736-3.072t-.96-4.752.96-4.752q.96-2.016 2.736-3.096t4.248-1.08q2.496 0 4.272 1.08 1.8 1.08 2.736 3.096.96 1.992.96 4.752t-.96 4.752q-.936 1.992-2.736 3.072-1.776 1.056-4.272 1.056m0-2.376q1.656 0 2.832-.768 1.2-.768 1.824-2.208.624-1.464.624-3.528t-.624-3.528-1.824-2.232q-1.176-.792-2.832-.792-1.632 0-2.808.792-1.176.768-1.824 2.232-.624 1.464-.624 3.528t.624 3.528q.648 1.44 1.824 2.208t2.808.768m10.823 5.592V44.232h2.4l.072 2.736-.288-.144q.48-1.416 1.584-2.136 1.104-.744 2.544-.744 1.872 0 3.072.936 1.224.912 1.8 2.424.6 1.512.6 3.312t-.6 3.312q-.576 1.512-1.8 2.448-1.2.912-3.072.912-.96 0-1.8-.336a4.2 4.2 0 0 1-1.44-.936 3.6 3.6 0 0 1-.816-1.464l.288-.288V60.6zm5.856-5.52q1.536 0 2.4-1.176.888-1.176.888-3.288t-.888-3.288q-.864-1.176-2.4-1.176-1.008 0-1.752.504-.744.48-1.152 1.488t-.408 2.472.384 2.472q.408 1.008 1.152 1.512.768.48 1.776.48m13.768 2.208q-1.872 0-3.24-.816-1.344-.816-2.088-2.328-.72-1.512-.72-3.528t.72-3.504q.744-1.512 2.088-2.328 1.344-.84 3.168-.84 1.728 0 3.048.816 1.32.792 2.04 2.304.744 1.512.744 3.648v.648h-9.168q.096 1.872.984 2.808.912.936 2.448.936 1.128 0 1.872-.528t1.032-1.416l2.64.168a5.3 5.3 0 0 1-1.992 2.88q-1.464 1.08-3.576 1.08m-3.408-7.848h6.48q-.12-1.704-.984-2.52-.84-.816-2.16-.816-1.368 0-2.256.864-.864.84-1.08 2.472M184.784 57V44.232h2.328l.096 3.408-.312-.168q.216-1.248.816-2.016t1.464-1.128a4.6 4.6 0 0 1 1.872-.384q1.44 0 2.376.648.96.624 1.44 1.728.504 1.08.504 2.472V57h-2.544v-7.44q0-1.128-.24-1.896t-.792-1.176-1.44-.408q-1.344 0-2.184.888t-.84 2.592V57zm14.21 0V39.96h6.36q2.928 0 4.56 1.416 1.632 1.392 1.632 3.888 0 1.656-.744 2.88-.744 1.2-2.136 1.848-1.368.624-3.312.624h-3.768V57zm2.592-8.736h3.696q1.752 0 2.664-.744.912-.768.912-2.256 0-1.464-.912-2.184-.912-.744-2.664-.744h-3.696zm15.954 9.024q-1.992 0-3.192-.912-1.176-.912-1.176-2.568t.984-2.568q1.008-.936 3.096-1.344l4.392-.84q0-1.488-.696-2.208-.696-.744-2.064-.744-1.224 0-1.92.552-.696.528-.96 1.584l-2.616-.168q.36-1.92 1.776-3.024 1.44-1.104 3.72-1.104 2.592 0 3.936 1.392 1.368 1.368 1.368 3.864v4.968q0 .456.144.648.168.168.528.168h.456V57q-.12.024-.384.048t-.552.024q-.816 0-1.416-.264a1.75 1.75 0 0 1-.864-.864q-.288-.624-.288-1.656l.264.12a3.03 3.03 0 0 1-.84 1.488q-.624.648-1.608 1.032a5.9 5.9 0 0 1-2.088.36m.408-2.016q1.152 0 1.968-.432.816-.456 1.272-1.248t.456-1.8v-.816l-3.744.72q-1.152.216-1.632.696-.456.456-.456 1.176 0 .816.552 1.272.576.432 1.584.432M227.464 57V44.232h2.328l.096 3.408-.312-.168q.216-1.248.816-2.016t1.464-1.128a4.6 4.6 0 0 1 1.872-.384q1.44 0 2.376.648.96.624 1.44 1.728.504 1.08.504 2.472V57h-2.544v-7.44q0-1.128-.24-1.896t-.792-1.176-1.44-.408q-1.344 0-2.184.888t-.84 2.592V57zm19.154.288q-1.87 0-3.239-.816-1.344-.816-2.088-2.328-.72-1.512-.72-3.528t.72-3.504q.744-1.512 2.088-2.328 1.344-.84 3.168-.84 1.728 0 3.048.816 1.32.792 2.04 2.304.744 1.512.744 3.648v.648h-9.168q.096 1.872.984 2.808.912.936 2.448.936 1.128 0 1.872-.528t1.032-1.416l2.64.168a5.3 5.3 0 0 1-1.992 2.88q-1.464 1.08-3.577 1.08m-3.407-7.848h6.48q-.12-1.704-.984-2.52-.84-.816-2.16-.816-1.368 0-2.256.864-.864.84-1.08 2.472M257.857 57q-1.248 0-2.016-.648t-.768-2.064V39.96h2.544v14.088q0 .432.216.648.24.216.672.216h1.008V57z"></path>
</svg>
)
}

interface Sponsor {
name: string
href: string
logo?: string
logoComponent?: ReactNode
}

const tiers: {
name: string
slots: number
sponsors: Sponsor[]
colors: {
bg: string
text: string
border: string
slotBg: string
slotBorder: string
}
}[] = [
{
name: "Open Source Program",
slots: 4,
sponsors: [
{
name: "OpenPanel",
href: "https://openpanel.dev/open-source?utm_source=justinlevine.me",
logoComponent: <OpenPanelLogo className="h-8 w-auto" />,
},
],
colors: {
bg: "linear-gradient(145deg, #22c55e 0%, #4ade80 30%, #16a34a 60%, #86efac 100%)",
text: "#052e16",
border: "#16a34a",
slotBg: "rgba(34, 197, 94, 0.06)",
slotBorder: "rgba(22, 163, 74, 0.2)",
},
},
{
name: "Gold",
slots: 3,
sponsors: [] as { name: string; href: string; logo?: string }[],
sponsors: [],
colors: {
bg: "linear-gradient(145deg, #d4a84b 0%, #f5d98a 30%, #c9952e 60%, #e8c55a 100%)",
text: "#5c3d0e",
Expand All @@ -62,7 +109,7 @@ const tiers = [
{
name: "Silver",
slots: 3,
sponsors: [] as { name: string; href: string; logo?: string }[],
sponsors: [],
colors: {
bg: "linear-gradient(145deg, #a8a8a8 0%, #d4d4d4 30%, #8a8a8a 60%, #c0c0c0 100%)",
text: "#2a2a2a",
Expand All @@ -74,7 +121,7 @@ const tiers = [
{
name: "Bronze",
slots: 4,
sponsors: [] as { name: string; href: string; logo?: string }[],
sponsors: [],
colors: {
bg: "linear-gradient(145deg, #b5745a 0%, #d4956e 30%, #8c5a3e 60%, #c98a68 100%)",
text: "#3d1e0e",
Expand Down Expand Up @@ -248,7 +295,11 @@ export default async function SponsorPage() {
borderColor: tier.colors.slotBorder,
}}
>
{sponsor.logo ? (
{sponsor.logoComponent ? (
<span className="opacity-60 transition-opacity group-hover:opacity-100">
{sponsor.logoComponent}
</span>
) : sponsor.logo ? (
<Image
src={sponsor.logo}
alt={sponsor.name}
Expand Down
14 changes: 14 additions & 0 deletions apps/docs/components/analytics.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
"use client"

import { useEffect } from "react"
import { op } from "@/lib/openpanel"

export function Analytics() {
useEffect(() => {
// OpenPanel auto-tracks screen views, outgoing links, and data-track attributes
// Accessing op ensures the client is initialized on mount
void op
}, [])

return null
}
11 changes: 11 additions & 0 deletions apps/docs/components/docs/footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,17 @@ export function SiteFooter() {
Open source React components for Tailwind CSS. Free forever, never
paywalled.
</p>
<p className="text-xs text-muted-foreground">
Analytics by{" "}
<a
href="https://openpanel.dev/open-source?utm_source=justinlevine.me"
target="_blank"
rel="noopener noreferrer"
className="underline underline-offset-2 hover:text-foreground"
>
OpenPanel
</a>
</p>
</div>

<div className="flex gap-10 text-sm">
Expand Down
8 changes: 8 additions & 0 deletions apps/docs/lib/openpanel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { OpenPanel } from "@openpanel/web"

export const op = new OpenPanel({
clientId: process.env.NEXT_PUBLIC_OPENPANEL_CLIENT_ID ?? "",
trackScreenViews: true,
trackOutgoingLinks: true,
trackAttributes: true,
})
1 change: 1 addition & 0 deletions apps/docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
},
"dependencies": {
"@chenglou/pretext": "^0.0.4",
"@openpanel/web": "^1.4.0",
"@orama/orama": "^3.1.18",
"@radix-ui/react-label": "^2.1.7",
"@radix-ui/react-slot": "^1.2.3",
Expand Down
70 changes: 70 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading