Further reduce CSS and markup differences with upstream (#2635)

* Further reduce CSS differences with upstream

* Reduce differences in markup and CSS with upstream

* Redo collapsible post notifications

* Reduce CSS differences further

* Reduce differences with upstream regarding `.status` and `.status__wrapper`

* Further reduce differences with upstream

* Reduce differences with upstream in DisplayName
main-rebase-security-fix
Claire 2024-02-20 18:49:59 +01:00 committed by GitHub
parent 0a2b95c4f5
commit 5f50b634cf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 389 additions and 359 deletions

View File

@ -147,7 +147,7 @@ class Account extends ImmutablePureComponent {
</div> </div>
<div className='account__contents'> <div className='account__contents'>
<DisplayName account={account} inline /> <DisplayName account={account} />
{!minimal && ( {!minimal && (
<div className='account__details'> <div className='account__details'>
{account.get('followers_count') !== -1 && ( {account.get('followers_count') !== -1 && (

View File

@ -0,0 +1,45 @@
import PropTypes from 'prop-types';
import { useCallback } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import ExpandLessIcon from '@/material-icons/400-24px/expand_less.svg?react';
import { IconButton } from './icon_button';
const messages = defineMessages({
collapse: { id: 'status.collapse', defaultMessage: 'Collapse' },
uncollapse: { id: 'status.uncollapse', defaultMessage: 'Uncollapse' },
});
export const CollapseButton = ({ collapsed, setCollapsed }) => {
const intl = useIntl();
const handleCollapsedClick = useCallback((e) => {
if (e.button === 0) {
setCollapsed(!collapsed);
e.preventDefault();
}
}, [collapsed, setCollapsed]);
return (
<IconButton
className='status__collapse-button'
animate
active={collapsed}
title={
collapsed ?
intl.formatMessage(messages.uncollapse) :
intl.formatMessage(messages.collapse)
}
icon='angle-double-up'
iconComponent={ExpandLessIcon}
onClick={handleCollapsedClick}
/>
);
};
CollapseButton.propTypes = {
collapsed: PropTypes.bool,
setCollapsed: PropTypes.func.isRequired,
};

View File

@ -1,7 +1,5 @@
import React from 'react'; import React from 'react';
import classNames from 'classnames';
import type { List } from 'immutable'; import type { List } from 'immutable';
import type { Account } from 'flavours/glitch/models/account'; import type { Account } from 'flavours/glitch/models/account';
@ -14,7 +12,6 @@ interface Props {
account?: Account; account?: Account;
others?: List<Account>; others?: List<Account>;
localDomain?: string; localDomain?: string;
inline?: boolean;
} }
export class DisplayName extends React.PureComponent<Props> { export class DisplayName extends React.PureComponent<Props> {
@ -51,7 +48,7 @@ export class DisplayName extends React.PureComponent<Props> {
}; };
render() { render() {
const { others, localDomain, inline } = this.props; const { others, localDomain } = this.props;
let displayName: React.ReactNode, let displayName: React.ReactNode,
suffix: React.ReactNode, suffix: React.ReactNode,
@ -114,13 +111,11 @@ export class DisplayName extends React.PureComponent<Props> {
return ( return (
<span <span
className={classNames('display-name', { inline })} className='display-name'
onMouseEnter={this.handleMouseEnter} onMouseEnter={this.handleMouseEnter}
onMouseLeave={this.handleMouseLeave} onMouseLeave={this.handleMouseLeave}
> >
{displayName} {displayName} {suffix}
{inline ? ' ' : null}
{suffix}
</span> </span>
); );
} }

View File

@ -23,6 +23,7 @@ import { MediaGallery, Video, Audio } from '../features/ui/util/async-components
import { displayMedia } from '../initial_state'; import { displayMedia } from '../initial_state';
import AttachmentList from './attachment_list'; import AttachmentList from './attachment_list';
import { CollapseButton } from './collapse_button';
import { getHashtagBarForStatus } from './hashtag_bar'; import { getHashtagBarForStatus } from './hashtag_bar';
import StatusActionBar from './status_action_bar'; import StatusActionBar from './status_action_bar';
import StatusContent from './status_content'; import StatusContent from './status_content';
@ -510,7 +511,6 @@ class Status extends ImmutablePureComponent {
render () { render () {
const { const {
handleRef,
parseClick, parseClick,
setCollapsed, setCollapsed,
} = this; } = this;
@ -763,7 +763,13 @@ class Status extends ImmutablePureComponent {
account={account} account={account}
parseClick={parseClick} parseClick={parseClick}
notificationId={this.props.notificationId} notificationId={this.props.notificationId}
/> >
{muted && settings.getIn(['collapsed', 'enabled']) && (
<div className='notification__message-collapse-button'>
<CollapseButton collapsed={isCollapsed} setCollapsed={setCollapsed} />
</div>
)}
</StatusPrepend>
); );
} }
@ -771,85 +777,77 @@ class Status extends ImmutablePureComponent {
rebloggedByText = intl.formatMessage({ id: 'status.reblogged_by', defaultMessage: '{name} boosted' }, { name: account.get('acct') }); rebloggedByText = intl.formatMessage({ id: 'status.reblogged_by', defaultMessage: '{name} boosted' }, { name: account.get('acct') });
} }
const computedClass = classNames('status', `status-${status.get('visibility')}`, {
collapsed: isCollapsed,
'has-background': isCollapsed && background,
'status__wrapper-reply': !!status.get('in_reply_to_id'),
'status--in-thread': !!rootId,
'status--first-in-thread': previousId && (!connectUp || connectToRoot),
unread,
muted,
}, 'focusable');
const {statusContentProps, hashtagBar} = getHashtagBarForStatus(status); const {statusContentProps, hashtagBar} = getHashtagBarForStatus(status);
contentMedia.push(hashtagBar); contentMedia.push(hashtagBar);
return ( return (
<HotKeys handlers={handlers}> <HotKeys handlers={handlers}>
<div <div
className={computedClass} className={classNames('status__wrapper', 'focusable', `status__wrapper-${status.get('visibility')}`, { 'status__wrapper-reply': !!status.get('in_reply_to_id'), unread, collapsed: isCollapsed })}
style={isCollapsed && background ? { backgroundImage: `url(${background})` } : null}
{...selectorAttribs} {...selectorAttribs}
ref={handleRef}
tabIndex={0} tabIndex={0}
data-featured={featured ? 'true' : null} data-featured={featured ? 'true' : null}
aria-label={textForScreenReader(intl, status, rebloggedByText, !status.get('hidden'))} aria-label={textForScreenReader(intl, status, rebloggedByText, !status.get('hidden'))}
ref={this.handleRef}
data-nosnippet={status.getIn(['account', 'noindex'], true) || undefined} data-nosnippet={status.getIn(['account', 'noindex'], true) || undefined}
> >
{!muted && prepend} {prepend}
{(connectReply || connectUp || connectToRoot) && <div className={classNames('status__line', { 'status__line--full': connectReply, 'status__line--first': !status.get('in_reply_to_id') && !connectToRoot })} />} <div
className={classNames('status', `status-${status.get('visibility')}`, { 'status-reply': !!status.get('in_reply_to_id'), 'status--in-thread': !!rootId, 'status--first-in-thread': previousId && (!connectUp || connectToRoot), muted: this.props.muted, 'has-background': isCollapsed && background, collapsed: isCollapsed })}
data-id={status.get('id')}
style={isCollapsed && background ? { backgroundImage: `url(${background})` } : null}
>
{(connectReply || connectUp || connectToRoot) && <div className={classNames('status__line', { 'status__line--full': connectReply, 'status__line--first': !status.get('in_reply_to_id') && !connectToRoot })} />}
<header className='status__info'> {(!muted || !isCollapsed) && (
<span> <header className='status__info'>
{muted && prepend}
{!muted || !isCollapsed ? (
<StatusHeader <StatusHeader
status={status} status={status}
friend={account} friend={account}
collapsed={isCollapsed} collapsed={isCollapsed}
parseClick={parseClick} parseClick={parseClick}
/> />
) : null} <StatusIcons
</span> status={status}
<StatusIcons mediaIcons={contentMediaIcons.concat(extraMediaIcons)}
collapsible={!muted && settings.getIn(['collapsed', 'enabled'])}
collapsed={isCollapsed}
setCollapsed={setCollapsed}
settings={settings.get('status_icons')}
/>
</header>
)}
<StatusContent
status={status} status={status}
mediaIcons={contentMediaIcons.concat(extraMediaIcons)} media={contentMedia}
collapsible={settings.getIn(['collapsed', 'enabled'])} extraMedia={extraMedia}
collapsed={isCollapsed} mediaIcons={contentMediaIcons}
setCollapsed={setCollapsed} expanded={isExpanded}
settings={settings.get('status_icons')} onExpandedToggle={this.handleExpandedToggle}
onTranslate={this.handleTranslate}
parseClick={parseClick}
disabled={!history}
tagLinks={settings.get('tag_misleading_links')}
rewriteMentions={settings.get('rewrite_mentions')}
{...statusContentProps}
/> />
</header>
<StatusContent
status={status}
media={contentMedia}
extraMedia={extraMedia}
mediaIcons={contentMediaIcons}
expanded={isExpanded}
onExpandedToggle={this.handleExpandedToggle}
onTranslate={this.handleTranslate}
parseClick={parseClick}
disabled={!history}
tagLinks={settings.get('tag_misleading_links')}
rewriteMentions={settings.get('rewrite_mentions')}
{...statusContentProps}
/>
{!isCollapsed || !(muted || !settings.getIn(['collapsed', 'show_action_bar'])) ? ( {(!isCollapsed || !(muted || !settings.getIn(['collapsed', 'show_action_bar']))) && (
<StatusActionBar <StatusActionBar
status={status} status={status}
account={status.get('account')} account={status.get('account')}
showReplyCount={settings.get('show_reply_count')} showReplyCount={settings.get('show_reply_count')}
onFilter={matchedFilters ? this.handleFilterClick : null} onFilter={matchedFilters ? this.handleFilterClick : null}
{...other} {...other}
/> />
) : null} )}
{notification ? ( {notification && (
<NotificationOverlayContainer <NotificationOverlayContainer
notification={notification} notification={notification}
/> />
) : null} )}
</div>
</div> </div>
</HotKeys> </HotKeys>
); );

View File

@ -45,26 +45,19 @@ export default class StatusHeader extends PureComponent {
} }
return ( return (
<div className='status__info__account'> <a
<a href={account.get('url')}
href={account.get('url')} className='status__display-name'
target='_blank' target='_blank'
className='status__avatar' onClick={this.handleAccountClick}
onClick={this.handleAccountClick} rel='noopener noreferrer'
rel='noopener noreferrer' >
> <div className='status__avatar'>
{statusAvatar} {statusAvatar}
</a> </div>
<a
href={account.get('url')} <DisplayName account={account} />
target='_blank' </a>
className='status__display-name'
onClick={this.handleAccountClick}
rel='noopener noreferrer'
>
<DisplayName account={account} />
</a>
</div>
); );
} }

View File

@ -6,7 +6,6 @@ import { defineMessages, injectIntl } from 'react-intl';
import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePropTypes from 'react-immutable-proptypes';
import ExpandLessIcon from '@/material-icons/400-24px/expand_less.svg?react';
import ForumIcon from '@/material-icons/400-24px/forum.svg?react'; import ForumIcon from '@/material-icons/400-24px/forum.svg?react';
import HomeIcon from '@/material-icons/400-24px/home.svg?react'; import HomeIcon from '@/material-icons/400-24px/home.svg?react';
import ImageIcon from '@/material-icons/400-24px/image.svg?react'; import ImageIcon from '@/material-icons/400-24px/image.svg?react';
@ -17,8 +16,7 @@ import MusicNoteIcon from '@/material-icons/400-24px/music_note.svg?react';
import { Icon } from 'flavours/glitch/components/icon'; import { Icon } from 'flavours/glitch/components/icon';
import { languages } from 'flavours/glitch/initial_state'; import { languages } from 'flavours/glitch/initial_state';
import { CollapseButton } from './collapse_button';
import { IconButton } from './icon_button';
import { VisibilityIcon } from './visibility_icon'; import { VisibilityIcon } from './visibility_icon';
const messages = defineMessages({ const messages = defineMessages({
@ -118,6 +116,7 @@ class StatusIcons extends PureComponent {
mediaIcons, mediaIcons,
collapsible, collapsible,
collapsed, collapsed,
setCollapsed,
settings, settings,
intl, intl,
} = this.props; } = this.props;
@ -143,21 +142,7 @@ class StatusIcons extends PureComponent {
/>} />}
{settings.get('media') && !!mediaIcons && mediaIcons.map(icon => this.renderIcon(icon))} {settings.get('media') && !!mediaIcons && mediaIcons.map(icon => this.renderIcon(icon))}
{settings.get('visibility') && <VisibilityIcon visibility={status.get('visibility')} />} {settings.get('visibility') && <VisibilityIcon visibility={status.get('visibility')} />}
{collapsible && ( {collapsible && <CollapseButton collapsed={collapsed} setCollapsed={setCollapsed} />}
<IconButton
className='status__collapse-button'
animate
active={collapsed}
title={
collapsed ?
intl.formatMessage(messages.uncollapse) :
intl.formatMessage(messages.collapse)
}
icon='angle-double-up'
iconComponent={ExpandLessIcon}
onClick={this.handleCollapsedClick}
/>
)}
</div> </div>
); );
} }

View File

@ -23,6 +23,7 @@ export default class StatusPrepend extends PureComponent {
account: ImmutablePropTypes.map.isRequired, account: ImmutablePropTypes.map.isRequired,
parseClick: PropTypes.func.isRequired, parseClick: PropTypes.func.isRequired,
notificationId: PropTypes.number, notificationId: PropTypes.number,
children: PropTypes.node,
}; };
handleClick = (e) => { handleClick = (e) => {
@ -38,11 +39,13 @@ export default class StatusPrepend extends PureComponent {
href={account.get('url')} href={account.get('url')}
className='status__display-name' className='status__display-name'
> >
<b <bdi>
dangerouslySetInnerHTML={{ <strong
__html : account.get('display_name_html') || account.get('username'), dangerouslySetInnerHTML={{
}} __html : account.get('display_name_html') || account.get('username'),
/> }}
/>
</bdi>
</a> </a>
); );
switch (type) { switch (type) {
@ -112,7 +115,7 @@ export default class StatusPrepend extends PureComponent {
render () { render () {
const { Message } = this; const { Message } = this;
const { type } = this.props; const { type, children } = this.props;
let iconId, iconComponent; let iconId, iconComponent;
@ -146,14 +149,13 @@ export default class StatusPrepend extends PureComponent {
return !type ? null : ( return !type ? null : (
<aside className={type === 'reblogged_by' || type === 'featured' ? 'status__prepend' : 'notification__message'}> <aside className={type === 'reblogged_by' || type === 'featured' ? 'status__prepend' : 'notification__message'}>
<div className={type === 'reblogged_by' || type === 'featured' ? 'status__prepend-icon-wrapper' : 'notification__favourite-icon-wrapper'}> <Icon
<Icon className={`status__prepend-icon ${type === 'favourite' ? 'star-icon' : ''}`}
className={`status__prepend-icon ${type === 'favourite' ? 'star-icon' : ''}`} id={iconId}
id={iconId} icon={iconComponent}
icon={iconComponent} />
/>
</div>
<Message /> <Message />
{children}
</aside> </aside>
); );
} }

View File

@ -95,9 +95,7 @@ class AdminReport extends ImmutablePureComponent {
<HotKeys handlers={this.getHandlers()}> <HotKeys handlers={this.getHandlers()}>
<div className={classNames('notification notification-admin-report focusable', { unread })} tabIndex={0}> <div className={classNames('notification notification-admin-report focusable', { unread })} tabIndex={0}>
<div className='notification__message'> <div className='notification__message'>
<div className='notification__favourite-icon-wrapper'> <Icon id='flag' icon={FlagIcon} />
<Icon id='flag' icon={FlagIcon} />
</div>
<span title={notification.get('created_at')}> <span title={notification.get('created_at')}>
<FormattedMessage id='notification.admin.report' defaultMessage='{name} reported {target}' values={{ name: link, target: targetLink }} /> <FormattedMessage id='notification.admin.report' defaultMessage='{name} reported {target}' values={{ name: link, target: targetLink }} />

View File

@ -86,9 +86,7 @@ class NotificationAdminSignup extends ImmutablePureComponent {
<HotKeys handlers={this.getHandlers()}> <HotKeys handlers={this.getHandlers()}>
<div className={classNames('notification notification-admin-sign-up focusable', { unread })} tabIndex={0}> <div className={classNames('notification notification-admin-sign-up focusable', { unread })} tabIndex={0}>
<div className='notification__message'> <div className='notification__message'>
<div className='notification__favourite-icon-wrapper'> <Icon id='user-plus' icon={PersonAddIcon} />
<Icon id='user-plus' icon={PersonAddIcon} />
</div>
<FormattedMessage <FormattedMessage
id='notification.admin.sign_up' id='notification.admin.sign_up'

View File

@ -86,9 +86,7 @@ class NotificationFollow extends ImmutablePureComponent {
<HotKeys handlers={this.getHandlers()}> <HotKeys handlers={this.getHandlers()}>
<div className={classNames('notification notification-follow focusable', { unread })} tabIndex={0}> <div className={classNames('notification notification-follow focusable', { unread })} tabIndex={0}>
<div className='notification__message'> <div className='notification__message'>
<div className='notification__favourite-icon-wrapper'> <Icon id='user-plus' icon={PersonAddIcon} />
<Icon id='user-plus' icon={PersonAddIcon} />
</div>
<FormattedMessage <FormattedMessage
id='notification.follow' id='notification.follow'

View File

@ -108,9 +108,7 @@ class FollowRequest extends ImmutablePureComponent {
<HotKeys handlers={this.getHandlers()}> <HotKeys handlers={this.getHandlers()}>
<div className={classNames('notification notification-follow-request focusable', { unread })} tabIndex={0}> <div className={classNames('notification notification-follow-request focusable', { unread })} tabIndex={0}>
<div className='notification__message'> <div className='notification__message'>
<div className='notification__favourite-icon-wrapper'> <Icon id='user' icon={PersonIcon} />
<Icon id='user' icon={PersonIcon} />
</div>
<FormattedMessage <FormattedMessage
id='notification.follow_request' id='notification.follow_request'

View File

@ -9,7 +9,6 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component'; import ImmutablePureComponent from 'react-immutable-pure-component';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import RepeatIcon from '@/material-icons/400-24px/repeat.svg?react'; import RepeatIcon from '@/material-icons/400-24px/repeat.svg?react';
import { changeBoostPrivacy } from 'flavours/glitch/actions/boosts'; import { changeBoostPrivacy } from 'flavours/glitch/actions/boosts';
import AttachmentList from 'flavours/glitch/components/attachment_list'; import AttachmentList from 'flavours/glitch/components/attachment_list';
@ -78,12 +77,11 @@ class BoostModal extends ImmutablePureComponent {
<div className='modal-root__modal boost-modal'> <div className='modal-root__modal boost-modal'>
<div className='boost-modal__container'> <div className='boost-modal__container'>
<div className={classNames('status', `status-${status.get('visibility')}`, 'light')}> <div className={classNames('status', `status-${status.get('visibility')}`, 'light')}>
<div className='boost-modal__status-header'> <div className='status__info'>
<div className='boost-modal__status-time'> <a href={status.get('url')} className='status__relative-time' target='_blank' rel='noopener noreferrer'>
<a href={status.get('url')} className='status__relative-time' target='_blank' rel='noopener noreferrer'> <span className='status__visibility-icon'><VisibilityIcon visibility={status.get('visibility')} /></span>
<VisibilityIcon visibility={status.get('visibility')} /> <RelativeTimestamp timestamp={status.get('created_at')} />
<RelativeTimestamp timestamp={status.get('created_at')} /></a> </a>
</div>
<a onClick={this.handleAccountClick} href={status.getIn(['account', 'url'])} className='status__display-name'> <a onClick={this.handleAccountClick} href={status.getIn(['account', 'url'])} className='status__display-name'>
<div className='status__avatar'> <div className='status__avatar'>

View File

@ -8,7 +8,6 @@ import { withRouter } from 'react-router-dom';
import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component'; import ImmutablePureComponent from 'react-immutable-pure-component';
import StarIcon from '@/material-icons/400-24px/star-fill.svg?react'; import StarIcon from '@/material-icons/400-24px/star-fill.svg?react';
import AttachmentList from 'flavours/glitch/components/attachment_list'; import AttachmentList from 'flavours/glitch/components/attachment_list';
import { Avatar } from 'flavours/glitch/components/avatar'; import { Avatar } from 'flavours/glitch/components/avatar';
@ -54,13 +53,11 @@ class FavouriteModal extends ImmutablePureComponent {
<div className='modal-root__modal boost-modal'> <div className='modal-root__modal boost-modal'>
<div className='boost-modal__container'> <div className='boost-modal__container'>
<div className={classNames('status', `status-${status.get('visibility')}`, 'light')}> <div className={classNames('status', `status-${status.get('visibility')}`, 'light')}>
<div className='boost-modal__status-header'> <div className='status__info'>
<div className='boost-modal__status-time'> <a href={status.get('url')} className='status__relative-time' target='_blank' rel='noopener noreferrer'>
<a href={status.get('url')} className='status__relative-time' target='_blank' rel='noopener noreferrer'> <span className='status__visibility-icon'><VisibilityIcon visibility={status.get('visibility')} /></span>
<VisibilityIcon visibility={status.get('visibility')} /> <RelativeTimestamp timestamp={status.get('created_at')} />
<RelativeTimestamp timestamp={status.get('created_at')} /> </a>
</a>
</div>
<a onClick={this.handleAccountClick} href={status.getIn(['account', 'url'])} className='status__display-name'> <a onClick={this.handleAccountClick} href={status.getIn(['account', 'url'])} className='status__display-name'>
<div className='status__avatar'> <div className='status__avatar'>
@ -68,7 +65,6 @@ class FavouriteModal extends ImmutablePureComponent {
</div> </div>
<DisplayName account={status.get('account')} /> <DisplayName account={status.get('account')} />
</a> </a>
</div> </div>

View File

@ -412,7 +412,7 @@ body > [data-popper-placement] {
.compose-form__warning { .compose-form__warning {
color: $inverted-text-color; color: $inverted-text-color;
margin-bottom: 15px; margin-bottom: 10px;
background: $ui-primary-color; background: $ui-primary-color;
box-shadow: 0 2px 6px rgba($base-shadow-color, 0.3); box-shadow: 0 2px 6px rgba($base-shadow-color, 0.3);
padding: 8px 10px; padding: 8px 10px;
@ -1033,8 +1033,7 @@ body > [data-popper-placement] {
.status { .status {
padding: 10px 14px; padding: 10px 14px;
position: relative; min-height: 54px;
height: auto;
border-bottom: 1px solid lighten($ui-base-color, 8%); border-bottom: 1px solid lighten($ui-base-color, 8%);
cursor: auto; cursor: auto;
@ -1090,17 +1089,69 @@ body > [data-popper-placement] {
color: $primary-text-color; color: $primary-text-color;
background: $ui-primary-color; background: $ui-primary-color;
&:hover { &:hover,
&:focus {
background: lighten($ui-primary-color, 8%); background: lighten($ui-primary-color, 8%);
} }
} }
} }
} }
&--in-thread {
$thread-margin: 46px + 10px;
border-bottom: 0;
.status__content,
.status__action-bar {
margin-inline-start: $thread-margin;
width: calc(100% - ($thread-margin));
}
}
&--first-in-thread {
border-top: 1px solid lighten($ui-base-color, 8%);
}
&__line {
height: 10px - 4px;
border-inline-start: 2px solid lighten($ui-base-color, 8%);
width: 0;
position: absolute;
top: 0;
inset-inline-start: 14px + ((46px - 2px) * 0.5);
&--full {
top: 0;
height: 100%;
&::before {
content: '';
display: block;
position: absolute;
top: 10px - 4px;
height: 46px + 4px + 4px;
width: 2px;
background: $ui-base-color;
inset-inline-start: -2px;
}
}
&--first {
top: 10px + 46px + 4px;
height: calc(100% - (10px + 46px + 4px));
&::before {
display: none;
}
}
}
&.collapsed { &.collapsed {
background-position: center; background-position: center;
background-size: cover; background-size: cover;
user-select: none; user-select: none;
min-height: 0;
&.has-background::before { &.has-background::before {
display: block; display: block;
@ -1161,25 +1212,30 @@ body > [data-popper-placement] {
rgba(mix($ui-base-color, $ui-highlight-color, 95%), 1) rgba(mix($ui-base-color, $ui-highlight-color, 95%), 1)
); );
} }
.notification__message {
margin-bottom: 0;
}
.status__info .notification__message > span {
white-space: nowrap;
}
} }
}
.status__wrapper.collapsed {
.notification__message { .notification__message {
margin: -10px 0 10px; margin-bottom: 0;
white-space: nowrap;
}
}
.notification__message-collapse-button {
text-align: end;
flex-grow: 2;
.status__collapse-button .icon {
width: 24px;
height: 24px;
} }
} }
.status__relative-time { .status__relative-time {
display: inline-block; display: block;
color: $dark-text-color;
font-size: 14px; font-size: 14px;
color: $dark-text-color;
text-align: end; text-align: end;
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
@ -1198,24 +1254,37 @@ body > [data-popper-placement] {
overflow: hidden; overflow: hidden;
} }
.status__info__account .status__display-name { .status__info .status__display-name {
display: block;
max-width: 100%; max-width: 100%;
display: flex;
font-size: 15px;
line-height: 22px;
align-items: center;
gap: 10px;
overflow: hidden;
.display-name {
bdi {
overflow: hidden;
text-overflow: ellipsis;
}
&__account {
white-space: nowrap;
display: block;
overflow: hidden;
text-overflow: ellipsis;
}
}
} }
.status__info { .status__info {
font-size: 15px;
padding-bottom: 10px;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
font-size: 15px; gap: 10px;
cursor: pointer;
> span {
text-overflow: ellipsis;
overflow: hidden;
}
.notification__message > span {
word-wrap: break-word;
}
} }
.status__info__icons { .status__info__icons {
@ -1223,23 +1292,21 @@ body > [data-popper-placement] {
align-items: center; align-items: center;
height: 1em; height: 1em;
color: $action-button-color; color: $action-button-color;
gap: 4px;
.status__media-icon,
.status__visibility-icon,
.status__reply-icon,
.text-icon {
padding-inline-start: 2px;
padding-inline-end: 2px;
}
& > .icon { & > .icon {
width: 16px; width: 16px;
height: 16px; height: 16px;
} }
}
.status__collapse-button.active > .icon { .status__collapse-button {
transform: rotate(-180deg); // compensate for large padding built into the icon
} margin: -4px;
}
.status__collapse-button.active > .icon {
transform: rotate(-180deg);
} }
.no-reduce-motion .status__collapse-button { .no-reduce-motion .status__collapse-button {
@ -1256,12 +1323,6 @@ body > [data-popper-placement] {
} }
} }
.status__info__account {
display: flex;
align-items: center;
justify-content: flex-start;
}
.status-check-box__status { .status-check-box__status {
display: block; display: block;
box-sizing: border-box; box-sizing: border-box;
@ -1298,6 +1359,8 @@ body > [data-popper-placement] {
} }
.status__prepend { .status__prepend {
padding: 8px 14px; // intentionally reduced padding in glitch-soc
padding-bottom: 0;
display: inline-flex; display: inline-flex;
gap: 10px; gap: 10px;
font-size: 14px; font-size: 14px;
@ -1317,14 +1380,14 @@ body > [data-popper-placement] {
} }
.status__action-bar { .status__action-bar {
align-items: center;
display: flex; display: flex;
align-items: center;
gap: 18px; gap: 18px;
margin-top: 8px; margin-top: 8px;
}
.status__action-bar-spacer { &-spacer {
flex-grow: 1; flex-grow: 1;
}
} }
.detailed-status__action-bar-dropdown { .detailed-status__action-bar-dropdown {
@ -1375,7 +1438,7 @@ body > [data-popper-placement] {
} }
.detailed-status__meta { .detailed-status__meta {
margin-top: 15px; margin-top: 16px;
color: $dark-text-color; color: $dark-text-color;
font-size: 14px; font-size: 14px;
line-height: 18px; line-height: 18px;
@ -1418,11 +1481,6 @@ body > [data-popper-placement] {
} }
} }
.notification__favourite-icon-wrapper {
inset-inline-start: 0;
position: absolute;
}
.detailed-status__link { .detailed-status__link {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
@ -1656,10 +1714,10 @@ a .account__avatar {
} }
} }
a.status__display-name, .status__display-name,
.reply-indicator__display-name, .reply-indicator__display-name,
.detailed-status__display-name, .detailed-status__display-name,
.account__display-name { a.account__display-name {
&:hover .display-name strong { &:hover .display-name strong {
text-decoration: underline; text-decoration: underline;
} }
@ -1698,15 +1756,9 @@ a.status__display-name,
} }
} }
.status__relative-time,
.detailed-status__datetime {
&:hover {
text-decoration: underline;
}
}
.status__avatar { .status__avatar {
margin-inline-end: 10px; width: 46px;
height: 46px;
} }
.muted { .muted {
@ -1738,41 +1790,53 @@ a.status__display-name,
} }
.notification__report { .notification__report {
padding: 8px 10px; padding: 10px; // deliberate glitch-soc change
padding-inline-start: 68px;
position: relative;
border-bottom: 1px solid lighten($ui-base-color, 8%); border-bottom: 1px solid lighten($ui-base-color, 8%);
min-height: 54px; display: flex;
gap: 10px;
&__avatar { &__avatar {
position: absolute; flex: 0 0 auto;
inset-inline-start: 10px;
top: 10px;
} }
&__details { &__details {
flex: 1 1 auto;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
color: $darker-text-color; color: $darker-text-color;
gap: 10px;
font-size: 15px; font-size: 15px;
line-height: 22px; line-height: 22px;
white-space: nowrap;
overflow: hidden;
& > div {
overflow: hidden;
text-overflow: ellipsis;
}
strong { strong {
font-weight: 500; font-weight: 500;
} }
} }
&__actions {
flex: 0 0 auto;
}
} }
.notification__message { .notification__message {
margin-inline-start: 42px; padding: 8px 14px 0; // padding intentionally reduced for glitch-soc
padding-top: 8px;
padding-inline-start: 26px;
cursor: default; cursor: default;
color: $darker-text-color; color: $darker-text-color;
font-size: 15px; font-size: 15px;
position: relative;
// line-height: 22px; omitted in glitch-soc for space saving
font-weight: 500;
display: flex;
align-items: center; align-items: center;
gap: 10px;
.icon { .icon {
color: $highlight-text-color; color: $highlight-text-color;
@ -1785,7 +1849,7 @@ a.status__display-name,
} }
> span { > span {
display: block; display: inline;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
} }
@ -1837,53 +1901,17 @@ a.status__display-name,
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden; overflow: hidden;
} }
a {
color: inherit;
text-decoration: inherit;
}
strong {
display: block;
}
> a:hover {
strong {
text-decoration: underline;
}
}
&.inline {
padding: 0;
height: 18px;
font-size: 15px;
line-height: 18px;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
strong {
display: inline;
height: auto;
font-size: inherit;
line-height: inherit;
}
span {
display: inline;
height: auto;
font-size: inherit;
line-height: inherit;
}
}
} }
.display-name__html { .display-name__html {
font-weight: 500; font-weight: 500;
} }
.display-name__account { .status__relative-time,
font-size: 14px; .detailed-status__datetime {
&:hover {
text-decoration: underline;
}
} }
.image-loader { .image-loader {
@ -3730,59 +3758,6 @@ a.status-card {
width: 100%; width: 100%;
} }
.notification,
.status {
position: relative;
&--in-thread {
border-bottom: 0;
.status__content,
.status__action-bar {
margin-inline-start: 46px + 10px;
width: calc(100% - (46px + 10px));
}
}
&--first-in-thread {
border-top: 1px solid lighten($ui-base-color, 8%);
}
&__line {
height: 10px - 4px;
border-inline-start: 2px solid lighten($ui-base-color, 8%);
width: 0;
position: absolute;
top: 0;
inset-inline-start: 14px + ((46px - 2px) * 0.5);
&--full {
top: 0;
height: 100%;
&::before {
content: '';
display: block;
position: absolute;
top: 10px - 4px;
height: 46px + 4px + 4px;
width: 2px;
background: $ui-base-color;
inset-inline-start: -2px;
}
}
&--first {
top: 10px + 46px + 4px;
height: calc(100% - (10px + 46px + 4px));
&::before {
display: none;
}
}
}
}
.load-more { .load-more {
display: block; display: block;
color: $dark-text-color; color: $dark-text-color;
@ -3929,6 +3904,7 @@ a.status-card {
margin: 0; margin: 0;
border: 0; border: 0;
padding: 13px; padding: 13px;
padding-inline-end: 0;
color: inherit; color: inherit;
background: transparent; background: transparent;
font: inherit; font: inherit;
@ -3963,7 +3939,6 @@ a.status-card {
.column-header__buttons { .column-header__buttons {
height: 48px; height: 48px;
display: flex; display: flex;
margin-inline-start: 0;
} }
.column-header__links { .column-header__links {
@ -5073,6 +5048,12 @@ a.status-card {
font-weight: 500; font-weight: 500;
display: block; display: block;
color: $inverted-text-color; color: $inverted-text-color;
@each $lang in $cjk-langs {
&:lang(#{$lang}) {
font-weight: 700;
}
}
} }
} }
@ -5109,12 +5090,6 @@ a.status-card {
strong { strong {
font-weight: 500; font-weight: 500;
@each $lang in $cjk-langs {
&:lang(#{$lang}) {
font-weight: 700;
}
}
} }
a { a {
@ -5270,7 +5245,6 @@ a.status-card {
.status__content { .status__content {
position: relative; position: relative;
margin: 10px 0;
font-size: 15px; font-size: 15px;
line-height: 20px; line-height: 20px;
word-wrap: break-word; word-wrap: break-word;
@ -6092,27 +6066,7 @@ a.status-card {
flex-direction: column; flex-direction: column;
.status__relative-time { .status__relative-time {
color: $dark-text-color; order: 2;
float: right;
font-size: 14px;
width: auto;
margin: initial;
padding: initial;
}
.status__visibility-icon {
color: $dark-text-color;
font-size: 14px;
padding: 0 4px;
}
.status__display-name {
display: flex;
}
.status__avatar {
height: 48px;
width: 48px;
} }
.status__content__spoiler-link { .status__content__spoiler-link {
@ -6161,15 +6115,6 @@ a.status-card {
} }
} }
.boost-modal__status-header {
font-size: 15px;
}
.boost-modal__status-time {
float: right;
font-size: 14px;
}
.mute-modal, .mute-modal,
.block-modal { .block-modal {
line-height: 24px; line-height: 24px;
@ -7462,11 +7407,8 @@ img.modal-warning {
.notification__filter-bar, .notification__filter-bar,
.account__section-headline { .account__section-headline {
background: darken( // deliberate glitch-soc choice for now
$ui-base-color, background: darken($ui-base-color, 4%);
4%
); // deliberate glitch-soc choice for now
border-bottom: 1px solid lighten($ui-base-color, 8%); border-bottom: 1px solid lighten($ui-base-color, 8%);
cursor: default; cursor: default;
display: flex; display: flex;
@ -7605,6 +7547,90 @@ noscript {
} }
} }
@media screen and (width <= 630px) and (height <= 400px) {
$duration: 400ms;
$delay: 100ms;
.search {
will-change: margin-top;
transition: margin-top $duration $delay;
}
.navigation-bar {
will-change: padding-bottom;
transition: padding-bottom $duration $delay;
}
.navigation-bar {
& > a:first-child {
will-change: margin-top, margin-inline-start, margin-inline-end, width;
transition:
margin-top $duration $delay,
margin-inline-start $duration ($duration + $delay),
margin-inline-end $duration ($duration + $delay);
}
& > .navigation-bar__profile-edit {
will-change: margin-top;
transition: margin-top $duration $delay;
}
.navigation-bar__actions {
& > .icon-button.close {
will-change: opacity transform;
transition:
opacity $duration * 0.5 $delay,
transform $duration $delay;
}
& > .compose__action-bar .icon-button {
will-change: opacity transform;
transition:
opacity $duration * 0.5 $delay + $duration * 0.5,
transform $duration $delay;
}
}
}
.is-composing {
.search {
margin-top: -50px;
}
.navigation-bar {
padding-bottom: 0;
& > a:first-child {
margin: -100px 10px 0 -50px;
}
.navigation-bar__profile {
padding-top: 2px;
}
.navigation-bar__profile-edit {
position: absolute;
margin-top: -60px;
}
.navigation-bar__actions {
.icon-button.close {
pointer-events: auto;
opacity: 1;
transform: scale(1, 1) translate(0, 0);
bottom: 5px;
}
.compose__action-bar .icon-button {
pointer-events: none;
opacity: 0;
transform: scale(0, 1) translate(100%, 0);
}
}
}
}
}
.embed-modal { .embed-modal {
width: auto; width: auto;
max-width: 80vw; max-width: 80vw;
@ -8682,7 +8708,7 @@ noscript {
} }
.notification, .notification,
.status { .status__wrapper {
position: relative; position: relative;
&.unread { &.unread {