Change appearance of account cards in web UI (#17689)
* Change appearance of account cards in web UI * Various fixes and improvements * Various fixes and improvements
This commit is contained in:
parent
292c75aa31
commit
dba4be1038
10 changed files with 178 additions and 347 deletions
|
@ -7,31 +7,28 @@ import { makeGetAccount } from 'mastodon/selectors';
|
||||||
import Avatar from 'mastodon/components/avatar';
|
import Avatar from 'mastodon/components/avatar';
|
||||||
import DisplayName from 'mastodon/components/display_name';
|
import DisplayName from 'mastodon/components/display_name';
|
||||||
import Permalink from 'mastodon/components/permalink';
|
import Permalink from 'mastodon/components/permalink';
|
||||||
import RelativeTimestamp from 'mastodon/components/relative_timestamp';
|
import Button from 'mastodon/components/button';
|
||||||
import IconButton from 'mastodon/components/icon_button';
|
|
||||||
import { FormattedMessage, injectIntl, defineMessages } from 'react-intl';
|
import { FormattedMessage, injectIntl, defineMessages } from 'react-intl';
|
||||||
import { autoPlayGif, me, unfollowModal } from 'mastodon/initial_state';
|
import { autoPlayGif, me, unfollowModal } from 'mastodon/initial_state';
|
||||||
import ShortNumber from 'mastodon/components/short_number';
|
import ShortNumber from 'mastodon/components/short_number';
|
||||||
import {
|
import {
|
||||||
followAccount,
|
followAccount,
|
||||||
unfollowAccount,
|
unfollowAccount,
|
||||||
blockAccount,
|
|
||||||
unblockAccount,
|
unblockAccount,
|
||||||
unmuteAccount,
|
unmuteAccount,
|
||||||
} from 'mastodon/actions/accounts';
|
} from 'mastodon/actions/accounts';
|
||||||
import { openModal } from 'mastodon/actions/modal';
|
import { openModal } from 'mastodon/actions/modal';
|
||||||
import { initMuteModal } from 'mastodon/actions/mutes';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
follow: { id: 'account.follow', defaultMessage: 'Follow' },
|
|
||||||
unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' },
|
unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' },
|
||||||
requested: { id: 'account.requested', defaultMessage: 'Awaiting approval' },
|
follow: { id: 'account.follow', defaultMessage: 'Follow' },
|
||||||
unblock: { id: 'account.unblock', defaultMessage: 'Unblock @{name}' },
|
cancel_follow_request: { id: 'account.cancel_follow_request', defaultMessage: 'Cancel follow request' },
|
||||||
unmute: { id: 'account.unmute', defaultMessage: 'Unmute @{name}' },
|
requested: { id: 'account.requested', defaultMessage: 'Awaiting approval. Click to cancel follow request' },
|
||||||
unfollowConfirm: {
|
unblock: { id: 'account.unblock_short', defaultMessage: 'Unblock' },
|
||||||
id: 'confirmations.unfollow.confirm',
|
unmute: { id: 'account.unmute_short', defaultMessage: 'Unmute' },
|
||||||
defaultMessage: 'Unfollow',
|
unfollowConfirm: { id: 'confirmations.unfollow.confirm', defaultMessage: 'Unfollow' },
|
||||||
},
|
edit_profile: { id: 'account.edit_profile', defaultMessage: 'Edit profile' },
|
||||||
});
|
});
|
||||||
|
|
||||||
const makeMapStateToProps = () => {
|
const makeMapStateToProps = () => {
|
||||||
|
@ -75,18 +72,15 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
|
||||||
onBlock(account) {
|
onBlock(account) {
|
||||||
if (account.getIn(['relationship', 'blocking'])) {
|
if (account.getIn(['relationship', 'blocking'])) {
|
||||||
dispatch(unblockAccount(account.get('id')));
|
dispatch(unblockAccount(account.get('id')));
|
||||||
} else {
|
|
||||||
dispatch(blockAccount(account.get('id')));
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onMute(account) {
|
onMute(account) {
|
||||||
if (account.getIn(['relationship', 'muting'])) {
|
if (account.getIn(['relationship', 'muting'])) {
|
||||||
dispatch(unmuteAccount(account.get('id')));
|
dispatch(unmuteAccount(account.get('id')));
|
||||||
} else {
|
|
||||||
dispatch(initMuteModal(account));
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export default
|
export default
|
||||||
|
@ -138,130 +132,92 @@ class AccountCard extends ImmutablePureComponent {
|
||||||
|
|
||||||
handleMute = () => {
|
handleMute = () => {
|
||||||
this.props.onMute(this.props.account);
|
this.props.onMute(this.props.account);
|
||||||
};
|
}
|
||||||
|
|
||||||
|
handleEditProfile = () => {
|
||||||
|
window.open('/settings/profile', '_blank');
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { account, intl } = this.props;
|
const { account, intl } = this.props;
|
||||||
|
|
||||||
let buttons;
|
let actionBtn;
|
||||||
|
|
||||||
if (
|
if (me !== account.get('id')) {
|
||||||
account.get('id') !== me &&
|
if (!account.get('relationship')) { // Wait until the relationship is loaded
|
||||||
account.get('relationship', null) !== null
|
actionBtn = '';
|
||||||
) {
|
} else if (account.getIn(['relationship', 'requested'])) {
|
||||||
const following = account.getIn(['relationship', 'following']);
|
actionBtn = <Button className={classNames('logo-button')} text={intl.formatMessage(messages.cancel_follow_request)} title={intl.formatMessage(messages.requested)} onClick={this.handleFollow} />;
|
||||||
const requested = account.getIn(['relationship', 'requested']);
|
} else if (account.getIn(['relationship', 'muting'])) {
|
||||||
const blocking = account.getIn(['relationship', 'blocking']);
|
actionBtn = <Button className='logo-button' text={intl.formatMessage(messages.unmute)} onClick={this.handleMute} />;
|
||||||
const muting = account.getIn(['relationship', 'muting']);
|
} else if (!account.getIn(['relationship', 'blocking'])) {
|
||||||
|
actionBtn = <Button disabled={account.getIn(['relationship', 'blocked_by'])} className={classNames('logo-button', { 'button--destructive': account.getIn(['relationship', 'following']) })} text={intl.formatMessage(account.getIn(['relationship', 'following']) ? messages.unfollow : messages.follow)} onClick={this.handleFollow} />;
|
||||||
if (requested) {
|
} else if (account.getIn(['relationship', 'blocking'])) {
|
||||||
buttons = (
|
actionBtn = <Button className='logo-button' text={intl.formatMessage(messages.unblock)} onClick={this.handleBlock} />;
|
||||||
<IconButton
|
|
||||||
disabled
|
|
||||||
icon='hourglass'
|
|
||||||
title={intl.formatMessage(messages.requested)}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
} else if (blocking) {
|
|
||||||
buttons = (
|
|
||||||
<IconButton
|
|
||||||
active
|
|
||||||
icon='unlock'
|
|
||||||
title={intl.formatMessage(messages.unblock, {
|
|
||||||
name: account.get('username'),
|
|
||||||
})}
|
|
||||||
onClick={this.handleBlock}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
} else if (muting) {
|
|
||||||
buttons = (
|
|
||||||
<IconButton
|
|
||||||
active
|
|
||||||
icon='volume-up'
|
|
||||||
title={intl.formatMessage(messages.unmute, {
|
|
||||||
name: account.get('username'),
|
|
||||||
})}
|
|
||||||
onClick={this.handleMute}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
} else if (!account.get('moved') || following) {
|
|
||||||
buttons = (
|
|
||||||
<IconButton
|
|
||||||
icon={following ? 'user-times' : 'user-plus'}
|
|
||||||
title={intl.formatMessage(
|
|
||||||
following ? messages.unfollow : messages.follow,
|
|
||||||
)}
|
|
||||||
onClick={this.handleFollow}
|
|
||||||
active={following}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
actionBtn = <Button className='logo-button' text={intl.formatMessage(messages.edit_profile)} onClick={this.handleEditProfile} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='directory__card'>
|
<div className='account-card'>
|
||||||
<div className='directory__card__img'>
|
<Permalink href={account.get('url')} to={`/@${account.get('acct')}`} className='account-card__permalink'>
|
||||||
<img
|
<div className='account-card__header'>
|
||||||
src={
|
<img
|
||||||
autoPlayGif ? account.get('header') : account.get('header_static')
|
src={
|
||||||
}
|
autoPlayGif ? account.get('header') : account.get('header_static')
|
||||||
alt=''
|
}
|
||||||
/>
|
alt=''
|
||||||
</div>
|
/>
|
||||||
|
|
||||||
<div className='directory__card__bar'>
|
|
||||||
<Permalink
|
|
||||||
className='directory__card__bar__name'
|
|
||||||
href={account.get('url')}
|
|
||||||
to={`/@${account.get('acct')}`}
|
|
||||||
>
|
|
||||||
<Avatar account={account} size={48} />
|
|
||||||
<DisplayName account={account} />
|
|
||||||
</Permalink>
|
|
||||||
|
|
||||||
<div className='directory__card__bar__relationship account__relationship'>
|
|
||||||
{buttons}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className='directory__card__extra' onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave}>
|
<div className='account-card__title'>
|
||||||
|
<div className='account-card__title__avatar'><Avatar account={account} size={56} /></div>
|
||||||
|
<DisplayName account={account} />
|
||||||
|
</div>
|
||||||
|
</Permalink>
|
||||||
|
|
||||||
|
{account.get('note').length > 0 && (
|
||||||
<div
|
<div
|
||||||
className='account__header__content translate'
|
className='account-card__bio translate'
|
||||||
|
onMouseEnter={this.handleMouseEnter}
|
||||||
|
onMouseLeave={this.handleMouseLeave}
|
||||||
dangerouslySetInnerHTML={{ __html: account.get('note_emojified') }}
|
dangerouslySetInnerHTML={{ __html: account.get('note_emojified') }}
|
||||||
/>
|
/>
|
||||||
</div>
|
)}
|
||||||
|
|
||||||
<div className='directory__card__extra'>
|
<div className='account-card__actions'>
|
||||||
<div className='accounts-table__count'>
|
<div className='account-card__counters'>
|
||||||
<ShortNumber value={account.get('statuses_count')} />
|
<div className='account-card__counters__item'>
|
||||||
<small>
|
<ShortNumber value={account.get('statuses_count')} />
|
||||||
<FormattedMessage id='account.posts' defaultMessage='Toots' />
|
<small>
|
||||||
</small>
|
<FormattedMessage id='account.posts' defaultMessage='Toots' />
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='account-card__counters__item'>
|
||||||
|
<ShortNumber value={account.get('followers_count')} />{' '}
|
||||||
|
<small>
|
||||||
|
<FormattedMessage
|
||||||
|
id='account.followers'
|
||||||
|
defaultMessage='Followers'
|
||||||
|
/>
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='account-card__counters__item'>
|
||||||
|
<ShortNumber value={account.get('following_count')} />{' '}
|
||||||
|
<small>
|
||||||
|
<FormattedMessage
|
||||||
|
id='account.following'
|
||||||
|
defaultMessage='Following'
|
||||||
|
/>
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className='accounts-table__count'>
|
|
||||||
<ShortNumber value={account.get('followers_count')} />{' '}
|
<div className='account-card__actions__button'>
|
||||||
<small>
|
{actionBtn}
|
||||||
<FormattedMessage
|
|
||||||
id='account.followers'
|
|
||||||
defaultMessage='Followers'
|
|
||||||
/>
|
|
||||||
</small>
|
|
||||||
</div>
|
|
||||||
<div className='accounts-table__count'>
|
|
||||||
{account.get('last_status_at') === null ? (
|
|
||||||
<FormattedMessage
|
|
||||||
id='account.never_active'
|
|
||||||
defaultMessage='Never'
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<RelativeTimestamp timestamp={account.get('last_status_at')} />
|
|
||||||
)}{' '}
|
|
||||||
<small>
|
|
||||||
<FormattedMessage
|
|
||||||
id='account.last_status'
|
|
||||||
defaultMessage='Last active'
|
|
||||||
/>
|
|
||||||
</small>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -10,9 +10,9 @@ import { fetchDirectory, expandDirectory } from 'mastodon/actions/directory';
|
||||||
import { List as ImmutableList } from 'immutable';
|
import { List as ImmutableList } from 'immutable';
|
||||||
import AccountCard from './components/account_card';
|
import AccountCard from './components/account_card';
|
||||||
import RadioButton from 'mastodon/components/radio_button';
|
import RadioButton from 'mastodon/components/radio_button';
|
||||||
import classNames from 'classnames';
|
|
||||||
import LoadMore from 'mastodon/components/load_more';
|
import LoadMore from 'mastodon/components/load_more';
|
||||||
import ScrollContainer from 'mastodon/containers/scroll_container';
|
import ScrollContainer from 'mastodon/containers/scroll_container';
|
||||||
|
import LoadingIndicator from 'mastodon/components/loading_indicator';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
title: { id: 'column.directory', defaultMessage: 'Browse profiles' },
|
title: { id: 'column.directory', defaultMessage: 'Browse profiles' },
|
||||||
|
@ -129,7 +129,7 @@ class Directory extends React.PureComponent {
|
||||||
const pinned = !!columnId;
|
const pinned = !!columnId;
|
||||||
|
|
||||||
const scrollableArea = (
|
const scrollableArea = (
|
||||||
<div className='scrollable' style={{ background: 'transparent' }}>
|
<div className='scrollable'>
|
||||||
<div className='filter-form'>
|
<div className='filter-form'>
|
||||||
<div className='filter-form__column' role='group'>
|
<div className='filter-form__column' role='group'>
|
||||||
<RadioButton name='order' value='active' label={intl.formatMessage(messages.recentlyActive)} checked={order === 'active'} onChange={this.handleChangeOrder} />
|
<RadioButton name='order' value='active' label={intl.formatMessage(messages.recentlyActive)} checked={order === 'active'} onChange={this.handleChangeOrder} />
|
||||||
|
@ -142,8 +142,10 @@ class Directory extends React.PureComponent {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={classNames('directory__list', { loading: isLoading })}>
|
<div className='directory__list'>
|
||||||
{accountIds.map(accountId => <AccountCard id={accountId} key={accountId} />)}
|
{isLoading ? <LoadingIndicator /> : accountIds.map(accountId => (
|
||||||
|
<AccountCard id={accountId} key={accountId} />
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<LoadMore onClick={this.handleLoadMore} visible={!isLoading} />
|
<LoadMore onClick={this.handleLoadMore} visible={!isLoading} />
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import Account from 'mastodon/containers/account_container';
|
import AccountCard from 'mastodon/features/directory/components/account_card';
|
||||||
import LoadingIndicator from 'mastodon/components/loading_indicator';
|
import LoadingIndicator from 'mastodon/components/loading_indicator';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { fetchSuggestions } from 'mastodon/actions/suggestions';
|
import { fetchSuggestions } from 'mastodon/actions/suggestions';
|
||||||
|
@ -29,9 +29,9 @@ class Suggestions extends React.PureComponent {
|
||||||
const { isLoading, suggestions } = this.props;
|
const { isLoading, suggestions } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='explore__links'>
|
<div className='explore__suggestions'>
|
||||||
{isLoading ? (<LoadingIndicator />) : suggestions.map(suggestion => (
|
{isLoading ? <LoadingIndicator /> : suggestions.map(suggestion => (
|
||||||
<Account key={suggestion.get('account')} id={suggestion.get('account')} />
|
<AccountCard key={suggestion.get('account')} id={suggestion.get('account')} />
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -40,19 +40,11 @@ html {
|
||||||
background: lighten($ui-base-color, 12%);
|
background: lighten($ui-base-color, 12%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.filter-form,
|
.filter-form {
|
||||||
.directory__card__bar {
|
|
||||||
background: $white;
|
background: $white;
|
||||||
border-bottom: 1px solid lighten($ui-base-color, 8%);
|
border-bottom: 1px solid lighten($ui-base-color, 8%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.scrollable .directory__list {
|
|
||||||
width: calc(100% + 2px);
|
|
||||||
margin-left: -1px;
|
|
||||||
margin-right: -1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.directory__card,
|
|
||||||
.table-of-contents {
|
.table-of-contents {
|
||||||
border: 1px solid lighten($ui-base-color, 8%);
|
border: 1px solid lighten($ui-base-color, 8%);
|
||||||
}
|
}
|
||||||
|
@ -75,8 +67,7 @@ html {
|
||||||
.column-header__back-button,
|
.column-header__back-button,
|
||||||
.column-header__button,
|
.column-header__button,
|
||||||
.column-header__button.active,
|
.column-header__button.active,
|
||||||
.account__header__bar,
|
.account__header__bar {
|
||||||
.directory__card__extra {
|
|
||||||
background: $white;
|
background: $white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1220,6 +1220,11 @@ a.sparkline {
|
||||||
background: $ui-base-color;
|
background: $ui-base-color;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
|
|
||||||
|
&__permalink {
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
&__header {
|
&__header {
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
|
@ -1236,20 +1241,22 @@ a.sparkline {
|
||||||
}
|
}
|
||||||
|
|
||||||
&__title {
|
&__title {
|
||||||
margin-top: -25px;
|
margin-top: -(15px + 8px);
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-end;
|
align-items: flex-end;
|
||||||
|
|
||||||
&__avatar {
|
&__avatar {
|
||||||
padding: 15px;
|
padding: 14px;
|
||||||
|
|
||||||
img {
|
img,
|
||||||
|
.account__avatar {
|
||||||
display: block;
|
display: block;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
width: 56px;
|
width: 56px;
|
||||||
height: 56px;
|
height: 56px;
|
||||||
background: darken($ui-base-color, 8%);
|
background-color: darken($ui-base-color, 8%);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
|
border: 1px solid $ui-base-color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1257,30 +1264,34 @@ a.sparkline {
|
||||||
color: $darker-text-color;
|
color: $darker-text-color;
|
||||||
padding-bottom: 15px;
|
padding-bottom: 15px;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
|
line-height: 20px;
|
||||||
|
|
||||||
bdi {
|
bdi {
|
||||||
display: block;
|
display: block;
|
||||||
color: $primary-text-color;
|
color: $primary-text-color;
|
||||||
font-weight: 500;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__bio {
|
&__bio {
|
||||||
padding: 0 15px;
|
padding: 0 15px;
|
||||||
|
margin: 8px 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
max-height: 18px * 2;
|
max-height: 21px * 2;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 21px;
|
||||||
|
|
||||||
&::after {
|
&::after {
|
||||||
display: block;
|
display: block;
|
||||||
content: "";
|
content: "";
|
||||||
width: 50px;
|
width: 50px;
|
||||||
height: 18px;
|
height: 21px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 0;
|
bottom: 8px;
|
||||||
right: 15px;
|
right: 15px;
|
||||||
background: linear-gradient(to left, $ui-base-color, transparent);
|
background: linear-gradient(to left, $ui-base-color, transparent);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
@ -1293,10 +1304,6 @@ a.sparkline {
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
|
|
||||||
.fa {
|
|
||||||
color: lighten($dark-text-color, 7%);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&.mention {
|
&.mention {
|
||||||
|
@ -1313,12 +1320,21 @@ a.sparkline {
|
||||||
|
|
||||||
&__actions {
|
&__actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding-top: 10px;
|
|
||||||
|
|
||||||
&__button {
|
&__button {
|
||||||
flex: 0 0 auto;
|
flex-shrink: 1;
|
||||||
padding: 0 15px;
|
padding: 0 15px;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.button {
|
||||||
|
min-width: 0;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1327,19 +1343,23 @@ a.sparkline {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-auto-columns: minmax(0, 1fr);
|
grid-auto-columns: minmax(0, 1fr);
|
||||||
grid-auto-flow: column;
|
grid-auto-flow: column;
|
||||||
|
max-width: 340px;
|
||||||
|
min-width: 65px * 3;
|
||||||
|
|
||||||
&__item {
|
&__item {
|
||||||
padding: 15px;
|
padding: 15px 0;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: $primary-text-color;
|
color: $primary-text-color;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
|
line-height: 21px;
|
||||||
|
|
||||||
small {
|
small {
|
||||||
display: block;
|
display: block;
|
||||||
color: $darker-text-color;
|
color: $darker-text-color;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
|
line-height: 18px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
font-family: inherit;
|
font-family: inherit;
|
||||||
font-size: 17px;
|
font-size: 15px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
letter-spacing: 0;
|
letter-spacing: 0;
|
||||||
line-height: 22px;
|
line-height: 22px;
|
||||||
|
@ -2333,17 +2333,7 @@ a.account__display-name {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.directory__list {
|
.account-card {
|
||||||
display: grid;
|
|
||||||
grid-gap: 10px;
|
|
||||||
grid-template-columns: minmax(0, 50%) minmax(0, 50%);
|
|
||||||
|
|
||||||
@media screen and (max-width: $no-gap-breakpoint) {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.directory__card {
|
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6219,136 +6209,20 @@ a.status-card.compact:hover {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.directory {
|
.scrollable .account-card {
|
||||||
&__list {
|
margin: 10px;
|
||||||
width: 100%;
|
background: lighten($ui-base-color, 8%);
|
||||||
margin: 10px 0;
|
}
|
||||||
transition: opacity 100ms ease-in;
|
|
||||||
|
|
||||||
&.loading {
|
.scrollable .account-card__title__avatar {
|
||||||
opacity: 0.7;
|
img,
|
||||||
}
|
.account__avatar {
|
||||||
|
border-color: lighten($ui-base-color, 8%);
|
||||||
@media screen and (max-width: $no-gap-breakpoint) {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&__card {
|
.scrollable .account-card__bio::after {
|
||||||
box-sizing: border-box;
|
background: linear-gradient(to left, lighten($ui-base-color, 8%), transparent);
|
||||||
margin-bottom: 10px;
|
|
||||||
|
|
||||||
&__img {
|
|
||||||
height: 125px;
|
|
||||||
position: relative;
|
|
||||||
background: darken($ui-base-color, 12%);
|
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
img {
|
|
||||||
display: block;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
margin: 0;
|
|
||||||
object-fit: cover;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__bar {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
background: lighten($ui-base-color, 4%);
|
|
||||||
padding: 10px;
|
|
||||||
|
|
||||||
&__name {
|
|
||||||
flex: 1 1 auto;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
text-decoration: none;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__relationship {
|
|
||||||
width: 23px;
|
|
||||||
min-height: 1px;
|
|
||||||
flex: 0 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.avatar {
|
|
||||||
flex: 0 0 auto;
|
|
||||||
width: 48px;
|
|
||||||
height: 48px;
|
|
||||||
padding-top: 2px;
|
|
||||||
|
|
||||||
img {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
display: block;
|
|
||||||
margin: 0;
|
|
||||||
border-radius: 4px;
|
|
||||||
background: darken($ui-base-color, 8%);
|
|
||||||
object-fit: cover;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.display-name {
|
|
||||||
margin-left: 15px;
|
|
||||||
text-align: left;
|
|
||||||
|
|
||||||
strong {
|
|
||||||
font-size: 15px;
|
|
||||||
color: $primary-text-color;
|
|
||||||
font-weight: 500;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
|
|
||||||
span {
|
|
||||||
display: block;
|
|
||||||
font-size: 14px;
|
|
||||||
color: $darker-text-color;
|
|
||||||
font-weight: 400;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__extra {
|
|
||||||
background: $ui-base-color;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
.accounts-table__count {
|
|
||||||
width: 33.33%;
|
|
||||||
flex: 0 0 auto;
|
|
||||||
padding: 15px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.account__header__content {
|
|
||||||
box-sizing: border-box;
|
|
||||||
padding: 15px 10px;
|
|
||||||
border-bottom: 1px solid lighten($ui-base-color, 8%);
|
|
||||||
width: 100%;
|
|
||||||
min-height: 18px + 30px;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
|
|
||||||
p {
|
|
||||||
display: none;
|
|
||||||
|
|
||||||
&:first-child {
|
|
||||||
display: inline;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
br {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.account-gallery__container {
|
.account-gallery__container {
|
||||||
|
@ -6452,6 +6326,7 @@ a.status-card.compact:hover {
|
||||||
|
|
||||||
&__column {
|
&__column {
|
||||||
padding: 10px 15px;
|
padding: 10px 15px;
|
||||||
|
padding-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.radio-button {
|
.radio-button {
|
||||||
|
|
|
@ -409,14 +409,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.directory__card {
|
|
||||||
border-radius: 4px;
|
|
||||||
|
|
||||||
@media screen and (max-width: $no-gap-breakpoint) {
|
|
||||||
border-radius: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-header {
|
.page-header {
|
||||||
@media screen and (max-width: $no-gap-breakpoint) {
|
@media screen and (max-width: $no-gap-breakpoint) {
|
||||||
border-bottom: 0;
|
border-bottom: 0;
|
||||||
|
@ -835,19 +827,21 @@
|
||||||
grid-gap: 10px;
|
grid-gap: 10px;
|
||||||
grid-template-columns: minmax(0, 50%) minmax(0, 50%);
|
grid-template-columns: minmax(0, 50%) minmax(0, 50%);
|
||||||
|
|
||||||
|
.account-card {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
@media screen and (max-width: $no-gap-breakpoint) {
|
@media screen and (max-width: $no-gap-breakpoint) {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
|
||||||
|
|
||||||
.icon-button {
|
.account-card {
|
||||||
font-size: 18px;
|
margin-bottom: 10px;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.directory__card {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-grid {
|
.card-grid {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
|
|
@ -12,11 +12,6 @@ body.rtl {
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.directory__card__bar .display-name {
|
|
||||||
margin-left: 0;
|
|
||||||
margin-right: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.display-name,
|
.display-name,
|
||||||
.announcements__item {
|
.announcements__item {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
|
|
|
@ -19,37 +19,36 @@
|
||||||
- else
|
- else
|
||||||
.directory__list
|
.directory__list
|
||||||
- @accounts.each do |account|
|
- @accounts.each do |account|
|
||||||
.directory__card
|
.account-card
|
||||||
.directory__card__img
|
= link_to TagManager.instance.url_for(account), class: 'account-card__permalink' do
|
||||||
= image_tag account.header.url, alt: ''
|
.account-card__header
|
||||||
.directory__card__bar
|
= image_tag account.header.url, alt: ''
|
||||||
= link_to TagManager.instance.url_for(account), class: 'directory__card__bar__name' do
|
.account-card__title
|
||||||
.avatar
|
.account-card__title__avatar
|
||||||
= image_tag account.avatar.url, alt: '', class: 'u-photo'
|
= image_tag account.avatar.url, alt: ''
|
||||||
|
|
||||||
.display-name
|
.display-name
|
||||||
%bdi
|
%bdi
|
||||||
%strong.emojify.p-name= display_name(account, custom_emojify: true)
|
%strong.emojify.p-name= display_name(account, custom_emojify: true)
|
||||||
%span= acct(account)
|
%span
|
||||||
.directory__card__bar__relationship.account__relationship
|
= acct(account)
|
||||||
= minimal_account_action_button(account)
|
= fa_icon('lock') if account.locked?
|
||||||
|
- if account.note.present?
|
||||||
.directory__card__extra
|
.account-card__bio.emojify
|
||||||
.account__header__content.emojify= Formatter.instance.simplified_format(account, custom_emojify: true)
|
= Formatter.instance.simplified_format(account, custom_emojify: true)
|
||||||
|
- else
|
||||||
.directory__card__extra
|
.flex-spacer
|
||||||
.accounts-table__count
|
.account-card__actions
|
||||||
= friendly_number_to_human account.statuses_count
|
.account-card__counters
|
||||||
%small= t('accounts.posts', count: account.statuses_count).downcase
|
.account-card__counters__item
|
||||||
.accounts-table__count
|
= friendly_number_to_human account.statuses_count
|
||||||
= friendly_number_to_human account.followers_count
|
%small= t('accounts.posts', count: account.statuses_count).downcase
|
||||||
%small= t('accounts.followers', count: account.followers_count).downcase
|
.account-card__counters__item
|
||||||
.accounts-table__count
|
= friendly_number_to_human account.followers_count
|
||||||
- if account.last_status_at.present?
|
%small= t('accounts.followers', count: account.followers_count).downcase
|
||||||
%time.time-ago{ datetime: account.last_status_at.to_date.iso8601, title: l(account.last_status_at.to_date) }= l account.last_status_at.to_date
|
.account-card__counters__item
|
||||||
- else
|
= friendly_number_to_human account.following_count
|
||||||
= t('accounts.never_active')
|
%small= t('accounts.following', count: account.following_count).downcase
|
||||||
|
.account-card__actions__button
|
||||||
%small= t('accounts.last_active')
|
= account_action_button(account)
|
||||||
|
|
||||||
= paginate @accounts
|
= paginate @accounts
|
||||||
|
|
|
@ -72,7 +72,6 @@ en:
|
||||||
media: Media
|
media: Media
|
||||||
moved_html: "%{name} has moved to %{new_profile_link}:"
|
moved_html: "%{name} has moved to %{new_profile_link}:"
|
||||||
network_hidden: This information is not available
|
network_hidden: This information is not available
|
||||||
never_active: Never
|
|
||||||
nothing_here: There is nothing here!
|
nothing_here: There is nothing here!
|
||||||
people_followed_by: People whom %{name} follows
|
people_followed_by: People whom %{name} follows
|
||||||
people_who_follow: People who follow %{name}
|
people_who_follow: People who follow %{name}
|
||||||
|
|
Loading…
Reference in a new issue