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
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
"dependencies": {
"@vercel/analytics": "^2.0.1",
"@vercel/speed-insights": "^2.0.0",
"framer-motion": "^12.38.0",
"lucide-react": "^1.11.0",
"next": "14.2.35",
"next-auth": "^4.24.14",
Expand Down
54 changes: 8 additions & 46 deletions pnpm-lock.yaml

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

4 changes: 3 additions & 1 deletion src/app/dashboard/dev/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1558,7 +1558,9 @@ export default function DevDashboardPage() {
<div style={{ textAlign: "center", marginTop: "var(--space-6)" }}>
<button
className="btn btn-secondary"
onClick={() => fetchRepos(page + 1, selectedOrg, debouncedSearch)}
onClick={() =>
fetchRepos(page + 1, selectedOrg, debouncedSearch)
}
disabled={isFetchingMore}
style={{
minWidth: "150px",
Expand Down
57 changes: 28 additions & 29 deletions src/app/faq/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import { useState } from "react";
import { ChevronDown, HelpCircle } from "lucide-react";
import { motion, AnimatePresence } from "framer-motion";
import FadeIn from "@/components/FadeIn";
import StaggerContainer, { StaggerItem } from "@/components/StaggerContainer";

Expand Down Expand Up @@ -84,37 +83,37 @@ function FAQItem({ item }: { item: { q: string; a: string } }) {
>
{item.q}
</span>
<motion.div
animate={{ rotate: open ? 180 : 0 }}
transition={{ duration: 0.2 }}
style={{ flexShrink: 0, display: "flex" }}
<div
style={{
flexShrink: 0,
display: "flex",
transition: "transform 0.2s ease",
transform: open ? "rotate(180deg)" : "none",
}}
>
<ChevronDown size={18} color="var(--text-muted)" />
</motion.div>
</div>
</button>
<AnimatePresence initial={false}>
{open && (
<motion.div
initial={{ height: 0, opacity: 0 }}
animate={{ height: "auto", opacity: 1 }}
exit={{ height: 0, opacity: 0 }}
transition={{ duration: 0.25, ease: [0.25, 0.1, 0.25, 1] }}
style={{ overflow: "hidden" }}
>
<div
style={{
padding: "0 var(--space-5) var(--space-5)",
fontSize: "0.875rem",
color: "var(--text-secondary)",
lineHeight: 1.7,
whiteSpace: "pre-line",
}}
>
{item.a}
</div>
</motion.div>
)}
</AnimatePresence>
<div
style={{
maxHeight: open ? "500px" : "0",
opacity: open ? 1 : 0,
overflow: "hidden",
transition: "max-height 0.25s ease, opacity 0.25s ease",
}}
>
<div
style={{
padding: "0 var(--space-5) var(--space-5)",
fontSize: "0.875rem",
color: "var(--text-secondary)",
lineHeight: 1.7,
whiteSpace: "pre-line",
}}
>
{item.a}
</div>
</div>
</div>
);
}
Expand Down
32 changes: 32 additions & 0 deletions src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,17 @@ ol {
color: var(--text-muted);
}

/* ── Focus Indicators ── */
.btn:focus-visible,
.input:focus-visible,
.card:focus-visible,
a:focus-visible,
button:focus-visible,
[role="button"]:focus-visible {
outline: 2px solid var(--accent-primary);
outline-offset: 2px;
}

/* ── Mobile Responsive ─────────────────────────────────────── */

@media (max-width: 768px) {
Expand Down Expand Up @@ -912,6 +923,27 @@ ol {
background: rgba(255, 255, 255, 0.2);
}

/* ── Entry Animations ── */
@keyframes fadeSlideUp {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: none;
}
}

@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}

/* ── Reduced Motion ── */
@media (prefers-reduced-motion: reduce) {
*,
Expand Down
8 changes: 7 additions & 1 deletion src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import HomeContent from "@/components/HomeContent";
import LatestPluginsSection from "@/components/LatestPluginsSection";
import type { Metadata } from "next";

export const metadata: Metadata = {
Expand Down Expand Up @@ -27,5 +28,10 @@ async function StatsSection() {
}

export default function Home() {
return <StatsSection />;
return (
<>
<StatsSection />
<LatestPluginsSection />
</>
);
}
54 changes: 51 additions & 3 deletions src/app/plugins/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
BadgeCheck,
} from "lucide-react";
import dynamic from "next/dynamic";
import { cache } from "react";
import Image from "next/image";
import PluginImage from "@/components/PluginImage";
import VersionSelector from "@/components/VersionSelector";
Expand Down Expand Up @@ -60,20 +61,68 @@ const PluginAnalyticsChart = dynamic(
);
const DependencyGraph = dynamic(() => import("@/components/DependencyGraph"), {
ssr: false,
loading: () => (
<div
className="card"
style={{
padding: "var(--space-6)",
height: "200px",
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
>
<p style={{ color: "var(--text-muted)", fontSize: "0.875rem" }}>
Loading dependency graph...
</p>
</div>
),
});
const PluginRatings = dynamic(() => import("@/components/PluginRatings"), {
ssr: false,
loading: () => (
<div
className="card"
style={{
padding: "var(--space-6)",
height: "200px",
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
>
<p style={{ color: "var(--text-muted)", fontSize: "0.875rem" }}>
Loading ratings...
</p>
</div>
),
});
const VirusTotalCard = dynamic(() => import("@/components/VirusTotalCard"), {
ssr: false,
loading: () => (
<div
className="card"
style={{
padding: "var(--space-6)",
height: "200px",
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
>
<p style={{ color: "var(--text-muted)", fontSize: "0.875rem" }}>
Loading security scan...
</p>
</div>
),
});

async function getPlugin(slug: string) {
const getPlugin = cache(async function getPlugin(slug: string) {
const { data } = await fetchApi(`/api/v1/plugins/${slug}`, {
revalidate: 30,
});
return data?.data || null;
}
});

export async function generateMetadata({
params,
Expand Down Expand Up @@ -1103,7 +1152,6 @@ export default async function PluginDetailPage({

{/* Dependency Graph */}
<DependencyGraph slug={plugin.slug} />

</aside>
</div>
</div>
Expand Down
Loading
Loading