Merge branch 'stillimage-tw' into 'develop'
Make StillImage Tailwind friendly See merge request soapbox-pub/soapbox!1925
This commit is contained in:
commit
41dd2bfcef
12 changed files with 72 additions and 111 deletions
|
@ -160,16 +160,22 @@ const Item: React.FC<IItem> = ({
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
} else if (attachment.type === 'image') {
|
} else if (attachment.type === 'image') {
|
||||||
const letterboxed = shouldLetterbox(attachment);
|
const letterboxed = total === 1 && shouldLetterbox(attachment);
|
||||||
|
|
||||||
thumbnail = (
|
thumbnail = (
|
||||||
<a
|
<a
|
||||||
className={classNames('media-gallery__item-thumbnail', { letterboxed })}
|
className='media-gallery__item-thumbnail'
|
||||||
href={attachment.url}
|
href={attachment.url}
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
target='_blank'
|
target='_blank'
|
||||||
>
|
>
|
||||||
<StillImage src={attachment.url} alt={attachment.description} />
|
<StillImage
|
||||||
|
className='w-full h-full'
|
||||||
|
src={attachment.url}
|
||||||
|
alt={attachment.description}
|
||||||
|
letterboxed={letterboxed}
|
||||||
|
showExt
|
||||||
|
/>
|
||||||
</a>
|
</a>
|
||||||
);
|
);
|
||||||
} else if (attachment.type === 'gifv') {
|
} else if (attachment.type === 'gifv') {
|
||||||
|
|
|
@ -136,7 +136,7 @@ export const ProfileHoverCard: React.FC<IProfileHoverCard> = ({ visible = true }
|
||||||
</HStack>
|
</HStack>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
{account.source.get('note', '').length > 0 && (
|
{account.note.length > 0 && (
|
||||||
<Text size='sm' dangerouslySetInnerHTML={accountBio} />
|
<Text size='sm' dangerouslySetInnerHTML={accountBio} />
|
||||||
)}
|
)}
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|
|
@ -12,10 +12,14 @@ interface IStillImage {
|
||||||
src: string,
|
src: string,
|
||||||
/** Extra CSS styles on the outer <div> element. */
|
/** Extra CSS styles on the outer <div> element. */
|
||||||
style?: React.CSSProperties,
|
style?: React.CSSProperties,
|
||||||
|
/** Whether to display the image contained vs filled in its container. */
|
||||||
|
letterboxed?: boolean,
|
||||||
|
/** Whether to show the file extension in the corner. */
|
||||||
|
showExt?: 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 }) => {
|
const StillImage: React.FC<IStillImage> = ({ alt, className, src, style, letterboxed = false, showExt = false }) => {
|
||||||
const settings = useSettings();
|
const settings = useSettings();
|
||||||
const autoPlayGif = settings.get('autoPlayGif');
|
const autoPlayGif = settings.get('autoPlayGif');
|
||||||
|
|
||||||
|
@ -34,10 +38,56 @@ const StillImage: React.FC<IStillImage> = ({ alt, className, src, style }) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** ClassNames shared between the `<img>` and `<canvas>` elements. */
|
||||||
|
const baseClassName = classNames('w-full h-full block', {
|
||||||
|
'object-contain': letterboxed,
|
||||||
|
'object-cover': !letterboxed,
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div data-testid='still-image-container' className={classNames(className, 'still-image', { 'still-image--play-on-hover': hoverToPlay })} style={style}>
|
<div
|
||||||
<img src={src} alt={alt} ref={img} onLoad={handleImageLoad} />
|
data-testid='still-image-container'
|
||||||
{hoverToPlay && <canvas ref={canvas} />}
|
className={classNames(className, 'relative group overflow-hidden isolate')}
|
||||||
|
style={style}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src={src}
|
||||||
|
alt={alt}
|
||||||
|
ref={img}
|
||||||
|
onLoad={handleImageLoad}
|
||||||
|
className={classNames(baseClassName, {
|
||||||
|
'invisible group-hover:visible': hoverToPlay,
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{hoverToPlay && (
|
||||||
|
<canvas
|
||||||
|
ref={canvas}
|
||||||
|
className={classNames(baseClassName, {
|
||||||
|
'group-hover:invisible': hoverToPlay,
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{(hoverToPlay && showExt) && (
|
||||||
|
<div className='group-hover:hidden absolute opacity-90 left-2 bottom-2 pointer-events-none'>
|
||||||
|
<ExtensionBadge ext='GIF' />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
interface IExtensionBadge {
|
||||||
|
/** File extension. */
|
||||||
|
ext: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Badge displaying a file extension. */
|
||||||
|
const ExtensionBadge: React.FC<IExtensionBadge> = ({ ext }) => {
|
||||||
|
return (
|
||||||
|
<div className='inline-flex items-center px-2 py-0.5 rounded text-sm font-medium bg-gray-100 dark:bg-gray-800 text-gray-900 dark:text-gray-100'>
|
||||||
|
{ext}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -33,7 +33,7 @@ const Card = React.forwardRef<HTMLDivElement, ICard>(({ children, variant = 'def
|
||||||
ref={ref}
|
ref={ref}
|
||||||
{...filteredProps}
|
{...filteredProps}
|
||||||
className={classNames({
|
className={classNames({
|
||||||
'bg-white dark:bg-primary-900 text-gray-900 dark:text-gray-100 shadow-lg dark:shadow-none overflow-hidden': variant === 'rounded',
|
'bg-white dark:bg-primary-900 text-gray-900 dark:text-gray-100 shadow-lg dark:shadow-none overflow-hidden isolate': variant === 'rounded',
|
||||||
[sizes[size]]: variant === 'rounded',
|
[sizes[size]]: variant === 'rounded',
|
||||||
}, className)}
|
}, className)}
|
||||||
>
|
>
|
||||||
|
|
|
@ -74,6 +74,7 @@ const MediaItem: React.FC<IMediaItem> = ({ attachment, displayWidth, onOpenMedia
|
||||||
src={attachment.preview_url}
|
src={attachment.preview_url}
|
||||||
alt={attachment.description}
|
alt={attachment.description}
|
||||||
style={{ objectPosition: `${x}% ${y}%` }}
|
style={{ objectPosition: `${x}% ${y}%` }}
|
||||||
|
className='w-full h-full rounded-lg overflow-hidden'
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
} else if (['gifv', 'video'].indexOf(attachment.type) !== -1) {
|
} else if (['gifv', 'video'].indexOf(attachment.type) !== -1) {
|
||||||
|
|
|
@ -551,13 +551,12 @@ const Header: React.FC<IHeader> = ({ account }) => {
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<div className='relative h-32 w-full lg:h-48 md:rounded-t-xl bg-gray-200 dark:bg-gray-900/50'>
|
<div className='relative flex flex-col justify-center h-32 w-full lg:h-48 md:rounded-t-xl bg-gray-200 dark:bg-gray-900/50 overflow-hidden isolate'>
|
||||||
{account.header && (
|
{account.header && (
|
||||||
<a href={account.header} onClick={handleHeaderClick} target='_blank'>
|
<a href={account.header} onClick={handleHeaderClick} target='_blank'>
|
||||||
<StillImage
|
<StillImage
|
||||||
src={account.header}
|
src={account.header}
|
||||||
alt='Profile Header'
|
alt='Profile Header'
|
||||||
className='absolute inset-0 object-cover md:rounded-t-xl'
|
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
)}
|
)}
|
||||||
|
@ -577,7 +576,7 @@ const Header: React.FC<IHeader> = ({ account }) => {
|
||||||
<Avatar
|
<Avatar
|
||||||
src={account.avatar}
|
src={account.avatar}
|
||||||
size={96}
|
size={96}
|
||||||
className='h-24 w-24 rounded-full ring-4 ring-white dark:ring-primary-900'
|
className='relative h-24 w-24 rounded-full ring-4 ring-white dark:ring-primary-900'
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -36,13 +36,9 @@ const UserPanel: React.FC<IUserPanel> = ({ accountId, action, badges, domain })
|
||||||
<div className='relative'>
|
<div className='relative'>
|
||||||
<Stack space={2}>
|
<Stack space={2}>
|
||||||
<Stack>
|
<Stack>
|
||||||
<div className='-mt-4 -mx-4 h-24 bg-gray-200 relative'>
|
<div className='-mt-4 -mx-4 h-24 bg-gray-200 relative overflow-hidden'>
|
||||||
{header && (
|
{header && (
|
||||||
<StillImage
|
<StillImage src={account.header} />
|
||||||
src={account.get('header')}
|
|
||||||
className='absolute inset-0 object-cover'
|
|
||||||
alt=''
|
|
||||||
/>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -72,10 +72,6 @@ a .account__avatar {
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
|
||||||
&.still-image {
|
|
||||||
position: absolute;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,6 @@
|
||||||
@import 'components/columns';
|
@import 'components/columns';
|
||||||
@import 'components/search';
|
@import 'components/search';
|
||||||
@import 'components/react-toggle';
|
@import 'components/react-toggle';
|
||||||
@import 'components/still-image';
|
|
||||||
@import 'components/spoiler-button';
|
@import 'components/spoiler-button';
|
||||||
@import 'components/video-player';
|
@import 'components/video-player';
|
||||||
@import 'components/audio-player';
|
@import 'components/audio-player';
|
||||||
|
|
|
@ -356,11 +356,6 @@
|
||||||
&__preview {
|
&__preview {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__item-thumbnail img,
|
|
||||||
&__item-thumbnail .still-image img {
|
|
||||||
object-fit: contain;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-messages__divider {
|
.chat-messages__divider {
|
||||||
|
|
|
@ -57,33 +57,8 @@
|
||||||
line-height: 0;
|
line-height: 0;
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
height: 100%;
|
||||||
&,
|
width: 100%;
|
||||||
.still-image {
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
img {
|
|
||||||
@apply object-cover rounded-lg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.still-image--play-on-hover::before {
|
|
||||||
content: 'GIF';
|
|
||||||
position: absolute;
|
|
||||||
color: var(--primary-text-color);
|
|
||||||
background: var(--foreground-color);
|
|
||||||
bottom: 6px;
|
|
||||||
left: 6px;
|
|
||||||
padding: 2px 6px;
|
|
||||||
border-radius: 2px;
|
|
||||||
font-size: 11px;
|
|
||||||
font-weight: 600;
|
|
||||||
pointer-events: none;
|
|
||||||
opacity: 0.9;
|
|
||||||
transition: opacity 0.1s ease;
|
|
||||||
line-height: 18px;
|
|
||||||
}
|
|
||||||
|
|
||||||
video {
|
video {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -92,17 +67,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.status__wrapper {
|
|
||||||
.media-gallery__item-thumbnail.letterboxed {
|
|
||||||
&,
|
|
||||||
.still-image {
|
|
||||||
img {
|
|
||||||
object-fit: contain;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.media-gallery__preview {
|
.media-gallery__preview {
|
||||||
@apply bg-gray-200 dark:bg-gray-900 rounded-lg;
|
@apply bg-gray-200 dark:bg-gray-900 rounded-lg;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -113,23 +77,6 @@
|
||||||
left: 0;
|
left: 0;
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
|
|
||||||
.still-image--play-on-hover::before {
|
|
||||||
content: 'GIF';
|
|
||||||
position: absolute;
|
|
||||||
color: var(--primary-text-color);
|
|
||||||
background: var(--foreground-color);
|
|
||||||
bottom: 6px;
|
|
||||||
left: 6px;
|
|
||||||
padding: 2px 6px;
|
|
||||||
border-radius: 2px;
|
|
||||||
font-size: 11px;
|
|
||||||
font-weight: 600;
|
|
||||||
pointer-events: none;
|
|
||||||
opacity: 0.9;
|
|
||||||
transition: opacity 0.1s ease;
|
|
||||||
line-height: 18px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&--hidden {
|
&--hidden {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
.still-image {
|
|
||||||
position: relative;
|
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
img,
|
|
||||||
canvas {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
display: block;
|
|
||||||
object-fit: cover;
|
|
||||||
font-family: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
&--play-on-hover {
|
|
||||||
img {
|
|
||||||
position: absolute;
|
|
||||||
visibility: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover img {
|
|
||||||
visibility: visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover canvas {
|
|
||||||
visibility: hidden;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue