Fix list and header overflow on mobile and tablet widths

This commit is contained in:
2026-09-06 09:54:48 +03:00
parent af250c0980
commit 3550f1a9bc
6 changed files with 62 additions and 12 deletions
@@ -0,0 +1,40 @@
{
"mobile": {
"content": 384,
"viewport": 384
},
"tablet": {
"content": 762,
"viewport": 762
},
"desktop": {
"content": 1434,
"viewport": 1434
},
"review": {
"content": 244,
"fields": [
{
"right": 311,
"tag": "TEXTAREA",
"width": 244
},
{
"right": 311,
"tag": "TEXTAREA",
"width": 244
},
{
"right": 193.296875,
"tag": "BUTTON",
"width": 126.296875
},
{
"right": 282.1171875,
"tag": "BUTTON",
"width": 207.1171875
}
],
"width": 244
}
}
+8
View File
@@ -387,3 +387,11 @@ Güncel backend ile localhost:5175 üzerinde izole test açıldı. Tek sayfalık
İki ayrı tarayıcı sekmesi aynı sürüm 1'i açtı. İlk sekmede not güncellenip sürüm 2 kaydedildi. İkinci sekmede eski sürümle kayıt girişimi reddedildi, kullanıcı notu formda korundu ve açık sürüm hatası gösterildi. Güncel kaydı yükleme sonrasında sürüm 2 ve ilk sekmenin notu geri geldi; eski sekme kaydı ezmedi. İki ayrı tarayıcı sekmesi aynı sürüm 1'i açtı. İlk sekmede not güncellenip sürüm 2 kaydedildi. İkinci sekmede eski sürümle kayıt girişimi reddedildi, kullanıcı notu formda korundu ve açık sürüm hatası gösterildi. Güncel kaydı yükleme sonrasında sürüm 2 ve ilk sekmenin notu geri geldi; eski sekme kaydı ezmedi.
Kanıt: evidence/qa-review-conflict.txt ve evidence/qa-review-reload.txt. Bu tur uygulama kodu değişmedi; daha önceki otomatik testlere ek gerçek UI kanıtı toplandı. Gerçek AI sağlayıcısı ile analiz sonucu ve çıktı sırasında inceleme değiştirme kabulü hâlâ açık. Sentetik tek sayfa karşılaştırması resmi ihale incelemesi değildir. Kanıt: evidence/qa-review-conflict.txt ve evidence/qa-review-reload.txt. Bu tur uygulama kodu değişmedi; daha önceki otomatik testlere ek gerçek UI kanıtı toplandı. Gerçek AI sağlayıcısı ile analiz sonucu ve çıktı sırasında inceleme değiştirme kabulü hâlâ açık. Sentetik tek sayfa karşılaştırması resmi ihale incelemesi değildir.
### Gerçek mobil/tablet genişlik kontrolü
In-app tarayıcı viewport özelliğiyle 390×844, 768×1024 ve 1440×1000 denendi. İlk mobil görünümde 384 px kullanılabilir genişliğe karşı 513 px belge genişliği vardı; hesap düğmesi ve liste araçları kesiliyordu. Ana içerik ve listeye min-width:0/w-full, araçlara satır kaydırma, üst aramaya mobil/tablette ayrı satır eklendi. Özet kartları dar alanda sarılıyor. Hesap ve bildirim ikonlarına erişilebilir ad eklendi.
Son ölçüm: mobil 384/384, tablet 762/762, masaüstü 1434/1434 (içerik/kullanılabilir genişlik; scrollbar 6 px). Mobil belge inceleme bölgesi 244/244, iki metin alanı ve kaydet/analiz düğmeleri viewport içinde. Normal viewport geri yüklendi. Kanıt: evidence/qa-responsive-widths.json.
80 test ve üretim derlemesi geçti. Bu test ana liste, üst çubuk ve belge inceleme formundaki taşmayı kapsar; tüm modüller, gerçek dokunmatik cihaz, ekran okuyucu ve bütün klavye akışları kabul edilmiş sayılmaz.
+1 -1
View File
@@ -42,7 +42,7 @@ const MainContent = () => {
const { activeTab, isAdmin, saveError, savingCount } = useApp(); const { activeTab, isAdmin, saveError, savingCount } = useApp();
return ( return (
<main className="max-w-[1600px] mx-auto px-4 pb-12"> <main className="w-full min-w-0 max-w-[1600px] mx-auto px-4 pb-12">
{/* 3-Column Main View */} {/* 3-Column Main View */}
<KotaUyarisi /> <KotaUyarisi />
{savingCount > 0 && <p role="status" className="p-3 bg-blue-50 text-blue-900">Kaydediliyor…</p>} {savingCount > 0 && <p role="status" className="p-3 bg-blue-50 text-blue-900">Kaydediliyor…</p>}
+10 -8
View File
@@ -36,26 +36,26 @@ export const Header = () => {
return ( return (
<header className="bg-[#1f2937] text-white border-b border-slate-700 sticky top-0 z-40 shadow-sm"> <header className="bg-[#1f2937] text-white border-b border-slate-700 sticky top-0 z-40 shadow-sm">
<div className="max-w-[1600px] mx-auto px-4 h-16 flex items-center justify-between gap-4"> <div className="max-w-[1600px] mx-auto px-3 sm:px-4 py-2 xl:py-0 xl:h-16 flex flex-wrap xl:flex-nowrap items-center justify-between gap-2 sm:gap-4">
{/* Logo */} {/* Logo */}
<div <div
onClick={() => { setActiveTab('list'); clearAllFilters(); }} onClick={() => { setActiveTab('list'); clearAllFilters(); }}
className="flex items-center gap-2.5 cursor-pointer select-none group" className="flex shrink-0 items-center gap-1.5 sm:gap-2.5 cursor-pointer select-none group"
> >
<div className="w-10 h-10 rounded-xl bg-blue-600 flex items-center justify-center shadow-md group-hover:bg-blue-500 transition-colors"> <div className="w-8 h-8 sm:w-10 sm:h-10 rounded-xl bg-blue-600 flex items-center justify-center shadow-md group-hover:bg-blue-500 transition-colors">
<Bot className="w-6 h-6 text-white" /> <Bot className="w-6 h-6 text-white" />
</div> </div>
<div className="flex flex-col"> <div className="flex flex-col">
<span className="font-black text-2xl tracking-tight text-white flex items-center gap-1"> <span className="font-black text-xl sm:text-2xl tracking-tight text-white flex items-center gap-1">
İhale<span className="text-blue-400 font-extrabold">ist</span> İhale<span className="text-blue-400 font-extrabold">ist</span>
</span> </span>
</div> </div>
</div> </div>
{/* Search Bar */} {/* Search Bar */}
<form onSubmit={handleSearchSubmit} className="flex-1 min-w-0 max-w-2xl flex items-center gap-2"> <form onSubmit={handleSearchSubmit} className="order-3 xl:order-none w-full xl:w-auto xl:flex-1 min-w-0 xl:max-w-2xl flex items-center gap-2">
<div className="relative flex-1"> <div className="relative flex-1 min-w-0">
<input <input
type="text" type="text"
value={searchQuery} value={searchQuery}
@@ -100,7 +100,7 @@ export const Header = () => {
</form> </form>
{/* Right Action Icons */} {/* Right Action Icons */}
<div className="flex items-center gap-2 sm:gap-3 shrink-0"> <div className="ml-auto flex items-center gap-1 sm:gap-3 shrink-0">
{/* Real Live EKAP Mode Badge */} {/* Real Live EKAP Mode Badge */}
<button <button
@@ -142,6 +142,7 @@ export const Header = () => {
{/* Notifications Dropdown */} {/* Notifications Dropdown */}
<div className="relative"> <div className="relative">
<button <button
aria-label="Bildirimler"
onClick={() => setShowNotifications(!showNotifications)} onClick={() => setShowNotifications(!showNotifications)}
className="relative p-2 text-slate-300 hover:text-white hover:bg-slate-700 rounded-lg transition-colors" className="relative p-2 text-slate-300 hover:text-white hover:bg-slate-700 rounded-lg transition-colors"
> >
@@ -175,6 +176,7 @@ export const Header = () => {
{/* User Profile */} {/* User Profile */}
<div className="relative"> <div className="relative">
<button <button
aria-label="Hesap menüsü"
onClick={() => setShowUserMenu(!showUserMenu)} onClick={() => setShowUserMenu(!showUserMenu)}
className="bg-slate-700 hover:bg-slate-600 text-white px-3 py-1.5 rounded-lg text-xs font-semibold flex items-center gap-2 transition-colors border border-slate-600" className="bg-slate-700 hover:bg-slate-600 text-white px-3 py-1.5 rounded-lg text-xs font-semibold flex items-center gap-2 transition-colors border border-slate-600"
> >
@@ -185,7 +187,7 @@ export const Header = () => {
{(authUser?.name || userProfile.username).charAt(0).toUpperCase()} {(authUser?.name || userProfile.username).charAt(0).toUpperCase()}
</div> </div>
)} )}
<span>{(authUser?.name || userProfile.username).split(' ')[0]}</span> <span className="hidden sm:inline">{(authUser?.name || userProfile.username).split(' ')[0]}</span>
<ChevronDown className="w-3.5 h-3.5 text-slate-400" /> <ChevronDown className="w-3.5 h-3.5 text-slate-400" />
</button> </button>
+1 -1
View File
@@ -77,7 +77,7 @@ export const SummaryCards = () => {
setQuickFilter(card.id); setQuickFilter(card.id);
setActiveTab('list'); setActiveTab('list');
}} }}
className={`bg-white rounded-xl p-4 border transition-all cursor-pointer select-none shadow-xs flex items-center justify-between group hover:shadow-md ${ className={`bg-white rounded-xl p-4 border transition-all cursor-pointer select-none shadow-xs flex flex-wrap gap-2 items-center justify-between group hover:shadow-md ${
isSelected isSelected
? 'border-blue-600 ring-2 ring-blue-500/20 bg-blue-50/20' ? 'border-blue-600 ring-2 ring-blue-500/20 bg-blue-50/20'
: 'border-slate-200 hover:border-slate-300' : 'border-slate-200 hover:border-slate-300'
+2 -2
View File
@@ -126,7 +126,7 @@ export const TenderList = () => {
}; };
return ( return (
<div className="flex-1 space-y-4"> <div className="w-full min-w-0 flex-1 space-y-4">
{/* Header bar above list */} {/* Header bar above list */}
<div className="bg-white rounded-xl border border-slate-200 p-4 shadow-xs flex flex-col sm:flex-row items-center justify-between gap-3"> <div className="bg-white rounded-xl border border-slate-200 p-4 shadow-xs flex flex-col sm:flex-row items-center justify-between gap-3">
@@ -137,7 +137,7 @@ export const TenderList = () => {
</h2> </h2>
</div> </div>
<div className="flex items-center gap-3 w-full sm:w-auto"> <div className="flex flex-wrap items-center gap-3 w-full sm:w-auto">
{/* Varsayılan: yalnızca ihale tarihi geçmemiş ilanlar */} {/* Varsayılan: yalnızca ihale tarihi geçmemiş ilanlar */}
<label <label
className="flex items-center gap-1.5 text-xs font-semibold text-slate-700 cursor-pointer select-none whitespace-nowrap" className="flex items-center gap-1.5 text-xs font-semibold text-slate-700 cursor-pointer select-none whitespace-nowrap"