Skip to content

Commit e15caa4

Browse files
authored
feat: add MediaBadge (#3103)
1 parent 4c423c1 commit e15caa4

8 files changed

Lines changed: 67 additions & 29 deletions

File tree

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { IconMicrophoneSolid, IconVideoFill } from '../Icons';
2+
import React, { type ComponentType } from 'react';
3+
import type { LocalAttachment } from 'stream-chat';
4+
import clsx from 'clsx';
5+
6+
export type MediaBadgeVariant = 'video' | 'voice-recording' | string;
7+
8+
export type MediaBadgeProps = {
9+
attachment: LocalAttachment;
10+
variant: 'video' | 'voice-recording' | string;
11+
};
12+
13+
const MediaBadgeVariantToIcon: Record<MediaBadgeVariant, ComponentType> = {
14+
video: IconVideoFill,
15+
voiceRecording: IconMicrophoneSolid,
16+
};
17+
18+
export const MediaBadge = ({ attachment, variant }: MediaBadgeProps) => {
19+
const Icon = MediaBadgeVariantToIcon[variant];
20+
return (
21+
<div
22+
className={clsx('str-chat__media-badge', {
23+
[`str-chat__media-badge--${variant}`]: variant,
24+
})}
25+
>
26+
{Icon && <Icon />}
27+
{attachment.duration && <div>{attachment.duration}</div>}
28+
</div>
29+
);
30+
};
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
.str-chat__media-badge {
2+
display: flex;
3+
align-items: center;
4+
gap: var(--spacing-xxs);
5+
position: absolute;
6+
bottom: var(--spacing-xs);
7+
inset-inline-start: var(--spacing-xs);
8+
padding: var(--spacing-xxs) var(--spacing-xs);
9+
border-radius: var(--radius-max);
10+
background: var(--badge-bg-inverse);
11+
color: var(--badge-text-on-inverse);
12+
font: var(--str-chat__numeric-md-text);
13+
overflow: hidden;
14+
text-overflow: ellipsis;
15+
16+
.str-chat__icon {
17+
width: var(--icon-size-xs);
18+
height: var(--icon-size-xs);
19+
fill: currentColor;
20+
}
21+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
@use 'Badge';
2+
@use 'MediaBadge';

β€Žsrc/components/Icons/icons.tsxβ€Ž

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -633,6 +633,14 @@ export const IconVoice = createIcon(
633633
/>,
634634
);
635635

636+
export const IconMicrophoneSolid = createIcon(
637+
'IconMicrophoneSolid',
638+
<path
639+
d='M6.25 10V5C6.25 4.00544 6.64509 3.05161 7.34835 2.34835C8.05161 1.64509 9.00544 1.25 10 1.25C10.9946 1.25 11.9484 1.64509 12.6517 2.34835C13.3549 3.05161 13.75 4.00544 13.75 5V10C13.75 10.9946 13.3549 11.9484 12.6517 12.6517C11.9484 13.3549 10.9946 13.75 10 13.75C9.00544 13.75 8.05161 13.3549 7.34835 12.6517C6.64509 11.9484 6.25 10.9946 6.25 10ZM16.25 10C16.25 9.83424 16.1842 9.67527 16.0669 9.55806C15.9497 9.44085 15.7908 9.375 15.625 9.375C15.4592 9.375 15.3003 9.44085 15.1831 9.55806C15.0658 9.67527 15 9.83424 15 10C15 11.3261 14.4732 12.5979 13.5355 13.5355C12.5979 14.4732 11.3261 15 10 15C8.67392 15 7.40215 14.4732 6.46447 13.5355C5.52678 12.5979 5 11.3261 5 10C5 9.83424 4.93415 9.67527 4.81694 9.55806C4.69973 9.44085 4.54076 9.375 4.375 9.375C4.20924 9.375 4.05027 9.44085 3.93306 9.55806C3.81585 9.67527 3.75 9.83424 3.75 10C3.7519 11.5489 4.32806 13.042 5.36707 14.1907C6.40607 15.3393 7.83409 16.062 9.375 16.2188V18.75C9.375 18.9158 9.44085 19.0747 9.55806 19.1919C9.67527 19.3092 9.83424 19.375 10 19.375C10.1658 19.375 10.3247 19.3092 10.4419 19.1919C10.5592 19.0747 10.625 18.9158 10.625 18.75V16.2188C12.1659 16.062 13.5939 15.3393 14.6329 14.1907C15.6719 13.042 16.2481 11.5489 16.25 10Z'
640+
fill='currentColor'
641+
/>,
642+
);
643+
636644
export const IconMute = createIcon(
637645
'IconMute',
638646
<path

β€Žsrc/components/MessageComposer/AttachmentPreviewList/MediaAttachmentPreview.tsxβ€Ž

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,12 @@ import React, {
1414
useState,
1515
} from 'react';
1616
import clsx from 'clsx';
17-
import { IconExclamationMark, IconRetry, IconVideoFill } from '../../Icons';
17+
import { IconExclamationMark, IconRetry } from '../../Icons';
1818
import { RemoveAttachmentPreviewButton } from '../RemoveAttachmentPreviewButton';
1919
import { Button } from '../../Button';
2020
import { UploadProgressIndicator } from '../../Loading/UploadProgressIndicator';
2121
import { AttachmentPreviewRoot } from './utils/AttachmentPreviewRoot';
22+
import { MediaBadge } from '../../Badge/MediaBadge';
2223

2324
export type MediaAttachmentPreviewProps<CustomLocalMetadata = Record<string, unknown>> =
2425
UploadAttachmentPreviewProps<
@@ -99,10 +100,7 @@ export const MediaAttachmentPreview = ({
99100
{isVideoAttachment(attachment) &&
100101
!hasUploadError &&
101102
uploadState !== 'uploading' && (
102-
<div className='str-chat__attachment-preview-media__video-indicator'>
103-
<IconVideoFill />
104-
{attachment.duration && <div>{attachment.duration}</div>}
105-
</div>
103+
<MediaBadge attachment={attachment} variant='video' />
106104
)}
107105

108106
{hasFatalError && <IconExclamationMark />}

β€Žsrc/components/MessageComposer/styling/AttachmentPreview.scssβ€Ž

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -160,28 +160,6 @@
160160
object-fit: cover;
161161
}
162162
}
163-
164-
.str-chat__attachment-preview-media__video-indicator {
165-
display: flex;
166-
align-items: center;
167-
gap: var(--spacing-xxs);
168-
position: absolute;
169-
bottom: var(--spacing-xs);
170-
inset-inline-start: var(--spacing-xs);
171-
padding: var(--spacing-xxs) var(--spacing-xs);
172-
border-radius: var(--radius-max);
173-
background: var(--badge-bg-inverse);
174-
color: var(--badge-text-on-inverse);
175-
font: var(--str-chat__numeric-md-text);
176-
overflow: hidden;
177-
text-overflow: ellipsis;
178-
179-
.str-chat__icon {
180-
width: var(--icon-size-xs);
181-
height: var(--icon-size-xs);
182-
fill: currentColor;
183-
}
184-
}
185163
}
186164

187165
.str-chat__attachment-preview-media__overlay {

β€Žsrc/components/VideoPlayer/styling/VideoThumbnail.scssβ€Ž

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
height: $size;
2121
width: $size;
2222
border-radius: var(--radius-max);
23-
background-color: var(--control-play-control-bg);
23+
background-color: var(--control-play-button-bg);
2424
left: calc(50% - calc($size / 2));
2525
top: calc(50% - calc($size / 2));
2626

@@ -29,7 +29,7 @@
2929
width: calc($size / 2);
3030

3131
path {
32-
fill: var(--control-play-control-icon);
32+
fill: var(--control-play-button-icon);
3333
}
3434
}
3535
}

β€Žsrc/styling/variables-tokens.cssβ€Ž

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,8 @@
568568
--badge-text: var(--text-primary);
569569
--badge-bg-default: #ffffff;
570570
--badge-text-on-accent: #ffffff;
571+
--badge-text-on-inverse: #ffffff;
572+
--badge-bg-inverse: var(--chrome-1000);
571573

572574
/* ─── Control (remove, progress bar, toggle, playback, checkbox, play button, thumb, radio) ─── */
573575
--control-remove-control-bg: #1a1b25;

0 commit comments

Comments
Β (0)