Restore onboarding modal (#6303)

* Restore onboarding modal
Revert 5ba8b3a396895ecec083c5258aaf9084d584a7c4

* Change greeting elephant graphic, fix up some design issues

* Fix wrong link color in onboarding modal
This commit is contained in:
Eugen Rochko authored and GitHub committed 2018-01-20 01:32:37 +01:00
1 parent 872a0d5bd8
commit 79b34a0fa2
8 files changed
+679 -4

No files matched your search

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" height="266.89999" width="463.97818" viewBox="0 0 463.97818 266.89999"><g transform="translate(-184 -205.1)"><defs><path id="a" d="M184 151h494.79999v321H184z"/></defs><clipPath id="b"><use height="100%" width="100%" xlink:href="#a" overflow="visible"/></clipPath><path clip-path="url(#b)" d="M525.7 478c-.5 0-.9-.2-1.2-.6-.3-.4-.4-.9-.2-1.3.2-.6 20-65 22-72 .2-.7.5-1.4.9-2.1.1-.4.3-.8.6-1.1l.3-.3c8.2-11.9 29.8-12.9 36.2-12.9 2.4 0 5 .1 7.6.3 13.6.9 25.2 3.7 33.6 8 6.4 3.3 10.7 7.4 12.2 11.8.1.2.2.4.2.6.2.6.3 1.3.4 1.9.6 5.4-1 13.6-2 18.5-1 5-11.9 47.7-12 48.1-.2.7-.8 1.1-1.5 1.1h-97.1z"/></g><g transform="translate(-184 -205.1)"><defs><path id="c" d="M184 151h494.79999v321H184z"/></defs><clipPath id="d"><use height="100%" width="100%" xlink:href="#c" overflow="visible"/></clipPath><path clip-path="url(#d)" d="M414.9 482.9c-.6 0-1.2-.4-1.4-.9H295.2l-81.3.8c-.6 0-1.1-.3-1.3-.8h-33.9c-.8 0-1.5-.7-1.5-1.5v-168c0-.3.1-.7.3-.9l2.9-3.8c-1.4-3-5.5-12.9-2.1-21.9-.2-.4-.3-.8-.5-1.2-1.9-5-2.6-10.8-2.3-17.1 0-1.1.1-2.2.3-3.3l.4-3.1.4-2.1c.5-3.2 1.3-6 2.2-8.4 2-5.4 5.5-10.4 10-14.3 4.1-3.6 9.1-6.5 15-8.6 7.6-2.7 16.2-4.1 25.5-4.1 2.4 0 5 .1 7.5.3 2.1-3.2 4.6-5.8 7.3-7.8 1.6-1.3 3.3-2.3 4.9-3.1 1.6-.8 3.5-1.7 5.4-2.2 2.9-.9 6.2-1.4 9.6-1.4.6 0 1.3 0 1.9.1 3.6.2 7.1 1 10.5 2.4 4.4-3.1 9.4-5.2 14.6-6.2 2.3-.4 4.7-.7 7.1-.7 3.3 0 6.5.4 9.6 1.3 2.8.8 5.5 1.8 7.8 3 2.5 1.3 4.8 2.9 6.9 4.7 3.9 3.3 7.2 7.6 9.5 12.5 7.9.2 15.5 3.2 21.7 8.3 3.2 2.7 5.9 5.9 7.9 9.4 2.1 3.6 3.5 7.5 4.2 11.5.7 3.7.7 7.8.2 12.2-.6 5-1.5 8.6-3 11.9-.8 1.8-1.9 3.5-3.3 5.3-1.4 1.6-2.6 2.9-3.9 4 25.8 10.3 47.4 26.8 62.7 48 8.3 11.3 16 24.7 22.9 39.7 7.1-5.1 14.6-12.5 23.2-23.3 22.7-28.1 60.2-50.7 89-53.6 4.5-.4 9-.7 13.3-.7 18.2 0 30.4 3.9 34.1 5.3 1.8-3.1 7.3-11.3 15.7-11.3 1.5 0 3 .3 4.5.8 4.6 1.5 7.8 4.3 9.4 8.2 1.5 3.5 1.3 7.4.7 10.5 1-.3 2.1-.5 3.4-.5 3.3 0 6.4 1.4 9.2 4.2 3.8 3.8 5.2 10.5 3.4 16.5-1.5 4.9-6.3 13.7-22.2 17-5.9 1.2-11.5 1.8-16.7 1.8-11.1 0-17.2-2.8-18.9-3.8-3.9.6-37.3 6.7-56.4 42.2-3.7 6.9-8.6 15.8-14 24.3 2.8 6.9 3.5 16 2.2 26.3-2.5 18.9-10 40-10.1 40.2-.2.6-.8 1-1.4 1l-94.8.9z"/></g><g transform="translate(-184 -205.1)"><defs><path id="e" d="M184 151h494.79999v321H184z"/></defs><clipPath id="f"><use height="100%" width="100%" xlink:href="#e" overflow="visible"/></clipPath><g clip-path="url(#f)"><path d="M414.9 481.4c-8.2-22.8-2.2-33.8 10.8-38.8s27 0 40 24c0 0 7-5 11-25s10-38 27-38c11 0 19 14 16 37-2.5 18.9-10 39.9-10 39.9l-94.8.9z" fill="#ebded8" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10"/><path d="M415.1 480.7c-6.4-18.1-4.1-29.8 7-35.9 6.6 4 12.9 11.4 18.7 22.1l.3.5.5-.3c.2-.2 5.6-4.2 9.7-18.8 4.9 4.2 9.6 10.5 14 18.6l-3.7-3.4-.8-1.9c.3-.2 12.4.2 16.4-19.8 2.4-11.8 5.7-24.7 12.7-31.8 4.9 6.5 6.7 17.6 5 30.7-2.3 17.4-8.9 36.7-9.9 39.4l-69.9.6z" class="st4" fill="#fff"/><path d="M469.8 480.5H178.7v-168l3.5-4.5c61-42 180-46.3 235 30" class="st5" fill="#fccf84" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10"/><path d="M417.2 338c-55.6-75.9-174-72-235-30l-3.5 4.5v168h291.1S458.9 395 417.2 338z" class="st6" fill="#fccf84"/><path d="M416.8 338.3c-6.4-8.7-13.8-16.6-22-23.5-8.2-6.9-17.3-12.8-26.9-17.7-19.2-9.8-40.4-15.4-61.8-17.4-21.4-2-43.2-.7-64.3 4-10.5 2.3-20.9 5.5-30.8 9.6-10 4.1-19.6 9.1-28.5 15.1l.1-.1-3.5 4.5.1-.3v168l-.5-.5h291.1l-.5.6c-1.8-12.6-4.4-25.1-7.4-37.5-3.1-12.4-6.6-24.6-10.9-36.7-4.2-12-9-23.9-14.7-35.3-2.8-5.7-5.9-11.3-9.1-16.8-3.2-5.5-6.7-10.8-10.4-16zm.8-.6c3.8 5.2 7.3 10.5 10.6 16 3.2 5.5 6.4 11.1 9.2 16.9 5.7 11.5 10.6 23.3 14.9 35.4 4.3 12.1 7.9 24.3 11 36.8 3.1 12.4 5.8 24.9 7.7 37.6.1.7-.4 1.3-1.1 1.4h-.2l-291-.8c-.3 0-.5-.2-.5-.5v-168c0-.1 0-.2.1-.3l3.5-4.5.1-.1c9-6.1 18.6-11.1 28.6-15.2s20.4-7.3 31-9.6c21.1-4.7 43-6.1 64.6-4 21.5 2.1 42.8 7.7 62.2 17.5 9.7 4.9 18.8 10.9 27.1 17.8s15.8 14.9 22.2 23.6z"/><path d="M182.3 479.7V323.5s42.9-30 87.3 15.6 79.6 126 148 110.2c56.4-13-17 21.8-17 21.8l-218.3 8.6z" class="st7" fill="#b88671"/><path d="M179.2 312.7l3.3-4.3c16.5-11.3 37.2-19.9 60.1-24.9l79.2.8c1 .5 9.3 4.6 9 10.1-.2 3.6-4.5 9.2-23.3 15-40.8 12.5-119.2 21.1-126.2 21.8l-2.1-18.5z" class="st7" fill="#b88671"/><path d="M181.1 283.7c-6.4 10.6 1.1 24.3 1.1 24.3l11.7-7.5-12.8-16.8z" fill="#a6725c" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10"/><path d="M646.4 325.7c-.2.2-.4.5-.6.8-4.6 8.1-16.2 13.7-32.9 13.7s-25.8-8.1-25.8-8.1c-65.8 3.5-80.5 51.6-124.5 93.1-44 41.5-131.1 34.9-220.8 17l-7.5 8.8 4.5 29.4s221.6-.5 230.5-.5c-1.6-12.3-2.6-16.4-2.6-16.4 31.7-17.9 49.4-44.9 65.1-74.1 21-39 58-43 58-43s11 7 35 2c17.1-3.5 22.5-14.3 21.6-22.7z" class="st7" fill="#b88671"/><path d="M241.8 392.5c-3.8 0-7-3.1-7.1-6.9l-.2-28c0-3.8 3.1-7 6.9-7.1 3.8 0 7 3.1 7.1 6.9l.2 28c.1 3.9-3 7.1-6.9 7.1zm157.5 0c-3.8.1-7.1-3-7.2-6.8l-.7-28c-.1-3.8 3-7.1 6.8-7.2 3.8-.1 7.1 3 7.2 6.8l.7 28c.1 3.9-2.9 7.1-6.8 7.2z"/><path d="M213.9 482.3c-.4 0-.8-.3-Line truncated

After

Width:  |  Height:  |  Size: 17 KiB

@@ -0,0 +1,14 @@
import { openModal } from './modal';
import { changeSetting, saveSettings } from './settings';
export function showOnboardingOnce() {
return (dispatch, getState) => {
const alreadySeen = getState().getIn(['settings', 'onboarded']);
if (!alreadySeen) {
dispatch(openModal('ONBOARDING'));
dispatch(changeSetting(['onboarded'], true));
dispatch(saveSettings());
}
};
};
@@ -2,6 +2,7 @@ import React from 'react';
import { Provider } from 'react-redux';
import PropTypes from 'prop-types';
import configureStore from '../store/configureStore';
import { showOnboardingOnce } from '../actions/onboarding';
import { BrowserRouter, Route } from 'react-router-dom';
import { ScrollContext } from 'react-router-scroll-4';
import UI from '../features/ui';
@@ -39,6 +40,8 @@ export default class Mastodon extends React.PureComponent {
const handlerUrl = window.location.protocol + '//' + window.location.host + '/intent?uri=%s';
window.setTimeout(() => navigator.registerProtocolHandler('web+mastodon', handlerUrl, 'Mastodon'), 5 * 60 * 1000);
}
store.dispatch(showOnboardingOnce());
}
componentWillUnmount () {
@@ -9,6 +9,7 @@ import VideoModal from './video_modal';
import BoostModal from './boost_modal';
import ConfirmationModal from './confirmation_modal';
import {
OnboardingModal,
MuteModal,
ReportModal,
EmbedModal,
@@ -17,6 +18,7 @@ import {
const MODAL_COMPONENTS = {
'MEDIA': () => Promise.resolve({ default: MediaModal }),
'ONBOARDING': OnboardingModal,
'VIDEO': () => Promise.resolve({ default: VideoModal }),
'BOOST': () => Promise.resolve({ default: BoostModal }),
'CONFIRM': () => Promise.resolve({ default: ConfirmationModal }),
@@ -0,0 +1,324 @@
import React from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import ReactSwipeableViews from 'react-swipeable-views';
import classNames from 'classnames';
import Permalink from '../../../components/permalink';
import ComposeForm from '../../compose/components/compose_form';
import Search from '../../compose/components/search';
import NavigationBar from '../../compose/components/navigation_bar';
import ColumnHeader from './column_header';
import { List as ImmutableList } from 'immutable';
import { me } from '../../../initial_state';
const noop = () => { };
const messages = defineMessages({
home_title: { id: 'column.home', defaultMessage: 'Home' },
notifications_title: { id: 'column.notifications', defaultMessage: 'Notifications' },
local_title: { id: 'column.community', defaultMessage: 'Local timeline' },
federated_title: { id: 'column.public', defaultMessage: 'Federated timeline' },
});
const PageOne = ({ acct, domain }) => (
<div className='onboarding-modal__page onboarding-modal__page-one'>
<div className='onboarding-modal__page-one__lead'>
<h1><FormattedMessage id='onboarding.page_one.welcome' defaultMessage='Welcome to Mastodon!' /></h1>
<p><FormattedMessage id='onboarding.page_one.federation' defaultMessage='Mastodon is a network of independent servers joining up to make one larger social network. We call these servers instances.' /></p>
</div>
<div className='onboarding-modal__page-one__extra'>
<div className='display-case'>
<div className='display-case__label'>
<FormattedMessage id='onboarding.page_one.full_handle' defaultMessage='Your full handle' />
</div>
<div className='display-case__case'>
@{acct}@{domain}
</div>
</div>
<p><FormattedMessage id='onboarding.page_one.handle_hint' defaultMessage='This is what you would tell your friends to search for.' /></p>
</div>
</div>
);
PageOne.propTypes = {
acct: PropTypes.string.isRequired,
domain: PropTypes.string.isRequired,
};
const PageTwo = ({ myAccount }) => (
<div className='onboarding-modal__page onboarding-modal__page-two'>
<div className='figure non-interactive'>
<div className='pseudo-drawer'>
<NavigationBar account={myAccount} />
<ComposeForm
text='Awoo! #introductions'
suggestions={ImmutableList()}
mentionedDomains={[]}
spoiler={false}
onChange={noop}
onSubmit={noop}
onPaste={noop}
onPickEmoji={noop}
onChangeSpoilerText={noop}
onClearSuggestions={noop}
onFetchSuggestions={noop}
onSuggestionSelected={noop}
showSearch
/>
</div>
</div>
<p><FormattedMessage id='onboarding.page_two.compose' defaultMessage='Write posts from the compose column. You can upload images, change privacy settings, and add content warnings with the icons below.' /></p>
</div>
);
PageTwo.propTypes = {
myAccount: ImmutablePropTypes.map.isRequired,
};
const PageThree = ({ myAccount }) => (
<div className='onboarding-modal__page onboarding-modal__page-three'>
<div className='figure non-interactive'>
<Search
value=''
onChange={noop}
onSubmit={noop}
onClear={noop}
onShow={noop}
/>
<div className='pseudo-drawer'>
<NavigationBar account={myAccount} />
</div>
</div>
<p><FormattedMessage id='onboarding.page_three.search' defaultMessage='Use the search bar to find people and look at hashtags, such as {illustration} and {introductions}. To look for a person who is not on this instance, use their full handle.' values={{ illustration: <Permalink to='/timelines/tag/illustration' href='/tags/illustration'>#illustration</Permalink>, introductions: <Permalink to='/timelines/tag/introductions' href='/tags/introductions'>#introductions</Permalink> }} /></p>
<p><FormattedMessage id='onboarding.page_three.profile' defaultMessage='Edit your profile to change your avatar, bio, and display name. There, you will also find other preferences.' /></p>
</div>
);
PageThree.propTypes = {
myAccount: ImmutablePropTypes.map.isRequired,
};
const PageFour = ({ domain, intl }) => (
<div className='onboarding-modal__page onboarding-modal__page-four'>
<div className='onboarding-modal__page-four__columns'>
<div className='row'>
<div>
<div className='figure non-interactive'><ColumnHeader icon='home' type={intl.formatMessage(messages.home_title)} /></div>
<p><FormattedMessage id='onboarding.page_four.home' defaultMessage='The home timeline shows posts from people you follow.' /></p>
</div>
<div>
<div className='figure non-interactive'><ColumnHeader icon='bell' type={intl.formatMessage(messages.notifications_title)} /></div>
<p><FormattedMessage id='onboarding.page_four.notifications' defaultMessage='The notifications column shows when someone interacts with you.' /></p>
</div>
</div>
<div className='row'>
<div>
<div className='figure non-interactive' style={{ marginBottom: 0 }}><ColumnHeader icon='users' type={intl.formatMessage(messages.local_title)} /></div>
</div>
<div>
<div className='figure non-interactive' style={{ marginBottom: 0 }}><ColumnHeader icon='globe' type={intl.formatMessage(messages.federated_title)} /></div>
</div>
</div>
<p><FormattedMessage id='onboarding.page_five.public_timelines' defaultMessage='The local timeline shows public posts from everyone on {domain}. The federated timeline shows public posts from everyone who people on {domain} follow. These are the Public Timelines, a great way to discover new people.' values={{ domain }} /></p>
</div>
</div>
);
PageFour.propTypes = {
domain: PropTypes.string.isRequired,
intl: PropTypes.object.isRequired,
};
const PageSix = ({ admin, domain }) => {
let adminSection = '';
if (admin) {
adminSection = (
<p>
<FormattedMessage id='onboarding.page_six.admin' defaultMessage="Your instance's admin is {admin}." values={{ admin: <Permalink href={admin.get('url')} to={`/accounts/${admin.get('id')}`}>@{admin.get('acct')}</Permalink> }} />
<br />
<FormattedMessage id='onboarding.page_six.read_guidelines' defaultMessage="Please read {domain}'s {guidelines}!" values={{ domain, guidelines: <a href='/about/more' target='_blank'><FormattedMessage id='onboarding.page_six.guidelines' defaultMessage='community guidelines' /></a> }} />
</p>
);
}
return (
<div className='onboarding-modal__page onboarding-modal__page-six'>
<h1><FormattedMessage id='onboarding.page_six.almost_done' defaultMessage='Almost done...' /></h1>
{adminSection}
<p><FormattedMessage id='onboarding.page_six.github' defaultMessage='Mastodon is free open-source software. You can report bugs, request features, or contribute to the code on {github}.' values={{ github: <a href='https://github.com/tootsuite/mastodon' target='_blank' rel='noopener'>GitHub</a> }} /></p>
<p><FormattedMessage id='onboarding.page_six.apps_available' defaultMessage='There are {apps} available for iOS, Android and other platforms.' values={{ apps: <a href='https://github.com/tootsuite/documentation/blob/master/Using-Mastodon/Apps.md' target='_blank' rel='noopener'><FormattedMessage id='onboarding.page_six.various_app' defaultMessage='mobile apps' /></a> }} /></p>
<p><em><FormattedMessage id='onboarding.page_six.appetoot' defaultMessage='Bon Appetoot!' /></em></p>
</div>
);
};
PageSix.propTypes = {
admin: ImmutablePropTypes.map,
domain: PropTypes.string.isRequired,
};
const mapStateToProps = state => ({
myAccount: state.getIn(['accounts', me]),
admin: state.getIn(['accounts', state.getIn(['meta', 'admin'])]),
domain: state.getIn(['meta', 'domain']),
});
@connect(mapStateToProps)
@injectIntl
export default class OnboardingModal extends React.PureComponent {
static propTypes = {
onClose: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired,
myAccount: ImmutablePropTypes.map.isRequired,
domain: PropTypes.string.isRequired,
admin: ImmutablePropTypes.map,
};
state = {
currentIndex: 0,
};
componentWillMount() {
const { myAccount, admin, domain, intl } = this.props;
this.pages = [
<PageOne acct={myAccount.get('acct')} domain={domain} />,
<PageTwo myAccount={myAccount} />,
<PageThree myAccount={myAccount} />,
<PageFour domain={domain} intl={intl} />,
<PageSix admin={admin} domain={domain} />,
];
};
componentDidMount() {
window.addEventListener('keyup', this.handleKeyUp);
}
componentWillUnmount() {
window.addEventListener('keyup', this.handleKeyUp);
}
handleSkip = (e) => {
e.preventDefault();
this.props.onClose();
}
handleDot = (e) => {
const i = Number(e.currentTarget.getAttribute('data-index'));
e.preventDefault();
this.setState({ currentIndex: i });
}
handlePrev = () => {
this.setState(({ currentIndex }) => ({
currentIndex: Math.max(0, currentIndex - 1),
}));
}
handleNext = () => {
const { pages } = this;
this.setState(({ currentIndex }) => ({
currentIndex: Math.min(currentIndex + 1, pages.length - 1),
}));
}
handleSwipe = (index) => {
this.setState({ currentIndex: index });
}
handleKeyUp = ({ key }) => {
switch (key) {
case 'ArrowLeft':
this.handlePrev();
break;
case 'ArrowRight':
this.handleNext();
break;
}
}
handleClose = () => {
this.props.onClose();
}
render () {
const { pages } = this;
const { currentIndex } = this.state;
const hasMore = currentIndex < pages.length - 1;
const nextOrDoneBtn = hasMore ? (
<button onClick={this.handleNext} className='onboarding-modal__nav onboarding-modal__next shake-bottom'>
<FormattedMessage id='onboarding.next' defaultMessage='Next' /> <i className='fa fa-fw fa-chevron-right' />
</button>
) : (
<button onClick={this.handleClose} className='onboarding-modal__nav onboarding-modal__done shake-bottom'>
<FormattedMessage id='onboarding.done' defaultMessage='Done' /> <i className='fa fa-fw fa-check' />
</button>
);
return (
<div className='modal-root__modal onboarding-modal'>
<ReactSwipeableViews index={currentIndex} onChangeIndex={this.handleSwipe} className='onboarding-modal__pager'>
{pages.map((page, i) => {
const className = classNames('onboarding-modal__page__wrapper', `onboarding-modal__page__wrapper-${i}`, {
'onboarding-modal__page__wrapper--active': i === currentIndex,
});
return (
<div key={i} className={className}>{page}</div>
);
})}
</ReactSwipeableViews>
<div className='onboarding-modal__paginator'>
<div>
<button
onClick={this.handleSkip}
className='onboarding-modal__nav onboarding-modal__skip'
>
<FormattedMessage id='onboarding.skip' defaultMessage='Skip' />
</button>
</div>
<div className='onboarding-modal__dots'>
{pages.map((_, i) => {
const className = classNames('onboarding-modal__dot', {
active: i === currentIndex,
});
return (
<div
key={`dot-${i}`}
role='button'
tabIndex='0'
data-index={i}
onClick={this.handleDot}
className={className}
/>
);
})}
</div>
<div>
{nextOrDoneBtn}
</div>
</div>
</div>
);
}
}
@@ -94,6 +94,10 @@ export function Mutes () {
return import(/* webpackChunkName: "features/mutes" */'../../mutes');
}
export function OnboardingModal () {
return import(/* webpackChunkName: "modals/onboarding_modal" */'../components/onboarding_modal');
}
export function MuteModal () {
return import(/* webpackChunkName: "modals/mute_modal" */'../components/mute_modal');
}
+1 -1
View File
@@ -174,7 +174,7 @@
"onboarding.page_four.home": "The home timeline shows posts from people you follow.",
"onboarding.page_four.notifications": "The notifications column shows when someone interacts with you.",
"onboarding.page_one.federation": "Mastodon is a network of independent servers joining up to make one larger social network. We call these servers instances.",
"onboarding.page_one.handle": "You are on {domain}, so your full handle is {handle}",
"onboarding.page_one.handle": "Your full handle is {handle}. This is what you would tell your friends to search for.",
"onboarding.page_one.welcome": "Welcome to Mastodon!",
"onboarding.page_six.admin": "Your instance's admin is {admin}.",
"onboarding.page_six.almost_done": "Almost done...",
+330 -3
View File
@@ -1419,6 +1419,10 @@
color: $primary-text-color;
}
a {
color: inherit;
}
.permalink {
text-decoration: none;
}
@@ -2760,6 +2764,7 @@
flex: 1 1 auto;
align-items: center;
justify-content: center;
@supports(display: grid) { // hack to fix Chrome <57
contain: strict;
}
@@ -2805,11 +2810,48 @@
}
}
.pulse-loading {
.no-reduce-motion .pulse-loading {
transform-origin: center center;
animation: heartbeat 1.5s ease-in-out infinite both;
}
@keyframes shake-bottom {
0%,
100% {
transform: rotate(0deg);
transform-origin: 50% 100%;
}
10% {
transform: rotate(2deg);
}
20%,
40%,
60% {
transform: rotate(-4deg);
}
30%,
50%,
70% {
transform: rotate(4deg);
}
80% {
transform: rotate(-2deg);
}
90% {
transform: rotate(2deg);
}
}
.no-reduce-motion .shake-bottom {
transform-origin: 50% 100%;
animation: shake-bottom 0.8s cubic-bezier(0.455, 0.030, 0.515, 0.955) 2s 2 both;
}
.emoji-picker-dropdown__menu {
background: $simple-background-color;
position: absolute;
@@ -3300,6 +3342,7 @@
z-index: 100;
}
.onboarding-modal,
.error-modal,
.embed-modal {
background: $ui-secondary-color;
@@ -3310,6 +3353,25 @@
flex-direction: column;
}
.onboarding-modal__pager {
height: 80vh;
width: 80vw;
max-width: 520px;
max-height: 470px;
.react-swipeable-view-container > div {
width: 100%;
height: 100%;
box-sizing: border-box;
display: none;
flex-direction: column;
align-items: center;
justify-content: center;
display: flex;
user-select: text;
}
}
.error-modal__body {
height: 80vh;
width: 80vw;
@@ -3343,6 +3405,23 @@
text-align: center;
}
@media screen and (max-width: 550px) {
.onboarding-modal {
width: 100%;
height: 100%;
border-radius: 0;
}
.onboarding-modal__pager {
width: 100%;
height: auto;
max-width: none;
max-height: none;
flex: 1 1 auto;
}
}
.onboarding-modal__paginator,
.error-modal__footer {
flex: 0 0 auto;
background: darken($ui-secondary-color, 8%);
@@ -3353,20 +3432,35 @@
min-width: 33px;
}
.onboarding-modal__nav,
.error-modal__nav {
color: darken($ui-secondary-color, 34%);
background-color: transparent;
border: 0;
font-size: 14px;
font-weight: 500;
padding: 0;
padding: 10px 25px;
line-height: inherit;
height: auto;
margin: -10px;
border-radius: 4px;
background-color: transparent;
&:hover,
&:focus,
&:active {
color: darken($ui-secondary-color, 38%);
background-color: darken($ui-secondary-color, 16%);
}
&.onboarding-modal__done,
&.onboarding-modal__next {
color: $ui-base-color;
&:hover,
&:focus,
&:active {
color: darken($ui-base-color, 4%);
}
}
}
}
@@ -3375,6 +3469,239 @@
justify-content: center;
}
.onboarding-modal__dots {
flex: 1 1 auto;
display: flex;
align-items: center;
justify-content: center;
}
.onboarding-modal__dot {
width: 14px;
height: 14px;
border-radius: 14px;
background: darken($ui-secondary-color, 16%);
margin: 0 3px;
cursor: pointer;
&:hover {
background: darken($ui-secondary-color, 18%);
}
&.active {
cursor: default;
background: darken($ui-secondary-color, 24%);
}
}
.onboarding-modal__page__wrapper {
pointer-events: none;
padding: 25px;
padding-bottom: 0;
&.onboarding-modal__page__wrapper--active {
pointer-events: auto;
}
}
.onboarding-modal__page {
cursor: default;
line-height: 21px;
h1 {
font-size: 18px;
font-weight: 500;
color: $ui-base-color;
margin-bottom: 20px;
}
a {
color: $ui-highlight-color;
&:hover,
&:focus,
&:active {
color: lighten($ui-highlight-color, 4%);
}
}
.navigation-bar a {
color: inherit;
}
p {
font-size: 16px;
color: lighten($ui-base-color, 8%);
margin-top: 10px;
margin-bottom: 10px;
&:last-child {
margin-bottom: 0;
}
strong {
font-weight: 500;
background: $ui-base-color;
color: $ui-secondary-color;
border-radius: 4px;
font-size: 14px;
padding: 3px 6px;
@each $lang in $cjk-langs {
&:lang(#{$lang}) {
font-weight: 700;
}
}
}
}
}
.onboarding-modal__page__wrapper-0 {
background: url('../images/elephant_ui_greeting.svg') no-repeat left bottom / auto 250px;
height: 100%;
padding: 0;
}
.onboarding-modal__page-one {
&__lead {
padding: 65px;
padding-top: 45px;
padding-bottom: 0;
margin-bottom: 10px;
h1 {
font-size: 26px;
line-height: 36px;
margin-bottom: 8px;
}
p {
margin-bottom: 0;
}
}
&__extra {
padding-right: 65px;
padding-left: 185px;
text-align: center;
}
}
.display-case {
text-align: center;
font-size: 15px;
margin-bottom: 15px;
&__label {
font-weight: 500;
color: $ui-base-color;
margin-bottom: 5px;
text-transform: uppercase;
font-size: 12px;
}
&__case {
background: $ui-base-color;
color: $ui-secondary-color;
font-weight: 500;
padding: 10px;
border-radius: 4px;
}
}
.onboarding-modal__page-two,
.onboarding-modal__page-three,
.onboarding-modal__page-four,
.onboarding-modal__page-five {
p {
text-align: left;
}
.figure {
background: darken($ui-base-color, 8%);
color: $ui-secondary-color;
margin-bottom: 20px;
border-radius: 4px;
padding: 10px;
text-align: center;
font-size: 14px;
box-shadow: 1px 2px 6px rgba($base-shadow-color, 0.3);
.onboarding-modal__image {
border-radius: 4px;
margin-bottom: 10px;
}
&.non-interactive {
pointer-events: none;
text-align: left;
}
}
}
.onboarding-modal__page-four__columns {
.row {
display: flex;
margin-bottom: 20px;
& > div {
flex: 1 1 0;
margin: 0 10px;
&:first-child {
margin-left: 0;
}
&:last-child {
margin-right: 0;
}
p {
text-align: center;
}
}
&:last-child {
margin-bottom: 0;
}
}
.column-header {
color: $primary-text-color;
}
}
@media screen and (max-width: 320px) and (max-height: 600px) {
.onboarding-modal__page p {
font-size: 14px;
line-height: 20px;
}
.onboarding-modal__page-two .figure,
.onboarding-modal__page-three .figure,
.onboarding-modal__page-four .figure,
.onboarding-modal__page-five .figure {
font-size: 12px;
margin-bottom: 10px;
}
.onboarding-modal__page-four__columns .row {
margin-bottom: 10px;
}
.onboarding-modal__page-four__columns .column-header {
padding: 5px;
font-size: 12px;
}
}
.onboard-sliders {
display: inline-block;
max-width: 30px;
max-height: auto;
margin-left: 10px;
}
.boost-modal,
.confirmation-modal,
.report-modal,