init
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
'use client';
|
||||
|
||||
import React from 'react';
|
||||
import Link from 'next/link';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { ArrowLeft } from 'lucide-react';
|
||||
|
||||
type BackButtonProps = {
|
||||
className?: string;
|
||||
ariaLabel?: string;
|
||||
hrefFallback?: string; // default '/'
|
||||
children?: React.ReactNode; // custom icon/content; defaults to ArrowLeft
|
||||
};
|
||||
|
||||
/**
|
||||
* BackButton
|
||||
* - Primary: behaves like browser back (router.back()), preserving previous page state (e.g., scroll, filters)
|
||||
* - Fallback: if no history entry exists (e.g., opened directly), navigates to '/'
|
||||
* - Uses <Link> so that Ctrl/Cmd-click or middle-click opens the fallback URL in a new tab naturally
|
||||
*/
|
||||
export default function BackButton({ className, ariaLabel = '返回', hrefFallback = '/', children }: BackButtonProps) {
|
||||
const router = useRouter();
|
||||
|
||||
const onClick = React.useCallback<React.MouseEventHandler<HTMLAnchorElement>>((e) => {
|
||||
// Respect modifier clicks (new tab/window) and non-left clicks
|
||||
if (e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;
|
||||
|
||||
// Prefer SPA back when we have some history to go back to
|
||||
if (typeof window !== 'undefined' && window.history.length > 1) {
|
||||
e.preventDefault();
|
||||
router.back();
|
||||
}
|
||||
// else: allow default <Link href> to navigate to fallback
|
||||
}, [router]);
|
||||
|
||||
return (
|
||||
<Link
|
||||
href={hrefFallback}
|
||||
aria-label={ariaLabel}
|
||||
onClick={onClick}
|
||||
className={className}
|
||||
>
|
||||
{children ?? <ArrowLeft size={18} />}
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user