Update component configurations and styles: add new registry for @magicui in components.json, remove unused opengraph image files, and enhance opengraph-image.tsx with new font loading and styling adjustments. Refactor button sizes and styles in various components for improved responsiveness and visual consistency. Overall, these changes aim to streamline the application and enhance user experience.
Some checks failed
Deploy / deploy (push) Has been cancelled
Some checks failed
Deploy / deploy (push) Has been cancelled
This commit is contained in:
@@ -22,6 +22,7 @@
|
||||
"hooks": "@/hooks"
|
||||
},
|
||||
"registries": {
|
||||
"@skiper-ui": "https://skiper-ui.com/registry/{name}.json"
|
||||
"@skiper-ui": "https://skiper-ui.com/registry/{name}.json",
|
||||
"@magicui": "https://magicui.design/r/{name}"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,4 +215,4 @@
|
||||
/* scroll-behavior: smooth KULLANMA — Lenis (ScrollFlow, anchors: true)
|
||||
kaydırmayı zaten yumuşatıyor; ikisi birlikte çift yumuşatma yapar. */
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
KolayTercih — YKS tercihin, gerçek YÖK Atlas verisiyle. Sıralamanı gir, dengeli 24 tercihlik listeni al.
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 43 KiB |
92
src/app/opengraph-image.tsx
Normal file
92
src/app/opengraph-image.tsx
Normal file
@@ -0,0 +1,92 @@
|
||||
import { ImageResponse } from "next/og";
|
||||
import { loadSiteOgFonts } from "@/lib/og-fonts";
|
||||
|
||||
export const alt =
|
||||
"KolayTercih — YKS tercihin, gerçek YÖK Atlas verisiyle. Sıralamanı gir, dengeli 24 tercihlik listeni al.";
|
||||
export const size = { width: 1200, height: 630 };
|
||||
export const contentType = "image/png";
|
||||
|
||||
export default async function OpenGraphImage() {
|
||||
const fonts = await loadSiteOgFonts();
|
||||
|
||||
return new ImageResponse(
|
||||
(
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
background: "white",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "center",
|
||||
maxWidth: 920,
|
||||
padding: "0 48px",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
fontFamily: "Bricolage Grotesque",
|
||||
letterSpacing: "-0.05em",
|
||||
color: "#0f172a",
|
||||
}}
|
||||
>
|
||||
<svg
|
||||
width="64"
|
||||
height="64"
|
||||
viewBox="0 0 180 180"
|
||||
style={{ display: "flex", marginRight: 4 }}
|
||||
>
|
||||
<rect x="27" y="56" width="57" height="57" rx="13" fill="#3b82f6" />
|
||||
<rect x="91" y="29" width="56" height="56" rx="13" fill="#fdc7a7" />
|
||||
<rect x="91" y="95" width="56" height="56" rx="13" fill="#ff5a00" />
|
||||
</svg>
|
||||
<span style={{ display: "flex", fontSize: 72, lineHeight: 1 }}>
|
||||
<span style={{ fontWeight: 300 }}>Kolay</span>
|
||||
<span style={{ fontWeight: 600 }}>Tercih</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
marginTop: 28,
|
||||
fontFamily: "Clarity City",
|
||||
fontSize: 34,
|
||||
fontWeight: 600,
|
||||
lineHeight: 1.25,
|
||||
textAlign: "center",
|
||||
color: "#1e293b",
|
||||
}}
|
||||
>
|
||||
YKS tercihin, gerçek YÖK Atlas verisiyle
|
||||
</div>
|
||||
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
marginTop: 16,
|
||||
fontFamily: "Clarity City",
|
||||
fontSize: 26,
|
||||
fontWeight: 300,
|
||||
lineHeight: 1.3,
|
||||
textAlign: "center",
|
||||
color: "#64748b",
|
||||
}}
|
||||
>
|
||||
Sıralamanı gir · Dengeli 24 tercihlik listeni al
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
{ ...size, fonts },
|
||||
);
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import { ImageResponse } from "next/og";
|
||||
import { getRehber } from "@/lib/rehber";
|
||||
import { loadRehberOgFonts } from "@/lib/og-fonts";
|
||||
import {
|
||||
rehberBasliginiBol,
|
||||
rehberMetniniParcala,
|
||||
@@ -18,6 +19,7 @@ export default async function RehberOpenGraphImage({
|
||||
const yazi = getRehber(slug);
|
||||
const baslik = yazi?.baslik ?? "Tercih Rehberi";
|
||||
const { vurgu, kalan } = rehberBasliginiBol(baslik);
|
||||
const fonts = await loadRehberOgFonts();
|
||||
|
||||
return new ImageResponse(
|
||||
(
|
||||
@@ -30,7 +32,7 @@ export default async function RehberOpenGraphImage({
|
||||
overflow: "hidden",
|
||||
background: "white",
|
||||
color: "#2563eb",
|
||||
fontFamily: "sans-serif",
|
||||
fontFamily: "Bricolage Grotesque",
|
||||
}}
|
||||
>
|
||||
{[
|
||||
@@ -108,6 +110,7 @@ export default async function RehberOpenGraphImage({
|
||||
style={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
fontFamily: "Clarity City",
|
||||
fontSize: 20,
|
||||
fontWeight: 700,
|
||||
letterSpacing: "0.18em",
|
||||
@@ -123,8 +126,9 @@ export default async function RehberOpenGraphImage({
|
||||
display: "flex",
|
||||
flexWrap: "wrap",
|
||||
maxWidth: 980,
|
||||
fontFamily: "Cal Sans",
|
||||
fontSize: baslik.length > 70 ? 48 : baslik.length > 52 ? 54 : 62,
|
||||
fontWeight: 300,
|
||||
fontWeight: 400,
|
||||
lineHeight: 1.02,
|
||||
letterSpacing: "-0.025em",
|
||||
color: "#2563eb",
|
||||
@@ -133,8 +137,9 @@ export default async function RehberOpenGraphImage({
|
||||
<span
|
||||
style={{
|
||||
display: "flex",
|
||||
fontFamily: "Bricolage Grotesque",
|
||||
color: "#ff5a00",
|
||||
fontWeight: 700,
|
||||
fontWeight: 600,
|
||||
letterSpacing: "-0.04em",
|
||||
}}
|
||||
>
|
||||
@@ -144,6 +149,7 @@ export default async function RehberOpenGraphImage({
|
||||
key={i}
|
||||
style={{
|
||||
display: "flex",
|
||||
fontFamily: "Bricolage Grotesque",
|
||||
fontStyle: "italic",
|
||||
fontWeight: 800,
|
||||
}}
|
||||
@@ -168,6 +174,7 @@ export default async function RehberOpenGraphImage({
|
||||
key={i}
|
||||
style={{
|
||||
display: "flex",
|
||||
fontFamily: "Bricolage Grotesque",
|
||||
fontStyle: "italic",
|
||||
fontWeight: 800,
|
||||
}}
|
||||
@@ -203,18 +210,19 @@ export default async function RehberOpenGraphImage({
|
||||
style={{
|
||||
display: "flex",
|
||||
marginLeft: 2,
|
||||
fontFamily: "Bricolage Grotesque",
|
||||
fontSize: 24,
|
||||
letterSpacing: "-0.05em",
|
||||
color: "#2563eb",
|
||||
}}
|
||||
>
|
||||
<span style={{ fontWeight: 300 }}>Kolay</span>
|
||||
<span style={{ fontWeight: 700 }}>Tercih</span>
|
||||
<span style={{ fontWeight: 600 }}>Tercih</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
size,
|
||||
{ ...size, fonts },
|
||||
);
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ export function KatalogArama() {
|
||||
type="button"
|
||||
onClick={() => setAcik(true)}
|
||||
aria-label="Bölüm veya üniversite ara"
|
||||
className="ml-auto flex size-10 cursor-pointer items-center justify-center rounded-full border border-slate-200 bg-white text-slate-700 transition-[background-color,transform] duration-150 hover:bg-slate-100 active:scale-[0.96] sm:hidden"
|
||||
className="ml-auto flex size-9 shrink-0 cursor-pointer items-center justify-center rounded-full border border-slate-200 bg-white text-slate-700 transition-[background-color,transform] duration-150 hover:bg-slate-100 active:scale-[0.96] sm:hidden"
|
||||
>
|
||||
<Search className="size-4" aria-hidden />
|
||||
</button>
|
||||
|
||||
@@ -29,9 +29,9 @@ export function ListemButonu() {
|
||||
aria-expanded={acik}
|
||||
aria-label={`Seçtiklerim — ${liste.length}/${MANUEL_LISTE_MAX} program`}
|
||||
title="Tablodan seçtiğin programlar"
|
||||
className="relative inline-flex h-12 cursor-pointer items-center gap-2 whitespace-nowrap rounded-full border border-slate-200 bg-white px-5 text-sm font-semibold text-slate-700 transition-[color,background-color,border-color,transform] duration-200 hover:border-slate-300 hover:bg-slate-50 active:scale-[0.97]"
|
||||
className="relative inline-flex h-9 cursor-pointer items-center gap-1.5 whitespace-nowrap rounded-full border border-slate-200 bg-white px-3 text-xs font-semibold text-slate-700 transition-[color,background-color,border-color,transform] duration-200 hover:border-slate-300 hover:bg-slate-50 active:scale-[0.97] sm:h-12 sm:gap-2 sm:px-5 sm:text-sm"
|
||||
>
|
||||
<ListChecks className="size-4 text-primary" aria-hidden />
|
||||
<ListChecks className="size-3.5 text-primary sm:size-4" aria-hidden />
|
||||
<span className="hidden sm:inline">Seçtiklerim</span>
|
||||
{liste.length > 0 ? (
|
||||
// key=length: her eklemede rozet yeniden doğar ve spring ile oturur
|
||||
|
||||
@@ -11,14 +11,14 @@ export function SignOutButton() {
|
||||
<Button
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
className="size-12 cursor-pointer rounded-full border border-slate-200 bg-white text-slate-600 transition-colors duration-200 hover:border-slate-300 hover:bg-slate-50 hover:text-slate-900"
|
||||
className="size-9 cursor-pointer rounded-full border border-slate-200 bg-white text-slate-600 transition-colors duration-200 hover:border-slate-300 hover:bg-slate-50 hover:text-slate-900 sm:size-12"
|
||||
aria-label="Çıkış yap"
|
||||
onClick={async () => {
|
||||
await authClient.signOut();
|
||||
router.refresh();
|
||||
}}
|
||||
>
|
||||
<LogOut className="size-5" aria-hidden />
|
||||
<LogOut className="size-4 sm:size-5" aria-hidden />
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,11 +6,11 @@ import { UserNav, UserNavFallback } from "@/components/user-nav";
|
||||
|
||||
export function SiteHeader() {
|
||||
return (
|
||||
<header className="sticky top-6 z-50 mt-6 print:hidden">
|
||||
<div className="relative mx-auto flex h-16 max-w-6xl items-center justify-between gap-3 px-4">
|
||||
<header className="sticky top-4 z-50 mt-4 sm:top-6 sm:mt-6 print:hidden">
|
||||
<div className="relative mx-auto flex h-12 max-w-6xl items-center justify-between gap-2 px-3 sm:h-16 sm:gap-3 sm:px-4">
|
||||
<Link
|
||||
href="/"
|
||||
className="group flex items-center font-bricolage text-xl"
|
||||
className="group flex min-w-0 shrink items-center font-bricolage"
|
||||
>
|
||||
<Image
|
||||
src="/kolay-tercih-mark.svg"
|
||||
@@ -18,11 +18,13 @@ export function SiteHeader() {
|
||||
width={44}
|
||||
height={44}
|
||||
aria-hidden="true"
|
||||
className="size-11 shrink-0"
|
||||
className="size-8 shrink-0 sm:size-11"
|
||||
/>
|
||||
<span>
|
||||
<span className="font-light text-3xl tracking-tighter">Kolay</span>
|
||||
<span className="font-semibold text-3xl tracking-tighter">
|
||||
<span className="truncate">
|
||||
<span className="text-lg font-light tracking-tighter sm:text-3xl">
|
||||
Kolay
|
||||
</span>
|
||||
<span className="text-lg font-semibold tracking-tighter sm:text-3xl">
|
||||
Tercih
|
||||
</span>
|
||||
</span>
|
||||
|
||||
@@ -11,8 +11,8 @@ import { SignOutButton } from "./sign-out-button";
|
||||
*/
|
||||
export function UserNavFallback() {
|
||||
return (
|
||||
<div className="flex items-center gap-2" aria-hidden>
|
||||
<div className="h-12 w-28 rounded-full bg-slate-900/10" />
|
||||
<div className="flex shrink-0 items-center gap-1.5 sm:gap-2" aria-hidden>
|
||||
<div className="h-9 w-16 rounded-full bg-slate-900/10 sm:h-12 sm:w-28" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -23,11 +23,11 @@ export async function UserNav() {
|
||||
// Manuel liste localStorage'ta yaşadığı için Listem girişsiz de çalışır
|
||||
if (!u) {
|
||||
return (
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="flex shrink-0 items-center gap-1.5 sm:gap-2">
|
||||
<ListemButonu />
|
||||
<Button
|
||||
asChild
|
||||
className="h-12 cursor-pointer rounded-full bg-slate-900 px-7 text-base font-medium text-white transition-colors duration-200 hover:bg-slate-700"
|
||||
className="h-9 cursor-pointer rounded-full bg-slate-900 px-3.5 text-sm font-medium text-white transition-colors duration-200 hover:bg-slate-700 sm:h-12 sm:px-7 sm:text-base"
|
||||
>
|
||||
<Link href="/giris">Giriş yap</Link>
|
||||
</Button>
|
||||
@@ -36,15 +36,16 @@ export async function UserNav() {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="flex shrink-0 items-center gap-1.5 sm:gap-2">
|
||||
<ListemButonu />
|
||||
<Link
|
||||
href="/paket"
|
||||
className="inline-flex h-12 items-center gap-2 whitespace-nowrap rounded-full border border-slate-200 bg-white px-5 text-sm font-semibold text-slate-700 transition-colors duration-200 hover:border-slate-300 hover:bg-slate-50"
|
||||
className="inline-flex h-9 items-center gap-1.5 whitespace-nowrap rounded-full border border-slate-200 bg-white px-3 text-xs font-semibold text-slate-700 transition-colors duration-200 hover:border-slate-300 hover:bg-slate-50 sm:h-12 sm:gap-2 sm:px-5 sm:text-sm"
|
||||
title="Kredilerin — yüklemek için tıkla"
|
||||
>
|
||||
<Coins className="size-4 text-amber-500" aria-hidden />
|
||||
{u.creditBalance} kredi
|
||||
<Coins className="size-3.5 text-amber-500 sm:size-4" aria-hidden />
|
||||
<span className="tabular-nums">{u.creditBalance}</span>
|
||||
<span className="hidden sm:inline">kredi</span>
|
||||
</Link>
|
||||
<SignOutButton />
|
||||
</div>
|
||||
|
||||
BIN
src/fonts/og/ClarityCity-Bold.ttf
Normal file
BIN
src/fonts/og/ClarityCity-Bold.ttf
Normal file
Binary file not shown.
BIN
src/fonts/og/ClarityCity-Light.ttf
Normal file
BIN
src/fonts/og/ClarityCity-Light.ttf
Normal file
Binary file not shown.
BIN
src/fonts/og/ClarityCity-SemiBold.ttf
Normal file
BIN
src/fonts/og/ClarityCity-SemiBold.ttf
Normal file
Binary file not shown.
BIN
src/fonts/og/bricolage-grotesque-latin-300-normal.woff
Normal file
BIN
src/fonts/og/bricolage-grotesque-latin-300-normal.woff
Normal file
Binary file not shown.
BIN
src/fonts/og/bricolage-grotesque-latin-600-normal.woff
Normal file
BIN
src/fonts/og/bricolage-grotesque-latin-600-normal.woff
Normal file
Binary file not shown.
BIN
src/fonts/og/bricolage-grotesque-latin-800-normal.woff
Normal file
BIN
src/fonts/og/bricolage-grotesque-latin-800-normal.woff
Normal file
Binary file not shown.
BIN
src/fonts/og/bricolage-grotesque-latin-ext-300-normal.woff
Normal file
BIN
src/fonts/og/bricolage-grotesque-latin-ext-300-normal.woff
Normal file
Binary file not shown.
BIN
src/fonts/og/bricolage-grotesque-latin-ext-600-normal.woff
Normal file
BIN
src/fonts/og/bricolage-grotesque-latin-ext-600-normal.woff
Normal file
Binary file not shown.
BIN
src/fonts/og/bricolage-grotesque-latin-ext-800-normal.woff
Normal file
BIN
src/fonts/og/bricolage-grotesque-latin-ext-800-normal.woff
Normal file
Binary file not shown.
BIN
src/fonts/og/cal-sans-latin-400-normal.woff
Normal file
BIN
src/fonts/og/cal-sans-latin-400-normal.woff
Normal file
Binary file not shown.
BIN
src/fonts/og/cal-sans-latin-ext-400-normal.woff
Normal file
BIN
src/fonts/og/cal-sans-latin-ext-400-normal.woff
Normal file
Binary file not shown.
129
src/lib/og-fonts.ts
Normal file
129
src/lib/og-fonts.ts
Normal file
@@ -0,0 +1,129 @@
|
||||
import { readFile } from "node:fs/promises";
|
||||
import { join } from "node:path";
|
||||
|
||||
const OG_FONT_DIR = join(process.cwd(), "src/fonts/og");
|
||||
|
||||
function toArrayBuffer(buf: Buffer): ArrayBuffer {
|
||||
return buf.buffer.slice(
|
||||
buf.byteOffset,
|
||||
buf.byteOffset + buf.byteLength,
|
||||
) as ArrayBuffer;
|
||||
}
|
||||
|
||||
async function loadFont(fileName: string): Promise<ArrayBuffer> {
|
||||
return toArrayBuffer(await readFile(join(OG_FONT_DIR, fileName)));
|
||||
}
|
||||
|
||||
type OgFont = {
|
||||
name: string;
|
||||
data: ArrayBuffer;
|
||||
weight: 300 | 400 | 600 | 700 | 800;
|
||||
style: "normal" | "italic";
|
||||
};
|
||||
|
||||
/** latin + latin-ext çiftini aynı aile/ağırlıkta kaydeder (Türkçe glifler için). */
|
||||
async function latinPair(
|
||||
name: string,
|
||||
weight: OgFont["weight"],
|
||||
latinFile: string,
|
||||
latinExtFile: string,
|
||||
style: OgFont["style"] = "normal",
|
||||
): Promise<OgFont[]> {
|
||||
const [latin, latinExt] = await Promise.all([
|
||||
loadFont(latinFile),
|
||||
loadFont(latinExtFile),
|
||||
]);
|
||||
return [
|
||||
{ name, data: latin, weight, style },
|
||||
{ name, data: latinExt, weight, style },
|
||||
];
|
||||
}
|
||||
|
||||
/** Ana sayfa OG: Bricolage (marka) + ClarityCity (gövde). */
|
||||
export async function loadSiteOgFonts(): Promise<OgFont[]> {
|
||||
const [bricolage, clarityLight, claritySemiBold] = await Promise.all([
|
||||
Promise.all([
|
||||
latinPair(
|
||||
"Bricolage Grotesque",
|
||||
300,
|
||||
"bricolage-grotesque-latin-300-normal.woff",
|
||||
"bricolage-grotesque-latin-ext-300-normal.woff",
|
||||
),
|
||||
latinPair(
|
||||
"Bricolage Grotesque",
|
||||
600,
|
||||
"bricolage-grotesque-latin-600-normal.woff",
|
||||
"bricolage-grotesque-latin-ext-600-normal.woff",
|
||||
),
|
||||
]).then((pairs) => pairs.flat()),
|
||||
loadFont("ClarityCity-Light.ttf"),
|
||||
loadFont("ClarityCity-SemiBold.ttf"),
|
||||
]);
|
||||
|
||||
return [
|
||||
...bricolage,
|
||||
{
|
||||
name: "Clarity City",
|
||||
data: clarityLight,
|
||||
weight: 300,
|
||||
style: "normal",
|
||||
},
|
||||
{
|
||||
name: "Clarity City",
|
||||
data: claritySemiBold,
|
||||
weight: 600,
|
||||
style: "normal",
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
/** Rehber kapak OG: ClarityCity + Cal Sans + Bricolage. */
|
||||
export async function loadRehberOgFonts(): Promise<OgFont[]> {
|
||||
const [clarityBold, calSans, light, semiBold, extraBold] = await Promise.all([
|
||||
loadFont("ClarityCity-Bold.ttf"),
|
||||
latinPair(
|
||||
"Cal Sans",
|
||||
400,
|
||||
"cal-sans-latin-400-normal.woff",
|
||||
"cal-sans-latin-ext-400-normal.woff",
|
||||
),
|
||||
latinPair(
|
||||
"Bricolage Grotesque",
|
||||
300,
|
||||
"bricolage-grotesque-latin-300-normal.woff",
|
||||
"bricolage-grotesque-latin-ext-300-normal.woff",
|
||||
),
|
||||
latinPair(
|
||||
"Bricolage Grotesque",
|
||||
600,
|
||||
"bricolage-grotesque-latin-600-normal.woff",
|
||||
"bricolage-grotesque-latin-ext-600-normal.woff",
|
||||
),
|
||||
latinPair(
|
||||
"Bricolage Grotesque",
|
||||
800,
|
||||
"bricolage-grotesque-latin-800-normal.woff",
|
||||
"bricolage-grotesque-latin-ext-800-normal.woff",
|
||||
),
|
||||
]);
|
||||
|
||||
// Sitede italic kullanılıyor; ayrı italic dosya yok — aynı kesimi italic olarak kaydet.
|
||||
const extraBoldItalic = extraBold.map((font) => ({
|
||||
...font,
|
||||
style: "italic" as const,
|
||||
}));
|
||||
|
||||
return [
|
||||
{
|
||||
name: "Clarity City",
|
||||
data: clarityBold,
|
||||
weight: 700,
|
||||
style: "normal",
|
||||
},
|
||||
...calSans,
|
||||
...light,
|
||||
...semiBold,
|
||||
...extraBold,
|
||||
...extraBoldItalic,
|
||||
];
|
||||
}
|
||||
Reference in New Issue
Block a user