Change labels and styles on the onboarding screen in web UI (#25559)

This commit is contained in:
Eugen Rochko 2023-06-23 16:34:27 +02:00 committed by GitHub
parent 0842a68532
commit a985d587e1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 101 additions and 56 deletions

View File

@ -1,6 +1,6 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { defineMessages, injectIntl } from 'react-intl'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import classNames from 'classnames'; import classNames from 'classnames';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
@ -49,6 +49,7 @@ class Account extends ImmutablePureComponent {
actionTitle: PropTypes.string, actionTitle: PropTypes.string,
defaultAction: PropTypes.string, defaultAction: PropTypes.string,
onActionClick: PropTypes.func, onActionClick: PropTypes.func,
withBio: PropTypes.bool,
}; };
static defaultProps = { static defaultProps = {
@ -80,7 +81,7 @@ class Account extends ImmutablePureComponent {
}; };
render () { render () {
const { account, intl, hidden, onActionClick, actionIcon, actionTitle, defaultAction, size, minimal } = this.props; const { account, intl, hidden, withBio, onActionClick, actionIcon, actionTitle, defaultAction, size, minimal } = this.props;
if (!account) { if (!account) {
return <EmptyAccount size={size} minimal={minimal} />; return <EmptyAccount size={size} minimal={minimal} />;
@ -171,6 +172,15 @@ class Account extends ImmutablePureComponent {
</div> </div>
)} )}
</div> </div>
{withBio && (account.get('note').length > 0 ? (
<div
className='account__note translate'
dangerouslySetInnerHTML={{ __html: account.get('note_emojified') }}
/>
) : (
<div className='account__note account__note--missing'><FormattedMessage id='account.no_bio' defaultMessage='No description provided.' /></div>
))}
</div> </div>
); );
} }

View File

@ -3,6 +3,8 @@ import PropTypes from 'prop-types';
import { Check } from 'mastodon/components/check'; import { Check } from 'mastodon/components/check';
import { Icon } from 'mastodon/components/icon'; import { Icon } from 'mastodon/components/icon';
import ArrowSmallRight from './arrow_small_right';
const Step = ({ label, description, icon, completed, onClick, href }) => { const Step = ({ label, description, icon, completed, onClick, href }) => {
const content = ( const content = (
<> <>
@ -15,11 +17,9 @@ const Step = ({ label, description, icon, completed, onClick, href }) => {
<p>{description}</p> <p>{description}</p>
</div> </div>
{completed && ( <div className={completed ? 'onboarding__steps__item__progress' : 'onboarding__steps__item__go'}>
<div className='onboarding__steps__item__progress'> {completed ? <Check /> : <ArrowSmallRight />}
<Check /> </div>
</div>
)}
</> </>
); );

View File

@ -12,20 +12,11 @@ import Column from 'mastodon/components/column';
import ColumnBackButton from 'mastodon/components/column_back_button'; import ColumnBackButton from 'mastodon/components/column_back_button';
import { EmptyAccount } from 'mastodon/components/empty_account'; import { EmptyAccount } from 'mastodon/components/empty_account';
import Account from 'mastodon/containers/account_container'; import Account from 'mastodon/containers/account_container';
import { me } from 'mastodon/initial_state';
import { makeGetAccount } from 'mastodon/selectors';
import ProgressIndicator from './components/progress_indicator'; const mapStateToProps = state => ({
suggestions: state.getIn(['suggestions', 'items']),
const mapStateToProps = () => { isLoading: state.getIn(['suggestions', 'isLoading']),
const getAccount = makeGetAccount(); });
return state => ({
account: getAccount(state, me),
suggestions: state.getIn(['suggestions', 'items']),
isLoading: state.getIn(['suggestions', 'isLoading']),
});
};
class Follows extends PureComponent { class Follows extends PureComponent {
@ -33,7 +24,6 @@ class Follows extends PureComponent {
onBack: PropTypes.func, onBack: PropTypes.func,
dispatch: PropTypes.func.isRequired, dispatch: PropTypes.func.isRequired,
suggestions: ImmutablePropTypes.list, suggestions: ImmutablePropTypes.list,
account: ImmutablePropTypes.map,
isLoading: PropTypes.bool, isLoading: PropTypes.bool,
multiColumn: PropTypes.bool, multiColumn: PropTypes.bool,
}; };
@ -49,7 +39,7 @@ class Follows extends PureComponent {
} }
render () { render () {
const { onBack, isLoading, suggestions, account, multiColumn } = this.props; const { onBack, isLoading, suggestions, multiColumn } = this.props;
let loadedContent; let loadedContent;
@ -58,7 +48,7 @@ class Follows extends PureComponent {
} else if (suggestions.isEmpty()) { } else if (suggestions.isEmpty()) {
loadedContent = <div className='follow-recommendations__empty'><FormattedMessage id='onboarding.follows.empty' defaultMessage='Unfortunately, no results can be shown right now. You can try using search or browsing the explore page to find people to follow, or try again later.' /></div>; loadedContent = <div className='follow-recommendations__empty'><FormattedMessage id='onboarding.follows.empty' defaultMessage='Unfortunately, no results can be shown right now. You can try using search or browsing the explore page to find people to follow, or try again later.' /></div>;
} else { } else {
loadedContent = suggestions.map(suggestion => <Account id={suggestion.get('account')} key={suggestion.get('account')} />); loadedContent = suggestions.map(suggestion => <Account id={suggestion.get('account')} key={suggestion.get('account')} withBio />);
} }
return ( return (
@ -71,8 +61,6 @@ class Follows extends PureComponent {
<p><FormattedMessage id='onboarding.follows.lead' defaultMessage='You curate your own home feed. The more people you follow, the more active and interesting it will be. These profiles may be a good starting point—you can always unfollow them later!' /></p> <p><FormattedMessage id='onboarding.follows.lead' defaultMessage='You curate your own home feed. The more people you follow, the more active and interesting it will be. These profiles may be a good starting point—you can always unfollow them later!' /></p>
</div> </div>
<ProgressIndicator steps={7} completed={account.get('following_count') * 1} />
<div className='follow-recommendations'> <div className='follow-recommendations'>
{loadedContent} {loadedContent}
</div> </div>

View File

@ -18,6 +18,7 @@ import { closeOnboarding } from 'mastodon/actions/onboarding';
import Column from 'mastodon/features/ui/components/column'; import Column from 'mastodon/features/ui/components/column';
import { me } from 'mastodon/initial_state'; import { me } from 'mastodon/initial_state';
import { makeGetAccount } from 'mastodon/selectors'; import { makeGetAccount } from 'mastodon/selectors';
import { assetHost } from 'mastodon/utils/config';
import ArrowSmallRight from './components/arrow_small_right'; import ArrowSmallRight from './components/arrow_small_right';
import Step from './components/step'; import Step from './components/step';
@ -121,21 +122,22 @@ class Onboarding extends ImmutablePureComponent {
<div className='onboarding__steps'> <div className='onboarding__steps'>
<Step onClick={this.handleProfileClick} href='/settings/profile' completed={(!account.get('avatar').endsWith('missing.png')) || (account.get('display_name').length > 0 && account.get('note').length > 0)} icon='address-book-o' label={<FormattedMessage id='onboarding.steps.setup_profile.title' defaultMessage='Customize your profile' />} description={<FormattedMessage id='onboarding.steps.setup_profile.body' defaultMessage='Others are more likely to interact with you with a filled out profile.' />} /> <Step onClick={this.handleProfileClick} href='/settings/profile' completed={(!account.get('avatar').endsWith('missing.png')) || (account.get('display_name').length > 0 && account.get('note').length > 0)} icon='address-book-o' label={<FormattedMessage id='onboarding.steps.setup_profile.title' defaultMessage='Customize your profile' />} description={<FormattedMessage id='onboarding.steps.setup_profile.body' defaultMessage='Others are more likely to interact with you with a filled out profile.' />} />
<Step onClick={this.handleFollowClick} completed={(account.get('following_count') * 1) >= 7} icon='user-plus' label={<FormattedMessage id='onboarding.steps.follow_people.title' defaultMessage='Find at least {count, plural, one {one person} other {# people}} to follow' values={{ count: 7 }} />} description={<FormattedMessage id='onboarding.steps.follow_people.body' defaultMessage="You curate your own home feed. Let's fill it with interesting people." />} /> <Step onClick={this.handleFollowClick} completed={(account.get('following_count') * 1) >= 7} icon='user-plus' label={<FormattedMessage id='onboarding.steps.follow_people.title' defaultMessage='Find at least {count, plural, one {one person} other {# people}} to follow' values={{ count: 7 }} />} description={<FormattedMessage id='onboarding.steps.follow_people.body' defaultMessage="You curate your own home feed. Let's fill it with interesting people." />} />
<Step onClick={this.handleComposeClick} completed={(account.get('statuses_count') * 1) >= 1} icon='pencil-square-o' label={<FormattedMessage id='onboarding.steps.publish_status.title' defaultMessage='Make your first post' />} description={<FormattedMessage id='onboarding.steps.publish_status.body' defaultMessage='Say hello to the world.' />} /> <Step onClick={this.handleComposeClick} completed={(account.get('statuses_count') * 1) >= 1} icon='pencil-square-o' label={<FormattedMessage id='onboarding.steps.publish_status.title' defaultMessage='Make your first post' />} description={<FormattedMessage id='onboarding.steps.publish_status.body' defaultMessage='Say hello to the world.' values={{ emoji: <img className='emojione' alt='🐘' src={`${assetHost}/emoji/1f418.svg`} /> }} />} />
<Step onClick={this.handleShareClick} completed={shareClicked} icon='copy' label={<FormattedMessage id='onboarding.steps.share_profile.title' defaultMessage='Share your profile' />} description={<FormattedMessage id='onboarding.steps.share_profile.body' defaultMessage='Let your friends know how to find you on Mastodon!' />} /> <Step onClick={this.handleShareClick} completed={shareClicked} icon='copy' label={<FormattedMessage id='onboarding.steps.share_profile.title' defaultMessage='Share your profile' />} description={<FormattedMessage id='onboarding.steps.share_profile.body' defaultMessage='Let your friends know how to find you on Mastodon!' />} />
</div> </div>
<p className='onboarding__lead'><FormattedMessage id='onboarding.start.skip' defaultMessage='Want to skip right ahead?' /></p> <p className='onboarding__lead'><FormattedMessage id='onboarding.start.skip' defaultMessage="Don't need help getting started?" /></p>
<div className='onboarding__links'> <div className='onboarding__links'>
<Link to='/explore' className='onboarding__link'> <Link to='/explore' className='onboarding__link'>
<FormattedMessage id='onboarding.actions.go_to_explore' defaultMessage='Take me to trending' />
<ArrowSmallRight /> <ArrowSmallRight />
<FormattedMessage id='onboarding.actions.go_to_explore' defaultMessage="See what's trending" />
</Link> </Link>
</div>
<div className='onboarding__footer'> <Link to='/home' className='onboarding__link'>
<button className='link-button' onClick={this.handleClose}><FormattedMessage id='onboarding.actions.close' defaultMessage="Don't show this screen again" /></button> <FormattedMessage id='onboarding.actions.go_to_home' defaultMessage='Take me to my home feed' />
<ArrowSmallRight />
</Link>
</div> </div>
</div> </div>

View File

@ -177,13 +177,13 @@ class Share extends PureComponent {
<div className='onboarding__links'> <div className='onboarding__links'>
<Link to='/home' className='onboarding__link'> <Link to='/home' className='onboarding__link'>
<FormattedMessage id='onboarding.actions.go_to_home' defaultMessage='Take me to my home feed' />
<ArrowSmallRight /> <ArrowSmallRight />
<FormattedMessage id='onboarding.actions.go_to_home' defaultMessage='Go to your home feed' />
</Link> </Link>
<Link to='/explore' className='onboarding__link'> <Link to='/explore' className='onboarding__link'>
<FormattedMessage id='onboarding.actions.go_to_explore' defaultMessage='Take me to trending' />
<ArrowSmallRight /> <ArrowSmallRight />
<FormattedMessage id='onboarding.actions.go_to_explore' defaultMessage="See what's trending" />
</Link> </Link>
</div> </div>

View File

@ -52,6 +52,7 @@
"account.mute_notifications_short": "Mute notifications", "account.mute_notifications_short": "Mute notifications",
"account.mute_short": "Mute", "account.mute_short": "Mute",
"account.muted": "Muted", "account.muted": "Muted",
"account.no_bio": "No description provided.",
"account.open_original_page": "Open original page", "account.open_original_page": "Open original page",
"account.posts": "Posts", "account.posts": "Posts",
"account.posts_with_replies": "Posts and replies", "account.posts_with_replies": "Posts and replies",
@ -452,28 +453,27 @@
"notifications_permission_banner.title": "Never miss a thing", "notifications_permission_banner.title": "Never miss a thing",
"onboarding.action.back": "Take me back", "onboarding.action.back": "Take me back",
"onboarding.actions.back": "Take me back", "onboarding.actions.back": "Take me back",
"onboarding.actions.close": "Don't show this screen again", "onboarding.actions.go_to_explore": "Take me to trending",
"onboarding.actions.go_to_explore": "See what's trending", "onboarding.actions.go_to_home": "Take me to my home feed",
"onboarding.actions.go_to_home": "Go to your home feed",
"onboarding.compose.template": "Hello #Mastodon!", "onboarding.compose.template": "Hello #Mastodon!",
"onboarding.follows.empty": "Unfortunately, no results can be shown right now. You can try using search or browsing the explore page to find people to follow, or try again later.", "onboarding.follows.empty": "Unfortunately, no results can be shown right now. You can try using search or browsing the explore page to find people to follow, or try again later.",
"onboarding.follows.lead": "You curate your own home feed. The more people you follow, the more active and interesting it will be. These profiles may be a good starting point—you can always unfollow them later!", "onboarding.follows.lead": "Your home feed is the primary way to experience Mastodon. The more people you follow, the more active and interesting it will be. To get you started, here are some suggestions:",
"onboarding.follows.title": "Popular on Mastodon", "onboarding.follows.title": "Personalize your home feed",
"onboarding.share.lead": "Let people know how they can find you on Mastodon!", "onboarding.share.lead": "Let people know how they can find you on Mastodon!",
"onboarding.share.message": "I'm {username} on #Mastodon! Come follow me at {url}", "onboarding.share.message": "I'm {username} on #Mastodon! Come follow me at {url}",
"onboarding.share.next_steps": "Possible next steps:", "onboarding.share.next_steps": "Possible next steps:",
"onboarding.share.title": "Share your profile", "onboarding.share.title": "Share your profile",
"onboarding.start.lead": "Your new Mastodon account is ready to go. Here's how you can make the most of it:", "onboarding.start.lead": "You're now part of Mastodon, a unique, decentralized social media platform where you—not an algorithm—curate your own experience. Let's get you started on this new social frontier:",
"onboarding.start.skip": "Want to skip right ahead?", "onboarding.start.skip": "Don't need help getting started?",
"onboarding.start.title": "You've made it!", "onboarding.start.title": "You've made it!",
"onboarding.steps.follow_people.body": "You curate your own home feed. Let's fill it with interesting people.", "onboarding.steps.follow_people.body": "Following interesting people is what Mastodon is all about.",
"onboarding.steps.follow_people.title": "Find at least {count, plural, one {one person} other {# people}} to follow", "onboarding.steps.follow_people.title": "Personalize your home feed",
"onboarding.steps.publish_status.body": "Say hello to the world.", "onboarding.steps.publish_status.body": "Say hello to the world with text, photos, videos, or polls {emoji}",
"onboarding.steps.publish_status.title": "Make your first post", "onboarding.steps.publish_status.title": "Make your first post",
"onboarding.steps.setup_profile.body": "Others are more likely to interact with you with a filled out profile.", "onboarding.steps.setup_profile.body": "Boost your interactions by having a comprehensive profile.",
"onboarding.steps.setup_profile.title": "Customize your profile", "onboarding.steps.setup_profile.title": "Personalize your profile",
"onboarding.steps.share_profile.body": "Let your friends know how to find you on Mastodon!", "onboarding.steps.share_profile.body": "Let your friends know how to find you on Mastodon",
"onboarding.steps.share_profile.title": "Share your profile", "onboarding.steps.share_profile.title": "Share your Mastodon profile",
"onboarding.tips.2fa": "<strong>Did you know?</strong> You can secure your account by setting up two-factor authentication in your account settings. It works with any TOTP app of your choice, no phone number necessary!", "onboarding.tips.2fa": "<strong>Did you know?</strong> You can secure your account by setting up two-factor authentication in your account settings. It works with any TOTP app of your choice, no phone number necessary!",
"onboarding.tips.accounts_from_other_servers": "<strong>Did you know?</strong> Since Mastodon is decentralized, some profiles you come across will be hosted on servers other than yours. And yet you can interact with them seamlessly! Their server is in the second half of their username!", "onboarding.tips.accounts_from_other_servers": "<strong>Did you know?</strong> Since Mastodon is decentralized, some profiles you come across will be hosted on servers other than yours. And yet you can interact with them seamlessly! Their server is in the second half of their username!",
"onboarding.tips.migration": "<strong>Did you know?</strong> If you feel like {domain} is not a great server choice for you in the future, you can move to another Mastodon server without losing your followers. You can even host your own server!", "onboarding.tips.migration": "<strong>Did you know?</strong> If you feel like {domain} is not a great server choice for you in the future, you can move to another Mastodon server without losing your followers. You can even host your own server!",

View File

@ -1514,12 +1514,37 @@ body > [data-popper-placement] {
} }
&__note { &__note {
font-size: 14px;
font-weight: 400;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
display: -webkit-box; display: -webkit-box;
-webkit-line-clamp: 2; -webkit-line-clamp: 1;
-webkit-box-orient: vertical; -webkit-box-orient: vertical;
color: $ui-secondary-color; margin-top: 10px;
color: $darker-text-color;
&--missing {
color: $dark-text-color;
}
p {
margin-bottom: 10px;
&:last-child {
margin-bottom: 0;
}
}
a {
color: inherit;
&:hover,
&:focus,
&:active {
text-decoration: none;
}
}
} }
} }
@ -2617,13 +2642,15 @@ $ui-header-height: 55px;
.onboarding__link { .onboarding__link {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between;
gap: 10px; gap: 10px;
color: $highlight-text-color; color: $highlight-text-color;
background: lighten($ui-base-color, 4%); background: lighten($ui-base-color, 4%);
border-radius: 8px; border-radius: 8px;
padding: 10px; padding: 10px 15px;
box-sizing: border-box; box-sizing: border-box;
font-size: 17px; font-size: 14px;
font-weight: 500;
height: 56px; height: 56px;
text-decoration: none; text-decoration: none;
@ -2685,6 +2712,7 @@ $ui-header-height: 55px;
align-items: center; align-items: center;
gap: 10px; gap: 10px;
padding: 10px; padding: 10px;
padding-inline-end: 15px;
margin-bottom: 2px; margin-bottom: 2px;
text-decoration: none; text-decoration: none;
text-align: start; text-align: start;
@ -2697,14 +2725,14 @@ $ui-header-height: 55px;
&__icon { &__icon {
flex: 0 0 auto; flex: 0 0 auto;
background: $ui-base-color;
border-radius: 50%; border-radius: 50%;
display: none; display: none;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
width: 36px; width: 36px;
height: 36px; height: 36px;
color: $dark-text-color; color: $highlight-text-color;
font-size: 1.2rem;
@media screen and (width >= 600px) { @media screen and (width >= 600px) {
display: flex; display: flex;
@ -2728,16 +2756,33 @@ $ui-header-height: 55px;
} }
} }
&__go {
flex: 0 0 auto;
display: flex;
align-items: center;
justify-content: center;
width: 21px;
height: 21px;
color: $highlight-text-color;
font-size: 17px;
svg {
height: 1.5em;
width: auto;
}
}
&__description { &__description {
flex: 1 1 auto; flex: 1 1 auto;
line-height: 18px; line-height: 20px;
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden; overflow: hidden;
h6 { h6 {
color: $primary-text-color; color: $highlight-text-color;
font-weight: 700; font-weight: 500;
font-size: 14px;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
} }