nicolium: avoid useless jsx fragments

Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
This commit is contained in:
nicole mikołajczyk
2026-03-07 11:03:26 +01:00
parent af3d777efa
commit 45f2473784
14 changed files with 348 additions and 372 deletions

View File

@ -98,9 +98,8 @@ interface IProfilePopper {
children: React.ReactNode;
}
const ProfilePopper: React.FC<IProfilePopper> = ({ condition, wrapper, children }) => (
<>{condition ? wrapper(children) : children}</>
);
const ProfilePopper: React.FC<IProfilePopper> = ({ condition, wrapper, children }) =>
condition ? wrapper(children) : children;
interface IAccount {
account: AccountSchema;

View File

@ -16,7 +16,7 @@ const Emoji: React.FC<IEmoji> = ({ emoji, emojiMap, hovered }) => {
const { autoPlayGif, reduceMotion, systemEmojiFont } = useSettings();
if (unicodeMapping[emoji]) {
if (systemEmojiFont) return <>{emoji}</>;
if (systemEmojiFont) return emoji;
const { unified, shortcode } = unicodeMapping[emoji];
const title = shortcode ? `:${shortcode}:` : '';

View File

@ -21,7 +21,7 @@ const AutosuggestEmoji: React.FC<IAutosuggestEmoji> = ({ emoji }) => {
<img className='emojione mr-2 block size-4' src={emoji.imageUrl} alt={emoji.colons} />
);
} else {
if (systemEmojiFont) emojiElement = <>{emoji.native}</>;
if (systemEmojiFont) emojiElement = emoji.native;
const mapping =
unicodeMapping[emoji.native] || unicodeMapping[emoji.native.replace(/\uFE0F$/, '')];

View File

@ -272,7 +272,7 @@ const ScrollableList = React.forwardRef<VirtuosoHandle, IScrollableList>(
itemClassName,
}}
components={{
Header: prepend ? () => <>{prepend}</> : undefined,
Header: prepend ? () => prepend : undefined,
ScrollSeekPlaceholder: Placeholder as React.ComponentType<any>,
EmptyPlaceholder: renderEmpty,
List,

View File

@ -328,7 +328,7 @@ const StatusContent: React.FC<IStatusContent> = React.memo(
if (onClick) {
return <div className='⁂-status-content__container'>{output}</div>;
} else {
return <>{output}</>;
return output;
}
},
);

View File

@ -164,22 +164,20 @@ const StatusList: React.FC<IStatusList> = ({
}
return (
<>
<ScrollableList
id='status-list'
key='scrollable-list'
isLoading={isLoading}
showLoading={isLoading && statusIds.length === 0}
onLoadMore={handleLoadOlder}
placeholderComponent={() => <PlaceholderStatus variant='slim' />}
placeholderCount={20}
ref={node}
listClassName={clsx('⁂-status-list', className)}
{...other}
>
{scrollableContent}
</ScrollableList>
</>
<ScrollableList
id='status-list'
key='scrollable-list'
isLoading={isLoading}
showLoading={isLoading && statusIds.length === 0}
onLoadMore={handleLoadOlder}
placeholderComponent={() => <PlaceholderStatus variant='slim' />}
placeholderCount={20}
ref={node}
listClassName={clsx('⁂-status-list', className)}
{...other}
>
{scrollableContent}
</ScrollableList>
);
};

View File

@ -16,7 +16,7 @@ interface IEmoji extends Pick<
}
/** A single emoji image. */
const Emoji: React.FC<IEmoji> = (props): React.JSX.Element | null => {
const Emoji: React.FC<IEmoji> = (props) => {
const { disableUserProvidedMedia, systemEmojiFont } = useSettings();
const { emoji, alt, src, staticSrc, noGroup, ...rest } = props;
@ -30,8 +30,7 @@ const Emoji: React.FC<IEmoji> = (props): React.JSX.Element | null => {
if (!filename && !src) return null;
if (src) {
if (disableUserProvidedMedia)
return <>{alt ?? <span className={rest.className}>{emoji}</span>}</>;
if (disableUserProvidedMedia) return alt ?? <span className={rest.className}>{emoji}</span>;
return (
<StillImage
alt={alt ?? emoji}

View File

@ -50,12 +50,11 @@ const Counter: React.FC<ICounter> = ({
let content;
if (!data) {
content = (
<>
{/* <span className='sparkline__value__total'><Skeleton width={43} /></span>
<span className='sparkline__value__change'><Skeleton width={43} /></span> */}
</>
);
content = null;
{
/* <span className='sparkline__value__total'><Skeleton width={43} /></span>
<span className='sparkline__value__change'><Skeleton width={43} /></span> */
}
} else {
const measure = data[0];
const percentChange =

View File

@ -279,154 +279,148 @@ const RegistrationForm: React.FC<IRegistrationForm> = ({ inviteToken }) => {
return (
<Form onSubmit={onSubmit} data-testid='registrations-open'>
<fieldset disabled={isLoading} className='space-y-3'>
<>
<FormGroup
hintText={
<FormattedMessage
id='registration.fields.username_hint'
defaultMessage='Only letters, numbers, and underscores are allowed.'
/>
}
errors={
usernameUnavailable ? [intl.formatMessage(messages.usernameUnavailable)] : undefined
}
>
<Input
type='text'
name='username'
placeholder={intl.formatMessage(messages.username)}
autoComplete='off'
autoCorrect='off'
autoCapitalize='off'
pattern='^[a-zA-Z\d_-]+'
icon={require('@phosphor-icons/core/regular/at.svg')}
onChange={onUsernameChange}
value={params.username}
required
<FormGroup
hintText={
<FormattedMessage
id='registration.fields.username_hint'
defaultMessage='Only letters, numbers, and underscores are allowed.'
/>
</FormGroup>
{domains && (
<FormGroup>
<Select onChange={onDomainChange} value={params.domain}>
{domains.map(({ id, domain }) => (
<option key={id} value={id}>
{domain}
</option>
))}
</Select>
</FormGroup>
)}
}
errors={
usernameUnavailable ? [intl.formatMessage(messages.usernameUnavailable)] : undefined
}
>
<Input
type='email'
name='email'
placeholder={intl.formatMessage(messages.email)}
type='text'
name='username'
placeholder={intl.formatMessage(messages.username)}
autoComplete='off'
autoCorrect='off'
autoCapitalize='off'
onChange={onInputChange}
value={params.email}
pattern='^[a-zA-Z\d_-]+'
icon={require('@phosphor-icons/core/regular/at.svg')}
onChange={onUsernameChange}
value={params.username}
required
/>
</FormGroup>
{domains && (
<FormGroup>
<Select onChange={onDomainChange} value={params.domain}>
{domains.map(({ id, domain }) => (
<option key={id} value={id}>
{domain}
</option>
))}
</Select>
</FormGroup>
)}
<Input
type='email'
name='email'
placeholder={intl.formatMessage(messages.email)}
autoComplete='off'
autoCorrect='off'
autoCapitalize='off'
onChange={onInputChange}
value={params.email}
required
/>
<Input
type='password'
name='password'
placeholder={intl.formatMessage(messages.password)}
autoComplete='off'
autoCorrect='off'
autoCapitalize='off'
onChange={onPasswordChange}
value={params.password}
required
/>
<FormGroup
errors={passwordMismatch ? [intl.formatMessage(messages.passwordMismatch)] : undefined}
>
<Input
type='password'
name='password'
placeholder={intl.formatMessage(messages.password)}
name='password_confirmation'
placeholder={intl.formatMessage(messages.confirm)}
autoComplete='off'
autoCorrect='off'
autoCapitalize='off'
onChange={onPasswordChange}
value={params.password}
onChange={onPasswordConfirmChange}
onBlur={onPasswordConfirmBlur}
value={passwordConfirmation}
required
/>
</FormGroup>
<FormGroup
errors={passwordMismatch ? [intl.formatMessage(messages.passwordMismatch)] : undefined}
>
<Input
type='password'
name='password_confirmation'
placeholder={intl.formatMessage(messages.confirm)}
autoComplete='off'
autoCorrect='off'
autoCapitalize='off'
onChange={onPasswordConfirmChange}
onBlur={onPasswordConfirmBlur}
value={passwordConfirmation}
required
/>
</FormGroup>
{birthdayRequired && (
<BirthdayInput
value={params.date_of_birth ?? ''}
onChange={onBirthdayChange}
required
/>
)}
{needsApproval && (
<FormGroup
labelText={
<FormattedMessage
id='registration.reason'
defaultMessage='Why do you want to join?'
/>
}
>
<Textarea
name='reason'
placeholder={intl.formatMessage(messages.reasonHint)}
maxLength={500}
onChange={onInputChange}
value={params.reason ?? ''}
autoGrow
required
/>
</FormGroup>
)}
<CaptchaField
onFetch={onFetchCaptcha}
onFetchFail={onFetchCaptchaFail}
onChange={onInputChange}
onClick={onCaptchaClick}
idempotencyKey={captchaIdempotencyKey}
name='captcha_solution'
value={params.captcha_solution ?? ''}
/>
{birthdayRequired && (
<BirthdayInput value={params.date_of_birth ?? ''} onChange={onBirthdayChange} required />
)}
{needsApproval && (
<FormGroup
labelText={
<FormattedMessage
id='registration.agreement'
defaultMessage='I agree to the {tos}.'
values={{
tos: (
<Link to='/about/{-$slug}' params={{ slug: 'tos' }} target='_blank'>
<FormattedMessage id='registration.tos' defaultMessage='Terms of Service' />
</Link>
),
}}
id='registration.reason'
defaultMessage='Why do you want to join?'
/>
}
>
<Checkbox
name='agreement'
onChange={onCheckboxChange}
checked={params.agreement}
<Textarea
name='reason'
placeholder={intl.formatMessage(messages.reasonHint)}
maxLength={500}
onChange={onInputChange}
value={params.reason ?? ''}
autoGrow
required
/>
</FormGroup>
)}
<FormActions>
<Button type='submit'>
<FormattedMessage id='registration.sign_up' defaultMessage='Sign up' />
</Button>
</FormActions>
</>
<CaptchaField
onFetch={onFetchCaptcha}
onFetchFail={onFetchCaptchaFail}
onChange={onInputChange}
onClick={onCaptchaClick}
idempotencyKey={captchaIdempotencyKey}
name='captcha_solution'
value={params.captcha_solution ?? ''}
/>
<FormGroup
labelText={
<FormattedMessage
id='registration.agreement'
defaultMessage='I agree to the {tos}.'
values={{
tos: (
<Link to='/about/{-$slug}' params={{ slug: 'tos' }} target='_blank'>
<FormattedMessage id='registration.tos' defaultMessage='Terms of Service' />
</Link>
),
}}
/>
}
>
<Checkbox
name='agreement'
onChange={onCheckboxChange}
checked={params.agreement}
required
/>
</FormGroup>
<FormActions>
<Button type='submit'>
<FormattedMessage id='registration.sign_up' defaultMessage='Sign up' />
</Button>
</FormActions>
</fieldset>
</Form>
);

View File

@ -75,20 +75,18 @@ const ChatListShoutbox: React.FC<IChatListShoutbox> = ({ onClick, onMoveUp, onMo
</div>
{lastMessage && (
<>
<p className='⁂-chat-list-item__message'>
{lastMessageAuthor && (
<span className='⁂-chat-list-item__message__author'>
<Emojify
text={lastMessageAuthor.display_name}
emojis={lastMessageAuthor.emojis}
/>
{': '}
</span>
)}
<ParsedContent html={lastMessage.text} />
</p>
</>
<p className='⁂-chat-list-item__message'>
{lastMessageAuthor && (
<span className='⁂-chat-list-item__message__author'>
<Emojify
text={lastMessageAuthor.display_name}
emojis={lastMessageAuthor.emojis}
/>
{': '}
</span>
)}
<ParsedContent html={lastMessage.text} />
</p>
)}
</div>
</div>

View File

@ -289,92 +289,87 @@ const ImageComponent = ({
return (
<Suspense fallback={null}>
<>
<div
className='relative'
draggable={draggable}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
onClick={handleClick}
role='button'
>
<HStack className='absolute right-2 top-2 z-10' space={2}>
<IconButton
onClick={previewImage}
src={require('@phosphor-icons/core/regular/magnifying-glass-plus.svg')}
theme='dark'
className='!p-1.5 hover:scale-105 hover:bg-gray-900'
iconClassName='h-5 w-5'
title={intl.formatMessage(messages.preview)}
/>
<IconButton
onClick={deleteNode}
src={require('@phosphor-icons/core/regular/x.svg')}
theme='dark'
className='!p-1.5 hover:scale-105 hover:bg-gray-900'
iconClassName='h-5 w-5'
title={intl.formatMessage(messages.delete)}
/>
</HStack>
<div
className='relative'
draggable={draggable}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
onClick={handleClick}
role='button'
>
<HStack className='absolute right-2 top-2 z-10' space={2}>
<IconButton
onClick={previewImage}
src={require('@phosphor-icons/core/regular/magnifying-glass-plus.svg')}
theme='dark'
className='!p-1.5 hover:scale-105 hover:bg-gray-900'
iconClassName='h-5 w-5'
title={intl.formatMessage(messages.preview)}
/>
<IconButton
onClick={deleteNode}
src={require('@phosphor-icons/core/regular/x.svg')}
theme='dark'
className='!p-1.5 hover:scale-105 hover:bg-gray-900'
iconClassName='h-5 w-5'
title={intl.formatMessage(messages.delete)}
/>
</HStack>
<div
<div
className={clsx(
'absolute inset-x-0 bottom-0 z-[2px] bg-gradient-to-b from-transparent via-gray-900/50 to-gray-900/80 p-2.5 opacity-0 transition-opacity duration-100 ease-linear',
{
'opacity-100': active,
},
)}
>
<label>
<span className='sr-only'>
<FormattedMessage
id='upload_form.description'
defaultMessage='Describe for the visually impaired'
/>
</span>
<textarea
className='m-0 w-full rounded-md border border-solid border-white/25 bg-transparent p-2.5 text-sm text-white placeholder:text-white/60'
placeholder={intl.formatMessage(messages.description)}
value={description}
onFocus={handleInputFocus}
onChange={handleInputChange}
onBlur={handleInputBlur}
onKeyDown={handleKeyDown}
/>
</label>
</div>
{missingDescriptionModal && !description && (
<span
title={intl.formatMessage(messages.descriptionMissingTitle)}
className={clsx(
'absolute inset-x-0 bottom-0 z-[2px] bg-gradient-to-b from-transparent via-gray-900/50 to-gray-900/80 p-2.5 opacity-0 transition-opacity duration-100 ease-linear',
'absolute bottom-2 left-2 z-10 inline-flex items-center gap-1 rounded bg-gray-900 px-2 py-1 text-xs font-medium uppercase text-white transition-opacity duration-100 ease-linear',
{
'opacity-100': active,
'pointer-events-none opacity-0': active,
'opacity-100': !active,
},
)}
>
<label>
<span className='sr-only'>
<FormattedMessage
id='upload_form.description'
defaultMessage='Describe for the visually impaired'
/>
</span>
<Icon className='size-4' src={require('@phosphor-icons/core/regular/warning.svg')} />
<FormattedMessage id='upload_form.description_missing.indicator' defaultMessage='Alt' />
</span>
)}
<textarea
className='m-0 w-full rounded-md border border-solid border-white/25 bg-transparent p-2.5 text-sm text-white placeholder:text-white/60'
placeholder={intl.formatMessage(messages.description)}
value={description}
onFocus={handleInputFocus}
onChange={handleInputChange}
onBlur={handleInputBlur}
onKeyDown={handleKeyDown}
/>
</label>
</div>
{missingDescriptionModal && !description && (
<span
title={intl.formatMessage(messages.descriptionMissingTitle)}
className={clsx(
'absolute bottom-2 left-2 z-10 inline-flex items-center gap-1 rounded bg-gray-900 px-2 py-1 text-xs font-medium uppercase text-white transition-opacity duration-100 ease-linear',
{
'pointer-events-none opacity-0': active,
'opacity-100': !active,
},
)}
>
<Icon className='size-4' src={require('@phosphor-icons/core/regular/warning.svg')} />
<FormattedMessage
id='upload_form.description_missing.indicator'
defaultMessage='Alt'
/>
</span>
)}
<LazyImage
className={clsx('mx-auto cursor-default', {
'select-none': isSelected,
'cursor-grab active:cursor-grabbing': isSelected && $isNodeSelection(selection),
})}
src={src}
altText={altText}
imageRef={imageRef}
/>
</div>
</>
<LazyImage
className={clsx('mx-auto cursor-default', {
'select-none': isSelected,
'cursor-grab active:cursor-grabbing': isSelected && $isNodeSelection(selection),
})}
src={src}
altText={altText}
imageRef={imageRef}
/>
</div>
</Suspense>
);
};

View File

@ -203,84 +203,82 @@ const BlockTypeDropdown = ({
};
return (
<>
<button
onClick={() => {
setShowDropDown(!showDropDown);
}}
className='relative flex cursor-pointer rounded-lg border-0 bg-none p-1 align-middle hover:bg-gray-100 disabled:cursor-not-allowed disabled:hover:bg-none dark:hover:bg-primary-700'
aria-label={intl.formatMessage(messages.blockType)}
type='button'
>
<Icon src={icon} />
<Icon
src={require('@phosphor-icons/core/regular/caret-down.svg')}
className='-bottom-2 size-4'
/>
{showDropDown && (
<div className='absolute left-0 top-9 z-10 flex h-[38px] gap-0.5 rounded-lg bg-white p-1 shadow-lg transition-opacity dark:bg-gray-900'>
<ToolbarButton
onClick={formatParagraph}
active={blockType === 'paragraph'}
icon={blockTypeToIcon.paragraph}
aria-label={intl.formatMessage(messages.paragraph)}
/>
{composeAllowHeadings && (
<>
<ToolbarButton
onClick={() => {
formatHeading('h1');
}}
active={blockType === 'h1'}
icon={blockTypeToIcon.h1}
aria-label={intl.formatMessage(messages.h1)}
/>
<ToolbarButton
onClick={() => {
formatHeading('h2');
}}
active={blockType === 'h2'}
icon={blockTypeToIcon.h2}
aria-label={intl.formatMessage(messages.h2)}
/>
<ToolbarButton
onClick={() => {
formatHeading('h3');
}}
active={blockType === 'h3'}
icon={blockTypeToIcon.h3}
aria-label={intl.formatMessage(messages.h3)}
/>
</>
)}
<ToolbarButton
onClick={formatBulletList}
active={blockType === 'bullet'}
icon={blockTypeToIcon.bullet}
aria-label={intl.formatMessage(messages.bulletList)}
/>
<ToolbarButton
onClick={formatNumberedList}
active={blockType === 'number'}
icon={blockTypeToIcon.number}
aria-label={intl.formatMessage(messages.numberedList)}
/>
<ToolbarButton
onClick={formatQuote}
active={blockType === 'quote'}
icon={blockTypeToIcon.quote}
aria-label={intl.formatMessage(messages.quote)}
/>
<ToolbarButton
onClick={formatCode}
active={blockType === 'code'}
icon={blockTypeToIcon.code}
aria-label={intl.formatMessage(messages.codeBlock)}
/>
</div>
)}
</button>
</>
<button
onClick={() => {
setShowDropDown(!showDropDown);
}}
className='relative flex cursor-pointer rounded-lg border-0 bg-none p-1 align-middle hover:bg-gray-100 disabled:cursor-not-allowed disabled:hover:bg-none dark:hover:bg-primary-700'
aria-label={intl.formatMessage(messages.blockType)}
type='button'
>
<Icon src={icon} />
<Icon
src={require('@phosphor-icons/core/regular/caret-down.svg')}
className='-bottom-2 size-4'
/>
{showDropDown && (
<div className='absolute left-0 top-9 z-10 flex h-[38px] gap-0.5 rounded-lg bg-white p-1 shadow-lg transition-opacity dark:bg-gray-900'>
<ToolbarButton
onClick={formatParagraph}
active={blockType === 'paragraph'}
icon={blockTypeToIcon.paragraph}
aria-label={intl.formatMessage(messages.paragraph)}
/>
{composeAllowHeadings && (
<>
<ToolbarButton
onClick={() => {
formatHeading('h1');
}}
active={blockType === 'h1'}
icon={blockTypeToIcon.h1}
aria-label={intl.formatMessage(messages.h1)}
/>
<ToolbarButton
onClick={() => {
formatHeading('h2');
}}
active={blockType === 'h2'}
icon={blockTypeToIcon.h2}
aria-label={intl.formatMessage(messages.h2)}
/>
<ToolbarButton
onClick={() => {
formatHeading('h3');
}}
active={blockType === 'h3'}
icon={blockTypeToIcon.h3}
aria-label={intl.formatMessage(messages.h3)}
/>
</>
)}
<ToolbarButton
onClick={formatBulletList}
active={blockType === 'bullet'}
icon={blockTypeToIcon.bullet}
aria-label={intl.formatMessage(messages.bulletList)}
/>
<ToolbarButton
onClick={formatNumberedList}
active={blockType === 'number'}
icon={blockTypeToIcon.number}
aria-label={intl.formatMessage(messages.numberedList)}
/>
<ToolbarButton
onClick={formatQuote}
active={blockType === 'quote'}
icon={blockTypeToIcon.quote}
aria-label={intl.formatMessage(messages.quote)}
/>
<ToolbarButton
onClick={formatCode}
active={blockType === 'code'}
icon={blockTypeToIcon.code}
aria-label={intl.formatMessage(messages.codeBlock)}
/>
</div>
)}
</button>
);
};

View File

@ -37,38 +37,36 @@ const GroupMembers: React.FC = () => {
);
return (
<>
<ScrollableList
scrollKey={`groupMembers:${groupId}`}
hasMore={hasNextPage}
onLoadMore={fetchNextPage}
isLoading={!group || isLoading}
showLoading={!group || ((isFetchingPending ?? isLoading) && members.length === 0)}
placeholderComponent={PlaceholderAccount}
placeholderCount={3}
className='⁂-status-list'
itemClassName='py-3 last:pb-0'
prepend={
membershipRequests.length > 0 && (
<div
className={clsx('py-3', {
'border-b border-gray-200 dark:border-gray-800': members.length,
})}
>
<PendingItemsRow
to='/groups/$groupId/manage/requests'
params={{ groupId }}
count={membershipRequests.length}
/>
</div>
)
}
>
{members.map((member) => (
<GroupMemberListItem group={group!} member={member} key={member.account_id} />
))}
</ScrollableList>
</>
<ScrollableList
scrollKey={`groupMembers:${groupId}`}
hasMore={hasNextPage}
onLoadMore={fetchNextPage}
isLoading={!group || isLoading}
showLoading={!group || ((isFetchingPending ?? isLoading) && members.length === 0)}
placeholderComponent={PlaceholderAccount}
placeholderCount={3}
className='⁂-status-list'
itemClassName='py-3 last:pb-0'
prepend={
membershipRequests.length > 0 && (
<div
className={clsx('py-3', {
'border-b border-gray-200 dark:border-gray-800': members.length,
})}
>
<PendingItemsRow
to='/groups/$groupId/manage/requests'
params={{ groupId }}
count={membershipRequests.length}
/>
</div>
)
}
>
{members.map((member) => (
<GroupMemberListItem group={group!} member={member} key={member.account_id} />
))}
</ScrollableList>
);
};

View File

@ -116,22 +116,20 @@ const SettingsPage = () => {
/>
)}
{features.manageMfa && (
<>
<ListItem
label={
<FormattedMessage id='settings.configure_mfa' defaultMessage='Configure MFA' />
}
to='/settings/mfa'
>
<span>
{isMfaEnabled ? (
<FormattedMessage id='mfa.enabled' defaultMessage='Enabled' />
) : (
<FormattedMessage id='mfa.disabled' defaultMessage='Disabled' />
)}
</span>
</ListItem>
</>
<ListItem
label={
<FormattedMessage id='settings.configure_mfa' defaultMessage='Configure MFA' />
}
to='/settings/mfa'
>
<span>
{isMfaEnabled ? (
<FormattedMessage id='mfa.enabled' defaultMessage='Enabled' />
) : (
<FormattedMessage id='mfa.disabled' defaultMessage='Disabled' />
)}
</span>
</ListItem>
)}
{features.sessions && (
<ListItem