refactor: swap Button ghost/outline semantics, clean up ImageLightbox thumbnail
ghost now means transparent bg (no fill); outline keeps cream bg with subtle border. Remove magnify icon overlay from ImageLightbox thumbnail — hover cursor-zoom-in is sufficient. Close button updated to variant="outline" for cream-on-blue contrast in the dialog.
This commit is contained in:
@@ -439,4 +439,5 @@
|
||||
/* Lightbox dialog backdrop */
|
||||
dialog.lightbox::backdrop {
|
||||
background-color: rgba(4, 28, 243, 0.25);
|
||||
backdrop-filter: blur(4px);
|
||||
}
|
||||
|
||||
@@ -24,11 +24,11 @@ describe('Button', () => {
|
||||
});
|
||||
it('applies outline variant', () => {
|
||||
render(<Button variant="outline">Go</Button>);
|
||||
expect(screen.getByRole('button')).toHaveClass('bg-transparent');
|
||||
expect(screen.getByRole('button')).toHaveClass('bg-cream');
|
||||
});
|
||||
it('applies ghost variant', () => {
|
||||
render(<Button variant="ghost">Go</Button>);
|
||||
expect(screen.getByRole('button')).toHaveClass('bg-cream');
|
||||
expect(screen.getByRole('button')).toHaveClass('bg-transparent');
|
||||
});
|
||||
});
|
||||
describe('sizes', () => {
|
||||
|
||||
@@ -46,9 +46,9 @@ const VARIANTS = {
|
||||
secondary:
|
||||
'brutal-border bg-blue text-cream shadow-brutal hover:-translate-x-0.5 hover:-translate-y-0.5 hover:shadow-brutal-md active:translate-x-0.5 active:translate-y-0.5 active:shadow-brutal-xs',
|
||||
outline:
|
||||
'brutal-border bg-transparent text-blue shadow-brutal hover:-translate-x-0.5 hover:-translate-y-0.5 hover:shadow-brutal-md active:translate-x-0.5 active:translate-y-0.5 active:shadow-brutal-xs',
|
||||
ghost:
|
||||
'brutal-border border-blue/35 bg-cream text-blue hover:border-blue hover:bg-blue/10 active:bg-blue active:text-cream',
|
||||
ghost:
|
||||
'brutal-border bg-transparent text-blue hover:-translate-x-0.5 hover:-translate-y-0.5 active:translate-x-0.5 active:translate-y-0.5',
|
||||
} as const satisfies Record<ButtonVariant, string>;
|
||||
|
||||
const SIZES = {
|
||||
|
||||
@@ -56,7 +56,7 @@ describe('ImageLightbox', () => {
|
||||
it('clicking inside the dialog (not backdrop) does not close', () => {
|
||||
render(<ImageLightbox {...DEFAULT_PROPS} />);
|
||||
const dialog = document.querySelector('dialog') as HTMLDialogElement;
|
||||
const inner = dialog.querySelector('div') as HTMLDivElement;
|
||||
const inner = dialog.querySelector('img') as HTMLImageElement;
|
||||
fireEvent.click(inner);
|
||||
expect(HTMLDialogElement.prototype.close).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import Image from 'next/image';
|
||||
import { useRef } from 'react';
|
||||
import { CloseIcon, MagnifyIcon } from '$shared/assets/icons';
|
||||
import { CloseIcon } from '$shared/assets/icons';
|
||||
import { cn } from '$shared/lib';
|
||||
import { Button } from '$shared/ui/Button';
|
||||
|
||||
@@ -66,10 +66,6 @@ export function ImageLightbox({ src, alt, className }: Props) {
|
||||
className={cn('relative block w-full aspect-video overflow-hidden cursor-zoom-in', className)}
|
||||
>
|
||||
<Image src={src} alt={alt} fill className="object-cover" />
|
||||
{/* Magnify hint — pointer-events-none so clicks pass through to the button */}
|
||||
<span aria-hidden={true} className="absolute bottom-2 right-2 bg-cream text-blue p-1 pointer-events-none">
|
||||
<MagnifyIcon />
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<dialog
|
||||
@@ -77,13 +73,18 @@ export function ImageLightbox({ src, alt, className }: Props) {
|
||||
aria-label={alt}
|
||||
onClick={handleBackdropClick}
|
||||
onKeyUp={handleBackdropKeyUp}
|
||||
className="lightbox relative bg-blue brutal-border shadow-brutal-xl p-0 max-w-5xl w-full"
|
||||
className="lightbox fixed inset-0 m-auto relative bg-blue brutal-border p-0 overflow-hidden"
|
||||
>
|
||||
<div className="relative aspect-video w-full">
|
||||
{/* Native img so the dialog sizes to the image — next/image fill requires a pre-sized container */}
|
||||
{/* aria-hidden: the dialog element itself carries the accessible label */}
|
||||
<Image src={src} alt={alt} fill className="object-contain" aria-hidden={true} />
|
||||
</div>
|
||||
<Button variant="ghost" size="sm" onClick={close} aria-label="Close image" className="absolute top-3 right-3">
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img
|
||||
src={src}
|
||||
alt={alt}
|
||||
aria-hidden={true}
|
||||
className="block max-w-[calc(100vw-2rem)] max-h-[calc(100vh-2rem)] w-auto h-auto"
|
||||
/>
|
||||
<Button variant="outline" size="sm" onClick={close} aria-label="Close image" className="absolute top-3 right-3">
|
||||
<CloseIcon />
|
||||
</Button>
|
||||
</dialog>
|
||||
|
||||
Reference in New Issue
Block a user