fix(web): kategori ağacını eski yapısına döndür + toggle tree ikonunu anında tepki verir yap
- category-tree: kılavuz çizgileri + grid-rows aç/kapa animasyonu geri alındı, orijinal smooth yapı (paddingLeft girinti) restore edildi - TreeViewIcon: 80ms gecikmeli/2px küçük hareket yerine gövdeden gecikmesiz scaleX büyüme (tree-grow keyframe, origin-left); grid/list ile aynı anında tepki Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -40,6 +40,7 @@ export function CategoryTree({
|
|||||||
key={cat.id}
|
key={cat.id}
|
||||||
category={cat}
|
category={cat}
|
||||||
vehicleId={vehicleId}
|
vehicleId={vehicleId}
|
||||||
|
level={0}
|
||||||
parentPrefetching={false}
|
parentPrefetching={false}
|
||||||
catalogMode={catalogMode}
|
catalogMode={catalogMode}
|
||||||
brandName={brandName}
|
brandName={brandName}
|
||||||
@@ -53,6 +54,7 @@ export function CategoryTree({
|
|||||||
function CategoryNode({
|
function CategoryNode({
|
||||||
category,
|
category,
|
||||||
vehicleId,
|
vehicleId,
|
||||||
|
level,
|
||||||
parentPrefetching,
|
parentPrefetching,
|
||||||
catalogMode,
|
catalogMode,
|
||||||
brandName,
|
brandName,
|
||||||
@@ -60,6 +62,7 @@ function CategoryNode({
|
|||||||
}: {
|
}: {
|
||||||
category: Category;
|
category: Category;
|
||||||
vehicleId: string;
|
vehicleId: string;
|
||||||
|
level: number;
|
||||||
parentPrefetching: boolean;
|
parentPrefetching: boolean;
|
||||||
catalogMode?: boolean;
|
catalogMode?: boolean;
|
||||||
brandName?: string;
|
brandName?: string;
|
||||||
@@ -164,6 +167,8 @@ function CategoryNode({
|
|||||||
category.unavailable && "pointer-events-none opacity-40",
|
category.unavailable && "pointer-events-none opacity-40",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const indentStyle = { paddingLeft: `${level * 16 + 12}px` };
|
||||||
|
|
||||||
const rowInner = (
|
const rowInner = (
|
||||||
<>
|
<>
|
||||||
<span aria-hidden className="flex h-5 w-5 shrink-0 items-center justify-center">
|
<span aria-hidden className="flex h-5 w-5 shrink-0 items-center justify-center">
|
||||||
@@ -184,7 +189,7 @@ function CategoryNode({
|
|||||||
name={category.name}
|
name={category.name}
|
||||||
shimmer={isShimmering}
|
shimmer={isShimmering}
|
||||||
/>
|
/>
|
||||||
<span className="min-w-0 flex-1 break-words leading-snug">{category.name}</span>
|
<span className="min-w-0 flex-1 truncate">{category.name}</span>
|
||||||
{category.partCount != null && category.partCount > 0 && (
|
{category.partCount != null && category.partCount > 0 && (
|
||||||
<span className="shrink-0 tabular-nums text-xs text-muted-foreground">
|
<span className="shrink-0 tabular-nums text-xs text-muted-foreground">
|
||||||
{category.partCount}
|
{category.partCount}
|
||||||
@@ -209,38 +214,35 @@ function CategoryNode({
|
|||||||
}
|
}
|
||||||
search={catalogMode && variantSearch ? variantSearch : undefined}
|
search={catalogMode && variantSearch ? variantSearch : undefined}
|
||||||
className={cn(rowClass, "no-underline")}
|
className={cn(rowClass, "no-underline")}
|
||||||
|
style={indentStyle}
|
||||||
>
|
>
|
||||||
{rowInner}
|
{rowInner}
|
||||||
</Link>
|
</Link>
|
||||||
) : (
|
) : (
|
||||||
<button type="button" onClick={handleExpand} aria-expanded={expanded} className={rowClass}>
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={handleExpand}
|
||||||
|
aria-expanded={expanded}
|
||||||
|
className={rowClass}
|
||||||
|
style={indentStyle}
|
||||||
|
>
|
||||||
{rowInner}
|
{rowInner}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
{hasChildren && (
|
{hasChildren && expanded && (
|
||||||
// Yumuşak aç/kapa: grid-rows 0fr↔1fr (içerik yüksekliği bilmeye gerek yok, JS animasyon yok)
|
<div>
|
||||||
<div
|
{children.map((child) => (
|
||||||
className={cn(
|
<CategoryNode
|
||||||
"grid transition-[grid-template-rows] duration-200 ease-out motion-reduce:transition-none",
|
key={child.id}
|
||||||
expanded ? "grid-rows-[1fr]" : "grid-rows-[0fr]",
|
category={child}
|
||||||
)}
|
vehicleId={vehicleId}
|
||||||
>
|
level={level + 1}
|
||||||
<div className="overflow-hidden">
|
parentPrefetching={prefetching}
|
||||||
{/* Girinti + kılavuz çizgisi: çizgi parent satırın chevron merkezine (≈22px) hizalanır */}
|
catalogMode={catalogMode}
|
||||||
<div className="ml-[22px] border-l border-border">
|
brandName={brandName}
|
||||||
{children.map((child) => (
|
variantSearch={variantSearch}
|
||||||
<CategoryNode
|
/>
|
||||||
key={child.id}
|
))}
|
||||||
category={child}
|
|
||||||
vehicleId={vehicleId}
|
|
||||||
parentPrefetching={prefetching}
|
|
||||||
catalogMode={catalogMode}
|
|
||||||
brandName={brandName}
|
|
||||||
variantSearch={variantSearch}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -75,8 +75,8 @@ export function ListViewIcon({ isActive, className }: ViewIconProps) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Tree → kök + iki dal; aktifken dallar gövdeden dışarı kayar ──
|
// ── Tree → kök + iki dal; aktifte dallar gövdeden anında "büyüyerek" çıkar ──
|
||||||
// Diğer ikonlar gibi transition tabanlı (anında tepki); dallar her zaman görünür.
|
// Gecikme yok, dallar her zaman görünür: tıklama anında belirgin tepki verir.
|
||||||
export function TreeViewIcon({ isActive, className }: ViewIconProps) {
|
export function TreeViewIcon({ isActive, className }: ViewIconProps) {
|
||||||
return (
|
return (
|
||||||
<span className={cn("relative inline-block h-4 w-4", className)} aria-hidden="true">
|
<span className={cn("relative inline-block h-4 w-4", className)} aria-hidden="true">
|
||||||
@@ -90,17 +90,15 @@ export function TreeViewIcon({ isActive, className }: ViewIconProps) {
|
|||||||
className="absolute rounded bg-current/50"
|
className="absolute rounded bg-current/50"
|
||||||
style={{ left: 3, top: 5, width: 1.5, height: 7.5 }}
|
style={{ left: 3, top: 5, width: 1.5, height: 7.5 }}
|
||||||
/>
|
/>
|
||||||
{/* iki çocuk dal: dirsek + düğüm */}
|
{/* iki çocuk dal: dirsek + düğüm — origin-left ile gövdeden büyür */}
|
||||||
{[0, 1].map((i) => (
|
{[0, 1].map((i) => (
|
||||||
<span
|
<span
|
||||||
key={i}
|
key={i}
|
||||||
className="absolute inline-flex items-center transition-transform duration-[340ms] ease-out motion-reduce:transition-none"
|
className={cn(
|
||||||
style={{
|
"absolute inline-flex origin-left items-center",
|
||||||
left: 3,
|
isActive && "animate-tree-grow",
|
||||||
top: i === 0 ? 6.25 : 10.25,
|
)}
|
||||||
transform: isActive ? "translateX(0)" : "translateX(-2px)",
|
style={{ left: 3, top: i === 0 ? 6.25 : 10.25 }}
|
||||||
transitionDelay: `${i * 80}ms`,
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<span className="rounded bg-current/50" style={{ width: 3.5, height: 1.5 }} />
|
<span className="rounded bg-current/50" style={{ width: 3.5, height: 1.5 }} />
|
||||||
<span
|
<span
|
||||||
|
|||||||
@@ -168,6 +168,18 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@keyframes tree-grow {
|
||||||
|
0% {
|
||||||
|
transform: scaleX(0.35);
|
||||||
|
}
|
||||||
|
70% {
|
||||||
|
transform: scaleX(1.05);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: scaleX(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@keyframes icon-pop {
|
@keyframes icon-pop {
|
||||||
0% {
|
0% {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
@@ -221,6 +233,10 @@
|
|||||||
.animate-icon-pop {
|
.animate-icon-pop {
|
||||||
animation: icon-pop 0.32s cubic-bezier(0.16, 1, 0.3, 1);
|
animation: icon-pop 0.32s cubic-bezier(0.16, 1, 0.3, 1);
|
||||||
}
|
}
|
||||||
|
.animate-tree-grow {
|
||||||
|
animation: tree-grow 0.24s cubic-bezier(0.16, 1, 0.3, 1);
|
||||||
|
transform-origin: left center;
|
||||||
|
}
|
||||||
.carousel-track:hover .animate-scroll-left {
|
.carousel-track:hover .animate-scroll-left {
|
||||||
animation-play-state: paused;
|
animation-play-state: paused;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user