pl-fe: display animated emojis on hover unless specified otherwise

Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
This commit is contained in:
marcin mikołajczak 2024-09-11 17:52:38 +02:00
parent a6deb34558
commit 7c3cb6a6eb
5 changed files with 29 additions and 9 deletions

View file

@ -45,7 +45,7 @@ const SidebarNavigationLink = React.forwardRef((props: ISidebarNavigationLink, r
ref={ref} ref={ref}
onClick={handleClick} onClick={handleClick}
className={clsx({ className={clsx({
'flex items-center py-2 text-sm font-semibold space-x-4 rtl:space-x-reverse transition-colors duration-200': true, 'group flex items-center py-2 text-sm font-semibold space-x-4 rtl:space-x-reverse transition-colors duration-200': true,
'text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200': !isActive, 'text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200': !isActive,
'text-gray-900 dark:text-white': isActive, 'text-gray-900 dark:text-white': isActive,
})} })}
@ -53,7 +53,7 @@ const SidebarNavigationLink = React.forwardRef((props: ISidebarNavigationLink, r
<span <span
className={clsx({ className={clsx({
'relative rounded-lg inline-flex p-2.5 transition-colors duration-200': true, 'relative rounded-lg inline-flex p-2.5 transition-colors duration-200': true,
'bg-primary-50 hover:bg-primary-100 dark:bg-slate-700 dark:hover:bg-slate-600 black:bg-gray-900 black:hover:bg-gray-800': !isActive, 'bg-primary-50 group-hover:bg-primary-100 dark:bg-slate-700 dark:group-hover:bg-slate-600 black:bg-gray-900 black:group-hover:bg-gray-800': !isActive,
'bg-primary-600': isActive, 'bg-primary-600': isActive,
})} })}
> >

View file

@ -59,7 +59,7 @@ const StatusReaction: React.FC<IStatusReaction> = ({ reaction, status, obfuscate
return ( return (
<button <button
className={clsx('flex cursor-pointer items-center gap-2 rounded-md border border-gray-400 p-1.5 transition-colors', { className={clsx('group flex cursor-pointer items-center gap-2 rounded-md border border-gray-400 p-1.5 transition-colors', {
'bg-primary-100 dark:border-primary-400 dark:bg-primary-400 black:border-primary-600 black:bg-primary-600': reaction.me, 'bg-primary-100 dark:border-primary-400 dark:bg-primary-400 black:border-primary-600 black:bg-primary-600': reaction.me,
'bg-transparent dark:border-primary-700 dark:bg-primary-700 black:border-primary-800 black:bg-primary-800': !reaction.me, 'bg-transparent dark:border-primary-700 dark:bg-primary-700 black:border-primary-800 black:bg-primary-800': !reaction.me,
'cursor-pointer': !disabled, 'cursor-pointer': !disabled,

View file

@ -18,17 +18,23 @@ interface IStillImage {
showExt?: boolean; showExt?: boolean;
/** Callback function if the image fails to load */ /** Callback function if the image fails to load */
onError?(): void; onError?(): void;
/** Treat as animated, no matter the extension */
isGif?: boolean;
/** Specify that the group is defined by the parent */
noGroup?: boolean;
} }
/** Renders images on a canvas, only playing GIFs if autoPlayGif is enabled. */ /** Renders images on a canvas, only playing GIFs if autoPlayGif is enabled. */
const StillImage: React.FC<IStillImage> = ({ alt, className, src, style, letterboxed = false, showExt = false, onError }) => { const StillImage: React.FC<IStillImage> = ({
alt, className, src, style, letterboxed = false, showExt = false, onError, isGif, noGroup,
}) => {
const { autoPlayGif } = useSettings(); const { autoPlayGif } = useSettings();
const canvas = useRef<HTMLCanvasElement>(null); const canvas = useRef<HTMLCanvasElement>(null);
const img = useRef<HTMLImageElement>(null); const img = useRef<HTMLImageElement>(null);
const hoverToPlay = ( const hoverToPlay = (
src && !autoPlayGif && (src.endsWith('.gif') || src.startsWith('blob:')) src && !autoPlayGif && (isGif || src.endsWith('.gif') || src.startsWith('blob:'))
); );
const handleImageLoad = () => { const handleImageLoad = () => {
@ -48,7 +54,7 @@ const StillImage: React.FC<IStillImage> = ({ alt, className, src, style, letterb
return ( return (
<div <div
data-testid='still-image-container' data-testid='still-image-container'
className={clsx(className, 'group relative isolate overflow-hidden')} className={clsx(className, 'relative isolate overflow-hidden', { 'group': !noGroup })}
style={style} style={style}
> >
<img <img

View file

@ -1,16 +1,18 @@
import React from 'react'; import React from 'react';
import StillImage from 'pl-fe/components/still-image';
import { removeVS16s, toCodePoints } from 'pl-fe/utils/emoji'; import { removeVS16s, toCodePoints } from 'pl-fe/utils/emoji';
import { joinPublicPath } from 'pl-fe/utils/static'; import { joinPublicPath } from 'pl-fe/utils/static';
interface IEmoji extends React.ImgHTMLAttributes<HTMLImageElement> { interface IEmoji extends Pick<React.ImgHTMLAttributes<HTMLImageElement>, 'alt' | 'className' | 'src' | 'title'> {
/** Unicode emoji character. */ /** Unicode emoji character. */
emoji?: string; emoji?: string;
noGroup?: boolean;
} }
/** A single emoji image. */ /** A single emoji image. */
const Emoji: React.FC<IEmoji> = (props): JSX.Element | null => { const Emoji: React.FC<IEmoji> = (props): JSX.Element | null => {
const { emoji, alt, src, ...rest } = props; const { emoji, alt, src, noGroup, ...rest } = props;
let filename; let filename;
@ -21,6 +23,18 @@ const Emoji: React.FC<IEmoji> = (props): JSX.Element | null => {
if (!filename && !src) return null; if (!filename && !src) return null;
if (src) {
return (
<StillImage
alt={alt || emoji}
src={src}
isGif
noGroup={noGroup}
{...rest}
/>
);
}
return ( return (
<img <img
draggable='false' draggable='false'

View file

@ -58,7 +58,7 @@ const EmojiPicker: React.FC<IEmojiPicker> = ({ emoji, emojiUrl, ...props }) => {
tabIndex={0} tabIndex={0}
> >
{emoji {emoji
? <Emoji height={20} width={20} emoji={emoji} /> ? <Emoji className='h-5 w-5' emoji={emoji} src={emojiUrl} />
: <Icon className='h-5 w-5 text-gray-600 hover:text-gray-700 dark:hover:text-gray-500' src={require('@tabler/icons/outline/mood-happy.svg')} />} : <Icon className='h-5 w-5 text-gray-600 hover:text-gray-700 dark:hover:text-gray-500' src={require('@tabler/icons/outline/mood-happy.svg')} />}
</button> </button>