basically move stuff around

Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
This commit is contained in:
nicole mikołajczyk
2025-10-04 15:50:42 +02:00
parent 0b74e7d832
commit 6128456657
9 changed files with 128 additions and 105 deletions

View File

@ -87,7 +87,7 @@ const AnimatedNumber: React.FC<IAnimatedNumber> = ({ value, obfuscate, short, ma
return ( return (
<TransitionMotion styles={styles} willEnter={willEnter} willLeave={willLeave}> <TransitionMotion styles={styles} willEnter={willEnter} willLeave={willLeave}>
{items => ( {items => (
<span className='relative inline-flex flex-col items-stretch overflow-hidden'> <span className='⁂-animated-number'>
{items.map(({ key, data, style }) => ( {items.map(({ key, data, style }) => (
<span <span
key={key} key={key}

View File

@ -18,7 +18,7 @@ const AttachmentThumbs = ({ status, onClick }: IAttachmentThumbs) => {
const { displayMedia } = useSettings(); const { displayMedia } = useSettings();
const { openModal } = useModalsStore(); const { openModal } = useModalsStore();
const fallback = <div className='media-gallery--compact' />; const fallback = <div className='⁂-media-gallery--compact' />;
const onOpenMedia = (media: Array<MediaAttachment>, index: number) => openModal('MEDIA', { media, index }); const onOpenMedia = (media: Array<MediaAttachment>, index: number) => openModal('MEDIA', { media, index });
const [visible] = useMediaVisible(status, displayMedia); const [visible] = useMediaVisible(status, displayMedia);

View File

@ -159,14 +159,14 @@ const Item: React.FC<IItem> = ({
return ( return (
<div <div
className={clsx('media-gallery__item', standalone)} className={clsx('⁂-media-gallery__item', standalone)}
key={attachment.id} key={attachment.id}
style={{ position, float, left, top, right, bottom, height, width: `${width}%` }} style={{ position, float, left, top, right, bottom, height, width: `${width}%` }}
> >
<a className='media-gallery__item-thumbnail' href={attachment.url} target='_blank' style={{ cursor: 'pointer' }}> <a className='⁂-media-gallery__item-thumbnail' href={attachment.url} target='_blank' style={{ cursor: 'pointer' }}>
<Blurhash hash={attachment.blurhash} className='media-gallery__preview' /> <Blurhash hash={attachment.blurhash} className='⁂-media-gallery__preview' />
<span className='media-gallery__item__icons'>{attachmentIcon}</span> <span className='⁂-media-gallery__item__icons'>{attachmentIcon}</span>
<span className='media-gallery__filename__label'>{filename}</span> <span className='⁂-media-gallery__filename__label'>{filename}</span>
</a> </a>
</div> </div>
); );
@ -176,7 +176,7 @@ const Item: React.FC<IItem> = ({
thumbnail = ( thumbnail = (
<> <>
<a <a
className='media-gallery__item-thumbnail' className='⁂-media-gallery__item-thumbnail'
href={attachment.url} href={attachment.url}
onClick={handleClick} onClick={handleClick}
target='_blank' target='_blank'
@ -220,9 +220,9 @@ const Item: React.FC<IItem> = ({
} }
thumbnail = ( thumbnail = (
<div className={clsx('media-gallery__gifv', { autoplay: autoPlayGif })}> <div className={clsx('⁂-media-gallery__gifv', { autoplay: autoPlayGif })}>
<video <video
className='media-gallery__item-gifv-thumbnail' className='⁂-media-gallery__item-gifv-thumbnail'
aria-label={attachment.description} aria-label={attachment.description}
title={attachment.description} title={attachment.description}
role='application' role='application'
@ -235,26 +235,26 @@ const Item: React.FC<IItem> = ({
{...conditionalAttributes} {...conditionalAttributes}
/> />
<span className='media-gallery__gifv__label'>GIF</span> <span className='⁂-media-gallery__gifv__label'>GIF</span>
</div> </div>
); );
} else if (attachment.type === 'audio') { } else if (attachment.type === 'audio') {
thumbnail = ( thumbnail = (
<a <a
className={clsx('media-gallery__item-thumbnail')} className={clsx('⁂-media-gallery__item-thumbnail')}
href={attachment.url} href={attachment.url}
onClick={handleClick} onClick={handleClick}
target='_blank' target='_blank'
title={attachment.description} title={attachment.description}
> >
<span className='media-gallery__item__icons'><Icon src={require('@tabler/icons/outline/volume.svg')} /></span> <span className='⁂-media-gallery__item__icons'><Icon src={require('@tabler/icons/outline/volume.svg')} /></span>
<span className='media-gallery__file-extension__label uppercase'>{ext}</span> <span className='⁂-media-gallery__file-extension__label uppercase'>{ext}</span>
</a> </a>
); );
} else if (attachment.type === 'video') { } else if (attachment.type === 'video') {
thumbnail = ( thumbnail = (
<a <a
className={clsx('media-gallery__item-thumbnail')} className={clsx('⁂-media-gallery__item-thumbnail')}
href={attachment.url} href={attachment.url}
onClick={handleClick} onClick={handleClick}
target='_blank' target='_blank'
@ -268,25 +268,25 @@ const Item: React.FC<IItem> = ({
> >
<source src={attachment.url} /> <source src={attachment.url} />
</video> </video>
<span className='media-gallery__file-extension__label uppercase'>{ext}</span> <span className='⁂-media-gallery__file-extension__label uppercase'>{ext}</span>
</a> </a>
); );
} }
return ( return (
<div <div
className={clsx('media-gallery__item', `media-gallery__item--${attachment.type}`, standalone)} className={clsx('⁂-media-gallery__item', `⁂-media-gallery__item--${attachment.type}`, standalone)}
key={attachment.id} key={attachment.id}
style={{ position, float, left, top, right, bottom, height, width: `${width}%` }} style={{ position, float, left, top, right, bottom, height, width: `${width}%` }}
> >
{last && total > ATTACHMENT_LIMIT && ( {last && total > ATTACHMENT_LIMIT && (
<div className='media-gallery__item-overflow'> <div className='⁂-media-gallery__item-overflow'>
+{total - ATTACHMENT_LIMIT + 1} +{total - ATTACHMENT_LIMIT + 1}
</div> </div>
)} )}
<Blurhash <Blurhash
hash={attachment.blurhash} hash={attachment.blurhash}
className='media-gallery__preview' className='⁂-media-gallery__preview'
/> />
{(visible || !attachment.blurhash) && thumbnail} {(visible || !attachment.blurhash) && thumbnail}
</div> </div>
@ -607,8 +607,8 @@ const MediaGallery: React.FC<IMediaGallery> = (props) => {
return ( return (
<div <div
className={clsx(className, 'media-gallery overflow-hidden rounded-md', { className={clsx(className, '⁂-media-gallery', {
'media-gallery--compact !h-12 bg-transparent': compact, '⁂-media-gallery--compact': compact,
})} })}
style={sizeData.style} style={sizeData.style}
ref={node} ref={node}

View File

@ -148,7 +148,7 @@ const Upload: React.FC<IUpload> = ({
onDragEnter={onDragEnter} onDragEnter={onDragEnter}
onDragEnd={onDragEnd} onDragEnd={onDragEnd}
> >
<Blurhash hash={media.blurhash} className='media-gallery__preview' /> <Blurhash hash={media.blurhash} className='⁂-media-gallery__preview' />
<Motion defaultStyle={{ scale: 0.8 }} style={{ scale: spring(1, { stiffness: 180, damping: 12 }) }}> <Motion defaultStyle={{ scale: 0.8 }} style={{ scale: spring(1, { stiffness: 180, damping: 12 }) }}>
{({ scale }) => ( {({ scale }) => (
<div <div

View File

@ -76,13 +76,13 @@ const PlaceholderMediaGallery: React.FC<IPlaceholderMediaGallery> = ({ media, de
const float = dimensions.float as any || 'left'; const float = dimensions.float as any || 'left';
const position = dimensions.pos as any || 'relative'; const position = dimensions.pos as any || 'relative';
return <div key={i} className='media-gallery__item animate-pulse bg-primary-200' style={{ position, float, left, top, right, bottom, height, width }} />; return <div key={i} className='⁂-media-gallery__item animate-pulse bg-primary-200' style={{ position, float, left, top, right, bottom, height, width }} />;
}; };
const sizeData = getSizeData(media.length); const sizeData = getSizeData(media.length);
return ( return (
<div className='media-gallery media-gallery--placeholder' style={sizeData.style} ref={handleRef}> <div className='⁂-media-gallery media-gallery--placeholder' style={sizeData.style} ref={handleRef}>
{media.slice(0, 4).map((_, i) => renderItem(sizeData.itemsDimensions[i], i))} {media.slice(0, 4).map((_, i) => renderItem(sizeData.itemsDimensions[i], i))}
</div> </div>
); );

View File

@ -466,7 +466,7 @@ const Video: React.FC<IVideo> = ({
tabIndex={0} tabIndex={0}
> >
{!fullscreen && ( {!fullscreen && (
<Blurhash hash={blurhash} className='media-gallery__preview' /> <Blurhash hash={blurhash} className='⁂-media-gallery__preview' />
)} )}
<video <video

View File

@ -1,81 +1 @@
.media-gallery {
@apply rounded-lg box-border overflow-hidden isolate relative w-full h-auto;
&__item {
@apply border-0 box-border block float-left relative overflow-hidden;
&__icons {
@apply absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2;
.svg-icon {
@apply size-24;
}
}
&-overflow {
@apply absolute w-full h-full inset-0 bg-white/75 z-[2] text-center font-bold text-5xl flex items-center justify-center pointer-events-none;
color: #333;
}
&-thumbnail {
@apply text-gray-400 cursor-zoom-in block no-underline leading-[0] relative z-[1] h-full w-full;
video {
@apply w-full h-full object-cover;
}
}
}
&__preview {
@apply bg-gray-200 dark:bg-gray-900 w-full h-full object-cover absolute top-0 left-0 z-0;
}
&__gifv {
@apply h-full overflow-hidden relative w-full;
}
&__item-gifv-thumbnail {
@apply cursor-zoom-in h-full object-cover relative w-full z-[1] transform-none top-0;
}
&__gifv__label,
&__filename__label,
&__file-extension__label {
@apply pointer-events-none absolute bottom-1.5 left-1.5 z-[1] block bg-black/50 py-0.5 px-1.5 font-semibold text-white opacity-90 text-xs leading-[18px];
transition: opacity 0.1s ease;
}
&__gifv {
&.autoplay {
.media-gallery__gifv__label {
@apply hidden;
}
}
&:hover {
.media-gallery__gifv__label {
@apply opacity-100;
}
}
}
&--compact {
@apply flex rounded-sm w-fit gap-0.5;
.media-gallery__item {
@apply h-12 w-12 inset-auto float-left #{!important};
&-overflow {
@apply text-xl;
}
&__icons .svg-icon {
@apply h-8 w-8;
}
}
.media-gallery__file-extension__label {
@apply hidden;
}
}
}

View File

@ -161,3 +161,11 @@ a.⁂-list-item,
.-card-title { .-card-title {
@include mixins.text($size: xl, $weight: bold, $truncate: truncate); @include mixins.text($size: xl, $weight: bold, $truncate: truncate);
} }
.-animated-number {
position: relative;
display: inline-flex;
flex-direction: column;
align-items: stretch;
overflow: hidden;
}

View File

@ -0,0 +1,95 @@
.-media-gallery {
@apply overflow-hidden rounded-md rounded-lg box-border overflow-hidden isolate relative w-full h-auto;
&__item {
@apply border-0 box-border block float-left relative overflow-hidden;
&__icons {
@apply absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2;
.svg-icon {
@apply size-24;
}
}
&-overflow {
@apply absolute w-full h-full inset-0 bg-white/75 z-[2] text-center font-bold text-5xl flex items-center justify-center pointer-events-none;
color: #333;
}
&-thumbnail {
@apply text-gray-400 cursor-zoom-in block no-underline leading-[0] relative z-[1] h-full w-full;
video {
@apply w-full h-full object-cover;
}
}
}
&__preview {
@apply bg-gray-200 dark:bg-gray-900 w-full h-full object-cover absolute top-0 left-0 z-0;
}
&__gifv {
@apply h-full overflow-hidden relative w-full;
}
&__item-gifv-thumbnail {
@apply cursor-zoom-in h-full object-cover relative w-full z-[1] transform-none top-0;
}
&__gifv__label,
&__filename__label,
&__file-extension__label {
pointer-events: none;
position: absolute;
display: block;
bottom: 0.375rem;
left: 0.375rem;
z-index: 1;
background: #00000050;
@apply py-0.5 px-1.5 font-semibold text-white opacity-90 text-xs leading-[18px];
transition: opacity 0.1s ease;
}
&__gifv {
&.autoplay {
.-media-gallery__gifv__label {
display: none;
}
}
&:hover {
.-media-gallery__gifv__label {
opacity: 1;
}
}
}
&--compact {
display: flex;
border-radius: 0.125rem;
gap: 0.125rem;
height: 3rem;
background: transparent;
.-media-gallery__item {
size: 3rem;
inset: auto;
float: left;
&-overflow {
font-size: 1.25rem;
line-height: 1.75rem;
}
&__icons svg {
size: 2rem;
}
}
.-media-gallery__file-extension__label {
display: none;
}
}
}