feat(ux): anlamsal yapı ve metin — içeriğe geç linki, sıralama yok sayfası

- Site geneli "İçeriğe geç" linki (klavyede ilk durak, WCAG 2.4.1)
- Sıralama yok sayfası: "Geçerli bir sıralama gerekli" yerine "Önce
  sıralamanı gir" ve ne işe yaradığı; CTA ok sonda, 48 px
- Rapor satırı aç/kapa düğmesi açtığı bölgeye bağlandı (aria-controls)
- Liste hazırlanırken "sayfayı kapatma" uyarısı 12 px griden okunur
  boya; bekleme metinleri "…" ile; başlık iri
- /sonuc başlığında dengeli satır kırılımı (text-balance)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
bilalgursen
2026-09-24 01:31:20 +03:00
parent aef4adc90b
commit ad086c3eca
5 changed files with 39 additions and 18 deletions

View File

@@ -82,6 +82,14 @@ export default function RootLayout({
className={`${calSans.variable} ${clarityCity.variable} ${geistMono.variable} ${bricolage.variable} antialiased`}
>
<body className="min-h-dvh flex flex-col bg-slate-50">
{/* Klavyeyle gelen için ilk durak: üst bandı ve menüyü atla
(WCAG 2.4.1). Odaklanınca görünür, sitenin hap ölçüsünde. */}
<a
href="#icerik"
className="sr-only focus:not-sr-only focus:fixed focus:top-3 focus:left-3 focus:z-[60] focus:inline-flex focus:h-11 focus:items-center focus:rounded-full focus:border focus:border-slate-200 focus:bg-white focus:px-4 focus:text-sm focus:font-semibold focus:text-slate-900 focus:shadow-lg focus:outline-none focus-visible:ring-3 focus-visible:ring-ring/50"
>
İçeriğe geç
</a>
<HeaderGate>
{/* Site geneli progressive blur — üst ve alt. Stil globals.css'te
(.kt-sayfa-blur): iOS/iPadOS'ta fixed + backdrop-filter katmanı
@@ -92,7 +100,11 @@ export default function RootLayout({
<SiteTopBanner />
<SiteHeader />
</HeaderGate>
<div className="flex min-h-0 flex-1 flex-col pb-28 print:pb-0">
<div
id="icerik"
tabIndex={-1}
className="flex min-h-0 flex-1 flex-col pb-28 outline-none print:pb-0"
>
{children}
</div>
{/* Manuel 24'lük liste çekmecesi + "+" uçuş katmanı (navbar'dan açılır) */}

View File

@@ -47,7 +47,7 @@ export function SonucBasligi({
];
return (
<header className="text-center lg:text-left">
<h1 className="font-heading text-3xl font-bold leading-tight text-slate-900 sm:text-5xl">
<h1 className="font-heading text-3xl font-bold leading-tight text-balance text-slate-900 sm:text-5xl">
Sıralamanla açılan programlar
</h1>
<p className="mx-auto mt-4 max-w-2xl text-base leading-relaxed text-slate-600 sm:text-lg lg:mx-0">

View File

@@ -304,8 +304,8 @@ export function ListeUretici({
onClick={() => profil && void uret(profil)}
className="mt-6 cursor-pointer bg-orange-500 text-white transition-colors duration-200 hover:bg-orange-600"
>
<RefreshCcw className="size-4" aria-hidden />
Tekrar dene
<RefreshCcw className="size-4" aria-hidden />
</Button>
{profil ? (
<p className="mt-4 text-xs text-slate-500">
@@ -358,7 +358,7 @@ function SunucuYokEkrani() {
disabled={deniyor}
className="mt-6 cursor-pointer bg-orange-500 text-white transition-colors duration-200 hover:bg-orange-600"
>
{deniyor ? "Kontrol ediliyor" : "Listemi aç"}
{deniyor ? "Kontrol ediliyor…" : "Listemi aç"}
<ArrowRight className="size-4" aria-hidden />
</Button>
<p aria-live="polite" className="mt-4 text-xs text-slate-500">
@@ -401,7 +401,7 @@ function UretimGovdesi({ uzunSurdu }: { uzunSurdu: boolean }) {
return (
<section aria-live="polite">
<header className="flex flex-col items-center gap-1.5 text-center">
<h1 className="font-heading text-xl font-bold sm:text-2xl">
<h1 className="font-heading text-2xl font-bold text-slate-900 sm:text-3xl">
Listen hazırlanıyor
</h1>
{uzunSurdu ? (
@@ -426,8 +426,8 @@ function UretimGovdesi({ uzunSurdu }: { uzunSurdu: boolean }) {
</Button>
</>
) : (
<p className="text-xs text-slate-400">
Bu işlem yarım dakika kadar sürebilir, sayfayı kapatma.
<p className="text-sm font-medium text-slate-600">
Yarım dakika kadar sürebilir; bu sayfayı kapatma.
</p>
)}
</header>

View File

@@ -293,6 +293,7 @@ export function RaporListesi({
<button
type="button"
aria-expanded={acikMi}
aria-controls={`rapor-satir-${t.sira}`}
onClick={(e) => {
e.stopPropagation();
tiklandi(t.sira);
@@ -311,7 +312,7 @@ export function RaporListesi({
</TableRow>
{acikMi ? (
<TableRow className="hover:bg-transparent">
<TableRow id={`rapor-satir-${t.sira}`} className="hover:bg-transparent">
<TableCell
colSpan={SUTUN_SAYISI}
className="whitespace-normal bg-slate-50 px-4 py-5 sm:px-5"

View File

@@ -7,7 +7,7 @@
import { useEffect } from "react";
import { useRouter } from "next/navigation";
import Link from "next/link";
import { ArrowLeft, Trophy } from "lucide-react";
import { ArrowLeft, ArrowRight } from "lucide-react";
import { Button } from "@/components/ui/button";
import { PagePixelDivider } from "@/components/pixel-decor";
import { profilCerezineYaz } from "@/features/sihirbaz/sihirbaz-profil";
@@ -34,19 +34,21 @@ export function SiraGerekli() {
if (!profilYuklendi || profil) {
return (
<main className="mx-auto flex max-w-2xl flex-col items-center px-4 py-24 text-center">
<p className="text-sm text-slate-500">Sıralaman kontrol ediliyor…</p>
<p role="status" className="text-base text-slate-500">
Sıralaman kontrol ediliyor…
</p>
</main>
);
}
return (
<main className="mx-auto flex max-w-2xl flex-col items-center px-4 py-24 text-center">
<h1 className="font-heading text-2xl font-bold">
Geçerli bir sıralama gerekli
<h1 className="font-heading text-3xl font-bold text-balance text-slate-900 sm:text-4xl">
Önce sıralamanı gir
</h1>
<p className="mt-3 text-slate-600">
Listeni kurabilmek için YKS başarı sıralamanı gir. Kaydettiğin sıra tüm
uygulamada kullanılır.
<p className="mt-4 max-w-md text-base leading-relaxed text-slate-600 sm:text-lg">
YKS başarı sıralamanı girince hangi programların sana açık olduğunu
hemen görürsün. Bir kez girmen yeter; her sayfada kullanılır.
</p>
<PagePixelDivider seed={59} className="mx-auto mt-6" />
<div className="mt-6 flex flex-wrap items-center justify-center gap-3">
@@ -56,12 +58,18 @@ export function SiraGerekli() {
const { href } = sonucaGitIste();
if (href) router.push(href);
}}
className="cursor-pointer bg-orange-500 text-white hover:bg-orange-600"
size="lg"
className="cursor-pointer bg-orange-500 text-white transition-[background-color,transform] duration-200 hover:bg-orange-600 active:scale-[0.97]"
>
<Trophy className="size-4" aria-hidden />
Sıralamamı gir
<ArrowRight className="size-4" aria-hidden />
</Button>
<Button asChild variant="outline" className="cursor-pointer">
<Button
asChild
size="lg"
variant="outline"
className="cursor-pointer px-6 transition-[background-color,border-color,color,transform] duration-150 hover:border-orange-500 hover:bg-orange-50/60 hover:text-orange-500 active:scale-[0.97]"
>
<Link href="/">
<ArrowLeft className="size-4" aria-hidden />
Ana sayfaya dön