[CLAUDE] FE-User FE-Admin: Plan AA wrap fix - sidebar label dài wrap về đầu hàng + text smaller
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m25s
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m25s
UAT feedback 2026-05-15 sau Run #213 deploy: bro screenshot sidebar label custom Mig 27 dài "1. Duyệt Nhà Cung Cấp - Thầu phụ (NCC -TP)" wrap 2 dòng, dòng 2 "(NCC -TP)" indent SAU icon thay vì về đầu hàng. Root cause: flex container [items-center, gap-2] + inner span chứa Icon + label text → text wraps within INNER span (đã indent past icon area). Pattern phù hợp cho 1-dòng label, KHÔNG phù hợp khi multi-line. Fix pattern (3 sites fe-user + 2 sites fe-admin mirror rule §3.9): - MenuGroup button: flex → relative block + inline-block icon + inline text + absolute ChevronDown right. Text wrap về left edge button (under icon). - MenuLeaf NavLink: flex → block + inline-block icon + inline text. - StaticLeaf NavLink (fe-user only): mirror MenuLeaf pattern. Smaller text: - text-[13px] → text-[12px] (medium label group + leaf) - text-sm (14px) → text-[12px] (MenuLeaf top level) - text-[12px] → text-[11px] (MenuLeaf deep level) - leading-snug (1.375) compact 2-line height Icon adjust: -mt-0.5 align with inline text baseline. Button px-3 pr-7: pad right 28px reserve cho absolute ChevronDown (KHÔNG bị đẩy xuống khi label wrap). Verify: - npm run build fe-user PASS clean 432ms - npm run build fe-admin PASS clean 494ms Em main solo CSS polish < 30 min (criteria #6 REFUSE Implementer). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@ -135,21 +135,21 @@ function MenuGroup({ node, depth }: { node: MenuNode; depth: number }) {
|
||||
<button
|
||||
onClick={() => setOpen(o => !o)}
|
||||
className={cn(
|
||||
'flex w-full items-center justify-between rounded-md transition',
|
||||
'relative block w-full rounded-md text-left transition',
|
||||
isTopLevel
|
||||
? 'px-3 py-2 text-[11px] font-semibold uppercase tracking-wide text-slate-500 hover:bg-slate-100 whitespace-nowrap'
|
||||
: 'px-3 py-1.5 text-[13px] font-medium text-slate-600 hover:bg-slate-100 hover:text-slate-900',
|
||||
? 'px-3 py-2 pr-7 text-[11px] font-semibold uppercase tracking-wide text-slate-500 hover:bg-slate-100 whitespace-nowrap'
|
||||
: 'px-3 py-1.5 pr-7 text-[12px] font-medium leading-snug text-slate-600 hover:bg-slate-100 hover:text-slate-900',
|
||||
)}
|
||||
>
|
||||
{/* [Plan AA S24 t1] Revert truncate Plan U S23 t11 — mirror fe-user
|
||||
rule §3.9. Admin sidebar không có label custom Mig 27 (luôn Label
|
||||
gốc) nên label rarely overflow, nhưng pattern uniform với fe-user.
|
||||
min-w-0 flex-1 + shrink-0 giữ responsive smooth. */}
|
||||
<span className="flex min-w-0 flex-1 items-center gap-2">
|
||||
<Icon className="h-4 w-4 shrink-0" />
|
||||
<span title={node.label}>{node.label}</span>
|
||||
</span>
|
||||
<ChevronDown className={cn('h-3.5 w-3.5 shrink-0 text-slate-400 transition', !open && '-rotate-90')} />
|
||||
{/* [Plan AA S24 t2 wrap fix] inline-block icon + inline text — label
|
||||
dài wrap về đầu hàng (under icon, KHÔNG indent sau icon). Mirror
|
||||
fe-user rule §3.9. ChevronDown absolute right. */}
|
||||
<Icon className="mr-1.5 -mt-0.5 inline-block h-4 w-4 align-middle" />
|
||||
<span className="align-middle" title={node.label}>{node.label}</span>
|
||||
<ChevronDown className={cn(
|
||||
'absolute right-2 top-2 h-3.5 w-3.5 text-slate-400 transition',
|
||||
!open && '-rotate-90',
|
||||
)} />
|
||||
</button>
|
||||
{open && (
|
||||
<div className={cn(
|
||||
@ -199,16 +199,16 @@ function MenuLeaf({ node, depth }: { node: MenuNode; depth: number }) {
|
||||
to={path}
|
||||
title={node.label}
|
||||
className={cn(
|
||||
'flex min-w-0 items-center gap-2.5 rounded-md transition',
|
||||
isDeep ? 'px-3 py-1 text-[12px]' : 'px-3 py-2 text-sm font-medium',
|
||||
'block rounded-md leading-snug transition',
|
||||
isDeep ? 'px-3 py-1 text-[11px]' : 'px-3 py-2 text-[12px] font-medium',
|
||||
isActive
|
||||
? 'bg-brand-50 text-brand-700'
|
||||
: 'text-slate-600 hover:bg-slate-100 hover:text-slate-900',
|
||||
)}
|
||||
>
|
||||
<Icon className={cn('shrink-0', isDeep ? 'h-3.5 w-3.5' : 'h-4 w-4')} />
|
||||
{/* [Plan AA S24 t1] Revert truncate Plan U S23 t11 — mirror fe-user. */}
|
||||
<span>{node.label}</span>
|
||||
{/* [Plan AA S24 t2 wrap fix] inline-block icon + inline text → mirror fe-user. */}
|
||||
<Icon className={cn('mr-2 -mt-0.5 inline-block align-middle', isDeep ? 'h-3.5 w-3.5' : 'h-4 w-4')} />
|
||||
<span className="align-middle">{node.label}</span>
|
||||
</NavLink>
|
||||
)
|
||||
}
|
||||
|
||||
@ -176,24 +176,25 @@ function MenuGroup({ node, depth }: { node: MenuNode; depth: number }) {
|
||||
<button
|
||||
onClick={toggle}
|
||||
className={cn(
|
||||
'flex w-full items-center justify-between rounded-md transition',
|
||||
'relative block w-full rounded-md text-left transition',
|
||||
isTopLevel
|
||||
? 'px-3 py-2 text-[11px] font-semibold uppercase tracking-wide text-slate-500 hover:bg-slate-100 whitespace-nowrap'
|
||||
: 'px-3 py-1.5 text-[13px] font-medium text-slate-600 hover:bg-slate-100 hover:text-slate-900',
|
||||
? 'px-3 py-2 pr-7 text-[11px] font-semibold uppercase tracking-wide text-slate-500 hover:bg-slate-100 whitespace-nowrap'
|
||||
: 'px-3 py-1.5 pr-7 text-[12px] font-medium leading-snug text-slate-600 hover:bg-slate-100 hover:text-slate-900',
|
||||
// Highlight Ct_ group đang active (accordion open) bằng tinted background
|
||||
isAccordion && open && 'bg-slate-50 text-slate-900',
|
||||
)}
|
||||
>
|
||||
{/* [Plan AA S24 t1] Revert truncate Plan U S23 t11 — bro request hiển
|
||||
thị đầy đủ label custom. Sidebar widen w-72 xl:w-80 fit ~44 chars
|
||||
1 dòng. Label cực dài fallback wrap multi-line natural CSS.
|
||||
min-w-0 flex-1 + shrink-0 icon/chevron giữ responsive smooth. title
|
||||
tooltip giữ (no harm — accessibility bonus). */}
|
||||
<span className="flex min-w-0 flex-1 items-center gap-2">
|
||||
<Icon className="h-4 w-4 shrink-0" />
|
||||
<span title={effectiveLabel(node)}>{effectiveLabel(node)}</span>
|
||||
</span>
|
||||
<ChevronDown className={cn('h-3.5 w-3.5 shrink-0 text-slate-400 transition', !open && '-rotate-90')} />
|
||||
{/* [Plan AA S24 t2 wrap fix] Bro UAT request: label dài 2 dòng phải về
|
||||
đầu hàng (under icon, KHÔNG indent sau icon). Pattern: inline-block
|
||||
icon + inline text → text wrap natural về left edge button.
|
||||
ChevronDown absolute right để KHÔNG bị đẩy xuống khi text wrap.
|
||||
Smaller text-[12px] + leading-snug compact 2-line height. */}
|
||||
<Icon className="mr-1.5 -mt-0.5 inline-block h-4 w-4 align-middle" />
|
||||
<span className="align-middle" title={effectiveLabel(node)}>{effectiveLabel(node)}</span>
|
||||
<ChevronDown className={cn(
|
||||
'absolute right-2 top-2 h-3.5 w-3.5 text-slate-400 transition',
|
||||
!open && '-rotate-90',
|
||||
)} />
|
||||
</button>
|
||||
{open && (
|
||||
<div className={cn(
|
||||
@ -246,17 +247,17 @@ function MenuLeaf({ node, depth }: { node: MenuNode; depth: number }) {
|
||||
to={path}
|
||||
title={effectiveLabel(node)}
|
||||
className={cn(
|
||||
'flex min-w-0 items-center gap-2.5 rounded-md transition',
|
||||
isDeep ? 'px-3 py-1 text-[12px]' : 'px-3 py-2 text-sm font-medium',
|
||||
'block rounded-md leading-snug transition',
|
||||
isDeep ? 'px-3 py-1 text-[11px]' : 'px-3 py-2 text-[12px] font-medium',
|
||||
isActive
|
||||
? 'bg-brand-50 text-brand-700'
|
||||
: 'text-slate-600 hover:bg-slate-100 hover:text-slate-900',
|
||||
)}
|
||||
>
|
||||
<Icon className={cn('shrink-0', isDeep ? 'h-3.5 w-3.5' : 'h-4 w-4')} />
|
||||
{/* [Plan AA S24 t1] Revert truncate Plan U S23 t11 — fit full label hoặc
|
||||
wrap natural. NavLink `title` (line 241) giữ tooltip accessibility. */}
|
||||
<span>{effectiveLabel(node)}</span>
|
||||
{/* [Plan AA S24 t2 wrap fix] inline-block icon + inline text → label dài
|
||||
wrap về đầu hàng (under icon, KHÔNG indent sau icon). */}
|
||||
<Icon className={cn('mr-2 -mt-0.5 inline-block align-middle', isDeep ? 'h-3.5 w-3.5' : 'h-4 w-4')} />
|
||||
<span className="align-middle">{effectiveLabel(node)}</span>
|
||||
</NavLink>
|
||||
)
|
||||
}
|
||||
@ -283,16 +284,15 @@ function StaticLeaf({ node }: { node: MenuNode }) {
|
||||
title={effectiveLabel(node)}
|
||||
className={({ isActive }) =>
|
||||
cn(
|
||||
'flex min-w-0 items-center gap-2.5 rounded-md px-3 py-2 text-sm font-medium transition',
|
||||
'block rounded-md px-3 py-2 text-[12px] font-medium leading-snug transition',
|
||||
isActive ? 'bg-brand-50 text-brand-700' : 'text-slate-600 hover:bg-slate-100 hover:text-slate-900',
|
||||
)
|
||||
}
|
||||
>
|
||||
<Icon className="h-4 w-4 shrink-0" />
|
||||
{/* [Plan AA S24 t1] Revert truncate Plan U S23 t11 — StaticLeaf "Hộp thư"
|
||||
label ngắn (7 chars) không bao giờ overflow, drop truncate cho
|
||||
consistent với MenuLeaf + MenuGroup. */}
|
||||
<span>{effectiveLabel(node)}</span>
|
||||
{/* [Plan AA S24 t2 wrap fix] inline-block icon + inline text — consistent
|
||||
với MenuLeaf + MenuGroup. */}
|
||||
<Icon className="mr-2 -mt-0.5 inline-block h-4 w-4 align-middle" />
|
||||
<span className="align-middle">{effectiveLabel(node)}</span>
|
||||
</NavLink>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user