pl-fe: add button for alt text preview

Signed-off-by: mkljczk <git@mkljczk.pl>
This commit is contained in:
mkljczk
2025-03-07 16:54:49 +01:00
parent 1062fd61f0
commit a3db301c20
3 changed files with 44 additions and 17 deletions

View File

@ -8,14 +8,15 @@ interface IAltIndicator extends Pick<React.HTMLAttributes<HTMLSpanElement>, 'tit
warning?: boolean;
}
const AltIndicator: React.FC<IAltIndicator> = ({ className, warning, ...props }) => (
const AltIndicator: React.FC<IAltIndicator> = React.forwardRef<HTMLSpanElement, IAltIndicator>(({ className, warning, ...props }, ref) => (
<span
className={clsx('inline-flex items-center gap-1 rounded bg-gray-900 px-2 py-1 text-xs font-medium uppercase text-white', className)}
{...props}
ref={ref}
>
{warning && <Icon className='size-4' src={require('@tabler/icons/outline/alert-triangle.svg')} />}
<FormattedMessage id='upload_form.description_missing.indicator' defaultMessage='Alt' />
</span>
);
));
export default AltIndicator;

View File

@ -1,9 +1,14 @@
import clsx from 'clsx';
import React, { useState, useRef, useLayoutEffect, CSSProperties } from 'react';
import { FormattedMessage } from 'react-intl';
import AltIndicator from 'pl-fe/components/alt-indicator';
import Blurhash from 'pl-fe/components/blurhash';
import Icon from 'pl-fe/components/icon';
import StillImage from 'pl-fe/components/still-image';
import Popover from 'pl-fe/components/ui/popover';
import Stack from 'pl-fe/components/ui/stack';
import Text from 'pl-fe/components/ui/text';
import { MIMETYPE_ICONS } from 'pl-fe/components/upload';
import { usePlFeConfig } from 'pl-fe/hooks/use-pl-fe-config';
import { useSettings } from 'pl-fe/hooks/use-settings';
@ -12,6 +17,7 @@ import { truncateFilename } from 'pl-fe/utils/media';
import { isIOS } from '../is-mobile';
import { isPanoramic, isPortrait, isNonConformingRatio, minimumAspectRatio, maximumAspectRatio } from '../utils/media-aspect-ratio';
import type { MediaAttachment } from 'pl-api';
const ATTACHMENT_LIMIT = 4;
@ -167,20 +173,40 @@ const Item: React.FC<IItem> = ({
const letterboxed = total === 1 && shouldLetterbox(attachment);
thumbnail = (
<a
className='media-gallery__item-thumbnail'
href={attachment.url}
onClick={handleClick}
target='_blank'
>
<StillImage
className='size-full'
src={mediaPreview ? attachment.preview_url : attachment.url}
alt={attachment.description}
letterboxed={letterboxed}
showExt
/>
</a>
<>
<a
className='media-gallery__item-thumbnail'
href={attachment.url}
onClick={handleClick}
target='_blank'
>
<StillImage
className='size-full'
src={mediaPreview ? attachment.preview_url : attachment.url}
alt={attachment.description}
letterboxed={letterboxed}
showExt
/>
</a>
{attachment.description && (
<Popover
interaction='click'
referenceElementClassName='cursor-pointer'
content={
<Stack space={1} className='max-w-80'>
<Text weight='semibold'>
<FormattedMessage id='media-gallery.description' defaultMessage='Image description' />
</Text>
<Text>
{attachment.description}
</Text>
</Stack>
}
>
<AltIndicator className='absolute bottom-2 left-2 z-10 opacity-80 transition-opacity hover:opacity-100' />
</Popover>
)}
</>
);
} else if (attachment.type === 'gifv') {
const conditionalAttributes: React.VideoHTMLAttributes<HTMLVideoElement> = {};

View File

@ -108,7 +108,7 @@ const Popover: React.FC<IPopover> = ({ children, content, referenceElementClassN
className={
clsx(
'overflow-hidden rounded-lg bg-white shadow-2xl dark:bg-gray-900 dark:ring-2 dark:ring-primary-700',
{ 'p-6': !isFlush },
{ 'p-4': !isFlush },
)
}
{...getFloatingProps()}