);
diff --git a/app/soapbox/features/ui/util/async-components.js b/app/soapbox/features/ui/util/async-components.js
index 1622ca575..24dc2f256 100644
--- a/app/soapbox/features/ui/util/async-components.js
+++ b/app/soapbox/features/ui/util/async-components.js
@@ -214,6 +214,10 @@ export function MentionsModal() {
return import(/* webpackChunkName: "features/ui" */'../components/mentions_modal');
}
+export function LandingPageModal() {
+ return import(/* webpackChunkName: "features/ui/modals/landing-page-modal" */'../components/modals/landing-page-modal');
+}
+
export function BirthdaysModal() {
return import(/* webpackChunkName: "features/ui" */'../components/birthdays_modal');
}
@@ -246,14 +250,34 @@ export function ExternalLogin() {
return import(/* webpackChunkName: "features/external_login" */'../../external_login');
}
-export function Preferences() {
- return import(/* webpackChunkName: "features/preferences" */'../../preferences');
+export function Settings() {
+ return import(/* webpackChunkName: "features/settings" */'../../settings');
+}
+
+export function MediaDisplay() {
+ return import(/* webpackChunkName: "features/settings" */'../../settings/media_display');
}
export function EditProfile() {
return import(/* webpackChunkName: "features/edit_profile" */'../../edit_profile');
}
+export function EditEmail() {
+ return import(/* webpackChunkName: "features/edit_email" */'../../edit_email');
+}
+
+export function EmailConfirmation() {
+ return import(/* webpackChunkName: "features/email_confirmation" */'../../email_confirmation');
+}
+
+export function EditPassword() {
+ return import(/* webpackChunkName: "features/edit_password" */'../../edit_password');
+}
+
+export function DeleteAccount() {
+ return import(/* webpackChunkName: "features/delete_account" */'../../delete_account');
+}
+
export function SoapboxConfig() {
return import(/* webpackChunkName: "features/soapbox_config" */'../../soapbox_config');
}
@@ -274,8 +298,8 @@ export function PasswordReset() {
return import(/* webpackChunkName: "features/auth_login" */'../../auth_login/components/password_reset');
}
-export function SecurityForm() {
- return import(/* webpackChunkName: "features/security" */'../../security');
+export function PasswordResetConfirm() {
+ return import(/* webpackChunkName: "features/auth_login/password_reset_confirm" */'../../auth_login/components/password_reset_confirm');
}
export function MfaForm() {
@@ -335,7 +359,7 @@ export function FundingPanel() {
}
export function TrendsPanel() {
- return import(/* webpackChunkName: "features/trends" */'../components/trends_panel');
+ return import(/* webpackChunkName: "features/trends" */'../components/trends-panel');
}
export function ProfileInfoPanel() {
@@ -427,7 +451,7 @@ export function ScheduleForm() {
}
export function WhoToFollowPanel() {
- return import(/* webpackChunkName: "features/follow_recommendations" */'../components/who_to_follow_panel');
+ return import(/* webpackChunkName: "features/follow_recommendations" */'../components/who-to-follow-panel');
}
export function FollowRecommendations() {
diff --git a/app/soapbox/features/ui/util/react_router_helpers.js b/app/soapbox/features/ui/util/react_router_helpers.js
index d5543c421..4942787b8 100644
--- a/app/soapbox/features/ui/util/react_router_helpers.js
+++ b/app/soapbox/features/ui/util/react_router_helpers.js
@@ -102,7 +102,7 @@ class WrappedRoute extends React.Component {
loginRedirect = () => {
const actualUrl = encodeURIComponent(`${this.props.computedMatch.url}${this.props.location.search}`); // eslint-disable-line react/prop-types
- return
;
}
render() {
diff --git a/app/soapbox/features/verification/email_passthru.js b/app/soapbox/features/verification/email_passthru.js
new file mode 100644
index 000000000..8bf6fecb9
--- /dev/null
+++ b/app/soapbox/features/verification/email_passthru.js
@@ -0,0 +1,163 @@
+import PropTypes from 'prop-types';
+import * as React from 'react';
+import { defineMessages, useIntl } from 'react-intl';
+import { useDispatch } from 'react-redux';
+import { withRouter } from 'react-router-dom';
+
+import snackbar from 'soapbox/actions/snackbar';
+import { confirmEmailVerification } from 'soapbox/actions/verification';
+import { Icon, Spinner, Stack, Text } from 'soapbox/components/ui';
+
+const Statuses = {
+ IDLE: 'IDLE',
+ SUCCESS: 'SUCCESS',
+ GENERIC_FAIL: 'GENERIC_FAIL',
+ TOKEN_NOT_FOUND: 'TOKEN_NOT_FOUND',
+ TOKEN_EXPIRED: 'TOKEN_EXPIRED',
+};
+
+const messages = defineMessages({
+ emailConfirmedHeading: { id: 'email_passthru.confirmed.heading', defaultMessage: 'Email Confirmed!' },
+ emailConfirmedBody: { id: 'email_passthru.confirmed.body', defaultMessage: 'Close this tab and continue the registration process on the {bold} from which you sent this email confirmation.' },
+ genericFailHeading: { id: 'email_passthru.generic_fail.heading', defaultMessage: 'Something Went Wrong' },
+ genericFailBody: { id: 'email_passthru.generic_fail.body', defaultMessage: 'Please request a new email confirmation.' },
+ tokenNotFoundHeading: { id: 'email_passthru.token_not_found.heading', defaultMessage: 'Invalid Token' },
+ tokenNotFoundBody: { id: 'email_passthru.token_not_found.body', defaultMessage: 'Your email token was not found. Please request a new email confirmation from the {bold} from which you sent this email confirmation.' },
+ tokenExpiredHeading: { id: 'email_passthru.token_expired.heading', defaultMessage: 'Token Expired' },
+ tokenExpiredBody: { id: 'email_passthru.token_expired.body', defaultMessage: 'Your email token has expired. Please request a new email confirmation from the {bold} from which you sent this email confirmation.' },
+});
+
+const Success = () => {
+ const intl = useIntl();
+
+ return (
+
+ );
+};
+
+const GenericFail = () => {
+ const intl = useIntl();
+
+ return (
+
+ );
+};
+
+const TokenNotFound = () => {
+ const intl = useIntl();
+
+ return (
+
+ );
+};
+
+const TokenExpired = () => {
+ const intl = useIntl();
+
+ return (
+
+ );
+};
+
+const EmailPassThru = ({ match }) => {
+ const { token } = match.params;
+
+ const intl = useIntl();
+ const dispatch = useDispatch();
+
+ const [status, setStatus] = React.useState(Statuses.IDLE);
+
+ React.useEffect(() => {
+ if (token) {
+ dispatch(confirmEmailVerification(token))
+ .then(() => {
+ setStatus(Statuses.SUCCESS);
+ dispatch(snackbar.success(intl.formatMessage({ id: 'email_passthru.success', defaultMessage: 'Your email has been verified!' })));
+ })
+ .catch((error) => {
+ const errorKey = error?.response?.data?.error;
+ let message = intl.formatMessage({
+ id: 'email_passthru.fail.generic',
+ defaultMessage: 'Unable to confirm your email',
+ });
+
+ if (errorKey) {
+ switch (errorKey) {
+ case 'token_expired':
+ message = intl.formatMessage({
+ id: 'email_passthru.fail.expired',
+ defaultMessage: 'Your email token has expired.',
+ });
+ setStatus(Statuses.TOKEN_EXPIRED);
+ break;
+ case 'token_not_found':
+ message = intl.formatMessage({
+ id: 'email_passthru.fail.not_found',
+ defaultMessage: 'Your email token is invalid.',
+ });
+ message = 'Your token is invalid';
+ setStatus(Statuses.TOKEN_NOT_FOUND);
+ break;
+ default:
+ setStatus(Statuses.GENERIC_FAIL);
+ break;
+ }
+ }
+
+ dispatch(snackbar.error(message));
+ });
+ }
+ }, [token]);
+
+ switch (status) {
+ case Statuses.SUCCESS:
+ return
;
+ }
+};
+
+EmailPassThru.propTypes = {
+ match: PropTypes.object,
+};
+
+export default withRouter(EmailPassThru);
diff --git a/app/soapbox/features/verification/index.js b/app/soapbox/features/verification/index.js
new file mode 100644
index 000000000..63ad1b07c
--- /dev/null
+++ b/app/soapbox/features/verification/index.js
@@ -0,0 +1,50 @@
+import * as React from 'react';
+import { useDispatch, useSelector } from 'react-redux';
+import { Redirect } from 'react-router-dom';
+
+import { fetchVerificationConfig } from 'soapbox/actions/verification';
+
+import Registration from './registration';
+import AgeVerification from './steps/age_verification';
+import EmailVerification from './steps/email_verification';
+import SmsVerification from './steps/sms_verification';
+
+const verificationSteps = {
+ email: EmailVerification,
+ sms: SmsVerification,
+ age: AgeVerification,
+};
+
+const Verification = () => {
+ const dispatch = useDispatch();
+
+ const isInstanceReady = useSelector((state) => state.getIn(['verification', 'instance', 'isReady'], false) === true);
+ const isRegistrationOpen = useSelector(state => state.getIn(['verification', 'instance', 'registrations'], false) === true);
+ const currentChallenge = useSelector((state) => state.getIn(['verification', 'currentChallenge']));
+ const isVerificationComplete = useSelector((state) => state.getIn(['verification', 'isComplete']));
+ const StepToRender = verificationSteps[currentChallenge];
+
+ React.useEffect(() => {
+ dispatch(fetchVerificationConfig());
+ }, []);
+
+ if (isInstanceReady && !isRegistrationOpen) {
+ return
+ );
+ }
+
+ if (!currentChallenge) {
+ return null;
+ }
+
+ return (
+
+ );
+};
+
+export default Verification;
diff --git a/app/soapbox/features/verification/registration.js b/app/soapbox/features/verification/registration.js
new file mode 100644
index 000000000..43ea15990
--- /dev/null
+++ b/app/soapbox/features/verification/registration.js
@@ -0,0 +1,122 @@
+import * as React from 'react';
+import { useIntl } from 'react-intl';
+import { useDispatch, useSelector } from 'react-redux';
+import { Redirect } from 'react-router-dom';
+
+import { logIn, verifyCredentials } from 'soapbox/actions/auth';
+import { fetchInstance } from 'soapbox/actions/instance';
+import snackbar from 'soapbox/actions/snackbar';
+import { createAccount } from 'soapbox/actions/verification';
+import { removeStoredVerification } from 'soapbox/actions/verification';
+
+import { Button, Form, FormGroup, Input } from '../../components/ui';
+
+const initialState = {
+ username: '',
+ password: '',
+};
+
+const Registration = () => {
+ const dispatch = useDispatch();
+ const intl = useIntl();
+
+ const isLoading = useSelector((state) => state.getIn(['verification', 'isLoading']));
+
+ const [state, setState] = React.useState(initialState);
+ const [shouldRedirect, setShouldRedirect] = React.useState(false);
+ const { username, password } = state;
+
+ const handleSubmit = React.useCallback((event) => {
+ event.preventDefault();
+
+ // TODO: handle validation errors from Pepe
+ dispatch(createAccount(username, password))
+ .then(() => dispatch(logIn(intl, username, password)))
+ .then(({ access_token }) => dispatch(verifyCredentials(access_token)))
+ .then(() => dispatch(fetchInstance()))
+ .then(() => {
+ setShouldRedirect(true);
+ removeStoredVerification();
+ dispatch(
+ snackbar.success(
+ intl.formatMessage({
+ id: 'registrations.success',
+ defaultMessage: 'Welcome to Truth Social!',
+ }),
+ ),
+ );
+ })
+ .catch((error) => {
+ if (error?.response?.status === 422) {
+ dispatch(
+ snackbar.error(
+ intl.formatMessage({
+ id: 'registrations.unprocessable_entity',
+ defaultMessage: 'This username has already been taken.',
+ }),
+ ),
+ );
+ } else {
+ dispatch(
+ snackbar.error(
+ intl.formatMessage({
+ id: 'registrations.error',
+ defaultMessage: 'Failed to register your account.',
+ }),
+ ),
+ );
+ }
+ });
+ }, [username, password]);
+
+ const handleInputChange = React.useCallback((event) => {
+ event.persist();
+
+ setState((prevState) => ({ ...prevState, [event.target.name]: event.target.value }));
+ }, []);
+
+ if (shouldRedirect) {
+ return
+ );
+};
+
+export default Registration;
diff --git a/app/soapbox/features/verification/steps/age_verification.js b/app/soapbox/features/verification/steps/age_verification.js
new file mode 100644
index 000000000..462ff7e64
--- /dev/null
+++ b/app/soapbox/features/verification/steps/age_verification.js
@@ -0,0 +1,101 @@
+import PropTypes from 'prop-types';
+import * as React from 'react';
+import DatePicker from 'react-datepicker';
+import { useIntl } from 'react-intl';
+import { useDispatch, useSelector } from 'react-redux';
+
+import snackbar from 'soapbox/actions/snackbar';
+import { verifyAge } from 'soapbox/actions/verification';
+
+import { Button, Form, FormGroup, Text } from '../../../components/ui';
+
+function meetsAgeMinimum(birthday, ageMinimum) {
+ const month = birthday.getUTCMonth();
+ const day = birthday.getUTCDate();
+ const year = birthday.getUTCFullYear();
+
+ return new Date(year + ageMinimum, month, day) <= new Date();
+}
+
+function getMaximumDate(ageMinimum) {
+ const date = new Date();
+ date.setUTCFullYear(date.getUTCFullYear() - ageMinimum);
+
+ return date;
+}
+
+const AgeVerification = () => {
+ const intl = useIntl();
+ const dispatch = useDispatch();
+
+ const isLoading = useSelector((state) => state.getIn(['verification', 'isLoading']));
+ const ageMinimum = useSelector((state) => state.getIn(['verification', 'ageMinimum']));
+
+ const [date, setDate] = React.useState('');
+ const isValid = typeof date === 'object';
+
+ const onChange = React.useCallback((date) => setDate(date), []);
+
+ const handleSubmit = React.useCallback((event) => {
+ event.preventDefault();
+
+ const birthday = new Date(date);
+
+ if (meetsAgeMinimum(birthday, ageMinimum)) {
+ dispatch(verifyAge(birthday));
+ } else {
+ dispatch(
+ snackbar.error(
+ intl.formatMessage({
+ id: 'age_verification.fail',
+ defaultMessage: `You must be ${ageMinimum} years old or older.`,
+ }),
+ ),
+ );
+ }
+ }, [date, ageMinimum]);
+
+ return (
+
+ );
+};
+
+AgeVerification.propTypes = {
+ verifyAge: PropTypes.func,
+};
+
+export default AgeVerification;
diff --git a/app/soapbox/features/verification/steps/email_verification.js b/app/soapbox/features/verification/steps/email_verification.js
new file mode 100644
index 000000000..f71d57c3c
--- /dev/null
+++ b/app/soapbox/features/verification/steps/email_verification.js
@@ -0,0 +1,138 @@
+import PropTypes from 'prop-types';
+import * as React from 'react';
+import { useIntl } from 'react-intl';
+import { useDispatch, useSelector } from 'react-redux';
+
+import snackbar from 'soapbox/actions/snackbar';
+import { checkEmailVerification, requestEmailVerification } from 'soapbox/actions/verification';
+import { postEmailVerification } from 'soapbox/actions/verification';
+import Icon from 'soapbox/components/icon';
+import { Button, Form, FormGroup, Input, Text } from 'soapbox/components/ui';
+
+const Statuses = {
+ IDLE: 'IDLE',
+ REQUESTED: 'REQUESTED',
+ FAIL: 'FAIL',
+};
+
+const EMAIL_REGEX = /^[^@\s]+@[^@\s]+$/;
+
+const EmailSent = ({ handleSubmit }) => {
+ const dispatch = useDispatch();
+
+ const checkEmailConfirmation = () => {
+ dispatch(checkEmailVerification())
+ .then(() => dispatch(postEmailVerification()))
+ .catch(() => null);
+ };
+
+ React.useEffect(() => {
+ const intervalId = setInterval(() => checkEmailConfirmation(), 2500);
+
+ return () => clearInterval(intervalId);
+ }, []);
+
+ return (
+
+ );
+};
+
+const EmailVerification = () => {
+ const intl = useIntl();
+ const dispatch = useDispatch();
+
+ const isLoading = useSelector((state) => state.getIn(['verification', 'isLoading']));
+
+ const [email, setEmail] = React.useState('');
+ const [status, setStatus] = React.useState(Statuses.IDLE);
+ const [errors, setErrors] = React.useState([]);
+
+ const isValid = email.length > 0 && EMAIL_REGEX.test(email);
+
+ const onChange = React.useCallback((event) => setEmail(event.target.value), []);
+
+ const handleSubmit = React.useCallback((event) => {
+ event.preventDefault();
+ setErrors([]);
+
+ submitEmailForVerification();
+ }, [email]);
+
+ const submitEmailForVerification = () => {
+ return dispatch(requestEmailVerification((email)))
+ .then(() => {
+ setStatus(Statuses.REQUESTED);
+
+ dispatch(
+ snackbar.success(
+ intl.formatMessage({
+ id: 'email_verification.exists',
+ defaultMessage: 'Verification email sent successfully.',
+ }),
+ ),
+ );
+ })
+ .catch(error => {
+ const isEmailTaken = error.response?.data?.error === 'email_taken';
+
+ const message = isEmailTaken ? (
+ intl.formatMessage({ id: 'email_verification.exists', defaultMessage: 'This email has already been taken.' })
+ ) : (
+ intl.formatMessage({ id: 'email_verification.fail', defaultMessage: 'Failed to request email verification.' })
+ );
+
+ if (isEmailTaken) {
+ setErrors([intl.formatMessage({ id: 'email_verification.taken', defaultMessage: 'is taken' })]);
+ }
+
+ dispatch(snackbar.error(message));
+ setStatus(Statuses.FAIL);
+ });
+ };
+
+ if (status === Statuses.REQUESTED) {
+ return
+ );
+};
+
+EmailSent.propTypes = {
+ handleSubmit: PropTypes.func.isRequired,
+};
+
+export default EmailVerification;
diff --git a/app/soapbox/features/verification/steps/sms_verification.js b/app/soapbox/features/verification/steps/sms_verification.js
new file mode 100644
index 000000000..6fd707c81
--- /dev/null
+++ b/app/soapbox/features/verification/steps/sms_verification.js
@@ -0,0 +1,170 @@
+import * as React from 'react';
+import { useIntl } from 'react-intl';
+import OtpInput from 'react-otp-input';
+import { useDispatch, useSelector } from 'react-redux';
+
+import snackbar from 'soapbox/actions/snackbar';
+import { confirmPhoneVerification, requestPhoneVerification } from 'soapbox/actions/verification';
+import { formatPhoneNumber } from 'soapbox/utils/phone';
+
+import { Button, Form, FormGroup, Input, Text } from '../../../components/ui';
+
+const Statuses = {
+ IDLE: 'IDLE',
+ REQUESTED: 'REQUESTED',
+ FAIL: 'FAIL',
+};
+
+const validPhoneNumberRegex = /^\+1\s\(\d{3}\)\s\d{3}-\d{4}/;
+
+const SmsVerification = () => {
+ const intl = useIntl();
+ const dispatch = useDispatch();
+
+ const isLoading = useSelector((state) => state.getIn(['verification', 'isLoading']));
+
+ const [phone, setPhone] = React.useState('');
+ const [status, setStatus] = React.useState(Statuses.IDLE);
+ const [verificationCode, setVerificationCode] = React.useState('');
+ const [requestedAnother, setAlreadyRequestedAnother] = React.useState(false);
+
+ const isValid = validPhoneNumberRegex.test(phone);
+
+ const onChange = React.useCallback((event) => {
+ const formattedPhone = formatPhoneNumber(event.target.value);
+
+ setPhone(formattedPhone);
+ }, []);
+
+ const handleSubmit = React.useCallback((event) => {
+ event.preventDefault();
+
+ if (!isValid) {
+ setStatus(Statuses.IDLE);
+ dispatch(
+ snackbar.error(
+ intl.formatMessage({
+ id: 'sms_verification.invalid',
+ defaultMessage: 'Please enter a valid phone number.',
+ }),
+ ),
+ );
+ return;
+ }
+
+ dispatch(requestPhoneVerification(phone)).then(() => {
+ dispatch(
+ snackbar.success(
+ intl.formatMessage({
+ id: 'sms_verification.success',
+ defaultMessage: 'A verification code has been sent to your phone number.',
+ }),
+ ),
+ );
+ setStatus(Statuses.REQUESTED);
+ }).catch(() => {
+ dispatch(
+ snackbar.error(
+ intl.formatMessage({
+ id: 'sms_verification.fail',
+ defaultMessage: 'Failed to send SMS message to your phone number.',
+ }),
+ ),
+ );
+ setStatus(Statuses.FAIL);
+ });
+ }, [phone, isValid]);
+
+ const resendVerificationCode = React.useCallback((event) => {
+ setAlreadyRequestedAnother(true);
+ handleSubmit(event);
+ }, [isValid]);
+
+ const submitVerification = () => {
+ // TODO: handle proper validation from Pepe -- expired vs invalid
+ dispatch(confirmPhoneVerification(verificationCode))
+ .catch(() => dispatch(
+ snackbar.error(
+ intl.formatMessage({
+ id: 'sms_verification.invalid',
+ defaultMessage: 'Your SMS token has expired.',
+ }),
+ ),
+ ));
+ };
+
+ React.useEffect(() => {
+ if (verificationCode.length === 6) {
+ submitVerification();
+ }
+ }, [verificationCode]);
+
+ if (status === Statuses.REQUESTED) {
+ return (
+
+ );
+};
+
+
+export default SmsVerification;
diff --git a/app/soapbox/features/verification/waitlist_page.js b/app/soapbox/features/verification/waitlist_page.js
new file mode 100644
index 000000000..819e6af85
--- /dev/null
+++ b/app/soapbox/features/verification/waitlist_page.js
@@ -0,0 +1,74 @@
+import PropTypes from 'prop-types';
+import React from 'react';
+import { useIntl } from 'react-intl';
+import { useDispatch, useSelector } from 'react-redux';
+import { Link } from 'react-router-dom';
+
+import { getSoapboxConfig } from 'soapbox/actions/soapbox';
+import BundleContainer from 'soapbox/features/ui/containers/bundle_container';
+import { NotificationsContainer } from 'soapbox/features/ui/util/async-components';
+
+import { logOut } from '../../actions/auth';
+import { Button, Stack, Text } from '../../components/ui';
+
+const WaitlistPage = ({ account }) => {
+ const dispatch = useDispatch();
+ const intl = useIntl();
+
+ const logo = useSelector((state) => getSoapboxConfig(state).get('logo'));
+
+ const waitlistPosition = account.getIn(['source', 'unapproved_position']);
+
+ const onClickLogOut = (event) => {
+ event.preventDefault();
+ dispatch(logOut(intl));
+ };
+
+ return (
+
+ );
+};
+
+WaitlistPage.propTypes = {
+ account: PropTypes.object,
+};
+
+export default WaitlistPage;
diff --git a/app/soapbox/features/video/index.js b/app/soapbox/features/video/index.js
index 90ce9a007..708d87149 100644
--- a/app/soapbox/features/video/index.js
+++ b/app/soapbox/features/video/index.js
@@ -339,7 +339,11 @@ class Video extends React.PureComponent {
}
}
- togglePlay = () => {
+ togglePlay = (e) => {
+ if (e) {
+ e.stopPropagation();
+ }
+
if (this.state.paused) {
this.setState({ paused: false }, () => this.video.play());
} else {
@@ -428,7 +432,9 @@ class Video extends React.PureComponent {
});
}
- toggleReveal = () => {
+ toggleReveal = (e) => {
+ e.stopPropagation();
+
if (this.props.onToggleVisibility) {
this.props.onToggleVisibility();
} else {
@@ -521,7 +527,7 @@ class Video extends React.PureComponent {
return (
= 0 && e < 2 ? "one" : "other";
-}
-```
-
-If your language, like Chinese, do not have any pluralization rule at all you
-may use the Chinese's version of it:
-```javascript
-function (e, a) {
- return "other";
-}
-```
diff --git a/app/soapbox/locales/lt.json b/app/soapbox/locales/lt.json
index 93e7fd5b7..5b265899a 100644
--- a/app/soapbox/locales/lt.json
+++ b/app/soapbox/locales/lt.json
@@ -223,7 +223,7 @@
"column.mfa_disable_button": "Disable",
"column.mfa_setup": "Proceed to Setup",
"column.mutes": "Muted users",
- "column.notifications": "Notifications",
+ "column.notifications": "Alerts",
"column.pins": "Pinned posts",
"column.preferences": "Preferences",
"column.profile_directory": "Profile directory",
@@ -244,7 +244,7 @@
"community.column_settings.title": "Local timeline settings",
"compose.character_counter.title": "Used {chars} out of {maxChars} characters",
"compose.invalid_schedule": "You must schedule a post at least 5 minutes out.",
- "compose.submit_success": "Your post was sent",
+ "compose.submit_success": "Your TRUTH was sent!",
"compose_form.direct_message_warning": "This post will only be sent to the mentioned users.",
"compose_form.hashtag_warning": "This post won't be listed under any hashtag as it is unlisted. Only public posts can be searched by hashtag.",
"compose_form.lock_disclaimer": "Your account is not {locked}. Anyone can follow you to view your follower-only posts.",
@@ -607,7 +607,7 @@
"navigation.direct_messages": "Messages",
"navigation.home": "Home",
"navigation.invites": "Invites",
- "navigation.notifications": "Notifications",
+ "navigation.notifications": "Alerts",
"navigation.search": "Search",
"navigation_bar.account_aliases": "Account aliases",
"navigation_bar.admin_settings": "Admin settings",
@@ -937,7 +937,7 @@
"tabs_bar.header": "Account Info",
"tabs_bar.home": "Home",
"tabs_bar.news": "News",
- "tabs_bar.notifications": "Notifications",
+ "tabs_bar.notifications": "Alerts",
"tabs_bar.post": "Post",
"tabs_bar.search": "Search",
"tabs_bar.theme_toggle_dark": "Switch to dark theme",
diff --git a/app/soapbox/locales/lv.json b/app/soapbox/locales/lv.json
index 7a9f39d78..275a88a47 100644
--- a/app/soapbox/locales/lv.json
+++ b/app/soapbox/locales/lv.json
@@ -244,7 +244,7 @@
"community.column_settings.title": "Local timeline settings",
"compose.character_counter.title": "Used {chars} out of {maxChars} characters",
"compose.invalid_schedule": "You must schedule a post at least 5 minutes out.",
- "compose.submit_success": "Your post was sent",
+ "compose.submit_success": "Your TRUTH was sent!",
"compose_form.direct_message_warning": "Šis ziņojums tiks nosūtīts tikai pieminētajiem lietotājiem.",
"compose_form.hashtag_warning": "Ziņojumu nebūs iespējams atrast zem haštagiem jo tas nav publisks. Tikai publiskos ziņojumus ir iespējams meklēt pēc tiem.",
"compose_form.lock_disclaimer": "Tavs konts nav {locked}. Ikviens var Tev sekot lai apskatītu tikai sekotājiem paredzētos ziņojumus.",
@@ -607,7 +607,7 @@
"navigation.direct_messages": "Messages",
"navigation.home": "Home",
"navigation.invites": "Invites",
- "navigation.notifications": "Notifications",
+ "navigation.notifications": "Alerts",
"navigation.search": "Search",
"navigation_bar.account_aliases": "Account aliases",
"navigation_bar.admin_settings": "Admin settings",
@@ -937,7 +937,7 @@
"tabs_bar.header": "Account Info",
"tabs_bar.home": "Home",
"tabs_bar.news": "News",
- "tabs_bar.notifications": "Notifications",
+ "tabs_bar.notifications": "Alerts",
"tabs_bar.post": "Post",
"tabs_bar.search": "Search",
"tabs_bar.theme_toggle_dark": "Switch to dark theme",
diff --git a/app/soapbox/locales/mk.json b/app/soapbox/locales/mk.json
index ebebc91fc..43998db99 100644
--- a/app/soapbox/locales/mk.json
+++ b/app/soapbox/locales/mk.json
@@ -244,7 +244,7 @@
"community.column_settings.title": "Local timeline settings",
"compose.character_counter.title": "Used {chars} out of {maxChars} characters",
"compose.invalid_schedule": "You must schedule a post at least 5 minutes out.",
- "compose.submit_success": "Your post was sent",
+ "compose.submit_success": "Your TRUTH was sent!",
"compose_form.direct_message_warning": "This post will only be sent to all the mentioned users.",
"compose_form.hashtag_warning": "This post won't be listed under any hashtag as it is unlisted. Only public posts can be searched by hashtag.",
"compose_form.lock_disclaimer": "Your account is not {locked}. Anyone can follow you to view your follower-only posts.",
@@ -607,7 +607,7 @@
"navigation.direct_messages": "Messages",
"navigation.home": "Home",
"navigation.invites": "Invites",
- "navigation.notifications": "Notifications",
+ "navigation.notifications": "Alerts",
"navigation.search": "Search",
"navigation_bar.account_aliases": "Account aliases",
"navigation_bar.admin_settings": "Admin settings",
@@ -937,7 +937,7 @@
"tabs_bar.header": "Account Info",
"tabs_bar.home": "Дома",
"tabs_bar.news": "News",
- "tabs_bar.notifications": "Notifications",
+ "tabs_bar.notifications": "Alerts",
"tabs_bar.post": "Post",
"tabs_bar.search": "Search",
"tabs_bar.theme_toggle_dark": "Switch to dark theme",
diff --git a/app/soapbox/locales/ms.json b/app/soapbox/locales/ms.json
index 489f6500f..8431e9b5b 100644
--- a/app/soapbox/locales/ms.json
+++ b/app/soapbox/locales/ms.json
@@ -223,7 +223,7 @@
"column.mfa_disable_button": "Disable",
"column.mfa_setup": "Proceed to Setup",
"column.mutes": "Muted users",
- "column.notifications": "Notifications",
+ "column.notifications": "Alerts",
"column.pins": "Pinned posts",
"column.preferences": "Preferences",
"column.profile_directory": "Profile directory",
@@ -244,7 +244,7 @@
"community.column_settings.title": "Local timeline settings",
"compose.character_counter.title": "Used {chars} out of {maxChars} characters",
"compose.invalid_schedule": "You must schedule a post at least 5 minutes out.",
- "compose.submit_success": "Your post was sent",
+ "compose.submit_success": "Your TRUTH was sent!",
"compose_form.direct_message_warning": "This toot will only be sent to all the mentioned users.",
"compose_form.hashtag_warning": "This post won't be listed under any hashtag as it is unlisted. Only public posts can be searched by hashtag.",
"compose_form.lock_disclaimer": "Your account is not {locked}. Anyone can follow you to view your follower-only posts.",
@@ -607,7 +607,7 @@
"navigation.direct_messages": "Messages",
"navigation.home": "Home",
"navigation.invites": "Invites",
- "navigation.notifications": "Notifications",
+ "navigation.notifications": "Alerts",
"navigation.search": "Search",
"navigation_bar.account_aliases": "Account aliases",
"navigation_bar.admin_settings": "Admin settings",
@@ -937,7 +937,7 @@
"tabs_bar.header": "Account Info",
"tabs_bar.home": "Home",
"tabs_bar.news": "News",
- "tabs_bar.notifications": "Notifications",
+ "tabs_bar.notifications": "Alerts",
"tabs_bar.post": "Post",
"tabs_bar.search": "Search",
"tabs_bar.theme_toggle_dark": "Switch to dark theme",
diff --git a/app/soapbox/locales/nl.json b/app/soapbox/locales/nl.json
index 56135f986..876637a27 100644
--- a/app/soapbox/locales/nl.json
+++ b/app/soapbox/locales/nl.json
@@ -244,7 +244,7 @@
"community.column_settings.title": "Local timeline settings",
"compose.character_counter.title": "Used {chars} out of {maxChars} characters",
"compose.invalid_schedule": "You must schedule a post at least 5 minutes out.",
- "compose.submit_success": "Your post was sent",
+ "compose.submit_success": "Your TRUTH was sent!",
"compose_form.direct_message_warning": "Deze toot wordt alleen naar vermelde gebruikers verstuurd. Echter, de beheerders en moderatoren van jouw en de ontvangende server(s) kunnen dit bericht mogelijk wel bekijken.",
"compose_form.hashtag_warning": "Deze toot valt niet onder een hashtag te bekijken, omdat deze niet op openbare tijdlijnen wordt getoond. Alleen openbare toots kunnen via hashtags gevonden worden.",
"compose_form.lock_disclaimer": "Jouw account is niet {locked}. Iedereen kan jou volgen en kan de toots zien die je alleen aan jouw volgers hebt gericht.",
@@ -607,7 +607,7 @@
"navigation.direct_messages": "Messages",
"navigation.home": "Home",
"navigation.invites": "Invites",
- "navigation.notifications": "Notifications",
+ "navigation.notifications": "Alerts",
"navigation.search": "Search",
"navigation_bar.account_aliases": "Account aliases",
"navigation_bar.admin_settings": "Admin settings",
diff --git a/app/soapbox/locales/nn.json b/app/soapbox/locales/nn.json
index 12b2e64ae..54c9381d7 100644
--- a/app/soapbox/locales/nn.json
+++ b/app/soapbox/locales/nn.json
@@ -244,7 +244,7 @@
"community.column_settings.title": "Local timeline settings",
"compose.character_counter.title": "Used {chars} out of {maxChars} characters",
"compose.invalid_schedule": "You must schedule a post at least 5 minutes out.",
- "compose.submit_success": "Your post was sent",
+ "compose.submit_success": "Your TRUTH was sent!",
"compose_form.direct_message_warning": "Denne tuten vil kun verte synleg for nemnde brukarar.",
"compose_form.hashtag_warning": "Denne tuten vill ikkje bli lista under nokon knagg ettersom den ikkje er opplista. Berre offentlege tutar kan ble søkt på ved emneknagg.",
"compose_form.lock_disclaimer": "Din brukar er ikkje {locked}. Alle kan følje deg for å sjå føljar-modus poster.",
@@ -607,7 +607,7 @@
"navigation.direct_messages": "Messages",
"navigation.home": "Home",
"navigation.invites": "Invites",
- "navigation.notifications": "Notifications",
+ "navigation.notifications": "Alerts",
"navigation.search": "Search",
"navigation_bar.account_aliases": "Account aliases",
"navigation_bar.admin_settings": "Admin settings",
@@ -937,7 +937,7 @@
"tabs_bar.header": "Account Info",
"tabs_bar.home": "Heim",
"tabs_bar.news": "News",
- "tabs_bar.notifications": "Notifications",
+ "tabs_bar.notifications": "Alerts",
"tabs_bar.post": "Post",
"tabs_bar.search": "Search",
"tabs_bar.theme_toggle_dark": "Switch to dark theme",
diff --git a/app/soapbox/locales/no.json b/app/soapbox/locales/no.json
index e3272cc76..24f3b849e 100644
--- a/app/soapbox/locales/no.json
+++ b/app/soapbox/locales/no.json
@@ -244,7 +244,7 @@
"community.column_settings.title": "Local timeline settings",
"compose.character_counter.title": "Used {chars} out of {maxChars} characters",
"compose.invalid_schedule": "You must schedule a post at least 5 minutes out.",
- "compose.submit_success": "Your post was sent",
+ "compose.submit_success": "Your TRUTH was sent!",
"compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
"compose_form.hashtag_warning": "Denne tuten blir ikke listet under noen emneknagger da den er ulistet. Kun offentlige tuter kan søktes etter med emneknagg.",
"compose_form.lock_disclaimer": "Din konto er ikke {locked}. Hvem som helst kan følge deg og se dine private poster.",
@@ -607,7 +607,7 @@
"navigation.direct_messages": "Messages",
"navigation.home": "Home",
"navigation.invites": "Invites",
- "navigation.notifications": "Notifications",
+ "navigation.notifications": "Alerts",
"navigation.search": "Search",
"navigation_bar.account_aliases": "Account aliases",
"navigation_bar.admin_settings": "Admin settings",
diff --git a/app/soapbox/locales/oc.json b/app/soapbox/locales/oc.json
index cd11328a9..5d2d879a4 100644
--- a/app/soapbox/locales/oc.json
+++ b/app/soapbox/locales/oc.json
@@ -244,7 +244,7 @@
"community.column_settings.title": "Local timeline settings",
"compose.character_counter.title": "Used {chars} out of {maxChars} characters",
"compose.invalid_schedule": "You must schedule a post at least 5 minutes out.",
- "compose.submit_success": "Your post was sent",
+ "compose.submit_success": "Your TRUTH was sent!",
"compose_form.direct_message_warning": "Sols los mencionats poiràn veire aqueste tut.",
"compose_form.hashtag_warning": "Aqueste tut serà pas ligat a cap d’etiqueta estant qu’es pas listat. Òm pòt pas cercar que los tuts publics per etiqueta.",
"compose_form.lock_disclaimer": "Vòstre compte es pas {locked}. Tot lo monde pòt vos sègre e veire los estatuts reservats als seguidors.",
@@ -607,7 +607,7 @@
"navigation.direct_messages": "Messages",
"navigation.home": "Home",
"navigation.invites": "Invites",
- "navigation.notifications": "Notifications",
+ "navigation.notifications": "Alerts",
"navigation.search": "Search",
"navigation_bar.account_aliases": "Account aliases",
"navigation_bar.admin_settings": "Admin settings",
diff --git a/app/soapbox/locales/pt-BR.json b/app/soapbox/locales/pt-BR.json
index 4fac771aa..16e8120c8 100644
--- a/app/soapbox/locales/pt-BR.json
+++ b/app/soapbox/locales/pt-BR.json
@@ -244,7 +244,7 @@
"community.column_settings.title": "Local timeline settings",
"compose.character_counter.title": "Used {chars} out of {maxChars} characters",
"compose.invalid_schedule": "You must schedule a post at least 5 minutes out.",
- "compose.submit_success": "Your post was sent",
+ "compose.submit_success": "Your TRUTH was sent!",
"compose_form.direct_message_warning": "Este toot só será enviado aos usuários mencionados.",
"compose_form.hashtag_warning": "Esse toot não será listado em nenhuma hashtag por ser não listado. Somente toots públicos podem ser pesquisados por hashtag.",
"compose_form.lock_disclaimer": "A sua conta não está {locked}. Qualquer pessoa pode te seguir e visualizar postagens direcionadas a apenas seguidores.",
@@ -607,7 +607,7 @@
"navigation.direct_messages": "Messages",
"navigation.home": "Home",
"navigation.invites": "Invites",
- "navigation.notifications": "Notifications",
+ "navigation.notifications": "Alerts",
"navigation.search": "Search",
"navigation_bar.account_aliases": "Account aliases",
"navigation_bar.admin_settings": "Admin settings",
diff --git a/app/soapbox/locales/pt.json b/app/soapbox/locales/pt.json
index b8c30f1bd..fcbd1f257 100644
--- a/app/soapbox/locales/pt.json
+++ b/app/soapbox/locales/pt.json
@@ -244,7 +244,7 @@
"community.column_settings.title": "Local timeline settings",
"compose.character_counter.title": "Used {chars} out of {maxChars} characters",
"compose.invalid_schedule": "You must schedule a post at least 5 minutes out.",
- "compose.submit_success": "Your post was sent",
+ "compose.submit_success": "Your TRUTH was sent!",
"compose_form.direct_message_warning": "Esta publicação será enviada apenas para os utilizadores mencionados.",
"compose_form.hashtag_warning": "Esta publicação não será listada em nenhuma hashtag por ser não listado. Apenas publicações públicas podem ser pesquisados por hashtags.",
"compose_form.lock_disclaimer": "A tua conta não está {locked}. Qualquer pessoa pode seguir-te e ver as publicações direcionadas apenas a seguidores.",
@@ -607,7 +607,7 @@
"navigation.direct_messages": "Messages",
"navigation.home": "Home",
"navigation.invites": "Invites",
- "navigation.notifications": "Notifications",
+ "navigation.notifications": "Alerts",
"navigation.search": "Search",
"navigation_bar.account_aliases": "Account aliases",
"navigation_bar.admin_settings": "Painel de Admin.",
diff --git a/app/soapbox/locales/ro.json b/app/soapbox/locales/ro.json
index 951b7782e..87d1cf68e 100644
--- a/app/soapbox/locales/ro.json
+++ b/app/soapbox/locales/ro.json
@@ -244,7 +244,7 @@
"community.column_settings.title": "Local timeline settings",
"compose.character_counter.title": "Used {chars} out of {maxChars} characters",
"compose.invalid_schedule": "You must schedule a post at least 5 minutes out.",
- "compose.submit_success": "Your post was sent",
+ "compose.submit_success": "Your TRUTH was sent!",
"compose_form.direct_message_warning": "Această postare va fi trimisă doar utilizatorilor menționați.",
"compose_form.hashtag_warning": "Această postare nu va fi listată sub nici un hastag. Doar postările publice pot fi găsite dupa un hastag.",
"compose_form.lock_disclaimer": "Contul tău nu este {locked}. Oricine te poate urmări fără aprobarea ta și vedea toate postările tale.",
@@ -607,7 +607,7 @@
"navigation.direct_messages": "Messages",
"navigation.home": "Home",
"navigation.invites": "Invites",
- "navigation.notifications": "Notifications",
+ "navigation.notifications": "Alerts",
"navigation.search": "Search",
"navigation_bar.account_aliases": "Account aliases",
"navigation_bar.admin_settings": "Admin settings",
diff --git a/app/soapbox/locales/ru.json b/app/soapbox/locales/ru.json
index c82de3ef6..ce079be77 100644
--- a/app/soapbox/locales/ru.json
+++ b/app/soapbox/locales/ru.json
@@ -244,7 +244,7 @@
"community.column_settings.title": "Local timeline settings",
"compose.character_counter.title": "Used {chars} out of {maxChars} characters",
"compose.invalid_schedule": "You must schedule a post at least 5 minutes out.",
- "compose.submit_success": "Your post was sent",
+ "compose.submit_success": "Your TRUTH was sent!",
"compose_form.direct_message_warning": "Этот статус будет виден только упомянутым пользователям.",
"compose_form.hashtag_warning": "Этот пост не будет показывается в поиске по хэштегу, т.к. он непубличный. Только публичные посты можно найти в поиске по хэштегу.",
"compose_form.lock_disclaimer": "Ваш аккаунт не {locked}. Любой человек может подписаться на Вас и просматривать посты для подписчиков.",
@@ -607,7 +607,7 @@
"navigation.direct_messages": "Messages",
"navigation.home": "Home",
"navigation.invites": "Invites",
- "navigation.notifications": "Notifications",
+ "navigation.notifications": "Alerts",
"navigation.search": "Search",
"navigation_bar.account_aliases": "Account aliases",
"navigation_bar.admin_settings": "Admin settings",
diff --git a/app/soapbox/locales/sk.json b/app/soapbox/locales/sk.json
index b80d5411f..ba1ed0514 100644
--- a/app/soapbox/locales/sk.json
+++ b/app/soapbox/locales/sk.json
@@ -244,7 +244,7 @@
"community.column_settings.title": "Local timeline settings",
"compose.character_counter.title": "Used {chars} out of {maxChars} characters",
"compose.invalid_schedule": "You must schedule a post at least 5 minutes out.",
- "compose.submit_success": "Your post was sent",
+ "compose.submit_success": "Your TRUTH was sent!",
"compose_form.direct_message_warning": "Tento príspevok bude videný výhradne iba spomenutými užívateľmi. Ber ale na vedomie že správci tvojej a všetkých iných zahrnutých instancií majú možnosť skontrolovať túto správu.",
"compose_form.hashtag_warning": "Tento toot nebude zobrazený pod žiadným haštagom lebo nieje listovaný. Iba verejné tooty môžu byť nájdené podľa haštagu.",
"compose_form.lock_disclaimer": "Tvoj účet nie je {locked}. Ktokoľvek ťa môže nasledovať a vidieť tvoje správy pre sledujúcich.",
@@ -607,7 +607,7 @@
"navigation.direct_messages": "Messages",
"navigation.home": "Home",
"navigation.invites": "Invites",
- "navigation.notifications": "Notifications",
+ "navigation.notifications": "Alerts",
"navigation.search": "Search",
"navigation_bar.account_aliases": "Account aliases",
"navigation_bar.admin_settings": "Admin settings",
diff --git a/app/soapbox/locales/sl.json b/app/soapbox/locales/sl.json
index bdc41af55..336667d48 100644
--- a/app/soapbox/locales/sl.json
+++ b/app/soapbox/locales/sl.json
@@ -244,7 +244,7 @@
"community.column_settings.title": "Local timeline settings",
"compose.character_counter.title": "Used {chars} out of {maxChars} characters",
"compose.invalid_schedule": "You must schedule a post at least 5 minutes out.",
- "compose.submit_success": "Your post was sent",
+ "compose.submit_success": "Your TRUTH was sent!",
"compose_form.direct_message_warning": "Ta tut bo viden le vsem omenjenim uporabnikom.",
"compose_form.hashtag_warning": "Ta tut ne bo naveden pod nobenim ključnikom, ker ni javen. Samo javne tute lahko iščete s ključniki.",
"compose_form.lock_disclaimer": "Vaš račun ni {locked}. Vsakdo vam lahko sledi in si ogleda objave, ki so namenjene samo sledilcem.",
@@ -607,7 +607,7 @@
"navigation.direct_messages": "Messages",
"navigation.home": "Home",
"navigation.invites": "Invites",
- "navigation.notifications": "Notifications",
+ "navigation.notifications": "Alerts",
"navigation.search": "Search",
"navigation_bar.account_aliases": "Account aliases",
"navigation_bar.admin_settings": "Admin settings",
diff --git a/app/soapbox/locales/sq.json b/app/soapbox/locales/sq.json
index 3e388b56f..531c4199a 100644
--- a/app/soapbox/locales/sq.json
+++ b/app/soapbox/locales/sq.json
@@ -244,7 +244,7 @@
"community.column_settings.title": "Local timeline settings",
"compose.character_counter.title": "Used {chars} out of {maxChars} characters",
"compose.invalid_schedule": "You must schedule a post at least 5 minutes out.",
- "compose.submit_success": "Your post was sent",
+ "compose.submit_success": "Your TRUTH was sent!",
"compose_form.direct_message_warning": "Ky mesazh do t’u dërgohet përdoruesve të përmendur.",
"compose_form.hashtag_warning": "Ky mesazh s’do të paraqitet nën ndonjë hashtag, ngaqë s’i është caktuar ndonjë. Vetëm mesazhet publike mund të kërkohen sipas hashtagësh.",
"compose_form.lock_disclaimer": "Llogaria juaj s’është {locked}. Mund ta ndjekë cilido, për të parë postimet tuaja vetëm për ndjekësit.",
@@ -607,7 +607,7 @@
"navigation.direct_messages": "Messages",
"navigation.home": "Home",
"navigation.invites": "Invites",
- "navigation.notifications": "Notifications",
+ "navigation.notifications": "Alerts",
"navigation.search": "Search",
"navigation_bar.account_aliases": "Account aliases",
"navigation_bar.admin_settings": "Admin settings",
diff --git a/app/soapbox/locales/sr-Latn.json b/app/soapbox/locales/sr-Latn.json
index b2e33e062..c8c0b8220 100644
--- a/app/soapbox/locales/sr-Latn.json
+++ b/app/soapbox/locales/sr-Latn.json
@@ -244,7 +244,7 @@
"community.column_settings.title": "Local timeline settings",
"compose.character_counter.title": "Used {chars} out of {maxChars} characters",
"compose.invalid_schedule": "You must schedule a post at least 5 minutes out.",
- "compose.submit_success": "Your post was sent",
+ "compose.submit_success": "Your TRUTH was sent!",
"compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
"compose_form.hashtag_warning": "This post won't be listed under any hashtag as it is unlisted. Only public posts can be searched by hashtag.",
"compose_form.lock_disclaimer": "Vaš nalog nije {locked}. Svako može da Vas zaprati i da vidi objave namenjene samo Vašim pratiocima.",
@@ -607,7 +607,7 @@
"navigation.direct_messages": "Messages",
"navigation.home": "Home",
"navigation.invites": "Invites",
- "navigation.notifications": "Notifications",
+ "navigation.notifications": "Alerts",
"navigation.search": "Search",
"navigation_bar.account_aliases": "Account aliases",
"navigation_bar.admin_settings": "Admin settings",
diff --git a/app/soapbox/locales/sr.json b/app/soapbox/locales/sr.json
index 5e6fc48b8..d1cd785f3 100644
--- a/app/soapbox/locales/sr.json
+++ b/app/soapbox/locales/sr.json
@@ -244,7 +244,7 @@
"community.column_settings.title": "Local timeline settings",
"compose.character_counter.title": "Used {chars} out of {maxChars} characters",
"compose.invalid_schedule": "You must schedule a post at least 5 minutes out.",
- "compose.submit_success": "Your post was sent",
+ "compose.submit_success": "Your TRUTH was sent!",
"compose_form.direct_message_warning": "Ова труба ће бити послата споменутим корисницима.",
"compose_form.hashtag_warning": "Ова труба неће бити излистана под било којом тарабом јер је сакривена. Само јавне трубе могу бити претражене тарабом.",
"compose_form.lock_disclaimer": "Ваш налог није {locked}. Свако може да Вас запрати и да види објаве намењене само Вашим пратиоцима.",
@@ -607,7 +607,7 @@
"navigation.direct_messages": "Messages",
"navigation.home": "Home",
"navigation.invites": "Invites",
- "navigation.notifications": "Notifications",
+ "navigation.notifications": "Alerts",
"navigation.search": "Search",
"navigation_bar.account_aliases": "Account aliases",
"navigation_bar.admin_settings": "Admin settings",
diff --git a/app/soapbox/locales/sv.json b/app/soapbox/locales/sv.json
index bad296144..ceab37c74 100644
--- a/app/soapbox/locales/sv.json
+++ b/app/soapbox/locales/sv.json
@@ -244,7 +244,7 @@
"community.column_settings.title": "Local timeline settings",
"compose.character_counter.title": "Used {chars} out of {maxChars} characters",
"compose.invalid_schedule": "You must schedule a post at least 5 minutes out.",
- "compose.submit_success": "Your post was sent",
+ "compose.submit_success": "Your TRUTH was sent!",
"compose_form.direct_message_warning": "Denna post kommer endast att skickas nämnda nämnda användare.",
"compose_form.hashtag_warning": "Denna toot kommer inte att listas under någon hashtag eftersom den är onoterad. Endast offentliga toots kan sökas med hashtag.",
"compose_form.lock_disclaimer": "Ditt konto är inte {locked}. Vem som helst kan följa dig och även se dina inlägg som bara är för följare.",
@@ -607,7 +607,7 @@
"navigation.direct_messages": "Messages",
"navigation.home": "Home",
"navigation.invites": "Invites",
- "navigation.notifications": "Notifications",
+ "navigation.notifications": "Alerts",
"navigation.search": "Search",
"navigation_bar.account_aliases": "Account aliases",
"navigation_bar.admin_settings": "Admin settings",
diff --git a/app/soapbox/locales/ta.json b/app/soapbox/locales/ta.json
index a7b673734..0c4bbc1c6 100644
--- a/app/soapbox/locales/ta.json
+++ b/app/soapbox/locales/ta.json
@@ -223,7 +223,7 @@
"column.mfa_disable_button": "Disable",
"column.mfa_setup": "Proceed to Setup",
"column.mutes": "முடக்கப்பட்ட பயனர்கள்",
- "column.notifications": "Notifications",
+ "column.notifications": "Alerts",
"column.pins": "Pinned posts",
"column.preferences": "Preferences",
"column.profile_directory": "Profile directory",
@@ -244,7 +244,7 @@
"community.column_settings.title": "Local timeline settings",
"compose.character_counter.title": "Used {chars} out of {maxChars} characters",
"compose.invalid_schedule": "You must schedule a post at least 5 minutes out.",
- "compose.submit_success": "Your post was sent",
+ "compose.submit_success": "Your TRUTH was sent!",
"compose_form.direct_message_warning": "This toot will only be sent to all the mentioned users.",
"compose_form.hashtag_warning": "இந்த toot பட்டியலிடப்படாதது போல எந்த ஹேஸ்டேக்கின் கீழ் பட்டியலிடப்படாது. ஹேஸ்டேக் மூலம் பொது டோட்டல்கள் மட்டுமே தேட முடியும்.",
"compose_form.lock_disclaimer": "உங்கள் கணக்கு அல்ல {locked}. உங்களுடைய பின்தொடர்பவர் மட்டும் இடுகைகளை யாராவது காணலாம்.",
@@ -607,7 +607,7 @@
"navigation.direct_messages": "Messages",
"navigation.home": "Home",
"navigation.invites": "Invites",
- "navigation.notifications": "Notifications",
+ "navigation.notifications": "Alerts",
"navigation.search": "Search",
"navigation_bar.account_aliases": "Account aliases",
"navigation_bar.admin_settings": "Admin settings",
@@ -937,7 +937,7 @@
"tabs_bar.header": "Account Info",
"tabs_bar.home": "Home",
"tabs_bar.news": "News",
- "tabs_bar.notifications": "Notifications",
+ "tabs_bar.notifications": "Alerts",
"tabs_bar.post": "Post",
"tabs_bar.search": "தேடு",
"tabs_bar.theme_toggle_dark": "Switch to dark theme",
diff --git a/app/soapbox/locales/te.json b/app/soapbox/locales/te.json
index 53c361321..c9b3066f5 100644
--- a/app/soapbox/locales/te.json
+++ b/app/soapbox/locales/te.json
@@ -244,7 +244,7 @@
"community.column_settings.title": "Local timeline settings",
"compose.character_counter.title": "Used {chars} out of {maxChars} characters",
"compose.invalid_schedule": "You must schedule a post at least 5 minutes out.",
- "compose.submit_success": "Your post was sent",
+ "compose.submit_success": "Your TRUTH was sent!",
"compose_form.direct_message_warning": "ఈ టూట్ పేర్కొన్న వినియోగదారులకు మాత్రమే పంపబడుతుంది.",
"compose_form.hashtag_warning": "ఈ టూట్ అన్లిస్టెడ్ కాబట్టి ఏ హాష్ ట్యాగ్ క్రిందకూ రాదు. పబ్లిక్ టూట్ లను మాత్రమే హాష్ ట్యాగ్ ద్వారా శోధించవచ్చు.",
"compose_form.lock_disclaimer": "మీ ఖాతా {locked} చేయబడలేదు. ఎవరైనా మిమ్మల్ని అనుసరించి మీ అనుచరులకు-మాత్రమే పోస్ట్లను వీక్షించవచ్చు.",
@@ -607,7 +607,7 @@
"navigation.direct_messages": "Messages",
"navigation.home": "Home",
"navigation.invites": "Invites",
- "navigation.notifications": "Notifications",
+ "navigation.notifications": "Alerts",
"navigation.search": "Search",
"navigation_bar.account_aliases": "Account aliases",
"navigation_bar.admin_settings": "Admin settings",
diff --git a/app/soapbox/locales/th.json b/app/soapbox/locales/th.json
index 0d1ff6407..bc6049959 100644
--- a/app/soapbox/locales/th.json
+++ b/app/soapbox/locales/th.json
@@ -244,7 +244,7 @@
"community.column_settings.title": "Local timeline settings",
"compose.character_counter.title": "Used {chars} out of {maxChars} characters",
"compose.invalid_schedule": "You must schedule a post at least 5 minutes out.",
- "compose.submit_success": "Your post was sent",
+ "compose.submit_success": "Your TRUTH was sent!",
"compose_form.direct_message_warning": "จะส่งโพสต์นี้ไปยังผู้ใช้ที่กล่าวถึงเท่านั้น",
"compose_form.hashtag_warning": "จะไม่แสดงรายการโพสต์นี้ภายใต้แฮชแท็กใด ๆ เนื่องจากไม่อยู่ในรายการ เฉพาะโพสต์สาธารณะเท่านั้นที่สามารถค้นหาโดยแฮชแท็ก",
"compose_form.lock_disclaimer": "บัญชีของคุณไม่ได้ {locked} ใครก็ตามสามารถติดตามคุณเพื่อดูโพสต์สำหรับผู้ติดตามเท่านั้นของคุณ",
@@ -607,7 +607,7 @@
"navigation.direct_messages": "Messages",
"navigation.home": "Home",
"navigation.invites": "Invites",
- "navigation.notifications": "Notifications",
+ "navigation.notifications": "Alerts",
"navigation.search": "Search",
"navigation_bar.account_aliases": "Account aliases",
"navigation_bar.admin_settings": "Admin settings",
diff --git a/app/soapbox/locales/tr.json b/app/soapbox/locales/tr.json
index 12eb21c09..9a5389031 100644
--- a/app/soapbox/locales/tr.json
+++ b/app/soapbox/locales/tr.json
@@ -244,7 +244,7 @@
"community.column_settings.title": "Local timeline settings",
"compose.character_counter.title": "Used {chars} out of {maxChars} characters",
"compose.invalid_schedule": "You must schedule a post at least 5 minutes out.",
- "compose.submit_success": "Your post was sent",
+ "compose.submit_success": "Your TRUTH was sent!",
"compose_form.direct_message_warning": "Bu gönderi sadece belirtilen kullanıcılara gönderilecektir.",
"compose_form.hashtag_warning": "Bu paylaşım liste dışı olduğu için hiç bir hashtag'de yer almayacak. Sadece herkese açık gönderiler hashtaglerde bulunabilir.",
"compose_form.lock_disclaimer": "Hesabınız {locked} değil. Sadece takipçilerle paylaştığınız gönderileri görebilmek için sizi herhangi bir kullanıcı takip edebilir.",
@@ -607,7 +607,7 @@
"navigation.direct_messages": "Messages",
"navigation.home": "Home",
"navigation.invites": "Invites",
- "navigation.notifications": "Notifications",
+ "navigation.notifications": "Alerts",
"navigation.search": "Search",
"navigation_bar.account_aliases": "Account aliases",
"navigation_bar.admin_settings": "Admin settings",
diff --git a/app/soapbox/locales/zh-HK.json b/app/soapbox/locales/zh-HK.json
index 8adb2bafb..efd98640b 100644
--- a/app/soapbox/locales/zh-HK.json
+++ b/app/soapbox/locales/zh-HK.json
@@ -244,7 +244,7 @@
"community.column_settings.title": "Local timeline settings",
"compose.character_counter.title": "Used {chars} out of {maxChars} characters",
"compose.invalid_schedule": "You must schedule a post at least 5 minutes out.",
- "compose.submit_success": "Your post was sent",
+ "compose.submit_success": "Your TRUTH was sent!",
"compose_form.direct_message_warning": "這文章只有被提及的用戶才可以看到。",
"compose_form.hashtag_warning": "這文章因為不是公開,所以不會被標籤搜索。只有公開的文章才會被標籤搜索。",
"compose_form.lock_disclaimer": "你的用戶狀態為「{locked}」,任何人都能立即關注你,然後看到「只有關注者能看」的文章。",
@@ -607,7 +607,7 @@
"navigation.direct_messages": "Messages",
"navigation.home": "Home",
"navigation.invites": "Invites",
- "navigation.notifications": "Notifications",
+ "navigation.notifications": "Alerts",
"navigation.search": "Search",
"navigation_bar.account_aliases": "Account aliases",
"navigation_bar.admin_settings": "Admin settings",
diff --git a/app/soapbox/locales/zh-TW.json b/app/soapbox/locales/zh-TW.json
index b6b3107c5..e65b40e7c 100644
--- a/app/soapbox/locales/zh-TW.json
+++ b/app/soapbox/locales/zh-TW.json
@@ -244,7 +244,7 @@
"community.column_settings.title": "Local timeline settings",
"compose.character_counter.title": "Used {chars} out of {maxChars} characters",
"compose.invalid_schedule": "You must schedule a post at least 5 minutes out.",
- "compose.submit_success": "Your post was sent",
+ "compose.submit_success": "Your TRUTH was sent!",
"compose_form.direct_message_warning": "這條嘟文只有被提及的使用者才看得到。",
"compose_form.hashtag_warning": "由於這則嘟文被設定成「不公開」,所以它將不會被列在任何主題標籤下。只有公開的嘟文才能藉主題標籤找到。",
"compose_form.lock_disclaimer": "您的帳戶尚未{locked}。任何人都能關注您並看到您設定成只有關注者能看的嘟文。",
@@ -607,7 +607,7 @@
"navigation.direct_messages": "Messages",
"navigation.home": "Home",
"navigation.invites": "Invites",
- "navigation.notifications": "Notifications",
+ "navigation.notifications": "Alerts",
"navigation.search": "Search",
"navigation_bar.account_aliases": "Account aliases",
"navigation_bar.admin_settings": "Admin settings",
diff --git a/app/soapbox/main.js b/app/soapbox/main.js
index dfac430e0..f2318d008 100644
--- a/app/soapbox/main.js
+++ b/app/soapbox/main.js
@@ -1,11 +1,11 @@
'use strict';
import './precheck';
-import * as OfflinePluginRuntime from '@lcdp/offline-plugin/runtime';
+// import * as OfflinePluginRuntime from '@lcdp/offline-plugin/runtime';
import React from 'react';
import ReactDOM from 'react-dom';
-import { NODE_ENV } from 'soapbox/build_config';
+// import { NODE_ENV } from 'soapbox/build_config';
import { default as Soapbox } from './containers/soapbox';
import * as monitoring from './monitoring';
@@ -23,10 +23,10 @@ function main() {
ReactDOM.render(
, mountNode);
- if (NODE_ENV === 'production') {
- // avoid offline in dev mode because it's harder to debug
- OfflinePluginRuntime.install();
- }
+ // if (NODE_ENV === 'production') {
+ // // avoid offline in dev mode because it's harder to debug
+ // OfflinePluginRuntime.install();
+ // }
perf.stop('main()');
});
}
diff --git a/app/soapbox/pages/default_page.js b/app/soapbox/pages/default_page.js
index cd7a7efce..05ae7d2d5 100644
--- a/app/soapbox/pages/default_page.js
+++ b/app/soapbox/pages/default_page.js
@@ -1,20 +1,19 @@
import React from 'react';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { connect } from 'react-redux';
-import Sticky from 'react-stickynode';
-import PrimaryNavigation from 'soapbox/components/primary_navigation';
+import SidebarNavigation from 'soapbox/components/sidebar-navigation';
import LinkFooter from 'soapbox/features/ui/components/link_footer';
import BundleContainer from 'soapbox/features/ui/containers/bundle_container';
import {
WhoToFollowPanel,
TrendsPanel,
- PromoPanel,
- FeaturesPanel,
SignUpPanel,
} from 'soapbox/features/ui/util/async-components';
import { getFeatures } from 'soapbox/utils/features';
+import { Layout } from '../components/ui';
+
const mapStateToProps = state => {
const me = state.get('me');
const features = getFeatures(state.get('instance'));
@@ -33,56 +32,34 @@ class DefaultPage extends ImmutablePureComponent {
const { me, children, showTrendsPanel, showWhoToFollowPanel } = this.props;
return (
-
-
-
+
+
+
+
-
+
+ {children}
+
-
-
-
-
-
- {me ? (
-
- {Component => }
-
- ) : (
-
- {Component => }
-
- )}
-
- {Component => }
-
- {showTrendsPanel && (
-
- {Component => }
-
- )}
- {showWhoToFollowPanel && (
-
- {Component => }
-
- )}
-
-
-
-
-
-
-
+
+ {!me && (
+
+ {Component => }
+
+ )}
+ {showTrendsPanel && (
+
+ {Component => }
+
+ )}
+ {showWhoToFollowPanel && (
+
+ {Component => }
+
+ )}
+
+
+
);
}
diff --git a/app/soapbox/pages/empty_page.js b/app/soapbox/pages/empty_page.js
index 45a7f24d1..042fd6c41 100644
--- a/app/soapbox/pages/empty_page.js
+++ b/app/soapbox/pages/empty_page.js
@@ -1,32 +1,23 @@
import React from 'react';
import ImmutablePureComponent from 'react-immutable-pure-component';
+import { Layout } from '../components/ui';
+
export default class DefaultPage extends ImmutablePureComponent {
render() {
const { children } = this.props;
return (
-
-
-
+
+
-
+
+ {children}
+
-
-
-
-
-
-
+
+
);
}
diff --git a/app/soapbox/pages/group_page.js b/app/soapbox/pages/group_page.js
index bd7b7f85d..c148c148c 100644
--- a/app/soapbox/pages/group_page.js
+++ b/app/soapbox/pages/group_page.js
@@ -10,7 +10,7 @@ import GroupPanel from '../features/groups/timeline/components/panel';
import HeaderContainer from '../features/groups/timeline/containers/header_container';
import LinkFooter from '../features/ui/components/link_footer';
import PromoPanel from '../features/ui/components/promo_panel';
-import WhoToFollowPanel from '../features/ui/components/who_to_follow_panel';
+import WhoToFollowPanel from '../features/ui/components/who-to-follow-panel';
const mapStateToProps = (state, { params: { id } }) => ({
group: state.getIn(['groups', id]),
diff --git a/app/soapbox/pages/groups_page.js b/app/soapbox/pages/groups_page.js
index 623e70727..76a86c714 100644
--- a/app/soapbox/pages/groups_page.js
+++ b/app/soapbox/pages/groups_page.js
@@ -7,7 +7,7 @@ import GroupSidebarPanel from '../features/groups/sidebar_panel';
import LinkFooter from '../features/ui/components/link_footer';
import PromoPanel from '../features/ui/components/promo_panel';
import UserPanel from '../features/ui/components/user_panel';
-import WhoToFollowPanel from '../features/ui/components/who_to_follow_panel';
+import WhoToFollowPanel from '../features/ui/components/who-to-follow-panel';
const mapStateToProps = state => {
const me = state.get('me');
diff --git a/app/soapbox/pages/home_page.js b/app/soapbox/pages/home_page.js
index 384c97307..65d581d28 100644
--- a/app/soapbox/pages/home_page.js
+++ b/app/soapbox/pages/home_page.js
@@ -2,25 +2,20 @@ import React from 'react';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { connect } from 'react-redux';
import { Link } from 'react-router-dom';
-import Sticky from 'react-stickynode';
import { getSoapboxConfig } from 'soapbox/actions/soapbox';
-import PrimaryNavigation from 'soapbox/components/primary_navigation';
+import SidebarNavigation from 'soapbox/components/sidebar-navigation';
import LinkFooter from 'soapbox/features/ui/components/link_footer';
import {
WhoToFollowPanel,
- CryptoDonatePanel,
- // UserPanel,
TrendsPanel,
- PromoPanel,
- FundingPanel,
- FeaturesPanel,
SignUpPanel,
} from 'soapbox/features/ui/util/async-components';
// import GroupSidebarPanel from '../features/groups/sidebar_panel';
import { getFeatures } from 'soapbox/utils/features';
import Avatar from '../components/avatar';
+import { Card, CardBody, Layout } from '../components/ui';
import ComposeFormContainer from '../features/compose/containers/compose_form_container';
import BundleContainer from '../features/ui/containers/bundle_container';
@@ -52,82 +47,55 @@ class HomePage extends ImmutablePureComponent {
}
render() {
- const { me, children, account, showFundingPanel, showCryptoDonatePanel, cryptoLimit, showTrendsPanel, showWhoToFollowPanel } = this.props;
+ const { me, children, account, showTrendsPanel, showWhoToFollowPanel } = this.props;
const acct = account ? account.get('acct') : '';
return (
-
-
-
+
+
+
+
-
-
+
+ }
-
-
- {me &&
}
+ {children}
+
- {children}
-
-
-
-
-
-
- {me ? (
-
- {Component => }
-
- ) : (
-
- {Component => }
-
- )}
-
- {Component => }
-
- {showFundingPanel && (
-
- {Component => }
-
- )}
- {showCryptoDonatePanel && (
-
- {Component => }
-
- )}
- {showTrendsPanel && (
-
- {Component => }
-
- )}
- {showWhoToFollowPanel && (
-
- {Component => }
-
- )}
-
-
-
-
-
-
-
+
+ {!me && (
+
+ {Component => }
+
+ )}
+ {showTrendsPanel && (
+
+ {Component => }
+
+ )}
+ {showWhoToFollowPanel && (
+
+ {Component => }
+
+ )}
+
+
+
);
}
diff --git a/app/soapbox/pages/profile_page.js b/app/soapbox/pages/profile_page.js
index 5b62910f2..58c2d53bc 100644
--- a/app/soapbox/pages/profile_page.js
+++ b/app/soapbox/pages/profile_page.js
@@ -2,32 +2,34 @@ import PropTypes from 'prop-types';
import React from 'react';
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
+import { FormattedMessage } from 'react-intl';
import { connect } from 'react-redux';
-import { Redirect } from 'react-router-dom';
-import Sticky from 'react-stickynode';
+import { Redirect, withRouter } from 'react-router-dom';
-import Helmet from 'soapbox/components/helmet';
+import SidebarNavigation from 'soapbox/components/sidebar-navigation';
+import LinkFooter from 'soapbox/features/ui/components/link_footer';
import BundleContainer from 'soapbox/features/ui/containers/bundle_container';
import {
WhoToFollowPanel,
- SignUpPanel,
+ TrendsPanel,
ProfileInfoPanel,
- ProfileMediaPanel,
- PinnedAccountsPanel,
+ SignUpPanel,
} from 'soapbox/features/ui/util/async-components';
-import { findAccountByUsername, makeGetAccount } from 'soapbox/selectors';
-import { getAcct, isLocal } from 'soapbox/utils/accounts';
+import { findAccountByUsername } from 'soapbox/selectors';
+import { getAcct } from 'soapbox/utils/accounts';
import { getFeatures } from 'soapbox/utils/features';
import { displayFqn } from 'soapbox/utils/state';
+import { Column, Layout, Tabs } from '../components/ui';
import HeaderContainer from '../features/account_timeline/containers/header_container';
-import LinkFooter from '../features/ui/components/link_footer';
+import { makeGetAccount } from '../selectors';
const mapStateToProps = (state, { params, withReplies = false }) => {
const username = params.username || '';
const accounts = state.getIn(['accounts']);
const accountFetchError = ((state.getIn(['accounts', -1, 'username']) || '').toLowerCase() === username.toLowerCase());
const getAccount = makeGetAccount();
+ const me = state.get('me');
let accountId = -1;
let account = null;
@@ -51,6 +53,7 @@ const mapStateToProps = (state, { params, withReplies = false }) => {
}
return {
+ me,
account: accountId ? getAccount(state, accountId) : account,
accountId,
accountUsername,
@@ -61,6 +64,7 @@ const mapStateToProps = (state, { params, withReplies = false }) => {
};
export default @connect(mapStateToProps)
+@withRouter
class ProfilePage extends ImmutablePureComponent {
static propTypes = {
@@ -71,71 +75,99 @@ class ProfilePage extends ImmutablePureComponent {
};
render() {
- const { children, accountId, account, displayFqn, accountUsername, features, realAccount } = this.props;
- const bg = account ? account.getIn(['customizations', 'background']) : undefined;
+ const { children, accountId, account, displayFqn, accountUsername, me, features, realAccount } = this.props;
if (realAccount) {
return
;
}
+ const tabItems = [
+ {
+ text:
,
+ to: `/@${accountUsername}`,
+ name: 'profile',
+ },
+ {
+ text:
,
+ to: `/@${accountUsername}/with_replies`,
+ name: 'replies',
+ },
+ {
+ text:
,
+ to: `/@${accountUsername}/media`,
+ name: 'media',
+ },
+ ];
+
+ if (account) {
+ const ownAccount = account.get('id') === me;
+ if (ownAccount || !account.getIn(['pleroma', 'hide_favorites'], true)) {
+ tabItems.push({
+ text:
,
+ to: `/@${account.get('acct')}/favorites`,
+ name: 'likes',
+ });
+ }
+ }
+
+ const showTrendsPanel = features.trends;
+ const showWhoToFollowPanel = features.suggestions;
+
+ let activeItem;
+ const pathname = this.props.history.location.pathname.replace(`@${accountUsername}/`);
+ if (pathname.includes('with_replies')) {
+ activeItem = 'replies';
+ } else if (pathname.includes('media')) {
+ activeItem = 'media';
+ } else if (pathname.includes('favorites')) {
+ activeItem = 'likes';
+ } else if (pathname === `/@${accountUsername}`) {
+ activeItem = 'profile';
+ }
+
return (
-
- {account &&
- @{getAcct(account, displayFqn)}
- }
+
+
+
+
-
-
-
+
+
+
+
-
-
+
+ {Component => }
+
-
-
-
-
- {Component => }
-
-
-
+ {account && (
+
+ )}
+
+ {children}
+
+
-
-
-
-
-
-
- {Component => }
-
- {account && (
-
- {Component => }
-
- )}
- {account && features.accountEndorsements && isLocal(account) ? (
-
- {Component => }
-
- ) : features.suggestions && (
-
- {Component => }
-
- )}
-
-
-
-
-
-
-
-
-
+
+ {!me && (
+
+ {Component => }
+
+ )}
+ {showTrendsPanel && (
+
+ {Component => }
+
+ )}
+ {showWhoToFollowPanel && (
+
+ {Component => }
+
+ )}
+
+
+
);
}
diff --git a/app/soapbox/pages/remote_instance_page.js b/app/soapbox/pages/remote_instance_page.js
index 87180f647..1733d7738 100644
--- a/app/soapbox/pages/remote_instance_page.js
+++ b/app/soapbox/pages/remote_instance_page.js
@@ -1,9 +1,8 @@
import React from 'react';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { connect } from 'react-redux';
-import Sticky from 'react-stickynode';
-import PrimaryNavigation from 'soapbox/components/primary_navigation';
+import SidebarNavigation from 'soapbox/components/sidebar-navigation';
import LinkFooter from 'soapbox/features/ui/components/link_footer';
import BundleContainer from 'soapbox/features/ui/containers/bundle_container';
import {
@@ -15,6 +14,8 @@ import {
import { isAdmin } from 'soapbox/utils/accounts';
import { federationRestrictionsDisclosed } from 'soapbox/utils/state';
+import { Layout } from '../components/ui';
+
const mapStateToProps = state => {
const me = state.get('me');
const account = state.getIn(['accounts', me]);
@@ -33,50 +34,35 @@ class RemoteInstancePage extends ImmutablePureComponent {
const { me, children, params: { instance: host }, disclosed, isAdmin } = this.props;
return (
-
-
-
+
+
+
+
-
+
+ {children}
+
-
-
-
-
-
- {me && (
-
- {Component => }
-
- )}
-
- {Component => }
-
-
- {Component => }
-
- {(disclosed || isAdmin) && (
-
- {Component => }
-
- )}
-
-
-
-
-
-
-
+
+ {me && (
+
+ {Component => }
+
+ )}
+
+ {Component => }
+
+
+ {Component => }
+
+ {(disclosed || isAdmin) && (
+
+ {Component => }
+
+ )}
+
+
+
);
}
diff --git a/app/soapbox/pages/status_page.js b/app/soapbox/pages/status_page.js
index eab6c2ebe..d37542331 100644
--- a/app/soapbox/pages/status_page.js
+++ b/app/soapbox/pages/status_page.js
@@ -1,20 +1,18 @@
import React from 'react';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { connect } from 'react-redux';
-import Sticky from 'react-stickynode';
-import PrimaryNavigation from 'soapbox/components/primary_navigation';
+import SidebarNavigation from 'soapbox/components/sidebar-navigation';
import LinkFooter from 'soapbox/features/ui/components/link_footer';
import {
WhoToFollowPanel,
TrendsPanel,
- PromoPanel,
- FeaturesPanel,
SignUpPanel,
} from 'soapbox/features/ui/util/async-components';
// import GroupSidebarPanel from '../features/groups/sidebar_panel';
import { getFeatures } from 'soapbox/utils/features';
+import { Layout } from '../components/ui';
import BundleContainer from '../features/ui/containers/bundle_container';
const mapStateToProps = state => {
@@ -35,56 +33,34 @@ class StatusPage extends ImmutablePureComponent {
const { me, children, showTrendsPanel, showWhoToFollowPanel } = this.props;
return (
-
-
-
+
+
+
+
-
+
+ {children}
+
-
-
-
-
-
- {me ? (
-
- {Component => }
-
- ) : (
-
- {Component => }
-
- )}
-
- {Component => }
-
- {showTrendsPanel && (
-
- {Component => }
-
- )}
- {showWhoToFollowPanel && (
-
- {Component => }
-
- )}
-
-
-
-
-
-
-
+
+ {!me && (
+
+ {Component => }
+
+ )}
+ {showTrendsPanel && (
+
+ {Component => }
+
+ )}
+ {showWhoToFollowPanel && (
+
+ {Component => }
+
+ )}
+
+
+
);
}
diff --git a/app/soapbox/reducers/__tests__/compose-test.js b/app/soapbox/reducers/__tests__/compose-test.js
index 454c787ca..57637209b 100644
--- a/app/soapbox/reducers/__tests__/compose-test.js
+++ b/app/soapbox/reducers/__tests__/compose-test.js
@@ -231,14 +231,16 @@ describe('compose reducer', () => {
});
});
- it('should handle COMPOSE_CHANGE', () => {
- const state = ImmutableMap({ text: 'prevtext' });
- const action = {
- type: actions.COMPOSE_CHANGE,
- text: 'nexttext',
- };
- expect(reducer(state, action).toJS()).toMatchObject({
- text: 'nexttext',
+ describe('COMPOSE_CHANGE', () => {
+ it('should handle text changing', () => {
+ const state = ImmutableMap({ text: 'prevtext' });
+ const action = {
+ type: actions.COMPOSE_CHANGE,
+ text: 'nexttext',
+ };
+ expect(reducer(state, action).toJS()).toMatchObject({
+ text: 'nexttext',
+ });
});
});
diff --git a/app/soapbox/reducers/__tests__/verification-test.js b/app/soapbox/reducers/__tests__/verification-test.js
new file mode 100644
index 000000000..4789def7e
--- /dev/null
+++ b/app/soapbox/reducers/__tests__/verification-test.js
@@ -0,0 +1,117 @@
+import { Map as ImmutableMap } from 'immutable';
+
+import { SET_LOADING } from 'soapbox/actions/verification';
+
+import { FETCH_CHALLENGES_SUCCESS, FETCH_TOKEN_SUCCESS, SET_CHALLENGES_COMPLETE, SET_NEXT_CHALLENGE } from '../../actions/verification';
+import reducer from '../verification';
+
+describe('verfication reducer', () => {
+ it('returns the initial state', () => {
+ expect(reducer(undefined, {})).toEqual(ImmutableMap({
+ ageMinimum: null,
+ currentChallenge: null,
+ isLoading: false,
+ isComplete: false,
+ token: null,
+ instance: ImmutableMap(),
+ }));
+ });
+
+ describe('FETCH_CHALLENGES_SUCCESS', () => {
+ it('sets the state', () => {
+ const state = ImmutableMap({
+ untouched: 'hello',
+ ageMinimum: null,
+ currentChallenge: null,
+ isLoading: true,
+ isComplete: null,
+ });
+ const action = {
+ type: FETCH_CHALLENGES_SUCCESS,
+ ageMinimum: 13,
+ currentChallenge: 'email',
+ isComplete: false,
+ };
+ const expected = ImmutableMap({
+ untouched: 'hello',
+ ageMinimum: 13,
+ currentChallenge: 'email',
+ isLoading: false,
+ isComplete: false,
+ });
+
+ expect(reducer(state, action)).toEqual(expected);
+ });
+ });
+
+ describe('FETCH_TOKEN_SUCCESS', () => {
+ it('sets the state', () => {
+ const state = ImmutableMap({
+ isLoading: true,
+ token: null,
+ });
+ const action = { type: FETCH_TOKEN_SUCCESS, value: '123' };
+ const expected = ImmutableMap({
+ isLoading: false,
+ token: '123',
+ });
+
+ expect(reducer(state, action)).toEqual(expected);
+ });
+ });
+
+ describe('SET_CHALLENGES_COMPLETE', () => {
+ it('sets the state', () => {
+ const state = ImmutableMap({
+ isLoading: true,
+ isComplete: false,
+ });
+ const action = { type: SET_CHALLENGES_COMPLETE };
+ const expected = ImmutableMap({
+ isLoading: false,
+ isComplete: true,
+ });
+
+ expect(reducer(state, action)).toEqual(expected);
+ });
+ });
+
+ describe('SET_NEXT_CHALLENGE', () => {
+ it('sets the state', () => {
+ const state = ImmutableMap({
+ currentChallenge: null,
+ isLoading: true,
+ });
+ const action = {
+ type: SET_NEXT_CHALLENGE,
+ challenge: 'sms',
+ };
+ const expected = ImmutableMap({
+ currentChallenge: 'sms',
+ isLoading: false,
+ });
+
+ expect(reducer(state, action)).toEqual(expected);
+ });
+ });
+
+ describe('SET_LOADING with no value', () => {
+ it('sets the state', () => {
+ const state = ImmutableMap({ isLoading: false });
+ const action = { type: SET_LOADING };
+ const expected = ImmutableMap({ isLoading: true });
+
+ expect(reducer(state, action)).toEqual(expected);
+ });
+ });
+
+ describe('SET_LOADING with a value', () => {
+ it('sets the state', () => {
+ const state = ImmutableMap({ isLoading: true });
+ const action = { type: SET_LOADING, value: false };
+ const expected = ImmutableMap({ isLoading: false });
+
+ expect(reducer(state, action)).toEqual(expected);
+ });
+ });
+});
diff --git a/app/soapbox/reducers/auth.js b/app/soapbox/reducers/auth.js
index a4b649441..9bd3f6f33 100644
--- a/app/soapbox/reducers/auth.js
+++ b/app/soapbox/reducers/auth.js
@@ -257,6 +257,7 @@ const importMastodonPreload = (state, data) => {
});
};
+
const persistAuthAccount = account => {
if (account && account.url) {
KVStore.setItem(`authAccount:${account.url}`, account).catch(console.error);
diff --git a/app/soapbox/reducers/compose.js b/app/soapbox/reducers/compose.js
index 43fd23154..c5e03f54e 100644
--- a/app/soapbox/reducers/compose.js
+++ b/app/soapbox/reducers/compose.js
@@ -104,7 +104,7 @@ const statusToTextMentions = (state, status, account) => {
.join('');
};
-export const statusToMentionsArray = (state, status, account) => {
+export const statusToMentionsArray = (status, account) => {
const author = status.getIn(['account', 'acct']);
const mentions = status.get('mentions', []).map(m => m.get('acct'));
@@ -330,7 +330,7 @@ export default function compose(state = initialState, action) {
case COMPOSE_REPLY:
return state.withMutations(map => {
map.set('in_reply_to', action.status.get('id'));
- map.set('to', action.explicitAddressing ? statusToMentionsArray(state, action.status, action.account) : undefined);
+ map.set('to', action.explicitAddressing ? statusToMentionsArray(action.status, action.account) : ImmutableOrderedSet());
map.set('text', !action.explicitAddressing ? statusToTextMentions(state, action.status, action.account) : '');
map.set('privacy', privacyPreference(action.status.get('visibility'), state.get('default_privacy')));
map.set('focusDate', new Date());
@@ -430,7 +430,7 @@ export default function compose(state = initialState, action) {
case REDRAFT:
return state.withMutations(map => {
map.set('text', action.raw_text || unescapeHTML(expandMentions(action.status)));
- map.set('to', action.explicitAddressing ? getExplicitMentions(action.status.get('account', 'id'), action.status) : undefined);
+ map.set('to', action.explicitAddressing ? getExplicitMentions(action.status.get('account', 'id'), action.status) : ImmutableOrderedSet());
map.set('in_reply_to', action.status.get('in_reply_to_id'));
map.set('privacy', action.status.get('visibility'));
map.set('focusDate', new Date());
diff --git a/app/soapbox/reducers/index.ts b/app/soapbox/reducers/index.ts
index d63400d27..19d9930c0 100644
--- a/app/soapbox/reducers/index.ts
+++ b/app/soapbox/reducers/index.ts
@@ -2,6 +2,7 @@ import { Record as ImmutableRecord } from 'immutable';
import { combineReducers } from 'redux-immutable';
import { AUTH_LOGGED_OUT } from 'soapbox/actions/auth';
+import * as BuildConfig from 'soapbox/build_config';
import account_notes from './account_notes';
import accounts from './accounts';
@@ -55,8 +56,10 @@ import status_lists from './status_lists';
import statuses from './statuses';
import suggestions from './suggestions';
import timelines from './timelines';
+import trending_statuses from './trending_statuses';
import trends from './trends';
import user_lists from './user_lists';
+import verification from './verification';
const reducers = {
dropdown_menu,
@@ -113,6 +116,8 @@ const reducers = {
pending_statuses,
aliases,
accounts_meta,
+ trending_statuses,
+ verification,
};
// Build a default state from all reducers: it has the key and `undefined`
@@ -127,6 +132,10 @@ const appReducer = combineReducers(reducers, StateRecord);
// Clear the state (mostly) when the user logs out
const logOut = (state: any = StateRecord()): ReturnType
=> {
+ if (BuildConfig.NODE_ENV === 'production') {
+ location.href = '/login';
+ }
+
const whitelist: string[] = ['instance', 'soapbox', 'custom_emojis', 'auth'];
return StateRecord(
diff --git a/app/soapbox/reducers/relationships.js b/app/soapbox/reducers/relationships.js
index 129040d99..09dd4d318 100644
--- a/app/soapbox/reducers/relationships.js
+++ b/app/soapbox/reducers/relationships.js
@@ -90,9 +90,9 @@ export default function relationships(state = initialState, action) {
case ACCOUNTS_IMPORT:
return importPleromaAccounts(state, action.accounts);
case ACCOUNT_FOLLOW_REQUEST:
- return state.setIn([action.id, 'requested'], true);
+ return state.setIn([action.id, 'following'], true);
case ACCOUNT_FOLLOW_FAIL:
- return state.setIn([action.id, 'requested'], false);
+ return state.setIn([action.id, 'following'], false);
case ACCOUNT_UNFOLLOW_REQUEST:
return state.setIn([action.id, 'following'], false);
case ACCOUNT_UNFOLLOW_FAIL:
diff --git a/app/soapbox/reducers/trending_statuses.js b/app/soapbox/reducers/trending_statuses.js
new file mode 100644
index 000000000..86038fbf7
--- /dev/null
+++ b/app/soapbox/reducers/trending_statuses.js
@@ -0,0 +1,31 @@
+import { Map as ImmutableMap, OrderedSet as ImmutableOrderedSet } from 'immutable';
+
+import {
+ TRENDING_STATUSES_FETCH_REQUEST,
+ TRENDING_STATUSES_FETCH_SUCCESS,
+} from 'soapbox/actions/trending_statuses';
+
+const initialState = ImmutableMap({
+ items: ImmutableOrderedSet(),
+ isLoading: false,
+});
+
+const toIds = items => ImmutableOrderedSet(items.map(item => item.id));
+
+const importStatuses = (state, statuses) => {
+ return state.withMutations(state => {
+ state.set('items', toIds(statuses));
+ state.set('isLoading', false);
+ });
+};
+
+export default function trending_statuses(state = initialState, action) {
+ switch(action.type) {
+ case TRENDING_STATUSES_FETCH_REQUEST:
+ return state.set('isLoading', true);
+ case TRENDING_STATUSES_FETCH_SUCCESS:
+ return importStatuses(state, action.statuses);
+ default:
+ return state;
+ }
+}
diff --git a/app/soapbox/reducers/verification.js b/app/soapbox/reducers/verification.js
new file mode 100644
index 000000000..d354e6294
--- /dev/null
+++ b/app/soapbox/reducers/verification.js
@@ -0,0 +1,48 @@
+import { Map as ImmutableMap, fromJS } from 'immutable';
+
+import {
+ PEPE_FETCH_INSTANCE_SUCCESS,
+ FETCH_CHALLENGES_SUCCESS,
+ FETCH_TOKEN_SUCCESS,
+ SET_CHALLENGES_COMPLETE,
+ SET_LOADING,
+ SET_NEXT_CHALLENGE,
+} from '../actions/verification';
+
+const initialState = ImmutableMap({
+ ageMinimum: null,
+ currentChallenge: null,
+ isLoading: false,
+ isComplete: false,
+ token: null,
+ instance: ImmutableMap(),
+});
+
+export default function verification(state = initialState, action) {
+ switch (action.type) {
+ case PEPE_FETCH_INSTANCE_SUCCESS:
+ return state.set('instance', fromJS(action.instance));
+ case FETCH_CHALLENGES_SUCCESS:
+ return state
+ .set('ageMinimum', action.ageMinimum)
+ .set('currentChallenge', action.currentChallenge)
+ .set('isLoading', false)
+ .set('isComplete', action.isComplete);
+ case FETCH_TOKEN_SUCCESS:
+ return state
+ .set('isLoading', false)
+ .set('token', action.value);
+ case SET_CHALLENGES_COMPLETE:
+ return state
+ .set('isLoading', false)
+ .set('isComplete', true);
+ case SET_NEXT_CHALLENGE:
+ return state
+ .set('currentChallenge', action.challenge)
+ .set('isLoading', false);
+ case SET_LOADING:
+ return state.set('isLoading', typeof action.value === 'boolean' ? action.value : true);
+ default:
+ return state;
+ }
+}
diff --git a/app/soapbox/selectors/index.js b/app/soapbox/selectors/index.js
index b7ca3a14a..2db849b3e 100644
--- a/app/soapbox/selectors/index.js
+++ b/app/soapbox/selectors/index.js
@@ -174,9 +174,10 @@ export const getAlerts = createSelector([getAlertsBase], (base) => {
actionLabel: item.get('actionLabel'),
actionLink: item.get('actionLink'),
key: item.get('key'),
- className: `snackbar snackbar--${item.get('severity', 'info')}`,
+ className: `notification-bar-${item.get('severity', 'info')}`,
activeClassName: 'snackbar--active',
dismissAfter: 6000,
+ style: false,
});
});
diff --git a/app/soapbox/test_helpers.js b/app/soapbox/test_helpers.js
index 90f41119e..5a1922702 100644
--- a/app/soapbox/test_helpers.js
+++ b/app/soapbox/test_helpers.js
@@ -1,10 +1,11 @@
'use strict';
+import { mount } from 'enzyme';
import { Map as ImmutableMap } from 'immutable';
import React from 'react';
import { IntlProvider } from 'react-intl';
import { Provider } from 'react-redux';
-import { BrowserRouter } from 'react-router-dom';
+import { BrowserRouter, MemoryRouter } from 'react-router-dom';
import renderer from 'react-test-renderer';
import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';
@@ -37,6 +38,23 @@ export const createComponent = (children, props = {}) => {
);
};
+export const createShallowComponent = (children, props = {}, routerProps = {}) => {
+ props = ImmutableMap({
+ locale: 'en',
+ store: mockStore(rootReducer(ImmutableMap(), {})),
+ }).merge(props);
+
+ return mount(
+
+
+
+ {children}
+
+
+ ,
+ );
+};
+
// Apply actions to the state, one at a time
export const applyActions = (state, actions, reducer) => {
return actions.reduce((state, action) => reducer(state, action), state);
diff --git a/app/soapbox/test_setup.js b/app/soapbox/test_setup.js
index a3432a744..dd40fc09e 100644
--- a/app/soapbox/test_setup.js
+++ b/app/soapbox/test_setup.js
@@ -12,3 +12,5 @@ configure({ adapter });
// API mocking
jest.mock('soapbox/api');
afterEach(() => clearApiMocks());
+
+jest.mock('uuid', () => ({ v4: jest.fn(() => 1) }));
diff --git a/app/soapbox/types/account.ts b/app/soapbox/types/account.ts
deleted file mode 100644
index b17935c35..000000000
--- a/app/soapbox/types/account.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
- * Account entity.
- * https://docs.joinmastodon.org/entities/account/
- **/
-
-interface IAccount {
- acct: string;
- avatar: string;
- avatar_static: string;
- birthday: Date | undefined;
- bot: boolean;
- created_at: Date;
- display_name: string;
- emojis: Iterable;
- fields: Iterable;
- followers_count: number;
- following_count: number;
- fqn: string;
- header: string;
- header_static: string;
- id: string;
- last_status_at: Date;
- location: string;
- locked: boolean;
- moved: null;
- note: string;
- pleroma: Record;
- source: Record;
- statuses_count: number;
- uri: string;
- url: string;
- username: string;
- verified: boolean;
-
- // Internal fields
- display_name_html: string;
- note_emojified: string;
- note_plain: string;
- patron: Record;
- relationship: Iterable;
- should_refetch: boolean;
-}
-
-export { IAccount };
diff --git a/app/soapbox/types/entities/account.ts b/app/soapbox/types/entities/account.ts
new file mode 100644
index 000000000..eeb06dd90
--- /dev/null
+++ b/app/soapbox/types/entities/account.ts
@@ -0,0 +1,10 @@
+/**
+ * Account entity.
+ * https://docs.joinmastodon.org/entities/account/
+ **/
+
+import { AccountRecord } from 'soapbox/normalizers';
+
+type Account = ReturnType
+
+export default Account;
diff --git a/app/soapbox/types/entities/index.ts b/app/soapbox/types/entities/index.ts
new file mode 100644
index 000000000..2bfc0daf8
--- /dev/null
+++ b/app/soapbox/types/entities/index.ts
@@ -0,0 +1,2 @@
+export { default as Account } from './account';
+export { default as Status } from './status';
diff --git a/app/soapbox/types/entities/status.ts b/app/soapbox/types/entities/status.ts
new file mode 100644
index 000000000..3c7f66c8b
--- /dev/null
+++ b/app/soapbox/types/entities/status.ts
@@ -0,0 +1,10 @@
+/**
+ * Status entity.
+ * https://docs.joinmastodon.org/entities/status/
+ **/
+
+import { StatusRecord } from 'soapbox/normalizers';
+
+type Status = ReturnType
+
+export default Status;
diff --git a/app/soapbox/types/index.ts b/app/soapbox/types/index.ts
deleted file mode 100644
index df14c2720..000000000
--- a/app/soapbox/types/index.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-import { IAccount } from './account';
-import { IStatus } from './status';
-
-export { IAccount, IStatus };
diff --git a/app/soapbox/types/status.ts b/app/soapbox/types/status.ts
deleted file mode 100644
index a1a1ed061..000000000
--- a/app/soapbox/types/status.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-/**
- * Status entity.
- * https://docs.joinmastodon.org/entities/status/
- **/
-
-interface IStatus {
- account: Record;
- application: Record | null;
- bookmarked: boolean;
- card: Record | null;
- content: string;
- created_at: Date;
- emojis: Iterable;
- favourited: boolean;
- favourites_count: number;
- in_reply_to_account_id: string | null;
- in_reply_to_id: string | null;
- id: string;
- language: null;
- media_attachments: Iterable;
- mentions: Iterable;
- muted: boolean;
- pinned: boolean;
- pleroma: Record;
- poll: null;
- quote: null;
- reblog: null;
- reblogged: boolean;
- reblogs_count: number;
- replies_count: number;
- sensitive: boolean;
- spoiler_text: string;
- tags: Iterable;
- uri: string;
- url: string;
- visibility: string;
-
- // Internal fields
- contentHtml: string;
- hidden: boolean;
- search_index: string;
- spoilerHtml: string;
-}
-
-export { IStatus };
diff --git a/app/soapbox/utils/__tests__/phone-test.js b/app/soapbox/utils/__tests__/phone-test.js
new file mode 100644
index 000000000..67e130773
--- /dev/null
+++ b/app/soapbox/utils/__tests__/phone-test.js
@@ -0,0 +1,29 @@
+import { formatPhoneNumber } from '../phone';
+
+describe('Phone unit tests', () => {
+ it('Properly formats', () => {
+ let number = '';
+ expect(formatPhoneNumber(number)).toEqual('');
+
+ number = '5';
+ expect(formatPhoneNumber(number)).toEqual('+1 (5');
+
+ number = '55';
+ expect(formatPhoneNumber(number)).toEqual('+1 (55');
+
+ number = '555';
+ expect(formatPhoneNumber(number)).toEqual('+1 (555');
+
+ number = '55513';
+ expect(formatPhoneNumber(number)).toEqual('+1 (555) 13');
+
+ number = '555135';
+ expect(formatPhoneNumber(number)).toEqual('+1 (555) 135');
+
+ number = '5551350';
+ expect(formatPhoneNumber(number)).toEqual('+1 (555) 135-0');
+
+ number = '5551350123';
+ expect(formatPhoneNumber(number)).toEqual('+1 (555) 135-0123');
+ });
+});
diff --git a/app/soapbox/utils/accounts.ts b/app/soapbox/utils/accounts.ts
index a97f76338..34e4429f9 100644
--- a/app/soapbox/utils/accounts.ts
+++ b/app/soapbox/utils/accounts.ts
@@ -1,5 +1,7 @@
import { Map as ImmutableMap, OrderedSet as ImmutableOrderedSet } from 'immutable';
+import { Account } from 'soapbox/types/entities';
+
const getDomainFromURL = (account: ImmutableMap): string => {
try {
const url = account.get('url');
@@ -34,8 +36,8 @@ export const acctFull = (account: ImmutableMap): string => (
account.get('fqn') || guessFqn(account) || ''
);
-export const getAcct = (account: ImmutableMap, displayFqn: boolean): string => (
- displayFqn === true ? acctFull(account) : account.get('acct')
+export const getAcct = (account: Account, displayFqn: boolean): string => (
+ displayFqn === true ? account.fqn : account.acct
);
export const isStaff = (account: ImmutableMap = ImmutableMap()): boolean => (
diff --git a/app/soapbox/utils/errors.js b/app/soapbox/utils/errors.js
new file mode 100644
index 000000000..1bf59e4f0
--- /dev/null
+++ b/app/soapbox/utils/errors.js
@@ -0,0 +1,21 @@
+import camelCase from 'lodash/camelCase';
+import startCase from 'lodash/startCase';
+
+const toSentence = (arr) => arr
+ .reduce(
+ (prev, curr, i) => prev + curr + (i === arr.length - 2 ? ' and ' : ', '),
+ '',
+ )
+ .slice(0, -2);
+
+const buildErrorMessage = (errors) => {
+ const individualErrors = Object.keys(errors).map(
+ (attribute) => `${startCase(camelCase(attribute))} ${toSentence(
+ errors[attribute],
+ )}`,
+ );
+
+ return toSentence(individualErrors);
+};
+
+export { buildErrorMessage };
diff --git a/app/soapbox/utils/features.js b/app/soapbox/utils/features.js
index 8f636eea0..2c787b922 100644
--- a/app/soapbox/utils/features.js
+++ b/app/soapbox/utils/features.js
@@ -26,6 +26,7 @@ export const getFeatures = createSelector([instance => instance], instance => {
media: true,
privacyScopes: true,
spoilers: true,
+ filters: true,
polls: any([
v.software === MASTODON && gte(v.version, '2.8.0'),
v.software === PLEROMA,
diff --git a/app/soapbox/utils/phone.js b/app/soapbox/utils/phone.js
new file mode 100644
index 000000000..d112e66eb
--- /dev/null
+++ b/app/soapbox/utils/phone.js
@@ -0,0 +1,33 @@
+
+function removeFormattingFromNumber(number = '') {
+ if (number) {
+ return number.toString().replace(/\D/g, '');
+ }
+
+ return number;
+}
+
+function formatPhoneNumber(phoneNumber = '') {
+ let formattedPhoneNumber = '';
+ let strippedPhone = removeFormattingFromNumber(phoneNumber);
+ if (strippedPhone.slice(0, 1) === '1') {
+ strippedPhone = strippedPhone.slice(1);
+ }
+
+ for (let i = 0; i < strippedPhone.length && i < 10; i++) {
+ const character = strippedPhone.charAt(i);
+ if (i === 0) {
+ const prefix = '+1 (';
+ formattedPhoneNumber += prefix + character;
+ } else if (i === 3) {
+ formattedPhoneNumber += `) ${character}`;
+ } else if (i === 6) {
+ formattedPhoneNumber += `-${character}`;
+ } else {
+ formattedPhoneNumber += character;
+ }
+ }
+ return formattedPhoneNumber;
+}
+
+export { formatPhoneNumber };
diff --git a/app/styles/about.scss b/app/styles/about.scss
index af281ff00..70b757bec 100644
--- a/app/styles/about.scss
+++ b/app/styles/about.scss
@@ -1,10 +1,58 @@
$maximum-width: 1235px;
$fluid-breakpoint: $maximum-width + 20px;
+@keyframes upAndFadeIn {
+ 0% {
+ transform: rotate(-15deg) translateX(40%) translateY(20%) scale(1.15);
+ }
+
+ 100% {
+ transform: rotate(-5deg) translateX(40%) translateY(0) scale(1.15);
+ }
+}
+
+@keyframes upAndFadeInLeft {
+ 0% {
+ transform: rotate(30deg) translateX(30%) scale(1.15) translateY(30%);
+ }
+
+ 100% {
+ transform: rotate(15deg) translateX(30%) scale(1.15) translateY(10%);
+ }
+}
+
+@keyframes wave {
+ 0% {
+ transform: rotate(0);
+ }
+
+ 25% {
+ transform: rotate(15deg);
+ }
+
+ 50% {
+ transform: rotate(-10deg);
+ }
+
+ 75% {
+ transform: rotate(15deg);
+ }
+
+ 100% {
+ transform: rotate(0);
+ }
+}
+
.public-layout {
+ .app-store-button {
+ width: auto;
+ height: 80px;
+ display: inline-block;
+ }
+
.container {
width: 100%;
- max-width: 960px;
+ max-width: 1440px;
@media screen and (max-width: $no-gap-breakpoint) {
padding: 0;
@@ -12,13 +60,11 @@ $fluid-breakpoint: $maximum-width + 20px;
}
.content {
+ width: 100%;
display: block;
margin: 40px 0;
- background: var(--foreground-color);
border-radius: 6px;
- @media screen and (max-width: 520px) { margin: 40px 20px; }
-
@media screen and (max-width: 767px) {
margin-top: 0;
}
@@ -30,17 +76,13 @@ $fluid-breakpoint: $maximum-width + 20px;
align-items: stretch;
justify-content: center;
flex-wrap: nowrap;
- padding: 14px 0;
+ padding: 14px 20px;
box-sizing: border-box;
position: relative;
- @media screen and (max-width: 1024px) {
- padding: 14px 20px;
- }
-
.header-container {
display: flex;
- width: 960px;
+ width: 1440px;
align-items: stretch;
justify-content: center;
flex-wrap: nowrap;
@@ -71,7 +113,8 @@ $fluid-breakpoint: $maximum-width + 20px;
justify-content: flex-end;
flex-wrap: nowrap;
- .simple_form.new_user {
+ .simple_form.new_user,
+ .simple_form--public {
display: flex;
flex-direction: row;
align-items: center;
@@ -115,7 +158,6 @@ $fluid-breakpoint: $maximum-width + 20px;
.button {
margin-bottom: 0 !important;
line-height: 38px !important;
- border: 1px solid #333 !important;
height: 38px !important;
box-sizing: border-box !important;
padding: 0 18px !important;
@@ -128,12 +170,11 @@ $fluid-breakpoint: $maximum-width + 20px;
.brand {
display: block;
- img {
+ svg {
display: block;
- height: 30px;
+ height: 50px;
width: auto;
position: relative;
- bottom: -2px;
@media screen and (max-width: $no-gap-breakpoint) {
height: 20px;
@@ -192,18 +233,479 @@ $fluid-breakpoint: $maximum-width + 20px;
}
}
}
+
+ .beta-page {
+ .app-cta {
+ display: flex;
+ align-items: center;
+ margin: 40px auto;
+
+ @media screen and (max-width: 768px) {
+ flex-direction: column;
+ }
+
+ .copy {
+ flex: 2;
+ background: white;
+ border: 1px solid #eee;
+ padding: 80px;
+ border-radius: 10px;
+
+ @media screen and (max-width: 768px) {
+ padding: 60px 20px 20px 20px;
+ order: 1;
+ text-align: center;
+ }
+ }
+
+ .icon {
+ border-radius: 10px;
+ transform: scale(1.25);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ flex: 1;
+ padding: 40px;
+ background: linear-gradient(to bottom, $color-4-light, $color-4);
+ box-shadow: 0 0 20px 10px rgba(0, 0, 0, 0.1);
+
+ @media screen and (max-width: 768px) {
+ order: 0;
+ transform: scale(0.75);
+ margin-bottom: -60px;
+ }
+
+ img {
+ border-radius: 16px;
+ box-shadow: 0 0 20px 10px rgba(0, 0, 0, 0.1);
+ }
+ }
+
+ h1 {
+ margin: 0 0 20px 0;
+ font-size: 80px;
+ line-height: 90px;
+ font-weight: 600;
+ background: -webkit-linear-gradient(135deg, $color-9, $color-4-light, $color-2-light);
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+
+ @media screen and (max-width: 767px) {
+ margin-bottom: 30px;
+ text-align: center;
+ font-size: 50px;
+ line-height: 55px;
+ }
+ }
+ }
+ }
+
+ .beta-header {
+ width: 100%;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+
+ .hand-wave {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 200px;
+ height: 200px;
+ background: white;
+ border-radius: 50%;
+ margin-bottom: 20px;
+
+ @media screen and (max-width: $fluid-breakpoint) {
+ width: 120px;
+ height: 120px;
+ }
+
+ img {
+ animation: 1s ease-in wave;
+ max-width: 140px;
+
+ @media screen and (max-width: $fluid-breakpoint) {
+ width: 80px;
+ height: 80px;
+ }
+ }
+ }
+
+ .message {
+ margin: 40px 0;
+ padding: 20px;
+ width: 100%;
+ background: lighten($color-4-light, 30%);
+ border-radius: 10px;
+
+ p {
+ color: $color-4;
+ text-align: center;
+ font-size: 20px;
+ font-weight: 500;
+ }
+
+ span {
+ font-style: italic;
+ font-weight: 600;
+ }
+ }
+
+ .group {
+ display: flex;
+ align-items: center;
+
+ @media screen and (max-width: $fluid-breakpoint) {
+ display: block;
+ }
+
+ .logo {
+ padding: 0 40px;
+ border-right: 10px solid transparentize($color-3, 0.9);
+
+ @media screen and (max-width: $fluid-breakpoint) {
+ border-right: none;
+ }
+ }
+
+ .text {
+ padding: 0 40px;
+ font-weight: 600;
+ font-size: 80px;
+ font-style: italic;
+ color: $color-4-dark;
+
+ @media screen and (max-width: $fluid-breakpoint) {
+ padding: 0;
+ font-weight: 600;
+ font-size: 40px;
+ text-align: center;
+ }
+ }
+ }
+ }
+
+ .faq {
+ margin-bottom: 80px;
+
+ .subtext {
+ a {
+ color: $color-4;
+ }
+ }
+
+ .lead {
+ font-weight: 600;
+ font-size: 32px;
+ line-height: 42px;
+ margin-bottom: 10px;
+ }
+
+ .columns {
+ display: flex;
+ @media screen and (max-width: $fluid-breakpoint) {
+ display: block;
+ }
+
+ .left-column {
+ flex: 2;
+ padding-right: 20px;
+ }
+
+ .right-column {
+ flex: 4;
+
+ span {
+ font-style: italic;
+ font-weight: 600;
+ color: $color-4-dark;
+ }
+ }
+
+ .question {
+ font-size: 20px;
+ font-weight: 600;
+ }
+ }
+ }
+
+ .mobile-page {
+ height: 100%;
+
+ .rich-formatting,
+ .mobile-cta {
+ height: 100%;
+ }
+
+ .rich-formatting {
+ padding: 10px 0;
+ }
+
+ .flexed {
+ height: 100%;
+ display: flex;
+
+ @media screen and (max-width: 768px) {
+ flex-direction: column;
+ }
+
+ p {
+ font-size: 20px;
+ line-height: 1.4;
+ margin-bottom: 40px;
+ }
+
+ h1 {
+ letter-spacing: -0.02em;
+ font-size: 80px;
+ font-weight: 400;
+ line-height: 80px;
+ margin: 0 0 20px 0;
+ -webkit-tap-highlight-color: lightblue !important;
+
+ @media screen and (max-width: 768px) {
+ font-size: 60px;
+ line-height: 60px;
+ }
+
+ .alt-gradient {
+ font-size: 70px;
+ line-height: 70px;
+ font-weight: 600;
+ background: -webkit-linear-gradient(135deg, $color-9, $color-4-light, $color-2-light);
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+
+ @media screen and (max-width: 768px) {
+ font-size: 50px;
+ line-height: 50px;
+ }
+ }
+
+ .big {
+ color: $color-4-dark;
+ display: block;
+ font-weight: 200;
+ }
+ }
+
+ .column {
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: flex-start;
+ flex: 1;
+
+ @media screen and (max-width: 768px) {
+ flex: 0;
+ width: 100%;
+ order: 1;
+ }
+
+ &:nth-of-type(2) {
+ flex-direction: row;
+ align-items: center;
+
+ @media screen and (max-width: 768px) {
+ padding-top: 80px;
+ order: 0;
+ }
+ }
+ }
+ }
+
+ .nested-column {
+ flex: 1;
+ }
+
+ .screenshot-1,
+ .screenshot-2 {
+ position: relative;
+ width: 100%;
+ z-index: 10;
+ }
+
+ .screenshot-1 {
+ animation: 1s ease-in upAndFadeIn;
+ transform: rotate(-5deg) translateX(40%) scale(1.15);
+
+ @media screen and (max-width: 768px) {
+ animation: none;
+ transform: rotate(-5deg) translateX(20%) scale(1.05);
+ }
+ }
+
+ .screenshot-2 {
+ animation: 1s ease-in upAndFadeInLeft;
+ transform: rotate(15deg) translateX(30%) scale(1.15) translateY(10%);
+ z-index: 9;
+
+ @media screen and (max-width: 768px) {
+ animation: none;
+ transform: rotate(15deg) translateX(-10%) scale(0.9) translateY(5%);
+ }
+ }
+ }
+
+ .tips {
+ padding: 80px 40px;
+ border-radius: 10px;
+ margin-bottom: 80px;
+
+ @media screen and (max-width: $fluid-breakpoint) {
+ padding: 20px;
+ }
+
+ .app-icon {
+ width: 100px;
+ border-radius: 16px;
+ }
+
+ .invite-icon {
+ width: 100px;
+ }
+
+ .small-invite-icon {
+ width: 40px;
+ }
+
+ span {
+ font-style: italic;
+ font-weight: 600;
+ color: $color-4-dark;
+ }
+
+ .mb-40 {
+ margin-bottom: 40px;
+ }
+
+ .tip {
+ font-size: 20px;
+ font-weight: 600;
+ }
+
+ ol {
+ padding-left: 10px;
+
+ li {
+ img {
+ width: 30px;
+ height: 30px;
+ display: inline;
+ margin-bottom: -5px;
+ }
+ }
+ }
+
+ .columns {
+ display: flex;
+ @media screen and (max-width: $fluid-breakpoint) {
+ display: block;
+ }
+
+ .left-column {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ flex: 2;
+ padding-right: 20px;
+
+ img {
+ width: 120px;
+ height: 120px;
+ }
+
+ h2 {
+ font-size: 32px;
+ margin: 20px 0;
+ font-weight: 600;
+ color: $color-4;
+ text-align: center;
+ }
+ }
+
+ .right-column {
+ flex: 4;
+ }
+ }
+ }
+
+ .static-pages-header {
+ width: 100%;
+ padding: 40px 0;
+ border-bottom: 1px solid $color-6-dark;
+ margin-bottom: 40px;
+
+ h1 {
+ font-size: 32px;
+ font-weight: 600;
+ color: $color-3-dark;
+ margin-bottom: 10px;
+ }
+
+ p {
+ font-size: 22px;
+ }
+ }
+
+ .static-list-wrapper {
+ display: grid;
+ grid-template-columns: 1fr 1fr 1fr;
+ grid-gap: 20px;
+ width: 100%;
+ list-style: none;
+ padding: 40px 0;
+
+ @media screen and (max-width: $fluid-breakpoint) {
+ grid-template-columns: 100%;
+ }
+
+ li {
+ .card {
+ border-radius: 10px;
+ background: linear-gradient(-45deg, $color-3-light, $color-3-dark);
+
+ h4 {
+ color: white;
+ font-size: 24px;
+ font-weight: 500;
+ margin: 0 0 20px 0;
+ }
+
+ a {
+ color: white;
+ }
+
+ p {
+ color: transparentize($color-6-light, 0.1);
+ }
+
+ .card-header {
+ padding: 20px;
+ height: 160px;
+ }
+
+ .card-footer {
+ background: transparentize($color-6-light, 0.9);
+ text-align: right;
+ border-radius: 0 0 10px 10px;
+ padding: 10px 20px;
+ }
+ }
+ }
+ }
}
.container {
+ position: relative;
+ z-index: 20;
box-sizing: border-box;
max-width: $maximum-width;
margin: 0 auto;
- position: relative;
-
- @media screen and (max-width: $fluid-breakpoint) {
- width: 100%;
- padding: 0 10px;
- }
+ width: 100%;
+ padding: 0 10px;
}
.rich-formatting {
@@ -211,10 +713,13 @@ $fluid-breakpoint: $maximum-width + 20px;
font-size: 16px;
font-weight: 400;
line-height: 30px;
- color: var(--primary-text-color--faint);
- max-width: 600px;
+ color: $color-5-dark;
padding: 15px 30px;
+ .text-center {
+ text-align: center;
+ }
+
& > :first-child {
margin-top: 0.5em;
}
@@ -234,7 +739,7 @@ $fluid-breakpoint: $maximum-width + 20px;
font-size: 16px;
font-weight: 400;
line-height: 30px;
- color: var(--primary-text-color--faint);
+ color: $color-5-dark;
a {
color: var(--highlight-text-color);
@@ -258,8 +763,7 @@ $fluid-breakpoint: $maximum-width + 20px;
font-family: var(--font-display), sans-serif;
margin-top: 2em;
margin-bottom: 1.25em;
- font-weight: 500;
- color: var(--primary-text-color--faint);
+ color: $color-5-dark;
}
hr + {
@@ -287,8 +791,9 @@ $fluid-breakpoint: $maximum-width + 20px;
}
h2 {
- font-size: 22px;
- line-height: 26px;
+ font-weight: 600;
+ font-size: 28px;
+ line-height: 32px;
}
h3 {
@@ -316,11 +821,11 @@ $fluid-breakpoint: $maximum-width + 20px;
padding: 0 0 0 2em;
margin: 0 0 0.85em;
- &[type='a'] {
+ &[type="a"] {
list-style-type: lower-alpha;
}
- &[type='i'] {
+ &[type="i"] {
list-style-type: lower-roman;
}
}
@@ -372,19 +877,18 @@ $fluid-breakpoint: $maximum-width + 20px;
display: inline;
&::after {
- content: ' · ';
+ content: " · ";
}
}
li:last-child::after {
- content: '';
+ content: "";
}
}
}
.public-layout {
position: relative;
- background-color: var(--brand-color);
background-size: 100% auto;
background-repeat: no-repeat;
background-position: 0 -106px;
@@ -397,9 +901,8 @@ $fluid-breakpoint: $maximum-width + 20px;
display: none;
}
- .brand__tagline,
- .brand h1 {
- color: #fff;
+ .follow-truth {
+ margin-bottom: 20px;
}
.header {
@@ -414,10 +917,6 @@ $fluid-breakpoint: $maximum-width + 20px;
}
}
- .brand {
- filter: brightness(0) invert(100%);
- }
-
.nav-button {
background: var(--accent-color);
color: #fff;
@@ -552,7 +1051,7 @@ $fluid-breakpoint: $maximum-width + 20px;
.simple_form .user_agreement .label_input > label {
font-weight: 400;
- color: var(--primary-text-color--faint);
+ color: $color-5-dark;
}
.simple_form p.lead {
@@ -601,7 +1100,6 @@ $fluid-breakpoint: $maximum-width + 20px;
margin-right: 15px;
h1 {
- @include font-montserrat;
color: var(--brand-color);
}
}
@@ -610,7 +1108,7 @@ $fluid-breakpoint: $maximum-width + 20px;
display: block;
width: 470px;
color: var(--primary-text-color);
- font-size: 30px;
+ font-size: 24px;
line-height: 1.4;
margin-top: 25px;
font-weight: 400;
diff --git a/app/styles/accounts.scss b/app/styles/accounts.scss
index 340680f10..5a482c5e0 100644
--- a/app/styles/accounts.scss
+++ b/app/styles/accounts.scss
@@ -280,12 +280,15 @@ a .account__avatar {
.account__relationship {
height: auto;
- padding: 0 0 0 5px;
position: relative;
display: flex;
align-items: center;
justify-content: center;
+ button {
+ margin-left: 5px;
+ }
+
.svg-icon {
width: 20px;
height: 20px;
@@ -424,7 +427,6 @@ a .account__avatar {
.account-gallery__container {
display: flex;
flex-wrap: wrap;
- padding: 4px 2px;
.empty-column-indicator {
margin: -4px -2px;
@@ -554,9 +556,3 @@ a .account__avatar {
padding-right: 3px;
}
}
-
-.account__birthday {
- display: flex;
- align-items: center;
- white-space: nowrap;
-}
diff --git a/app/styles/application.scss b/app/styles/application.scss
index 41ef7cf14..243894ca5 100644
--- a/app/styles/application.scss
+++ b/app/styles/application.scss
@@ -1,9 +1,11 @@
// Fonts from elsewhere
@import '~line-awesome/dist/font-awesome-line-awesome/css/all.css';
-@import '~@fontsource/roboto/300.css';
-@import '~@fontsource/roboto/400.css';
-@import '~@fontsource/roboto/700.css';
-@import '~@fontsource/montserrat/800.css';
+@import '~@fontsource/inter/200.css';
+@import '~@fontsource/inter/300.css';
+@import '~@fontsource/inter/400.css';
+@import '~@fontsource/inter/500.css';
+@import '~@fontsource/inter/700.css';
+@import '~@fontsource/inter/900.css';
@import 'mixins';
@import 'themes';
@@ -13,7 +15,6 @@
@import 'basics';
@import 'containers';
@import 'footer';
-@import 'forms';
@import 'accounts';
@import 'boost';
@import 'loading';
@@ -31,7 +32,6 @@
@import 'navigation';
@import 'placeholder';
@import 'autosuggest';
-@import 'developers';
// COMPONENTS
@import 'components/buttons';
@@ -63,7 +63,6 @@
@import 'components/getting-started';
@import 'components/promo-panel';
@import 'components/still-image';
-@import 'components/timeline-queue-header';
@import 'components/badge';
@import 'components/theme-toggle';
@import 'components/trends';
@@ -85,7 +84,6 @@
@import 'components/admin';
@import 'components/backups';
@import 'components/crypto-donate';
-@import 'components/datepicker';
@import 'components/remote-timeline';
@import 'components/federation-restrictions';
@import 'components/aliases';
@@ -98,3 +96,14 @@
// Holiday
@import 'holiday/halloween';
+
+// Truth custom styles
+@import 'truth';
+
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+@import 'forms';
+@import 'utilities';
+@import 'components/datepicker';
diff --git a/app/styles/autosuggest.scss b/app/styles/autosuggest.scss
index 33a8f062d..4a8aa94fe 100644
--- a/app/styles/autosuggest.scss
+++ b/app/styles/autosuggest.scss
@@ -7,45 +7,45 @@
.autosuggest-textarea__textarea,
.autosuggest-input input,
.react-datepicker__input-container input {
- display: block;
- box-sizing: border-box;
- width: 100%;
- margin: 0;
- background: transparent;
- color: var(--primary-text-color);
- padding: 10px;
- font-family: inherit;
- font-size: 16px;
- resize: vertical;
- border: 0;
- outline: 0;
+ // display: block;
+ // box-sizing: border-box;
+ // width: 100%;
+ // margin: 0;
+ // background: transparent;
+ // color: var(--primary-text-color);
+ // padding: 10px;
+ // font-family: inherit;
+ // font-size: 16px;
+ // resize: vertical;
+ // border: 0;
+ // outline: 0;
- &:focus {
- outline: 0;
- }
+ // &:focus {
+ // outline: 0;
+ // }
- @media screen and (max-width: 600px) {
- font-size: 16px;
- }
+ // @media screen and (max-width: 600px) {
+ // font-size: 16px;
+ // }
}
.autosuggest-textarea__textarea {
min-height: 100px;
- border-radius: 5px 5px 0 0;
- padding-bottom: 0;
- padding-right: 10px + 22px;
- resize: none;
- scrollbar-color: initial;
- transition: 0.2s;
+ // border-radius: 5px 5px 0 0;
+ // padding-bottom: 0;
+ // padding-right: 10px + 22px;
+ // resize: none;
+ // scrollbar-color: initial;
+ // transition: 0.2s;
- &::-webkit-scrollbar {
- all: unset;
- }
+ // &::-webkit-scrollbar {
+ // all: unset;
+ // }
- @media screen and (max-width: 600px) {
- max-height: 100px !important; // prevent auto-resize textarea
- resize: vertical;
- }
+ // @media screen and (max-width: 600px) {
+ // max-height: 100px !important; // prevent auto-resize textarea
+ // resize: vertical;
+ // }
}
.autosuggest-textarea__suggestions-wrapper {
diff --git a/app/styles/basics.scss b/app/styles/basics.scss
index 4694adbfd..6cd9df90f 100644
--- a/app/styles/basics.scss
+++ b/app/styles/basics.scss
@@ -1,72 +1,18 @@
-@function hex-color($color) {
- @if type-of($color) == 'color' {
- $color: str-slice(ie-hex-str($color), 4);
- }
- @return '%23' + unquote($color);
+body {
+ @apply antialiased;
+ -webkit-overflow-scrolling: touch;
+ -ms-overflow-style: -ms-autohiding-scrollbar;
}
-html {
- @include font-roboto;
- @include font-weight(normal);
- font-size: 62.5%;
- text-size-adjust: 100%;
- -ms-text-size-adjust: 100%;
- -webkit-text-size-adjust: 100%;
+body.with-modals {
+ @apply overflow-hidden;
}
body {
- @include font-size(16);
- @include line-height(19);
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
- text-rendering: optimizeLegibility;
- font-feature-settings: "kern";
- -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
- -webkit-tap-highlight-color: transparent;
- color: var(--primary-text-color);
- background-color: var(--background-color);
-
- &.system-font {
- // system-ui => standard property (Chrome/Android WebView 56+, Opera 43+, Safari 11+)
- // -apple-system => Safari <11 specific
- // BlinkMacSystemFont => Chrome <56 on macOS specific
- // Segoe UI => Windows 7/8/10
- // Oxygen => KDE
- // Ubuntu => Unity/Ubuntu
- // Cantarell => GNOME
- // Fira Sans => Firefox OS
- // Droid Sans => Older Androids (<4.0)
- // Helvetica Neue => Older macOS <10.11
- font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
- }
-
- &.app-body {
- position: absolute;
- width: 100%;
- min-height: 100%;
- padding: 0;
- overflow: hidden;
- overflow-y: scroll;
-
- &.with-modals--active {
- overflow-y: hidden;
- }
- }
-
&.lighter {
background: var(--brand-color--med);
}
- &.with-modals {
- overflow-x: hidden;
- overflow-y: scroll;
-
- &--active {
- overflow-y: hidden;
- margin-right: 13px;
- }
- }
-
&.player {
text-align: center;
}
@@ -127,21 +73,10 @@ body {
}
}
-.app-body {
- -webkit-overflow-scrolling: touch;
- -ms-overflow-style: -ms-autohiding-scrollbar;
-}
-
-.app-holder {
- &,
- & > div {
- display: flex;
- width: 100%;
- height: 100%;
- align-items: flex-start;
- justify-content: center;
- outline: 0 !important;
- }
+// Note: this is needed for React HotKeys performance. Removing this
+// will cause severe performance degradation on Safari.
+div[tabindex="-1"]:focus {
+ outline: 0;
}
.visuallyhidden {
@@ -156,8 +91,7 @@ body {
}
::selection {
- background-color: var(--highlight-text-color);
- color: #fff;
+ @apply bg-primary-600 text-white;
}
noscript {
diff --git a/app/styles/components/account-header.scss b/app/styles/components/account-header.scss
index deaf47a3a..d3580232a 100644
--- a/app/styles/components/account-header.scss
+++ b/app/styles/components/account-header.scss
@@ -114,67 +114,15 @@
}
}
- @keyframes fadeIn {
- 1% {
- visibility: visible;
- }
-
- 100% {
- visibility: visible;
- }
- }
-
- @keyframes fadeOut {
- 1% {
- visibility: visible;
- }
-
- 100% {
- visibility: hidden;
- }
- }
-
- &__card {
- display: flex;
- flex-direction: column;
- position: absolute;
- left: 0;
- top: -90px;
-
- &.is-locked {
- .account__header__avatar {
- top: -20px;
- opacity: 0;
- animation: 0.3s fadeOut;
- animation-fill-mode: forwards;
- }
-
- .account__header__name {
- top: 90px;
- opacity: 1;
- animation: 0.3s fadeIn;
- animation-fill-mode: forwards;
- }
- }
-
- @media screen and (max-width: 895px) {
- top: -45px;
- left: 10px;
- }
- }
-
&__avatar {
display: block;
position: absolute;
- top: 0;
+ left: 0;
+ top: -90px;
border-radius: 50%;
height: 200px;
width: 200px;
background-color: var(--foreground-color);
- opacity: 1;
- animation: 0.3s fadeIn;
- animation-fill-mode: forwards;
- transition: top 0.3s, opacity 0.15s;
// NOTE - patch fix for avatar size. Wrapper may not be needed when I do polish up on the page
.account__avatar {
@@ -201,6 +149,7 @@
}
@media screen and (max-width: 895px) {
+ top: -45px;
left: 20px;
left: max(20px + env(safe-area-inset-left));
height: 90px;
@@ -214,49 +163,6 @@
}
}
- &__name {
- display: flex;
- align-items: center;
- column-gap: 10px;
- width: 265px;
- height: 74px;
- position: absolute;
- top: 100px;
- opacity: 0;
- animation: 0.3s fadeOut;
- animation-fill-mode: forwards;
- transition: top 0.3s, opacity 0.15s;
-
- div:nth-child(2) {
- width: calc(100% - 50px);
- color: var(--primary-text-color);
-
- span:first-of-type {
- display: inline-block;
- max-width: 100%;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- font-size: 18px;
- line-height: 1.25;
- font-weight: 600;
-
- &.with-badge {
- max-width: calc(100% - 20px);
- }
- }
-
- small {
- display: flex;
- font-size: 14px;
- color: var(--primary-text-color--faint);
- font-weight: 400;
- overflow: hidden;
- text-overflow: ellipsis;
- }
- }
- }
-
&__extra {
display: flex;
flex-direction: row;
@@ -405,13 +311,6 @@
// end .account__header
-.account-timeline {
- &__header {
- display: block;
- width: 100%;
- }
-}
-
.account__header__content {
color: var(--primary-text-color--faint);
font-size: 14px;
@@ -437,9 +336,3 @@
}
}
}
-
-@media (min-width: 896px) {
- .account-timeline .sub-navigation {
- top: 134px;
- }
-}
diff --git a/app/styles/components/badge.scss b/app/styles/components/badge.scss
index 1d55ce445..1710c6e47 100644
--- a/app/styles/components/badge.scss
+++ b/app/styles/components/badge.scss
@@ -1,37 +1,23 @@
.badge {
- background-color: var(--brand-color);
- color: #fff;
- font-size: 12px;
- font-weight: normal;
- text-transform: uppercase;
- padding: 2px 6px;
- border-radius: 5px;
- margin: 0 5px 5px 0;
+ @apply inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-primary-600 text-white;
&--patron {
- background-color: #8a2be2;
- color: #fff;
+ @apply bg-primary-600 text-white;
}
&--admin {
- background-color: #000;
- color: #fff;
+ @apply bg-black;
}
&--moderator {
- background-color: #048ba8;
- color: #fff;
+ @apply bg-cyan-600 text-white;
}
&--bot {
- margin-left: 5px;
- color: var(--primary-text-color);
- background-color: hsla(var(--primary-text-color_hsl), 0.1);
- border: 1px solid hsla(var(--primary-text-color_hsl), 0.5);
- text-transform: none;
- padding: 4px 6px;
- vertical-align: top;
- display: inline-block;
- line-height: 12px;
+ @apply bg-gray-100 text-gray-800;
+ }
+
+ &--opaque {
+ @apply bg-white bg-opacity-75 text-gray-900;
}
}
diff --git a/app/styles/components/buttons.scss b/app/styles/components/buttons.scss
index 677ae8e28..f095682e6 100644
--- a/app/styles/components/buttons.scss
+++ b/app/styles/components/buttons.scss
@@ -8,32 +8,23 @@ button {
}
.button {
- background-color: var(--brand-color);
- border: 10px none;
+ align-items: center;
+ border-color: transparent;
border-radius: 999px;
+ border-width: 1px;
+ box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
box-sizing: border-box;
- color: #fff;
cursor: pointer;
display: inline-flex;
- align-items: center;
- justify-content: center;
- font-family: inherit;
font-size: 14px;
font-weight: 500;
- height: 36px;
- letter-spacing: 0;
- line-height: 36px;
- overflow: hidden;
- padding: 0 16px;
- position: relative;
- text-align: center;
- text-decoration: none;
- text-overflow: ellipsis;
- white-space: nowrap;
- width: auto;
+ justify-content: center;
+ line-height: 20px;
+ padding: 8px 16px;
transition: 0.2s;
- .svg-icon {
+ .svg-icon,
+ i.fa {
margin-right: 5px;
}
@@ -41,33 +32,28 @@ button {
text-decoration: none;
}
- &:active,
- &:focus,
- &:hover {
- background-color: var(--brand-color--hicontrast);
- }
-
&--destructive {
- transition: none;
-
- &:active,
- &:focus,
- &:hover {
- background-color: $error-red;
- transition: none;
- }
+ background-color: var(--brand-color);
}
&--small {
font-size: 13px;
height: auto;
line-height: normal;
- padding: 4px 8px;
+ padding: 6px 10px;
+ }
+
+ &--large {
+ font-size: 16px;
+ padding: 10px 20px;
}
&:disabled,
- &.disabled {
- opacity: 0.2;
+ &.disabled,
+ &:disabled:hover,
+ &.disabled:hover {
+ opacity: 0.75;
+ user-select: none;
cursor: default;
}
@@ -101,31 +87,6 @@ button {
background-color: var(--accent-color--bright);
}
}
-
- &.button-secondary {
- color: var(--primary-text-color);
- background: transparent;
- border: 1px solid var(--brand-color);
-
- &:active,
- &:focus,
- &:hover {
- border-color: var(--accent-color);
- }
-
- &:disabled {
- opacity: 0.5;
- }
-
- i.fa {
- margin-right: 0.5em;
- }
- }
-
- &.button--block {
- display: flex;
- width: 100%;
- }
}
button,
@@ -164,3 +125,9 @@ a.button {
height: 20px;
}
}
+
+.button--welcome {
+ .emojione {
+ margin: -1px 6px 0 -4px;
+ }
+}
diff --git a/app/styles/components/columns.scss b/app/styles/components/columns.scss
index 6670d41ea..9509b0f37 100644
--- a/app/styles/components/columns.scss
+++ b/app/styles/components/columns.scss
@@ -109,7 +109,7 @@
}
.autosuggest-textarea__textarea {
- font-size: 16px;
+ // font-size: 16px;
}
.search__input {
@@ -760,19 +760,7 @@
.empty-column-indicator,
.error-column {
- color: var(--primary-text-color);
- background: var(--accent-color--med);
- text-align: center;
- padding: 40px;
- font-size: 15px;
- font-weight: 400;
- cursor: default;
- display: flex;
- flex: 1 1 auto;
- align-items: center;
- justify-content: center;
- min-height: 160px;
- border-radius: 0 0 10px 10px;
+ @apply bg-primary-50 text-gray-900 text-center p-10 flex flex-1 items-center justify-center min-h-[160px] rounded-lg;
@supports (display: grid) { // hack to fix Chrome <57
contain: strict;
@@ -783,16 +771,7 @@
}
a {
- color: var(--highlight-text-color);
- text-decoration: none;
-
- &:hover {
- text-decoration: underline;
- }
- }
-
- @media screen and (max-width: 580px) {
- border-radius: 0;
+ @apply text-primary-600 no-underline hover:underline;
}
}
@@ -984,6 +963,15 @@
}
}
+.follow_heading {
+ color: var(--accent-color);
+}
+
+.follow_subhead {
+ margin: 50px 0;
+ font-size: 20px;
+}
+
.column .explanation-box {
background: var(--foreground-color);
}
diff --git a/app/styles/components/compose-form.scss b/app/styles/components/compose-form.scss
index 4c1537f4f..a88ed1bd5 100644
--- a/app/styles/components/compose-form.scss
+++ b/app/styles/components/compose-form.scss
@@ -60,12 +60,6 @@
}
}
- .emoji-picker-dropdown {
- position: absolute;
- top: 10px;
- right: 5px;
- }
-
&__autosuggest-wrapper {
position: relative;
}
@@ -84,27 +78,13 @@
.spoiler-input__input { border-radius: 4px; }
- &__quoted-status-wrapper {
- background: var(--background-color);
-
- .quoted-status {
- &:hover,
- &:focus,
- &:active {
- background: transparent;
- cursor: unset;
- }
- }
- }
-
&.condensed {
.autosuggest-textarea__textarea {
min-height: 46px;
border-radius: 5px;
}
- .compose-form__buttons-wrapper,
- .compose-form__quoted-status-wrapper {
+ .compose-form__buttons-wrapper {
height: 0;
padding: 0;
overflow: hidden;
@@ -340,58 +320,6 @@
transform: translateY(1px);
}
-.upload-area {
- align-items: center;
- background: rgba($base-overlay-background, 0.8);
- display: flex;
- height: 100%;
- justify-content: center;
- left: 0;
- opacity: 0;
- position: absolute;
- top: 0;
- visibility: hidden;
- width: 100%;
- z-index: 2000;
-
- * {
- pointer-events: none;
- }
-}
-
-.upload-area__drop {
- width: 320px;
- height: 160px;
- display: flex;
- box-sizing: border-box;
- position: relative;
- padding: 8px;
-}
-
-.upload-area__background {
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- z-index: -1;
- border-radius: 4px;
- background: var(--brand-color--med);
- box-shadow: 0 0 5px rgba($base-shadow-color, 0.2);
-}
-
-.upload-area__content {
- flex: 1;
- display: flex;
- align-items: center;
- justify-content: center;
- color: var(--primary-text-color--faint);
- font-size: 18px;
- font-weight: 500;
- border: 2px dashed var(--brand-color--med);
- border-radius: 4px;
-}
-
.upload-progress {
padding: 10px;
color: var(--highlight-text-color);
diff --git a/app/styles/components/datepicker.scss b/app/styles/components/datepicker.scss
index dd74db173..f5a25d018 100644
--- a/app/styles/components/datepicker.scss
+++ b/app/styles/components/datepicker.scss
@@ -1,194 +1,117 @@
-.datepicker {
- margin: 0;
- box-sizing: border-box;
- padding: 10px 10px 0;
- width: 100%;
- border-top: 1px solid var(--foreground-color);
-
- &__hint {
- font-style: italic;
- color: var(--primary-text-color--faint);
- padding-bottom: 10px;
- }
-
- &__input {
- display: flex;
- align-items: center;
- justify-content: center;
- }
-
- &__cancel {
- padding-left: 10px;
-
- .svg-icon {
- height: 24px;
- width: 24px;
- }
- }
-
- &--error .react-datepicker__input-container {
- border-color: $error-red !important;
- }
+.react-datepicker {
+ @apply p-4 font-sans text-xs text-gray-900 border border-solid border-gray-200 rounded-lg;
}
-.datepicker .react-datepicker {
- box-shadow: 0 0 6px 0 rgb(0 0 0 / 30%);
- font-family: inherit;
- font-size: 12px;
- border: 0;
- border-radius: 10px;
- background-color: var(--foreground-color);
- color: var(--primary-text-color);
-
- &-wrapper {
- width: 100%;
- }
-
- &__input-container {
- border: 2px solid var(--brand-color);
- border-radius: 6px;
- display: flex;
- align-items: center;
- justify-content: center;
- box-sizing: border-box;
- width: 100%;
- margin: 0;
- background: var(--background-color);
- color: var(--primary-text-color);
- padding: 10px;
- font-family: inherit;
- font-size: 16px;
- resize: vertical;
- outline: 0;
-
- &:focus {
- outline: 0;
- }
-
- @media screen and (max-width: 600px) {
- font-size: 16px;
- }
-
- input {
- padding: 0 0 0 8px;
- }
-
- &::before {
- content: '\f073';
- display: inline-block;
- font: normal normal normal 14px/1 "Font Awesome 5 Free";
- font-size: 18px;
- color: var(--primary-text-color--faint);
- }
- }
-
- &__current-month,
- &-time__header,
- &-year-header {
- font-size: 14px;
- color: var(--primary-text-color);
- }
-
- &__day--keyboard-selected,
- &__month-text--keyboard-selected,
- &__quarter-text--keyboard-selected,
- &__year-text--keyboard-selected {
- background-color: var(--brand-color);
- color: white !important;
- }
-
- &__day,
- &__day-name,
- &__time-name {
- width: 22px;
- line-height: 21px;
- color: var(--primary-text-color);
- }
-
- &__day,
- &__month-text,
- &__quarter-text,
- &__year-text {
- transition: 0.2s;
-
- &:hover {
- background-color: var(--background-color);
- color: var(--primary-text-color) !important;
- }
-
- &--disabled {
- color: hsla(var(--primary-text-color_hsl), 0.4);
- }
-
- &--selected {
- background-color: var(--brand-color);
- color: white;
- }
- }
-
- &__day-names {
- padding-top: 8px;
- }
-
- &__time {
- background-color: var(--foreground-color);
- }
-
- &__header {
- background-color: var(--background-color);
- border: 0;
- border-top-left-radius: 10px;
- padding: 8px 0 14px;
- }
-
- &__triangle::before,
- &__triangle::after {
- border-bottom-color: var(--background-color) !important;
- }
-
- &__navigation-icon::before,
- &__year-read-view--down-arrow,
- &__month-read-view--down-arrow,
- &__month-year-read-view--down-arrow {
- border-color: hsla(var(--primary-text-color_hsl), 0.4);
- transition: 0.2s;
- }
-
- &__navigation-icon:hover::before {
- border-color: var(--primary-text-color--faint);
- }
-
- &__time-list-item {
- display: flex !important;
- align-items: center !important;
- transition: 0.2s !important;
- background: var(--foreground-color);
-
- &:hover {
- background-color: var(--background-color) !important;
- color: var(--primary-text-color) !important;
- }
-
- &--disabled {
- color: hsla(var(--primary-text-color_hsl), 0.4) !important;
- }
-
- &--selected {
- background-color: var(--brand-color) !important;
- color: white;
- }
- }
-
- &__header:not(.react-datepicker__header--has-time-select) {
- border-top-left-radius: 0;
- border-top-right-radius: 10px;
- }
-
- &__month {
- margin: 8px 14px 16px;
- }
-
- &__time-container {
- border-color: var(--background-color);
- }
+.react-datepicker-popper[data-placement^=bottom] .react-datepicker__triangle::before,
+.react-datepicker-popper[data-placement^=bottom] .react-datepicker__triangle::after {
+ @apply border-b-white;
+}
+
+.react-datepicker-popper[data-placement^=bottom] .react-datepicker__triangle::before {
+ @apply border-b-gray-200;
+}
+
+.react-datepicker__header:not(.react-datepicker__header--has-time-select) {
+ border-top-right-radius: var(--border-radius-lg);
+}
+
+.react-datepicker__header {
+ @apply bg-white border-b-0 py-1 px-0;
+ // border-top-left-radius: var(--border-radius-lg);
+}
+
+.react-datepicker__current-month,
+.react-datepicker-time__header,
+.react-datepicker-year-header {
+ @apply text-gray-900 font-bold text-sm;
+}
+
+.react-datepicker__current-month {
+ margin-top: 2px;
+}
+
+.react-datepicker__navigation {
+ @apply top-4 h-8 w-8 rounded hover:bg-gray-50;
+}
+
+.react-datepicker__navigation-icon {
+ margin-top: -3px;
+}
+
+.react-datepicker__navigation-icon--previous::before {
+ right: -5px;
+}
+
+.react-datepicker__navigation-icon--next::before {
+ left: -5px;
+}
+
+.react-datepicker__navigation--previous {
+ left: 16px;
+}
+
+.react-datepicker__navigation--next {
+ right: 16px;
+}
+
+.react-datepicker__year-read-view--down-arrow,
+.react-datepicker__month-read-view--down-arrow,
+.react-datepicker__month-year-read-view--down-arrow,
+.react-datepicker__navigation-icon::before {
+ border-width: 2px 2px 0 0;
+ height: 7px;
+ width: 7px;
+ top: 8px;
+}
+
+.react-datepicker__header__dropdown {
+ @apply py-4;
+}
+
+.react-datepicker__day-names,
+.react-datepicker__week {
+ display: flex;
+ justify-content: space-between;
+}
+
+.react-datepicker__day-name,
+.react-datepicker__day,
+.react-datepicker__time-name {
+ @apply text-gray-900;
+ width: 30px;
+ height: 30px;
+ line-height: 30px;
+}
+
+.react-datepicker__day:hover,
+.react-datepicker__month-text:hover,
+.react-datepicker__quarter-text:hover,
+.react-datepicker__year-text:hover {
+ @apply bg-gray-100 rounded;
+}
+
+.react-datepicker__day--selected,
+.react-datepicker__day--in-selecting-range,
+.react-datepicker__day--in-range,
+.react-datepicker__month-text--selected,
+.react-datepicker__month-text--in-selecting-range,
+.react-datepicker__month-text--in-range,
+.react-datepicker__quarter-text--selected,
+.react-datepicker__quarter-text--in-selecting-range,
+.react-datepicker__quarter-text--in-range,
+.react-datepicker__year-text--selected,
+.react-datepicker__year-text--in-selecting-range,
+.react-datepicker__year-text--in-range {
+ @apply bg-primary-600 hover:bg-primary-700 text-white rounded;
+}
+
+.react-datepicker__day--disabled {
+ @apply text-gray-400;
+}
+
+.react-datepicker__day--keyboard-selected,
+.react-datepicker__month-text--keyboard-selected,
+.react-datepicker__quarter-text--keyboard-selected,
+.react-datepicker__year-text--keyboard-selected {
+ @apply bg-primary-50 hover:bg-primary-100 text-primary-600;
}
diff --git a/app/styles/components/detailed-status.scss b/app/styles/components/detailed-status.scss
index 2defdcd3e..5bcab11c3 100644
--- a/app/styles/components/detailed-status.scss
+++ b/app/styles/components/detailed-status.scss
@@ -7,7 +7,7 @@
}
.detailed-status {
- padding: 14px 10px;
+ // padding: 14px 10px;
&--flex {
display: flex;
@@ -127,7 +127,6 @@
.detailed-status__wrapper {
position: relative;
- overflow: hidden;
}
.detailed-status__application,
@@ -169,68 +168,66 @@
}
.thread {
- @include standard-panel;
- border-top-left-radius: 0;
- border-top-right-radius: 0;
-
- @media screen and (max-width: 580px) {
- border-radius: 0;
- }
+ @apply sm:bg-white p-4 sm:shadow-xl sm:p-6 sm:rounded-xl;
&__status {
- position: relative;
+ @apply relative;
- // Only display line if posts are below
- &:last-child .detailed-status__action-bar {
- border-bottom: 0;
+ .status__wrapper {
+ @apply shadow-none p-0;
}
+
+ // // Only display line if posts are below
+ // &:last-child .detailed-status__action-bar {
+ // border-bottom: 0;
+ // }
}
- &__descendants &__status:first-child {
- margin-top: 10px;
-
- .status__wrapper--filtered {
- margin-top: -10px;
- }
+ &__descendants {
+ @apply pt-4;
}
- &__status--focused:first-child,
- &__ancestors &__status:first-child {
- margin-top: 10px;
-
- .status__wrapper--filtered {
- margin-top: -10px;
- }
+ &__descendants .thread__status {
+ // @apply py-4;
}
- &__descendants &__status:last-child {
- margin-bottom: 10px;
-
- .status__wrapper--filtered {
- margin-bottom: -10px;
- }
+ &__descendants .status__content-wrapper,
+ &__ancestors .status__content-wrapper {
+ padding-left: calc(42px + 12px);
}
+ // &__descendants &__status:first-child {
+ // margin-top: 10px;
+
+ // .status__wrapper--filtered {
+ // margin-top: -10px;
+ // }
+ // }
+
+ // &__status--focused:first-child,
+ // &__ancestors &__status:first-child {
+ // margin-top: 10px;
+
+ // .status__wrapper--filtered {
+ // margin-top: -10px;
+ // }
+ // }
+
+ // &__descendants &__status:last-child {
+ // margin-bottom: 10px;
+
+ // .status__wrapper--filtered {
+ // margin-bottom: -10px;
+ // }
+ // }
+
&__connector {
- background: hsla(var(--primary-text-color_hsl), 0.2);
- position: absolute;
- width: 2px;
- left: 33px;
- display: none;
+ @apply bg-gray-200 absolute w-0.5 left-5 hidden;
&--bottom {
- height: calc(100% - 8px - 48px - 14px);
- top: calc(8px + 48px + 13px);
- display: block;
- }
-
- @media screen and (min-width: 630px) {
- left: 38px;
-
- &--bottom {
- height: calc(100% - 15px - 48px);
- top: calc(15px + 48px + 9px);
- }
+ @apply block;
+ height: calc(100% - 42px - 8px);
+ top: calc(12px + 42px);
}
}
}
diff --git a/app/styles/components/dropdown-menu.scss b/app/styles/components/dropdown-menu.scss
index 9d6c13038..b31d8b55a 100644
--- a/app/styles/components/dropdown-menu.scss
+++ b/app/styles/components/dropdown-menu.scss
@@ -1,95 +1,56 @@
.dropdown-menu {
- @include font-size(13);
- @include line-height(26);
- @include font-weight(normal);
- z-index: 9999;
- position: absolute;
- background: var(--background-color);
- border-radius: 6px;
- padding: 4px 0;
- color: var(--primary-text-color);
- box-shadow: 0 0 6px 0 rgba(0, 0, 0, 0.5);
- max-width: 350px;
+ @apply absolute bg-white z-40 rounded-md shadow-lg py-1 w-56;
+
&.left { transform-origin: 100% 50%; }
&.top { transform-origin: 50% 100%; }
&.bottom { transform-origin: 50% 0; }
&.right { transform-origin: 0 50%; }
&__arrow {
- position: absolute;
- width: 0;
- height: 0;
+ @apply absolute w-0 h-0;
border: 0 solid transparent;
&.left {
right: -5px;
margin-top: -5px;
border-width: 5px 0 5px 5px;
- border-left-color: var(--background-color);
+ border-left-color: #fff;
}
&.top {
bottom: -5px;
margin-left: -5px;
border-width: 5px 5px 0;
- border-top-color: var(--background-color);
+ border-top-color: #fff;
}
&.bottom {
top: -5px;
margin-left: -5px;
border-width: 0 5px 5px;
- border-bottom-color: var(--background-color);
+ border-bottom-color: #fff;
}
&.right {
left: -5px;
margin-top: -5px;
border-width: 5px 5px 5px 0;
- border-right-color: var(--background-color);
+ border-right-color: #fff;
}
}
ul {
overflow: hidden;
- padding: 2px 0;
}
&__item {
a {
- display: flex;
- align-items: center;
- box-sizing: border-box;
- overflow: hidden;
- margin: 0 6px;
- padding: 4px;
- border-radius: 6px;
- font-size: 15px;
- text-decoration: none;
- text-overflow: ellipsis;
- white-space: nowrap;
- color: var(--primary-text-color);
+ @apply flex px-4 py-2.5 text-sm text-gray-700 hover:bg-gray-100 cursor-pointer;
}
a {
- &:focus,
- &:hover,
- &:active {
- outline: 0;
- color: #fff;
- background: var(--brand-color);
-
- * {
- color: #fff;
- }
- }
-
> .svg-icon:first-child {
- height: 20px;
- width: 20px;
- min-width: 20px;
- margin-right: 10px;
- transition: none;
+ @apply h-5 w-5 mr-2.5 transition-none;
svg {
stroke-width: 1.5;
@@ -99,26 +60,12 @@
}
&.destructive a {
- color: var(--warning-color--hicontrast);
-
- &:focus,
- &:hover,
- &:active {
- background: var(--warning-color);
- color: #fff;
- }
+ @apply text-danger-600;
}
}
&__separator {
- display: block;
- margin: 10px !important;
- height: 1px;
- background: hsla(var(--primary-text-color_hsl), 0.12);
- }
-
- &__item .account {
- line-height: normal;
+ @apply block my-2 h-[1px] bg-gray-200;
}
}
// end .dropdown-menu
diff --git a/app/styles/components/emoji-reacts.scss b/app/styles/components/emoji-reacts.scss
index 353ab043e..a423a22eb 100644
--- a/app/styles/components/emoji-reacts.scss
+++ b/app/styles/components/emoji-reacts.scss
@@ -48,7 +48,11 @@
.emoji-react--favourites {
.svg-icon {
- color: $gold-star;
+ color: var(--accent-color);
+
+ svg path {
+ fill: var(--accent-color);
+ }
}
}
diff --git a/app/styles/components/error-boundary.scss b/app/styles/components/error-boundary.scss
index fbf515c12..b809a1efa 100644
--- a/app/styles/components/error-boundary.scss
+++ b/app/styles/components/error-boundary.scss
@@ -63,11 +63,6 @@
}
}
- &__version {
- font-size: 12px;
- margin: 6px 0;
- }
-
p.help-text {
text-align: left;
font-style: italic;
diff --git a/app/styles/components/filters.scss b/app/styles/components/filters.scss
index 93ebd230b..030b3f9d2 100644
--- a/app/styles/components/filters.scss
+++ b/app/styles/components/filters.scss
@@ -98,7 +98,7 @@
}
}
- .simple_form select {
- margin-top: 0;
- }
+ // .simple_form select {
+ // margin-top: 0;
+ // }
}
diff --git a/app/styles/components/getting-started.scss b/app/styles/components/getting-started.scss
index 4bb228234..61566e2e1 100644
--- a/app/styles/components/getting-started.scss
+++ b/app/styles/components/getting-started.scss
@@ -17,7 +17,6 @@
&__footer {
flex: 0 0 auto;
- padding: 20px 10px 40px;
ul {
margin-bottom: 10px;
diff --git a/app/styles/components/media-gallery.scss b/app/styles/components/media-gallery.scss
index a07558cbd..397e98133 100644
--- a/app/styles/components/media-gallery.scss
+++ b/app/styles/components/media-gallery.scss
@@ -199,9 +199,8 @@ $media-compact-size: 50px;
height: $media-compact-size !important;
background: transparent;
- .spoiler-button .svg-icon {
- width: 16px;
- height: 16px;
+ .spoiler-button {
+ display: none;
}
.media-gallery__item {
diff --git a/app/styles/components/mfa_form.scss b/app/styles/components/mfa_form.scss
index f16f782e3..ffd221c83 100644
--- a/app/styles/components/mfa_form.scss
+++ b/app/styles/components/mfa_form.scss
@@ -1,85 +1,69 @@
.security-settings-panel {
- margin: 20px;
-
- .simple_form {
- padding: 0 !important;
- }
-
- h1.security-settings-panel__setup-otp {
- font-size: 20px;
- line-height: 1.25;
- color: var(--primary-text-color);
- font-weight: 600;
- }
-
- h2.security-settings-panel__setup-otp {
- display: block;
- font-size: 16px;
- line-height: 1.5;
- color: var(--primary-text-color--faint);
- font-weight: 400;
- }
-
- .security-warning {
- color: var(--primary-text-color);
- padding: 15px 20px;
- font-size: 14px;
- background-color: var(--warning-color--faint);
- margin: 20px auto;
- border-radius: 8px;
+ .security-settings-panel__setup-otp {
+ margin-bottom: 5px;
}
.backup_codes {
- margin: 10px 0;
- font-weight: bold;
- padding: 15px 20px;
- font-size: 14px;
+ display: inline-block;
background-color: var(--brand-color--faint);
- border-radius: 8px;
- text-align: center;
- position: relative;
- min-height: 125px;
- display: flex;
- justify-content: center;
- align-items: center;
+ padding: 10px;
+ border-radius: var(--border-radius-lg);
- .backup_code {
- margin: 5px auto;
+ .backup_code:not(:last-child) {
+ margin-bottom: 5px;
}
}
-
- .security-settings-panel__setup-otp__buttons {
- margin: 15px 0;
- display: flex;
- justify-content: space-between;
-
- .button {
- flex: 1;
- }
- }
-
- &__qr-code {
- margin: 20px 0;
- display: flex;
- flex-direction: column;
- justify-content: center;
- align-items: center;
- }
-
- &__confirm-key {
- display: block;
- font-size: 14px;
- line-height: 1.5;
- color: var(--primary-text-color--faint);
- font-weight: 400;
- margin-top: 10px;
- }
}
+// margin: 20px;
-form.otp-auth {
- .error-box {
- width: 100%;
- text-align: center;
- color: $error-red;
- }
-}
+// h1.security-settings-panel__setup-otp {
+// font-size: 20px;
+// line-height: 1.25;
+// color: var(--primary-text-color);
+// font-weight: 600;
+// }
+
+// h2.security-settings-panel__setup-otp {
+// display: block;
+// font-size: 16px;
+// line-height: 1.5;
+// color: var(--primary-text-color--faint);
+// font-weight: 400;
+// }
+
+// .security-warning {
+// color: var(--primary-text-color);
+// padding: 15px 20px;
+// font-size: 14px;
+// background-color: var(--warning-color--faint);
+// margin: 20px auto;
+// border-radius: 8px;
+// }
+
+// .security-settings-panel__setup-otp__buttons {
+// margin: 20px;
+// display: flex;
+// justify-content: space-between;
+
+// .button {
+// min-width: 182px;
+// }
+// }
+
+// div.confirm-key {
+// display: block;
+// font-size: 16px;
+// line-height: 1.5;
+// color: var(--primary-text-color--faint);
+// font-weight: 400;
+// margin: 0 0 20px 20px;
+// }
+// }
+
+// form.otp-auth {
+// .error-box {
+// width: 100%;
+// text-align: center;
+// color: $error-red;
+// }
+// }
diff --git a/app/styles/components/modal.scss b/app/styles/components/modal.scss
index 7d40aab68..c04089318 100644
--- a/app/styles/components/modal.scss
+++ b/app/styles/components/modal.scss
@@ -1,35 +1,3 @@
-.modal-root {
- position: relative;
- transition: opacity 0.3s linear;
- will-change: opacity;
- z-index: 9999;
-}
-
-.modal-root__overlay {
- position: fixed;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- background: rgba($base-overlay-background, 0.9);
-}
-
-.modal-root__container {
- position: fixed;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- align-content: space-around;
- z-index: 9999;
- pointer-events: none;
- user-select: none;
-}
-
.modal-root__modal {
pointer-events: auto;
display: flex;
@@ -54,7 +22,6 @@
.media-modal {
width: 100%;
height: 100%;
- position: relative;
.audio-player.detailed,
.extended-video-player {
@@ -126,9 +93,7 @@
top: 0;
bottom: 0;
- @media screen and (max-width: 600px) {
- padding: 30px 2px;
- }
+ @media screen and (max-width: 600px) { padding: 30px 2px; }
.svg-icon {
width: 24px;
@@ -344,8 +309,7 @@
.mute-modal,
.reactions-modal,
.reblogs-modal,
-.mentions-modal,
-.account-note-modal {
+.mentions-modal {
position: relative;
flex-direction: column;
overflow: hidden;
@@ -376,18 +340,8 @@
}
.actions-modal {
- .status {
- background: var(--background-color);
- border-bottom-color: var(--background-color);
- padding-top: 10px;
- padding-bottom: 10px;
- }
-
.dropdown-menu__separator {
- display: block;
- margin: 10px;
- height: 1px;
- background: var(--background-color);
+ @apply block m-2 h-[1px] bg-gray-200;
}
}
@@ -414,8 +368,7 @@
.boost-modal__action-bar,
.confirmation-modal__action-bar,
-.mute-modal__action-bar,
-.account-note-modal__action-bar {
+.mute-modal__action-bar {
display: flex;
align-items: center;
justify-content: space-between;
@@ -468,8 +421,7 @@
vertical-align: middle;
}
-.report-modal,
-.account-note-modal {
+.report-modal {
width: 90vw;
max-width: 700px;
}
@@ -526,6 +478,27 @@
margin-bottom: 20px;
}
+ .setting-text {
+ display: block;
+ box-sizing: border-box;
+ width: 100%;
+ margin: 0;
+ color: var(--primary-text-color);
+ background: var(--background-color);
+ padding: 10px;
+ font-family: inherit;
+ font-size: 14px;
+ resize: vertical;
+ outline: 0;
+ border: 1px solid var(--background-color);
+ border-radius: 4px;
+ margin-bottom: 20px;
+
+ &:focus {
+ border: 1px solid var(--background-color);
+ }
+ }
+
.setting-toggle {
margin-top: 20px;
margin-bottom: 24px;
@@ -548,74 +521,33 @@
}
.actions-modal {
- max-height: calc(100% - 16px);
- width: calc(100% - 16px);
- max-width: 500px;
- margin: auto 0 8px;
+ @apply w-full max-h-full max-w-lg mt-auto mb-2 bg-white;
.status {
overflow-y: auto;
max-height: 300px;
}
- .actions-modal__item-label {
- font-weight: 500;
- }
+ .actions-modal__item-label { font-weight: 500; }
ul {
- overflow-y: auto;
- flex-shrink: 0;
+ @apply my-2 flex-shrink-0 overflow-y-auto;
max-height: calc(100vh - 147px);
// NOTE - not sure what this is yet, leaving alone for now until I find out.
- &.with-status {
- max-height: calc(80vh - 75px);
- }
-
- li:empty {
- margin: 0;
- }
+ &.with-status { max-height: calc(80vh - 75px); }
li:not(:empty) {
- &:first-of-type {
- margin: 10px 0 0;
- }
-
- a {
- display: flex;
- align-items: center;
- padding: 13px 10px 12px;
- color: var(--primary-text-color);
- text-decoration: none;
- opacity: 0.6;
-
- &,
- button {
- transition: none;
- }
+ a,
+ button {
+ @apply flex items-center px-4 py-3 text-gray-600 no-underline hover:bg-gray-100 hover:text-gray-800;
&.destructive {
- color: var(--warning-color--hicontrast);
- opacity: 1;
- }
-
- &.active,
- &:hover,
- &:focus {
- opacity: 1;
-
- &,
- button {
- background: var(--background-color);
- color: var(--highlight-text-color);
- box-shadow: 0 0 6px 0 rgba(0, 0, 0, 0.5);
- }
+ @apply text-danger-600;
}
.svg-icon:first-child {
- height: 20px;
- width: 20px;
- margin-right: 10px;
+ @apply w-5 h-5 mr-2.5;
svg {
stroke-width: 1.5;
@@ -627,6 +559,10 @@
}
}
}
+
+ button {
+ @apply w-full justify-center;
+ }
}
}
@@ -646,12 +582,10 @@
}
.confirmation-modal__action-bar,
-.mute-modal__action-bar,
-.account-note-modal__action-bar {
+.mute-modal__action-bar {
.confirmation-modal__secondary-button,
.confirmation-modal__cancel-button,
- .mute-modal__cancel-button,
- .account-note-modal__cancel-button {
+ .mute-modal__cancel-button {
background-color: transparent;
color: var(--highlight-text-color);
font-size: 14px;
@@ -719,22 +653,6 @@
}
}
-.modal-layout {
- background: var(--brand-color--med)
- url('data:image/svg+xml;utf8,')
- repeat-x bottom fixed;
- display: flex;
- flex-direction: column;
- height: 100vh;
- padding: 0;
-}
-
-@media screen and (max-width: 600px) {
- .account-header {
- margin-top: 0;
- }
-}
-
.compose-modal,
.reply-mentions-modal {
overflow: hidden;
@@ -815,7 +733,7 @@
padding: 0 !important;
.compose-form__autosuggest-wrapper .autosuggest-textarea__textarea {
- max-height: 160px !important;
+ // max-height: 160px !important;
}
.compose-form__autosuggest-wrapper::before {
@@ -1064,8 +982,7 @@
}
.confirmation-modal,
-.mute-modal,
-.account-note-modal {
+.mute-modal {
&__header {
display: flex;
align-items: center;
@@ -1087,35 +1004,3 @@
text-align: left;
}
}
-
-.report-modal__comment,
-.account-note-modal__container {
- .setting-text {
- display: block;
- box-sizing: border-box;
- width: 100%;
- margin: 0;
- color: var(--primary-text-color);
- background: var(--background-color);
- padding: 10px;
- font-family: inherit;
- font-size: 14px;
- resize: vertical;
- outline: 0;
- border: 1px solid var(--background-color);
- border-radius: 4px;
- margin-bottom: 20px;
-
- &:focus {
- border: 1px solid var(--background-color);
- }
- }
-}
-
-.account-note-modal {
- .setting-text {
- margin-top: 20px;
- margin-bottom: 0;
- resize: none;
- }
-}
diff --git a/app/styles/components/notification.scss b/app/styles/components/notification.scss
index 1bcbb937c..63439e79a 100644
--- a/app/styles/components/notification.scss
+++ b/app/styles/components/notification.scss
@@ -1,106 +1,3 @@
-.notification {
- border-bottom: 1px solid var(--brand-color--med);
- padding: 10px 0;
-}
-
-.notification-mention {
- padding: 15px 0;
-}
-
-.notification-favourite {
- .status.status-direct {
- background: transparent;
-
- .icon-button.disabled {
- color: hsla(var(--brand-color_hsl), 0.2);
- }
- }
-}
-
-.notification__message {
- margin: 0 10px 0 68px;
- padding: 8px 0 0;
- cursor: default;
- color: var(--primary-text-color--faint);
- font-size: 15px;
- line-height: 22px;
- position: relative;
-
- .fa {
- color: var(--highlight-text-color);
- }
-
- > span {
- display: inline;
- overflow: hidden;
- text-overflow: ellipsis;
- }
-}
-
-.notification__icon-wrapper {
- left: -26px;
- position: absolute;
-
- .svg-icon {
- width: 20px;
- height: 20px;
- color: var(--highlight-text-color);
-
- svg.icon-tabler-thumb-up {
- color: $gold-star;
- }
-
- svg.feather-repeat {
- color: var(--highlight-text-color);
- }
- }
-}
-
-.notification__display-name {
- color: inherit;
- font-weight: 500;
- text-decoration: none;
-
- &:hover {
- color: var(--primary-text-color);
- text-decoration: underline;
- }
-}
-
-.notification__relative_time {
- float: right;
-}
-
.notification .status__wrapper {
- box-shadow: none;
-}
-
-.notification {
- .status-container {
- padding: 0;
- }
-
- .status__wrapper {
- border-radius: 0;
- padding: 0;
- }
-
- .status {
- padding-bottom: 8px !important;
- }
-}
-
-.notification-birthday span[type="button"] {
- &:focus,
- &:hover,
- &:active {
- text-decoration: underline;
- cursor: pointer;
- }
-}
-
-.columns-area .notification-birthday {
- .notification__message {
- padding-top: 0;
- }
+ @apply p-0 shadow-none rounded-none;
}
diff --git a/app/styles/components/profile-info-panel.scss b/app/styles/components/profile-info-panel.scss
index 3089622fc..8fb977700 100644
--- a/app/styles/components/profile-info-panel.scss
+++ b/app/styles/components/profile-info-panel.scss
@@ -22,10 +22,7 @@
flex-wrap: wrap;
}
- &__join-date,
- &__birthday,
- &__location,
- &__note {
+ &__join-date {
display: flex;
font-size: 14px;
color: var(--primary-text-color--faint);
@@ -41,15 +38,6 @@
}
}
- &__note {
- text-decoration: none;
-
- &:hover,
- &:focus {
- text-decoration: underline;
- }
- }
-
&__stats {
margin: 15px 0;
@@ -60,6 +48,7 @@
&__name {
display: block;
+ margin-bottom: 15px;
.emojione {
width: 22px;
@@ -86,7 +75,7 @@
font-size: 15px;
line-height: 1.5;
color: var(--primary-text-color--faint);
- font-weight: 400;
+ font-weight: 600;
overflow: hidden;
text-overflow: ellipsis;
}
@@ -97,7 +86,7 @@
display: block;
flex: 1 1;
color: var(--primary-text-color);
- margin-top: 15px;
+ margin-bottom: 15px;
font-size: 15px;
line-height: 1.25;
overflow: hidden;
@@ -154,6 +143,32 @@
display: none;
}
}
+
+ &__meta {
+ display: flex;
+ flex-wrap: wrap;
+ margin-top: -10px;
+
+ > div {
+ display: flex;
+ font-size: 14px;
+ color: var(--primary-text-color--faint);
+ align-items: center;
+ line-height: normal;
+ margin-top: 10px;
+ margin-right: 20px;
+
+ .svg-icon {
+ width: 20px;
+ height: 20px;
+ margin-right: 8px;
+
+ svg {
+ stroke: currentColor;
+ }
+ }
+ }
+ }
}
.profile-info-panel.deactivated {
@@ -174,10 +189,10 @@
}
.profile-info-panel__name-content::before {
- content: "[";
+ content: '[';
}
.profile-info-panel__name-content::after {
- content: "]";
+ content: ']';
}
}
diff --git a/app/styles/components/profile_hover_card.scss b/app/styles/components/profile_hover_card.scss
index e90cd64ad..76bbb2b97 100644
--- a/app/styles/components/profile_hover_card.scss
+++ b/app/styles/components/profile_hover_card.scss
@@ -1,5 +1,6 @@
.display-name__account {
position: relative;
+ font-weight: 600;
}
.display-name .profile-hover-card {
diff --git a/app/styles/components/react-toggle.scss b/app/styles/components/react-toggle.scss
index 5a72c3b2d..7a75e696f 100644
--- a/app/styles/components/react-toggle.scss
+++ b/app/styles/components/react-toggle.scss
@@ -28,22 +28,12 @@
}
.react-toggle-track {
- width: 50px;
- height: 24px;
- padding: 0;
- border-radius: 30px;
- background-color: hsla(var(--brand-color_h), var(--brand-color_s), var(--brand-color_l), 0.35);
- transition: background-color 0.2s ease;
-}
-
-.react-toggle:hover:not(.react-toggle--disabled) .react-toggle-track,
-.react-toggle.react-toggle--focus:not(.react-toggle--disabled) .react-toggle-track,
-.react-toggle--checked:hover:not(.react-toggle--disabled) .react-toggle-track {
- background-color: var(--brand-color--hicontrast);
+ @apply bg-gray-200 w-[50px] p-0 rounded-full transition-colors;
+ height: var(--input-height);
}
.react-toggle--checked .react-toggle-track {
- background-color: var(--brand-color);
+ @apply bg-primary-600;
}
.react-toggle-track-check {
@@ -87,17 +77,17 @@
position: absolute;
top: 1px;
left: 1px;
- width: 22px;
- height: 22px;
- border: 1px solid var(--brand-color--med);
+ width: 28px;
+ height: 28px;
+ border: 1px solid #fff;
border-radius: 50%;
- background-color: var(--background-color);
+ background-color: #fff;
box-sizing: border-box;
transition: all 0.25s ease;
transition-property: border-color, left;
}
.react-toggle--checked .react-toggle-thumb {
- left: 27px;
- border-color: var(--brand-color);
+ @apply border-primary-600;
+ left: 21px;
}
diff --git a/app/styles/components/reply-mentions.scss b/app/styles/components/reply-mentions.scss
index cd693803e..f94ba5181 100644
--- a/app/styles/components/reply-mentions.scss
+++ b/app/styles/components/reply-mentions.scss
@@ -1,23 +1,17 @@
.reply-mentions {
- margin: 0 10px;
- color: var(--primary-text-color--faint);
- font-size: 15px;
- text-decoration: none;
+ @apply text-gray-500 mb-1 text-sm;
- &__account,
- a {
- color: var(--highlight-text-color);
- text-decoration: none;
+ &__account {
+ @apply text-primary-600 no-underline;
&:hover {
- text-decoration: underline;
+ @apply underline text-primary-800;
}
}
}
.status__wrapper,
-.detailed-status,
-.quoted-status {
+.detailed-status {
.reply-mentions {
display: block;
margin: 4px 0 0 0;
diff --git a/app/styles/components/setting-toggle.scss b/app/styles/components/setting-toggle.scss
index 4be4864f8..b940eb013 100644
--- a/app/styles/components/setting-toggle.scss
+++ b/app/styles/components/setting-toggle.scss
@@ -1,12 +1,13 @@
-.setting-toggle {
- display: block;
- line-height: 24px;
+.setting-toggle__text {
+ display: flex;
+ flex-direction: column;
}
.setting-toggle__label {
- color: var(--primary-text-color--faint);
- display: inline-block;
- margin-bottom: 14px;
- margin-left: 8px;
- vertical-align: middle;
+ color: var(--gray-800);
+}
+
+.setting-toggle__hint {
+ color: var(--gray-500);
+ font-size: 12px;
}
diff --git a/app/styles/components/sidebar-menu.scss b/app/styles/components/sidebar-menu.scss
index 321cadc95..0b67c4d46 100644
--- a/app/styles/components/sidebar-menu.scss
+++ b/app/styles/components/sidebar-menu.scss
@@ -1,15 +1,5 @@
.sidebar-menu {
- display: flex;
- position: fixed;
- flex-direction: column;
- width: 275px;
- top: 0;
- bottom: 0;
- left: 0;
- background-color: var(--foreground-color);
- transform: translateX(-275px);
- transition: all 0.15s linear;
- z-index: 10001;
+ @apply flex inset-0 fixed flex-col w-80 bg-white transition-all ease-linear -translate-x-80 z-1000;
&__wrapper {
opacity: 0;
@@ -145,7 +135,7 @@
text-decoration: none;
color: var(--primary-text-color--faint);
font-size: 15px;
- font-weight: 400;
+ font-weight: 500;
align-items: center;
&:hover {
diff --git a/app/styles/components/snackbar.scss b/app/styles/components/snackbar.scss
index 3f43043ca..da22a3ff3 100644
--- a/app/styles/components/snackbar.scss
+++ b/app/styles/components/snackbar.scss
@@ -1,73 +1,52 @@
.notification-list {
- position: fixed;
- bottom: var(--thumb-navigation-height);
- z-index: 1000; /* Above ThumbNavigation */
- width: 100%;
-
- @media (min-width: 895px) {
- bottom: 0;
- }
+ @apply w-full flex flex-col items-center space-y-2 sm:items-end;
}
-.snackbar {
- font-size: 16px !important;
- padding: 10px 20px 10px 14px !important;
- position: absolute !important;
- display: flex;
- align-items: center;
- justify-content: center;
+.notification-bar {
+ @apply max-w-sm w-full flex flex-row items-center bg-white shadow-lg rounded-lg pointer-events-auto ring-1 ring-black ring-opacity-5 overflow-hidden;
&::before {
font-family: 'Font Awesome 5 Free';
font-weight: 900;
font-size: 20px;
- margin-right: 8px;
- }
-
- &--info {
- background-color: #19759e !important;
-
- &::before {
- content: '\f05a';
- }
- }
-
- &--post {
- background-color: #0482d8 !important;
- }
-
- &--success {
- background-color: #199e5a !important;
-
- &::before {
- content: '\f00c';
- }
- }
-
- &--error {
- background-color: #9e1919 !important;
-
- &::before {
- content: '\f05e';
- }
- }
-
- .notification-bar-wrapper {
- transform: translateY(1px);
- }
-
- .notification-bar-action a {
- @include font-roboto;
- font-size: 16px;
- color: white;
- font-weight: 700;
- text-decoration: none;
- text-transform: none;
-
- &:hover,
- &:active,
- &:focus {
- text-decoration: underline;
- }
}
}
+
+.notification-bar-success {
+ @apply text-success-500;
+
+ &::before {
+ @apply ml-4;
+ content: '\f058';
+ }
+}
+
+.notification-bar-error {
+ @apply text-danger-500 ml-4;
+
+ &::before {
+ @apply ml-4;
+ content: '\f057';
+ }
+}
+
+.notification-bar-info {
+ @apply text-primary-500 ml-4;
+
+ &::before {
+ @apply ml-4;
+ content: '\f05a';
+ }
+}
+
+.notification-bar-wrapper {
+ @apply p-4 flex items-start;
+}
+
+.notification-bar-title {
+ @apply mb-1 text-sm font-medium text-gray-900;
+}
+
+.notification-bar-message {
+ @apply text-sm text-gray-700;
+}
diff --git a/app/styles/components/status.scss b/app/styles/components/status.scss
index ba06c5039..8a85c3067 100644
--- a/app/styles/components/status.scss
+++ b/app/styles/components/status.scss
@@ -71,6 +71,7 @@
line-height: normal !important;
img.emojione {
+ display: inline;
width: 36px;
height: 36px;
padding: 5px;
@@ -158,12 +159,12 @@
}
}
+.status-link {
+ @apply hover:underline text-primary-600 hover:text-primary-800;
+}
+
.status {
- padding: 8px 10px;
- padding-left: 68px;
- position: relative;
- min-height: 54px;
- cursor: default;
+ @apply min-h-[54px] cursor-default;
@supports (-ms-overflow-style: -ms-autohiding-scrollbar) {
// Add margin to avoid Edge auto-hiding scrollbar appearing over content.
@@ -236,6 +237,15 @@
}
}
+.status__wrapper {
+ @apply bg-white px-4 py-6 sm:shadow-xl sm:p-5 sm:rounded-xl;
+}
+
+[column-type=filled] .status__wrapper,
+[column-type=filled] .status-placeholder {
+ @apply rounded-none shadow-none p-4;
+}
+
.status__display-name {
color: var(--primary-text-color--faint);
}
@@ -338,16 +348,6 @@
font-weight: 500;
color: var(--brand-color);
}
-
- &--reblog {
- > div {
- display: flex;
-
- > .icon-button {
- margin-right: 8px;
- }
- }
- }
}
}
@@ -379,25 +379,17 @@
.status__content,
.reply-indicator__content {
- position: relative;
- font-size: 15px;
- line-height: 20px;
- word-wrap: break-word;
- font-weight: 400;
- overflow: hidden;
- text-overflow: ellipsis;
- padding-top: 2px;
- color: var(--primary-text-color);
+ @apply text-gray-900 break-words text-ellipsis overflow-hidden relative;
&:focus {
- outline: 0;
+ @apply outline-none;
}
&.status__content--with-spoiler {
- white-space: normal;
+ @apply whitespace-normal;
.status__content__text {
- white-space: pre-wrap;
+ @apply whitespace-pre-wrap;
}
}
@@ -405,6 +397,7 @@
width: 20px;
height: 20px;
margin: -3px 0 0;
+ display: inline;
}
p {
@@ -417,26 +410,7 @@
}
a {
- color: var(--highlight-text-color);
- text-decoration: none;
-
- &:hover {
- text-decoration: underline;
-
- .fa {
- color: var(--primary-text-color);
- }
- }
-
- &.mention {
- &:hover {
- text-decoration: none;
-
- span {
- text-decoration: underline;
- }
- }
- }
+ @apply text-primary-600 hover:underline;
.fa {
color: var(--primary-text-color);
@@ -484,8 +458,8 @@
.focusable:focus,
.focusable-within:focus-within {
- outline: 0;
- box-shadow: 0 0 6px 0 hsla(var(--brand-color_hsl), 0.7);
+ outline: 0; /* Required b/c HotKeys lib sets this outline */
+ @apply ring-2 ring-primary-300;
.status.status-direct {
&.muted {
@@ -495,82 +469,15 @@
}
.status-card {
- display: flex;
- font-size: 14px;
- border: 1px solid var(--brand-color--med);
- border-radius: 10px;
- color: var(--primary-text-color);
- margin-top: 14px;
- min-height: 150px;
- text-decoration: none;
- overflow: hidden;
-
- &__actions {
- bottom: 0;
- left: 0;
- position: absolute;
- right: 0;
- top: 0;
- display: flex;
- justify-content: center;
- align-items: center;
-
- & > div {
- background: var(--background-color);
- border-radius: 8px;
- padding: 12px 9px;
- flex: 0 0 auto;
- display: flex;
- justify-content: center;
- align-items: center;
- }
-
- button,
- a {
- display: inline;
- color: var(--primary-text-color--faint);
- background: transparent;
- border: 0;
- padding: 0 8px;
- text-decoration: none;
- font-size: 18px;
- line-height: 18px;
-
- &:hover,
- &:active,
- &:focus {
- color: var(--primary-text-color);
- }
- }
-
- a {
- font-size: 19px;
- position: relative;
- bottom: -1px;
- }
-
- .svg-icon {
- width: 20px;
- height: 20px;
- }
- }
+ @apply flex text-sm border border-solid border-gray-200 rounded-lg text-gray-800 mt-3 min-h-[150px] no-underline overflow-hidden;
}
a.status-card {
- cursor: pointer;
-
- &:hover {
- background: var(--brand-color--med);
- }
+ @apply cursor-pointer hover:bg-gray-50 hover:no-underline;
}
.status-card-photo {
- cursor: zoom-in;
- display: block;
- text-decoration: none;
- width: 100%;
- height: auto;
- margin: 0;
+ @apply cursor-zoom-in block no-underline w-full h-auto;
}
.status-card-video,
@@ -582,27 +489,15 @@ a.status-card {
}
.status-card__title {
- display: block;
- font-size: 16px;
- font-weight: 500;
- margin-bottom: 10px;
- color: var(--primary-text-color);
- text-decoration: none;
+ @apply block font-medium mb-2 text-gray-800 no-underline;
}
.status-card__content {
- flex: 1 1 auto;
- overflow: hidden;
- padding: 16px;
+ @apply flex-1 overflow-hidden p-4;
}
.status-card__description {
- color: var(--primary-text-color--faint);
- overflow: hidden;
- text-overflow: ellipsis;
- display: -webkit-box;
- -webkit-line-clamp: 5;
- -webkit-box-orient: vertical;
+ @apply text-gray-500;
}
.status-card__host {
@@ -648,44 +543,25 @@ a.status-card {
.status-card.horizontal {
display: block;
- .status-card__image {
- width: 100%;
- }
-
.status-card__title {
white-space: inherit;
}
}
.status-card.compact {
- border-color: var(--brand-color--faint);
-}
-
-a.status-card.compact:hover {
- background-color: var(--brand-color--faint);
+ @apply border-gray-200;
}
.status-card__image-image {
- border-radius: 4px 0 0 4px;
- display: block;
- margin: 0;
- width: 100%;
- height: 100%;
- object-fit: cover;
- background-size: cover;
- background-position: center center;
+ @apply block w-full h-full object-cover bg-cover bg-center;
}
-@media (max-width: 600px) {
- .status-card--link {
- flex-direction: column;
+.status-card--link {
+ @apply flex flex-col md:flex-row;
+}
- .status-card__image {
- width: 100%;
- height: 200px;
- flex: none;
- }
- }
+.status-card--link .status-card__image {
+ @apply w-full rounded-l md:w-auto h-[200px] md:h-auto flex-none md:flex-auto;
}
.status__favicon {
@@ -741,6 +617,47 @@ a.status-card.compact:hover {
@include standard-panel;
padding: 15px 0 10px;
}
+
+ .status {
+ padding: 8px 10px;
+
+ &__avatar {
+ position: relative;
+ margin-right: 10px;
+ top: 0;
+ left: 0;
+ }
+
+ &__profile {
+ display: flex;
+ align-items: center;
+ }
+
+ &__content {
+ padding-top: 10px;
+ }
+
+ &__display-name {
+ .display-name__account {
+ display: block;
+ }
+ }
+ }
+}
+
+@media screen and (min-width: 630px) {
+ .columns-area .material-status .status {
+ padding: 15px;
+
+ &__avatar {
+ top: 0;
+ left: 0;
+ }
+
+ &__content {
+ padding-top: 10px;
+ }
+ }
}
.attachment-thumbs {
@@ -761,79 +678,3 @@ a.status-card.compact:hover {
.pending-status {
opacity: 0.5;
}
-
-.quoted-status {
- margin-top: 14px;
- border: 1px solid var(--brand-color--med);
- border-radius: 10px;
- padding: 12px;
- transition: background 0.2s;
- cursor: pointer;
-
- &:hover,
- &:focus,
- &:active {
- background: var(--brand-color--faint);
- }
-
- &__relative-time {
- padding-top: 4px;
- }
-
- &__display-name {
- color: var(--primary-text-color);
- display: block;
- max-width: 100%;
- line-height: 24px;
- overflow: hidden;
- padding-right: 25px;
- text-decoration: none;
-
- .display-name__account {
- color: var(--primary-text-color--faint);
- }
- }
-
- &__display-avatar {
- float: left;
- margin-right: 5px;
- }
-
- .reply-mentions {
- font-size: 14px;
- }
-
- &__content {
- display: -webkit-box;
- overflow: hidden;
- text-overflow: ellipsis;
- -webkit-line-clamp: 6;
- -webkit-box-orient: vertical;
- max-height: 114px;
- margin-top: 5px;
- font-size: 14px;
-
- a {
- color: var(--highlight-text-color);
- text-decoration: none;
-
- &:hover {
- text-decoration: underline;
- }
- }
- }
-
- .attachment-thumbs .media-gallery {
- margin-top: 5px !important;
- }
-
- &-tombstone {
- margin-top: 14px;
- padding: 12px;
- border: 1px solid var(--brand-color--med);
- border-radius: 10px;
- color: var(--primary-text-color--faint);
- font-size: 14px;
- text-align: center;
- }
-}
diff --git a/app/styles/components/timeline-queue-header.scss b/app/styles/components/timeline-queue-header.scss
deleted file mode 100644
index 93cf73d6f..000000000
--- a/app/styles/components/timeline-queue-header.scss
+++ /dev/null
@@ -1,53 +0,0 @@
-.timeline-queue-header {
- display: flex;
- align-self: center;
- align-items: center;
- justify-content: space-evenly;
- height: 30px;
- position: fixed;
- top: 60px;
- margin: 0 auto;
- background-color: var(--brand-color);
- color: #fff;
- border-radius: 100px;
- transition: 150ms ease;
- overflow: hidden;
- padding: 0 10px;
- z-index: 500;
-
- .sub-navigation ~ & {
- top: calc(60px + 41px);
- }
-
- .svg-icon {
- margin-right: 5px;
- }
-
- &.hidden {
- transform: scaleY(0);
- pointer-events: none;
-
- .timeline-queue-header__label {
- opacity: 0;
- }
- }
-
- &__btn {
- display: flex;
- line-height: 46px;
- font-size: 14px;
- cursor: pointer;
- color: #fff;
- white-space: nowrap;
- align-items: center;
- justify-content: center;
-
- span {
- height: 46px;
- }
- }
-
- &__label {
- transition: 150ms ease;
- }
-}
diff --git a/app/styles/components/video-player.scss b/app/styles/components/video-player.scss
index 57061a2ff..4f40b06aa 100644
--- a/app/styles/components/video-player.scss
+++ b/app/styles/components/video-player.scss
@@ -115,7 +115,7 @@
}
}
- &.inline {
+ &--inline {
video {
object-fit: contain;
position: relative;
@@ -139,7 +139,7 @@
}
}
- &.inactive {
+ &--inactive {
min-height: 300px;
video,
diff --git a/app/styles/components/wtf-panel.scss b/app/styles/components/wtf-panel.scss
index 1e5e13230..120abe338 100644
--- a/app/styles/components/wtf-panel.scss
+++ b/app/styles/components/wtf-panel.scss
@@ -30,7 +30,6 @@
&.svg-icon {
width: 20px;
- min-width: 20px;
height: 20px;
}
}
diff --git a/app/styles/demetricator.scss b/app/styles/demetricator.scss
index 2810e5820..441e68ea1 100644
--- a/app/styles/demetricator.scss
+++ b/app/styles/demetricator.scss
@@ -18,10 +18,4 @@ body.demetricator {
.svg-icon--unread svg {
transform: rotate(0);
}
-
- @media (min-width: 896px) {
- .account-timeline .sub-navigation {
- top: 110px;
- }
- }
}
diff --git a/app/styles/developers.scss b/app/styles/developers.scss
deleted file mode 100644
index b33877120..000000000
--- a/app/styles/developers.scss
+++ /dev/null
@@ -1,21 +0,0 @@
-.developers-challenge {
- .code {
- font-family: 'Roboto Mono', monospace;
- cursor: text;
- background-color: var(--background-color);
- }
-
- span.code {
- padding: 2px 4px;
- border-radius: 4px;
- }
-
- pre.code {
- line-height: 1.6em;
- overflow-x: auto;
- border-radius: 6px;
- padding: 8px 12px;
- margin: 20px 0;
- word-break: break-all;
- }
-}
diff --git a/app/styles/emoji_picker.scss b/app/styles/emoji_picker.scss
index 9fb1a326c..ae4d95213 100644
--- a/app/styles/emoji_picker.scss
+++ b/app/styles/emoji_picker.scss
@@ -1,184 +1,139 @@
+.emoji-mart,
+.emoji-mart * {
+ box-sizing: border-box;
+ line-height: 1.15;
+}
+
.emoji-mart {
- font-size: 13px;
- display: inline-block;
+ @apply text-base inline-block text-gray-900 rounded bg-white shadow-lg;
+}
- &,
- * {
- box-sizing: border-box;
- line-height: 1.15;
- color: var(--primary-text-color);
- }
-
- .emoji-mart-emoji {
- padding: 6px;
- }
+.emoji-mart .emoji-mart-emoji {
+ @apply p-1.5;
}
.emoji-mart-bar {
- border: 0 solid var(--background-color);
+ border: 0 solid #e5e7eb;
+}
- &:first-child {
- border-bottom-width: 1px;
- border-top-left-radius: 5px;
- border-top-right-radius: 5px;
- background: var(--foreground-color);
- }
+.emoji-mart-bar:first-child {
+ border-bottom-width: 1px;
+ border-top-left-radius: 5px;
+ border-top-right-radius: 5px;
+}
- &:last-child {
- border-top-width: 1px;
- border-bottom-left-radius: 5px;
- border-bottom-right-radius: 5px;
- display: none;
- }
+.emoji-mart-bar:last-child {
+ border-top-width: 1px;
+ border-bottom-left-radius: 5px;
+ border-bottom-right-radius: 5px;
}
.emoji-mart-anchors {
- display: flex;
- justify-content: space-between;
- padding: 0 6px;
- color: var(--primary-text-color--faint);
- line-height: 0;
+ @apply flex flex-row justify-between px-1.5;
}
.emoji-mart-anchor {
- position: relative;
- flex: 1;
- text-align: center;
- padding: 12px 4px;
- overflow: hidden;
- transition: color 0.1s ease-out;
- cursor: pointer;
- background: transparent;
- border: 0;
-
- &:hover {
- color: var(--primary-text-color--faint);
- }
+ @apply relative block flex-auto text-gray-400 text-center overflow-hidden transition-colors py-3 px-1;
}
+.emoji-mart-anchor:focus { outline: 0; }
+
+.emoji-mart-anchor:hover,
+.emoji-mart-anchor:focus,
.emoji-mart-anchor-selected {
- color: var(--highlight-text-color);
+ @apply text-gray-600;
+}
- &:hover {
- color: var(--highlight-text-color);
- }
-
- .emoji-mart-anchor-bar {
- bottom: -1px;
- }
+.emoji-mart-anchor-selected .emoji-mart-anchor-bar {
+ @apply bottom-0;
}
.emoji-mart-anchor-bar {
- position: absolute;
- bottom: -5px;
- left: 0;
- width: 100%;
- height: 4px;
- background-color: var(--highlight-text-color);
+ @apply absolute -bottom-0.5 left-0 w-11/12 h-0.5 bg-primary-600;
}
-.emoji-mart-anchors {
- i {
- display: inline-block;
- width: 100%;
- max-width: 22px;
- }
+.emoji-mart-anchors i {
+ @apply inline-block w-full;
+ max-width: 22px;
+}
- svg {
- fill: currentColor;
- max-height: 18px;
- }
+.emoji-mart-anchors svg,
+.emoji-mart-anchors img {
+ fill: currentColor;
+ height: 18px;
+ width: 18px;
}
.emoji-mart-scroll {
overflow-y: scroll;
+ overflow-x: hidden;
height: 270px;
- max-height: 35vh;
- padding: 0 6px 6px;
- background: var(--foreground-color);
- will-change: transform;
-
- &::-webkit-scrollbar-track:hover,
- &::-webkit-scrollbar-track:active {
- background-color: rgba($base-overlay-background, 0.3);
- }
+ padding: 0 6px 6px 6px;
+ will-change: transform; /* avoids "repaints on scroll" in mobile Chrome */
}
.emoji-mart-search {
- padding: 10px;
- padding-right: 45px;
- background: var(--foreground-color);
- position: relative;
+ @apply relative mt-1.5 p-2.5 pr-12 bg-white;
+}
- input {
- font-size: 14px;
- font-weight: 400;
- padding: 7px 9px;
- padding-right: 25px;
- font-family: inherit;
- display: block;
- width: 100%;
- background: var(--background-color);
- color: var(--primary-text-color);
- border: 1px solid var(--brand-color--faint);
- border-radius: 9999px;
+.emoji-mart-search input {
+ @apply text-sm pr-9 block w-full border-gray-300 rounded-full focus:ring-primary-500 focus:border-primary-500;
- &::-moz-focus-inner {
- border: 0;
- }
-
- &::-moz-focus-inner,
- &:focus,
- &:active {
- outline: 0 !important;
- }
+ &::-moz-focus-inner {
+ border: 0;
}
+
+ &::-webkit-search-cancel-button {
+ @apply hidden;
+ }
+
+ &::-moz-focus-inner,
+ &:focus,
+ &:active {
+ outline: 0 !important;
+ }
+}
+
+.emoji-mart-search input,
+.emoji-mart-search input::-webkit-search-decoration,
+.emoji-mart-search input::-webkit-search-cancel-button,
+.emoji-mart-search input::-webkit-search-results-button,
+.emoji-mart-search input::-webkit-search-results-decoration {
+ /* remove webkit/blink styles for
+ * via https://stackoverflow.com/a/9422689 */
+ -webkit-appearance: none;
}
.emoji-mart-search-icon {
- position: absolute;
- top: 18px;
- right: 45px + 5px;
- z-index: 2;
+ @apply absolute z-10 border-0;
+ top: 20px;
+ right: 56px;
padding: 2px 5px 1px;
- border: 0;
- background: none;
- transition: all 100ms linear;
- transition-property: opacity;
- pointer-events: auto;
- opacity: 0.7;
-
- &:disabled {
- cursor: default;
- pointer-events: none;
- opacity: 0.3;
- }
-
- svg {
- fill: var(--primary-text-color);
- }
}
-.emoji-mart-category .emoji-mart-emoji {
- cursor: pointer;
+.emoji-mart-search-icon svg {
+ @apply stroke-gray-400;
+}
- span {
- z-index: 1;
- position: relative;
- text-align: center;
- }
+.emoji-mart-search-icon:hover svg {
+ @apply stroke-gray-800;
+}
- &:hover::before {
- z-index: -1;
- content: "";
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- background-color: hsla(var(--background-color_hsl), 0.7);
- border-radius: 100%;
- }
+.emoji-mart-category .emoji-mart-emoji span {
+ @apply relative text-center;
+ z-index: 1;
+}
+
+.emoji-mart-category .emoji-mart-emoji:hover::before {
+ z-index: 0;
+ content: "";
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background-color: #f4f4f4;
+ border-radius: 100%;
}
.emoji-mart-category-label {
@@ -187,26 +142,15 @@
position: -webkit-sticky;
position: sticky;
top: 0;
-
- span {
- display: block;
- width: 100%;
- font-weight: 500;
- padding: 5px 6px;
- background: var(--foreground-color);
- }
}
-/* For screenreaders only, via https://stackoverflow.com/a/19758620 */
-.emoji-mart-sr-only {
- position: absolute;
- width: 1px;
- height: 1px;
- padding: 0;
- margin: -1px;
- overflow: hidden;
- clip: rect(0, 0, 0, 0);
- border: 0;
+.emoji-mart-category-label span {
+ display: block;
+ width: 100%;
+ font-weight: 500;
+ padding: 5px 6px;
+ background-color: #fff;
+ background-color: rgba(255, 255, 255, 0.95);
}
.emoji-mart-category-list {
@@ -224,43 +168,60 @@
.emoji-mart-emoji {
position: relative;
display: inline-block;
- background: transparent;
- border: 0;
- padding: 0;
font-size: 0;
+ margin: 0;
+ padding: 0;
+ border: none;
+ background: none;
+ box-shadow: none;
+}
- span {
- width: 22px;
- height: 22px;
- }
+.emoji-mart-emoji-native {
+ font-family: "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "Apple Color Emoji", "Twemoji Mozilla", "Noto Color Emoji", "Android Emoji";
}
.emoji-mart-no-results {
- font-size: 14px;
- color: var(--primary-text-color--faint);
- text-align: center;
- padding: 5px 6px;
+ @apply text-sm text-center text-gray-600;
padding-top: 70px;
-
- .emoji-mart-no-results-label {
- margin-top: 0.2em;
- }
-
- .emoji-mart-emoji:hover::before {
- cursor: default;
- content: none;
- }
}
-.emoji-mart-preview {
+.emoji-mart-no-results-img {
+ display: block;
+ margin-left: auto;
+ margin-right: auto;
+ width: 50%;
+}
+
+.emoji-mart-no-results .emoji-mart-category-label {
display: none;
}
-.emoji-picker-dropdown__menu {
- @include standard-panel;
- background: var(--foreground-color);
+.emoji-mart-no-results .emoji-mart-no-results-label {
+ margin-top: 0.2em;
+}
+
+.emoji-mart-no-results .emoji-mart-emoji:hover::before {
+ content: none;
+}
+
+.emoji-mart-preview {
+ @apply hidden;
+}
+
+/* For screenreaders only, via https://stackoverflow.com/a/19758620 */
+.emoji-mart-sr-only {
position: absolute;
- margin-top: 5px;
+ width: 1px;
+ height: 1px;
+ padding: 0;
+ margin: -1px;
+ overflow: hidden;
+ clip: rect(0, 0, 0, 0);
+ border: 0;
+}
+
+.emoji-picker-dropdown__menu {
+ @apply rounded-lg absolute mt-1.5;
transform: translateX(calc(-1 * env(safe-area-inset-right))); /* iOS PWA */
z-index: 20000;
@@ -275,20 +236,16 @@
.emoji-picker-dropdown__modifiers {
position: absolute;
- top: 60px;
- right: 11px;
+ top: 65px;
+ right: 14px;
cursor: pointer;
}
.emoji-picker-dropdown__modifiers__menu {
- position: absolute;
+ @apply absolute bg-white rounded-3xl shadow overflow-hidden;
z-index: 4;
top: -4px;
left: -8px;
- background: var(--foreground-color);
- border-radius: 4px;
- box-shadow: 1px 2px 6px rgba($base-shadow-color, 0.2);
- overflow: hidden;
button {
display: block;
@@ -308,44 +265,3 @@
height: 22px;
}
}
-
-.emoji-mart-emoji {
- span {
- background-repeat: no-repeat;
- }
-}
-
-.font-icon-picker {
- .emoji-mart-search {
- // Search doesn't work. Hide it for now.
- display: none;
- padding: 10px !important;
- }
-
- .emoji-mart-category-label > span {
- padding: 9px 6px 5px;
- }
-
- .emoji-mart-scroll {
- border-radius: 4px;
- }
-
- .emoji-mart-search-icon {
- right: 18px;
- }
-
- .emoji-mart-bar {
- display: none;
- }
-
- .fa {
- font-size: 18px;
- width: 22px;
- height: 22px;
- text-align: center;
- }
-
- .fa-hack {
- margin: 0 auto;
- }
-}
diff --git a/app/styles/fonts.scss b/app/styles/fonts.scss
index 9a0dfd758..6f8da5e30 100644
--- a/app/styles/fonts.scss
+++ b/app/styles/fonts.scss
@@ -28,9 +28,7 @@
// TYPEOGRAPHY MIXINS
// declare the font family using these shortcuts
-@mixin font-roboto { font-family: 'Roboto', Arial, sans-serif !important; }
-
-@mixin font-montserrat { font-family: 'Montserrat', Arial, sans-serif !important; }
+@mixin font-inter { font-family: 'Inter', Arial, sans-serif !important; }
// Declare font weights as a numerical value in rendered output
// Prevents certain browsers which do not play nice with "light, medium" textual declarations
diff --git a/app/styles/footer.scss b/app/styles/footer.scss
index a15490a5e..e73994922 100644
--- a/app/styles/footer.scss
+++ b/app/styles/footer.scss
@@ -15,19 +15,11 @@
.footer-container {
display: flex;
- width: 960px;
- flex-direction: row;
- flex-wrap: wrap;
+ width: 1440px;
align-items: center;
-
- @media screen and (max-width: 1024px) {
- width: 100%;
- }
-
- @media screen and (max-width: 767px) {
- flex-direction: column-reverse;
- justify-content: center;
- }
+ padding: 0 20px;
+ flex-direction: column-reverse;
+ justify-content: center;
}
h4 {
@@ -45,7 +37,8 @@
}
.copyright {
- margin-right: auto;
+ margin: 0 auto auto;
+ text-align: center;
span {
font-size: 1.3rem;
@@ -57,12 +50,12 @@
ul {
display: flex;
flex-wrap: wrap;
- margin-left: auto;
+ margin: 0 auto 20px;
li {
a {
text-decoration: none;
- color: #fff;
+ color: $color-5-dark;
font-size: 1.3rem;
font-weight: 500;
line-height: 1.5;
@@ -77,16 +70,5 @@
}
}
}
-
- @media screen and (max-width: 767px) {
- .copyright {
- margin: 0 auto auto;
- text-align: center;
- }
-
- ul {
- margin: 0 auto 20px;
- }
- }
}
}
diff --git a/app/styles/forms.scss b/app/styles/forms.scss
index 53551941a..06a797036 100644
--- a/app/styles/forms.scss
+++ b/app/styles/forms.scss
@@ -1,3 +1,26 @@
+select {
+ @apply pl-3 pr-10 py-2 text-base border-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md;
+}
+
+.form-error::before,
+.form-error::after {
+ border: solid transparent;
+ bottom: 100%;
+ content: '';
+ height: 0;
+ left: 10px;
+ pointer-events: none;
+ width: 0;
+ position: absolute;
+}
+
+.form-error::before {
+ --tw-bg-opacity: 1;
+ border-bottom-color: rgba(254, 202, 202, var(--tw-bg-opacity));
+ border-width: 6px;
+ margin-left: -1px;
+}
+
$no-columns-breakpoint: 600px;
code {
@@ -13,8 +36,9 @@ code {
.simple_form {
.input {
- margin-bottom: 8px;
- overflow: hidden;
+ + .input {
+ margin-top: 20px;
+ }
&.hidden {
margin: 0;
@@ -164,11 +188,11 @@ code {
}
}
- .input.with_label {
+ .input {
.label_input > label {
font-family: inherit;
font-size: 14px;
- color: var(--primary-text-color);
+ color: var(--gray-700);
display: block;
word-wrap: break-word;
font-weight: 500;
@@ -212,6 +236,10 @@ code {
.fields-group {
margin-bottom: 25px;
+ &:last-child {
+ margin-bottom: 0;
+ }
+
.input:last-child {
margin-bottom: 0;
}
@@ -318,10 +346,10 @@ code {
outline: 0;
font-family: inherit;
resize: vertical;
- background-color: var(--background-color);
- border: 1px solid var(--highlight-text-color);
- border-radius: 4px;
- padding: 10px;
+ box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
+ border: 1px solid var(--input-border-color);
+ border-radius: 6px;
+ padding: 8px 12px;
transition: 0.2s;
&:invalid {
@@ -332,13 +360,18 @@ code {
border-color: lighten($error-red, 12%);
}
- &:required:valid {
- border-color: $valid-value-color;
- }
+ // &:required:valid {
+ // border-color: $valid-value-color;
+ // }
&:active,
&:focus {
- border-color: var(--brand-color--hicontrast);
+ border-color: var(--brand-color);
+ outline: 2px solid transparent;
+ outline-offset: 2px;
+ box-shadow: rgb(255, 255, 255) 0 0 0 0,
+ var(--brand-color) 0 0 0 1px,
+ rgba(0, 0, 0, 0.05) 0 1px 2px 0;
}
}
@@ -385,8 +418,9 @@ code {
}
.actions {
- margin-top: 30px;
+ margin-top: 20px;
display: flex;
+ justify-content: flex-end;
&.actions--top {
margin-top: 0;
@@ -394,104 +428,91 @@ code {
}
}
- button,
- .button,
- .block-button,
- .color-swatch {
- display: block;
- width: 100%;
- border: 0;
- border-radius: 4px;
- background: var(--brand-color);
- color: #fff;
- font-size: 18px;
- line-height: inherit;
- height: auto;
- padding: 10px;
- text-transform: uppercase;
- text-decoration: none;
- text-align: center;
- box-sizing: border-box;
- cursor: pointer;
- font-weight: 500;
- outline: 0;
- margin-bottom: 10px;
- margin-right: 10px;
+ // button,
+ // .button,
+ // .block-button,
+ // .color-swatch {
+ // display: block;
+ // width: 100%;
+ // border: 0;
+ // border-radius: 4px;
+ // background: var(--brand-color);
+ // color: #fff;
+ // line-height: inherit;
+ // height: auto;
+ // padding: 10px;
+ // text-decoration: none;
+ // text-align: center;
+ // box-sizing: border-box;
+ // cursor: pointer;
+ // font-weight: 500;
+ // outline: 0;
- accent_color {
- background: var(--accent-color);
- }
+ // &:last-child {
+ // margin-right: 0;
+ // }
- &:last-child {
- margin-right: 0;
- }
+ // &:hover,
+ // &:active,
+ // &:focus {
+ // background-color: var(--brand-color--hicontrast);
+ // }
- &:hover,
- &:active,
- &:focus {
- background-color: var(--brand-color--hicontrast);
- }
+ // &.negative {
+ // background: $error-value-color;
- &.negative {
- background: $error-value-color;
+ // &:hover {
+ // background-color: lighten($error-value-color, 5%);
+ // }
- &:hover {
- background-color: lighten($error-value-color, 5%);
- }
+ // &:active,
+ // &:focus {
+ // background-color: darken($error-value-color, 5%);
+ // }
+ // }
- &:active,
- &:focus {
- background-color: darken($error-value-color, 5%);
- }
- }
+ // &.accordion__toggle {
+ // display: inline-block;
+ // width: auto;
+ // border: 0;
+ // border-radius: 0;
+ // background: none;
+ // color: var(--primary-text-color--faint);
+ // font-size: 18px;
+ // line-height: inherit;
+ // height: auto;
+ // padding: 0 10px;
+ // text-transform: none;
+ // text-decoration: none;
+ // text-align: center;
+ // box-sizing: border-box;
+ // cursor: pointer;
+ // font-weight: 500;
+ // outline: 0;
+ // margin-bottom: 0;
+ // margin-right: 10px;
+ // }
+ // }
- &.accordion__toggle {
- display: inline-block;
- width: auto;
- border: 0;
- border-radius: 0;
- background: none;
- color: var(--primary-text-color--faint);
- font-size: 18px;
- line-height: inherit;
- height: auto;
- padding: 0 10px;
- text-transform: none;
- text-decoration: none;
- text-align: center;
- box-sizing: border-box;
- cursor: pointer;
- font-weight: 500;
- outline: 0;
- margin-bottom: 0;
- margin-right: 10px;
- }
- }
-
- select {
- appearance: none;
- box-sizing: border-box;
- font-size: 16px;
- color: var(--primary-text-color);
- background: var(--background-color);
- display: block;
- width: 100%;
- outline: 0;
- font-family: inherit;
- resize: vertical;
- border: 1px solid var(--highlight-text-color);
- border-radius: 4px;
- padding-left: 10px;
- padding-right: 30px;
- height: 41px;
- position: relative;
- margin-top: 8px;
- cursor: pointer;
-
- &:focus {
- background: var(--accent-color--faint);
- }
- }
+ // select {
+ // appearance: none;
+ // background-color: transparent;
+ // background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
+ // background-position: right 0.5rem center;
+ // background-repeat: no-repeat;
+ // background-size: 1.5em 1.5em;
+ // border-radius: 0.375rem;
+ // border: none;
+ // color: var(--gray-500);
+ // display: inline-block;
+ // font-family: var(--font-sans-serif), sans-serif;
+ // font-size: 14px;
+ // height: var(--input-height);
+ // padding-bottom: 0.5rem;
+ // padding-left: 0.75rem;
+ // padding-right: 2.5rem;
+ // padding-top: 0.5rem;
+ // }
.select-wrapper {
display: flex;
@@ -514,7 +535,7 @@ code {
.label_input {
&__color {
- display: flex;
+ display: inline-flex;
font-size: 14px;
.color-swatch {
@@ -536,7 +557,7 @@ code {
display: flex;
align-items: center;
justify-content: center;
- height: 41px;
+ height: 38px;
box-sizing: border-box;
.fa {
@@ -625,7 +646,7 @@ code {
position: absolute;
top: 0;
right: 0;
- height: 41px;
+ height: 38px;
width: 36px;
padding: 0;
margin: 0;
@@ -638,61 +659,6 @@ code {
}
}
}
-
- .datepicker {
- padding: 0;
- margin-bottom: 8px;
- border: none;
-
- &__hint {
- padding-bottom: 0;
- color: var(--primary-text-color);
- font-size: 14px;
- font-style: unset;
- }
-
- .react-datepicker {
- &__header {
- padding-top: 4px;
- }
-
- &__input-container {
- border: 1px solid var(--highlight-text-color);
-
- input {
- border: none;
- }
- }
- }
-
- &__years,
- &__months {
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin: 0 4px;
- font-size: 16px;
- }
-
- &__button {
- width: 28px;
- margin: 0;
- padding: 4px;
- background: transparent;
- color: var(--primary-text-color);
-
- &:hover,
- &:active,
- &:focus {
- background: none;
- }
-
- .svg-icon {
- height: 20px;
- width: 20px;
- }
- }
- }
}
.block-icon {
@@ -743,8 +709,10 @@ code {
}
.columns-area {
- form.simple_form {
- padding: 15px;
+ form.simple_form--public {
+ @include standard-panel;
+ margin-top: 20px;
+ padding: 60px 30px;
}
}
@@ -812,6 +780,12 @@ code {
}
}
+.delete-account {
+ margin-top: 50px;
+ display: flex;
+ justify-content: center;
+}
+
.input .row > .svg-icon.delete-field {
height: 20px;
width: 20px;
diff --git a/app/styles/loading.scss b/app/styles/loading.scss
index b5ee78662..78f640f6f 100644
--- a/app/styles/loading.scss
+++ b/app/styles/loading.scss
@@ -1,40 +1,20 @@
-.loading-indicator {
- color: var(--primary-text-color--faint);
- font-size: 12px;
- font-weight: 400;
- text-transform: uppercase;
- overflow: visible;
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
+.loading-indicator-wrapper {
+ @apply h-screen w-screen flex justify-center items-center;
+}
- span {
- display: block;
- margin-top: 10px;
- white-space: nowrap;
- }
+.loading-indicator {
+ @apply text-gray-50 text-xs uppercase flex flex-col items-center justify-center overflow-visible;
}
.loading-indicator__container {
- width: 42px;
- height: 42px;
- position: relative;
+ @apply w-10 h-10 relative;
}
.loading-indicator__figure {
- position: absolute;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
- width: 42px;
- height: 42px;
- box-sizing: border-box;
- background-color: transparent;
+ @apply absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-12 h-12 rounded-full bg-transparent;
border: 0 solid;
- border-color: hsla(var(--brand-color_hsl), 0.5);
border-width: 6px;
- border-radius: 50%;
+ border-color: #e5e7eb;
}
.no-reduce-motion .loading-indicator span {
@@ -45,41 +25,30 @@
animation: loader-figure 1.15s infinite cubic-bezier(0.215, 0.61, 0.355, 1);
}
-.app-body--loading .loading-indicator {
- width: 100vw;
- height: 100vh;
- align-items: center;
+.loading-indicator-wrapper .loading-indicator {
+ @apply h-screen w-screen items-center;
&__figure {
- border-color: #ddd;
+ @apply border-gray-200;
}
}
@keyframes loader-figure {
0% {
- width: 0;
- height: 0;
- background-color: hsla(var(--brand-color_hsl), 0.5);
+ @apply bg-gray-200 w-0 h-0;
}
29% {
- background-color: hsla(var(--brand-color_hsl), 0.5);
+ @apply bg-gray-200;
}
30% {
- width: 42px;
- height: 42px;
- background-color: transparent;
- border-width: 21px;
- opacity: 1;
+ @apply w-12 h-12 bg-transparent opacity-100;
+ border-width: 6px;
}
100% {
- width: 42px;
- height: 42px;
- border-width: 0;
- opacity: 0;
- background-color: transparent;
+ @apply w-12 h-12 border-0 opacity-0 bg-transparent;
}
}
@@ -221,119 +190,7 @@
}
}
-// Pull to refresh
-.lds-ellipsis div {
- background: var(--primary-text-color--faint) !important;
-}
-
.ptr,
.ptr__children {
overflow: visible !important;
}
-
-.ptr .lds-spinner {
- width: 40px;
- height: 40px;
-}
-
-/**
- * iOS style loading spinner.
- * Adapted from: https://loading.io/css/
- * With some help scaling it: https://signalvnoise.com/posts/2577-loading-spinner-animation-using-css-and-webkit
- */
-.lds-spinner {
- display: inline-block;
- position: relative;
- width: 80px;
- height: 80px;
-
- div {
- position: absolute;
- transform-origin: 50% 50%;
- animation: lds-spinner 1.2s linear infinite;
- width: 100%;
- height: 100%;
-
- &::after {
- content: ' ';
- display: block;
- position: absolute;
- top: 3.75%;
- left: 46.25%;
- width: 7.5%;
- height: 22.5%;
- border-radius: 20%;
- background: var(--primary-text-color);
- }
-
- &:nth-child(1) {
- transform: rotate(0deg);
- animation-delay: -1.1s;
- }
-
- &:nth-child(2) {
- transform: rotate(30deg);
- animation-delay: -1s;
- }
-
- &:nth-child(3) {
- transform: rotate(60deg);
- animation-delay: -0.9s;
- }
-
- &:nth-child(4) {
- transform: rotate(90deg);
- animation-delay: -0.8s;
- }
-
- &:nth-child(5) {
- transform: rotate(120deg);
- animation-delay: -0.7s;
- }
-
- &:nth-child(6) {
- transform: rotate(150deg);
- animation-delay: -0.6s;
- }
-
- &:nth-child(7) {
- transform: rotate(180deg);
- animation-delay: -0.5s;
- }
-
- &:nth-child(8) {
- transform: rotate(210deg);
- animation-delay: -0.4s;
- }
-
- &:nth-child(9) {
- transform: rotate(240deg);
- animation-delay: -0.3s;
- }
-
- &:nth-child(10) {
- transform: rotate(270deg);
- animation-delay: -0.2s;
- }
-
- &:nth-child(11) {
- transform: rotate(300deg);
- animation-delay: -0.1s;
- }
-
- &:nth-child(12) {
- transform: rotate(330deg);
- animation-delay: 0s;
- }
- }
-}
-
-@keyframes lds-spinner {
- 0% {
- opacity: 1;
- }
-
- 100% {
- opacity: 0;
- }
-}
diff --git a/app/styles/navigation.scss b/app/styles/navigation.scss
index 87646cee0..da6c2b5bb 100644
--- a/app/styles/navigation.scss
+++ b/app/styles/navigation.scss
@@ -2,16 +2,32 @@
.primary-navigation {
flex-direction: column;
+ &:hover .btn.grouped:hover::before {
+ height: auto;
+ opacity: 0 !important;
+ }
+
> button,
- > .btn {
+ > .btn.grouped {
justify-content: flex-start;
- font-size: 19px;
- font-weight: bold;
+ font-weight: 700;
+ font-size: 15px;
+ margin: 0;
+ padding: 10px 0;
+ color: var(--gray-400);
.svg-icon {
- width: 26px;
- height: 26px;
- margin-right: 10px;
+ height: 22px;
+ width: 22px;
+ padding: 10px;
+ margin-right: 15px;
+ background-color: var(--electric-blue-contrast);
+ border-radius: var(--border-radius-lg);
+
+ svg {
+ stroke: var(--electric-blue);
+ fill: var(--electric-blue-contrast);
+ }
svg.icon-tabler {
stroke-width: 1.5px;
@@ -25,6 +41,24 @@
}
}
+ &.active {
+ color: var(--black-800);
+
+ &::before {
+ height: auto;
+ opacity: 0;
+ }
+
+ .svg-icon {
+ background-color: var(--electric-blue);
+ }
+
+ .svg-icon svg {
+ stroke: #fff;
+ fill: var(--electric-blue);
+ }
+ }
+
&::before {
left: 0;
border-radius: 999px;
@@ -52,67 +86,48 @@
}
.thumb-navigation {
- position: fixed;
- bottom: 0;
- left: 0;
- right: 0;
- width: 100%;
- height: var(--thumb-navigation-base-height);
- display: flex;
- background: var(--foreground-color);
- justify-content: space-between;
- box-shadow: 0 -1px hsla(var(--primary-text-color_hsl), 0.2);
- border-radius: 0;
- z-index: 1000;
+ @apply fixed lg:hidden bottom-0 bg-white border-t border-solid border-gray-200 left-0 right-0 shadow-2xl w-full flex z-50;
padding-bottom: env(safe-area-inset-bottom); /* iOS PWA */
overflow-x: auto;
scrollbar-width: thin;
- scrollbar-color: var(--background-color);
-
- &::before,
- &::after {
- content: '';
- }
+ scrollbar-color: #fff;
&::-webkit-scrollbar {
display: none;
}
&__link {
- padding: 8px 10px;
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: end;
- color: var(--primary-text-color);
- text-decoration: none;
- font-size: 20px;
- width: 55px;
+ @apply px-2 py-2.5 space-y-1 flex flex-col flex-1 items-center text-gray-600 text-lg;
+ // padding: 8px 10px;
+ // display: flex;
+ // flex-direction: column;
+ // align-items: center;
+ // justify-content: end;
+ // color: var(--primary-text-color);
+ // text-decoration: none;
+ // font-size: 20px;
+ // width: 55px;
- span {
- margin-top: 1px;
- text-align: center;
- font-size: 1.2rem;
- }
+ // span {
+ // margin-top: 1px;
+ // text-align: center;
+ // font-size: 1.2rem;
+ // }
- .svg-icon {
- width: 24px;
- height: 24px;
+ // .svg-icon {
+ // width: 24px;
+ // height: 24px;
- svg {
- stroke-width: 1px;
- }
- }
+ // svg {
+ // stroke-width: 1px;
+ // }
+ // }
.icon-with-counter__counter {
right: -7px;
top: -5px;
}
}
-
- @media (min-width: 895px) {
- display: none;
- }
}
.sub-navigation {
diff --git a/app/styles/placeholder.scss b/app/styles/placeholder.scss
index cbdc03a55..b9ae99295 100644
--- a/app/styles/placeholder.scss
+++ b/app/styles/placeholder.scss
@@ -1,4 +1,3 @@
-.placeholder-status,
.placeholder-hashtag,
.notification--placeholder,
.status-card--placeholder,
@@ -30,35 +29,22 @@
}
}
-.placeholder-status .display-name__account {
- display: none;
-}
-
@keyframes placeholder-pulse {
0% { background-position-x: 200%; }
100% { background-position-x: 0; }
}
-.notification--placeholder .notification__message span,
.placeholder-hashtag .trends__item__name {
color: var(--brand-color);
opacity: 0.1;
}
-.status__content--placeholder,
-.display-name--placeholder,
.chat-list-item--placeholder .chat__last-message {
letter-spacing: -1px;
color: var(--brand-color) !important;
opacity: 0.1;
}
-.display-name--placeholder {
- .display-name__html {
- color: var(--brand-color) !important;
- }
-}
-
.slist {
position: relative;
diff --git a/app/styles/rtl.scss b/app/styles/rtl.scss
index 483ff5449..31694eac0 100644
--- a/app/styles/rtl.scss
+++ b/app/styles/rtl.scss
@@ -213,9 +213,9 @@ body.rtl {
}
}
- .simple_form select {
- background: var(--background-color) url("data:image/svg+xml;utf8,") no-repeat left 8px center / auto 16px;
- }
+ // .simple_form select {
+ // background: var(--background-color) url("data:image/svg+xml;utf8,") no-repeat left 8px center / auto 16px;
+ // }
.table th,
.table td {
diff --git a/app/styles/themes.scss b/app/styles/themes.scss
index de6a6b1bf..d23808161 100644
--- a/app/styles/themes.scss
+++ b/app/styles/themes.scss
@@ -29,7 +29,7 @@ body,
// Primary variables
--brand-color: hsl(var(--brand-color_hsl));
--accent-color: hsl(var(--accent-color_hsl));
- --primary-text-color: hsl(var(--primary-text-color_hsl));
+ --primary-text-color: var(--gray-900);
--background-color: hsl(var(--background-color_hsl));
--foreground-color: hsl(var(--foreground-color_hsl));
--warning-color: hsla(var(--warning-color_hsl));
@@ -41,6 +41,9 @@ body,
--background-color_hsl: var(--background-color_h), var(--background-color_s), var(--background-color_l);
--foreground-color_hsl: var(--foreground-color_h), var(--foreground-color_s), var(--foreground-color_l);
--warning-color_hsl: var(--warning-color_h), var(--warning-color_s), var(--warning-color_l);
+ --accent-color_h: calc(var(--brand-color_h) - 15);
+ --accent-color_s: 86%;
+ --accent-color_l: 44%;
// Modifiers
--brand-color--faint: hsla(var(--brand-color_hsl), 0.1);
@@ -52,8 +55,36 @@ body,
var(--accent-color_s),
calc(var(--accent-color_l) + 3%)
);
- --primary-text-color--faint: hsla(var(--primary-text-color_hsl), 0.6);
+ --primary-text-color--faint: var(--gray-400);
--warning-color--faint: hsla(var(--warning-color_hsl), 0.5);
+
+ // Colors
+ --gray-900: #08051b;
+ // --gray-800: #1d1932;
+ --gray-700: #37344c;
+ --gray-500: #656175;
+ --gray-400: #868393;
+ --gray-300: #c9c8cc;
+ --gray-50: #f9f8fc;
+ --white: #fff;
+ --dark-blue: #1d1953;
+ --electric-blue: #5448ee;
+ --electric-blue-contrast: #e8e7fd;
+ --sea-blue: #2feecc;
+
+ // Sizes
+ --border-radius-base: 4px;
+ --border-radius-lg: 8px;
+ --border-radius-xl: 12px;
+
+ // Forms
+ --input-height: 30px;
+ --input-border-color: #d1d5db;
+
+ // Typography
+ --font-sans: 'Inter', Arial, sans-serif;
+ --font-weight-heading: 700;
+ --font-weight-body: 400;
}
.theme-mode-light {
@@ -83,7 +114,7 @@ body,
--brand-color--hicontrast: hsl(
var(--brand-color_h),
var(--brand-color_s),
- calc(var(--brand-color_l) - 12%)
+ calc(var(--brand-color_l) - 5%)
);
--warning-color--hicontrast: hsl(
var(--warning-color_h),
diff --git a/app/styles/truth.scss b/app/styles/truth.scss
new file mode 100644
index 000000000..5fb35380a
--- /dev/null
+++ b/app/styles/truth.scss
@@ -0,0 +1,353 @@
+:root {
+ --tmg-green: #008000;
+}
+
+.tabs-bar {
+ background: var(--foreground-color);
+ border-bottom: 1px solid hsla(var(--primary-text-color_hsl), 0.1);
+}
+
+.tabs-bar__link {
+ &--logo {
+ padding: 9px 5px;
+ align-self: center;
+ justify-self: center;
+ filter: none;
+ }
+
+ .svg-icon {
+ color: var(--brand-color);
+ transition: none;
+ }
+
+ &:hover .svg-icon {
+ color: white;
+ }
+}
+
+.tabs-bar .react-toggle-track {
+ background-color: var(--brand-color) !important;
+}
+
+.theme-mode-dark .primary-navigation > button::before,
+.theme-mode-dark .primary-navigation > .btn::before {
+ background-color: var(--brand-color) !important;
+}
+
+body,
+.site-preview {
+ --accent-color_h: 345;
+ --accent-color_s: 100%;
+ --accent-color_l: 64%;
+}
+
+@media screen and (max-width: 450px) {
+ .tabs-bar__link--logo {
+ margin: 0 auto;
+ padding: 12px 5px;
+ position: absolute;
+ left: 0;
+ right: 0;
+ text-align: center;
+ }
+
+ .tabs-bar__split--right {
+ margin: 0;
+ order: -1;
+ }
+}
+
+.account__section-headline .column-header__buttons,
+.account__header__extra__links > div {
+ display: none;
+}
+
+.account__header__extra__links {
+ justify-content: flex-start;
+ border-bottom: 1px solid #ccc;
+
+ a {
+ display: flex;
+ align-items: center;
+ }
+
+ span:first-of-type {
+ margin-right: 5px;
+ }
+}
+
+.display-name__name {
+ display: inline-flex;
+ align-items: center;
+}
+
+// .verified-icon {
+// display: inline-flex;
+// align-items: center;
+// margin: 0 3px;
+// padding-top: 2px;
+
+// svg {
+// width: 18px;
+// height: 18px;
+// }
+// }
+
+.theme-mode-light {
+ --background-color_h: 0;
+ --background-color_s: 0%;
+ --background-color_l: 96%;
+}
+
+.status__action-bar__counter--reblog,
+.detailed-status__button--reblog {
+ .icon-button.active {
+ color: var(--tmg-green);
+
+ .svg-icon svg {
+ color: var(--tmg-green);
+ }
+ }
+}
+
+.status__action-bar__counter--favourite,
+.detailed-status__button--favourite {
+ .icon-button.active {
+ color: var(--accent-color);
+ fill: var(--accent-color);
+
+ .svg-icon svg {
+ color: var(--accent-color);
+ fill: var(--accent-color);
+ }
+ }
+}
+
+.emoji-react--reblogs {
+ .svg-icon {
+ color: var(--tmg-green);
+ }
+}
+
+.sidebar-menu__close {
+ top: 20px;
+}
+
+.primary-navigation__icon {
+ stroke: currentColor;
+}
+
+.public-layout {
+ background: linear-gradient(135deg, #fff, #f5f5f5);
+
+ .header {
+ .simple_form {
+ button {
+ background: $color-6-light;
+ color: $color-3;
+ font-size: 14px;
+ line-height: 14px;
+ padding: 10px 15px;
+ border: 1px solid $color-3 !important;
+
+ &:hover,
+ &:active,
+ &:focus {
+ background: $color-6;
+ }
+
+ &::selection {
+ background-color: transparent;
+ color: $color-3;
+ }
+ }
+
+ input[type="text"],
+ input[type="password"] {
+ padding: 8px 15px;
+ font-size: 14px;
+ line-height: 14px;
+ background: $color-6-light;
+ border-color: $color-6-dark;
+ }
+ }
+
+ .nav-right .simple_form.new_user .fields-group p.hint.subtle-hint a {
+ background-color: transparent;
+ }
+ }
+}
+
+.landing {
+ .landing-columns--left {
+ display: flex;
+ align-items: center;
+ }
+
+ .landing-columns--right {
+ display: flex;
+ align-items: center;
+
+ .simple_form {
+ position: relative;
+ z-index: 10;
+ box-shadow: 0 0 30px 5px rgba(0, 0, 0, 0.05);
+ background-color: $color-6-light;
+ padding: 40px;
+
+ h1 {
+ text-align: center;
+ font-size: 32px;
+ font-weight: 600;
+ color: $color-4-dark;
+ margin-bottom: 30px;
+ }
+
+ input[type="text"],
+ input[type="password"],
+ input[type="email"] {
+ padding: 10 15px;
+ font-size: 14px;
+ line-height: 14px;
+ background: $color-6;
+ border-color: $color-6-dark;
+ margin-bottom: 10px;
+ }
+
+ button {
+ background: $color-2;
+ font-size: 16px;
+ line-height: 16px;
+ padding: 15px;
+ border: none;
+ border-radius: 8px;
+ color: $color-6-light;
+
+ &:hover,
+ &:active,
+ &:focus {
+ background: $color-1;
+ }
+
+ &::selection {
+ background-color: transparent;
+ color: $color-3;
+ }
+ }
+ }
+ }
+}
+
+.public-layout {
+ .brand__tagline {
+ width: auto;
+ max-width: 800px;
+ }
+
+ .landing__brand {
+ align-items: flex-start;
+ }
+
+ .public-layout__top {
+ display: flex;
+ flex-direction: column;
+
+ .lottie-wrapper {
+ position: absolute;
+ z-index: 0;
+ margin-left: -410px;
+ margin-top: -40px;
+ }
+
+ .header-container {
+ position: relative;
+ padding-top: 10px;
+ }
+
+ .nav-left,
+ .nav-right {
+ position: relative;
+ z-index: 10;
+ }
+
+ .container {
+ display: flex;
+ flex: 1;
+ }
+
+ .landing {
+ display: flex;
+ flex: 1;
+ align-items: center;
+ justify-content: space-between;
+ }
+
+ .landing-columns {
+ width: 100%;
+
+ .landing-columns--right {
+ margin-left: auto;
+
+ form {
+ margin: 0 auto;
+ }
+ }
+
+ .landing-columns--left {
+ position: relative;
+ z-index: 10;
+ margin-right: 0;
+
+ svg {
+ width: 700px;
+ max-width: 100%;
+ fill: $color-3-dark;
+
+ .cls-1 {
+ opacity: 0.33;
+ }
+
+ .cls-2 {
+ opacity: 0.66;
+ }
+ }
+ }
+ }
+ }
+
+ .footer {
+ display: flex;
+ padding: 40px 0;
+ font-size: 12px;
+ justify-content: center;
+ align-items: center;
+ margin-top: auto;
+ color: #fff;
+ background-color: transparent;
+
+ ul {
+ justify-content: center;
+ }
+
+ .copyright {
+ color: $color-5;
+ }
+ }
+}
+
+.compose-form__publish--direct button {
+ background-color: var(--brand-color);
+}
+
+.sub-navigation__cog {
+ display: none;
+}
+
+.detailed-status__link {
+ pointer-events: none;
+}
+
+// Pull to refresh
+.ptr__pull-down {
+ transform: translateY(10px);
+}
diff --git a/app/styles/ui.scss b/app/styles/ui.scss
index cbe53e07f..4accc54b5 100644
--- a/app/styles/ui.scss
+++ b/app/styles/ui.scss
@@ -168,11 +168,11 @@
.spoiler-input__input,
.autosuggest-textarea__textarea {
- background-color: var(--background-color);
+ // background-color: var(--background-color);
}
.autosuggest-textarea__textarea {
- padding: 14px 32px 13px 10px !important;
+ // padding: 14px 32px 13px 10px !important;
}
.compose-form__autosuggest-wrapper {
@@ -208,6 +208,7 @@
}
.emojione {
+ display: inline-block;
font-size: inherit;
vertical-align: middle;
object-fit: contain;
@@ -220,9 +221,7 @@
}
}
-.status__relative-time,
-.notification__relative_time,
-.quoted-status__relative-time {
+.status__relative-time {
color: var(--primary-text-color--faint);
float: right;
font-size: 14px;
@@ -313,20 +312,12 @@ article:last-child > .domain {
}
.zoomable-image {
- position: relative;
- width: 100%;
- height: 100%;
- display: flex;
- align-items: center;
- justify-content: center;
+ @apply relative w-full h-full flex items-center justify-center;
img {
+ @apply w-auto h-auto object-contain shadow-2xl;
max-width: $media-modal-media-max-width;
max-height: $media-modal-media-max-height;
- width: auto;
- height: auto;
- object-fit: contain;
- box-shadow: 0 0 5px 2px rgba(0, 0, 0, 0.5);
}
}
@@ -350,6 +341,14 @@ article:last-child > .domain {
width: 100%;
padding: 0 0 calc(var(--thumb-navigation-height) + 86px);
+ .bg-shape-container {
+ position: fixed;
+ left: 0;
+ right: 0;
+ top: 0;
+ bottom: 0;
+ }
+
.page {
display: flex;
flex-direction: column;
@@ -379,39 +378,14 @@ article:last-child > .domain {
}
.floating-action-button {
- z-index: 1000;
- display: none;
- position: fixed;
- bottom: calc(var(--thumb-navigation-height) + 14px);
- right: 14px;
- width: 58px;
- height: 58px;
- background-color: var(--brand-color);
- color: white;
- border: 0;
- border-radius: 10px;
- font-size: 30px;
- align-items: center;
- justify-content: center;
- transition: 0.2s;
-
- @media screen and (max-width: 630px) {
- display: flex;
- }
-
- &:hover,
- &:focus,
- &:active {
- background-color: var(--brand-color--hicontrast);
- }
+ @apply z-40 lg:hidden transition-all fixed bottom-24 right-4 p-4 text-white bg-accent-300 hover:bg-accent-500 rounded-full;
.svg-icon {
- width: 30px;
- height: 30px;
+ @apply w-6 h-6;
svg {
+ @apply w-6; // iOS fix
stroke-width: 1.5px;
- width: 30px; // iOS fix
}
}
}
@@ -428,7 +402,6 @@ article:last-child > .domain {
height: 100%;
&__badge {
- @include font-montserrat;
@include font-size(14);
@include line-height(14);
position: absolute;
@@ -639,7 +612,6 @@ article:last-child > .domain {
.filter-bar,
.account__section-headline {
- border-bottom: 1px solid var(--brand-color--faint);
cursor: default;
display: flex;
flex-shrink: 0;
@@ -651,37 +623,13 @@ article:last-child > .domain {
button,
a {
- display: block;
- flex: 1 1 auto;
- color: var(--primary-text-color--faint);
- padding: 15px 0;
- font-size: 14px;
- font-weight: 500;
- text-align: center;
- text-decoration: none;
- position: relative;
- background: transparent;
+ @apply block flex-1 text-gray-500 py-4 text-sm font-semibold text-center relative no-underline;
&:active,
&:focus,
&:hover,
&.active {
- color: var(--primary-text-color);
- }
-
- &.active {
- &::before,
- &::after {
- display: block;
- content: "";
- position: absolute;
- bottom: 0;
- left: 50%;
- width: 100%;
- height: 3px;
- transform: translateX(-50%);
- background-color: var(--accent-color);
- }
+ @apply text-gray-900;
}
.svg-icon {
@@ -693,13 +641,14 @@ article:last-child > .domain {
}
.filter-bar {
- position: relative;
+ @apply relative;
&__active {
- position: absolute;
- height: 3px;
- bottom: 0;
- background-color: var(--accent-color);
+ @apply absolute h-[3px] bottom-0 bg-primary-600;
+ }
+
+ &__bottom {
+ @apply absolute h-[3px] w-full bottom-0 bg-primary-200;
}
}
@@ -729,23 +678,11 @@ article:last-child > .domain {
100% { opacity: 1; }
}
-.verified-icon {
- display: inline-flex;
- margin: 0 4px 0 1px;
- vertical-align: top;
- position: relative;
- width: 20px;
- height: 20px;
- flex-shrink: 0;
- color: var(--brand-color);
-}
-
.icon-with-counter {
position: relative;
display: inline;
&__counter {
- @include font-montserrat;
@include font-size(14);
@include line-height(14);
position: absolute;
@@ -767,3 +704,11 @@ article:last-child > .domain {
padding-top: 10px;
}
}
+
+.text-muted {
+ color: var(--gray-500);
+}
+
+.mb-10 {
+ margin-bottom: 10px;
+}
diff --git a/app/styles/utilities.scss b/app/styles/utilities.scss
new file mode 100644
index 000000000..30eb71eed
--- /dev/null
+++ b/app/styles/utilities.scss
@@ -0,0 +1,17 @@
+.w-10i {
+ width: 2.5rem !important;
+}
+
+.z-1000 {
+ z-index: 1000;
+}
+
+.divide-x-dot > *:not(:last-child)::after {
+ content: '·';
+ padding-right: 4px;
+ padding-left: 4px;
+}
+
+.mention {
+ @apply text-primary-600 hover:underline;
+}
diff --git a/app/styles/variables.scss b/app/styles/variables.scss
index e2d7f393a..114eaf0e3 100644
--- a/app/styles/variables.scss
+++ b/app/styles/variables.scss
@@ -1,3 +1,32 @@
+// Truth Colors
+$color-1: #c62828;
+$color-1-dark: #8e0000;
+$color-1-light: #ff5f52;
+$color-2: #e53935;
+$color-2-dark: #ab000d;
+$color-2-light: #ff6f60;
+$color-3: #1a237e;
+$color-3-dark: #000051;
+$color-3-light: #534bae;
+$color-4: #3949ab;
+$color-4-dark: #00227b;
+$color-4-light: #6f74dd;
+$color-5: #37474f;
+$color-5-dark: #102027;
+$color-5-light: #62727b;
+$color-6: #f5f5f5;
+$color-6-dark: #c2c2c2;
+$color-6-light: #fff;
+$color-7: #00e676;
+$color-7-dark: #00b248;
+$color-7-light: #66ffa6;
+$color-8: #ffea00;
+$color-8-dark: #c7b800;
+$color-8-light: #ffff56;
+$color-9: #ffab00;
+$color-9-dark: #c67c00;
+$color-9-light: #ffdd4b;
+
// BREAKPOINT SETS
// navigation breakpoints - by default show all elements and link names along with icons
@@ -13,10 +42,10 @@ $nav-breakpoint-4: 375px;
// Commonly used web colors
-$success-green: #79bd9a !default; // Padua
-$error-red: #df405a !default; // Cerise
-$warning-red: #ff5050 !default; // Sunset Orange
-$gold-star: #ca8f04 !default; // Dark Goldenrod
+$success-green: #79bd9a !default; // Padua
+$error-red: #df405a !default; // Cerise
+$warning-red: #ff5050 !default; // Sunset Orange
+$gold-star: #ca8f04 !default; // Dark Goldenrod
// Variables for defaults in UI
$base-shadow-color: #000 !default;
@@ -40,5 +69,7 @@ $no-gap-breakpoint: 415px;
// They're future-proof and more flexible.
:root {
--thumb-navigation-base-height: 60px;
- --thumb-navigation-height: calc(var(--thumb-navigation-base-height) + env(safe-area-inset-bottom));
+ --thumb-navigation-height: calc(
+ var(--thumb-navigation-base-height) + env(safe-area-inset-bottom)
+ );
}
diff --git a/package.json b/package.json
index 81a861e97..3b8c75df7 100644
--- a/package.json
+++ b/package.json
@@ -49,11 +49,17 @@
"@babel/preset-react": "^7.14.5",
"@babel/preset-typescript": "^7.16.7",
"@babel/runtime": "^7.15.4",
- "@fontsource/montserrat": "^4.5.1",
+ "@fontsource/inter": "^4.5.1",
"@fontsource/roboto": "^4.5.0",
"@gamestdio/websocket": "^0.3.2",
"@lcdp/offline-plugin": "^5.1.0",
"@popperjs/core": "^2.4.4",
+ "@reach/menu-button": "^0.16.2",
+ "@reach/popover": "^0.16.2",
+ "@reach/portal": "^0.16.2",
+ "@reach/rect": "^0.16.0",
+ "@reach/tabs": "^0.16.4",
+ "@reach/tooltip": "^0.16.2",
"@redux-devtools/extension": "^3.2.2",
"@sentry/browser": "^6.12.0",
"@sentry/react": "^6.12.0",
@@ -135,8 +141,10 @@
"react-immutable-pure-component": "^2.0.0",
"react-inlinesvg": "^2.3.0",
"react-intl": "^5.0.0",
+ "react-lottie": "^1.2.3",
"react-motion": "^0.5.2",
"react-notification": "^6.8.4",
+ "react-otp-input": "^2.4.0",
"react-overlays": "^0.9.0",
"react-popper": "^2.2.3",
"react-redux": "^7.2.5",
@@ -175,6 +183,9 @@
},
"devDependencies": {
"@jest/globals": "^27.5.1",
+ "@types/lodash": "^4.14.180",
+ "@types/react-router-dom": "^4.2.6",
+ "@types/uuid": "^8.3.4",
"@typescript-eslint/eslint-plugin": "^5.15.0",
"@typescript-eslint/parser": "^5.15.0",
"axios-mock-adapter": "^1.18.1",
diff --git a/tailwind.config.js b/tailwind.config.js
index 8ae924dde..9b88abf0d 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -32,6 +32,61 @@ module.exports = {
],
},
colors: {
+ gray: {
+ 50: '#f9fafb',
+ 100: '#f3f4f6',
+ 200: '#e5e7eb',
+ 300: '#d1d5db',
+ 400: '#9ca3af',
+ 500: '#6b7280',
+ 600: '#4b5563',
+ 700: '#374151',
+ 800: '#1f2937',
+ 900: '#111827',
+ },
+ primary: {
+ 50: '#eef2ff',
+ 100: '#e0e7ff',
+ 200: '#c7d2fe',
+ 300: '#a5b4fc',
+ 400: '#818cf8',
+ 500: '#6366f1',
+ 600: '#5448ee',
+ 700: '#4338ca',
+ 800: '#3730a3',
+ 900: '#312e81',
+ },
+ success: {
+ 50: '#f0fdf4',
+ 100: '#dcfce7',
+ 200: '#bbf7d0',
+ 300: '#86efac',
+ 400: '#4ade80',
+ 500: '#22c55e',
+ 600: '#16a34a',
+ 700: '#15803d',
+ 800: '#166534',
+ 900: '#14532d',
+ },
+ danger: {
+ 50: '#fef2f2',
+ 100: '#fee2e2',
+ 200: '#fecaca',
+ 300: '#fca5a5',
+ 400: '#f87171',
+ 500: '#ef4444',
+ 600: '#dc2626',
+ 700: '#b91c1c',
+ 800: '#991b1b',
+ 900: '#7f1d1d',
+ },
+ accent: {
+ 300: '#ff5f87',
+ 500: '#ff4775',
+ },
+ 'gradient-purple': '#b8a3f9',
+ 'gradient-blue': '#9bd5ff',
+ 'sea-blue': '#2feecc',
},
},
},
diff --git a/webpack/development.js b/webpack/development.js
index 526ff5c0b..d9c9aa01c 100644
--- a/webpack/development.js
+++ b/webpack/development.js
@@ -17,7 +17,7 @@ const {
} = process.env;
const DEFAULTS = {
- DEVSERVER_URL: 'http://localhost:3036',
+ DEVSERVER_URL: 'http://localhost:4545',
PATRON_URL: 'http://localhost:3037',
};
@@ -29,7 +29,6 @@ const backendEndpoints = [
'/nodeinfo',
'/socket',
'/oauth',
- '/auth/password',
'/.well-known/webfinger',
'/static',
'/main/ostatus',
diff --git a/webpack/production.js b/webpack/production.js
index 53265caf3..521ad6245 100644
--- a/webpack/production.js
+++ b/webpack/production.js
@@ -1,16 +1,16 @@
// Note: You must restart bin/webpack-dev-server for changes to take effect
console.log('Running in production mode'); // eslint-disable-line no-console
-const { join } = require('path');
+// const { join } = require('path');
-const OfflinePlugin = require('@lcdp/offline-plugin');
+// const OfflinePlugin = require('@lcdp/offline-plugin');
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
const { merge } = require('webpack-merge');
const sharedConfig = require('./shared');
-const { FE_SUBDIRECTORY } = require(join(__dirname, '..', 'app', 'soapbox', 'build_config'));
-const joinPublicPath = (...paths) => join(FE_SUBDIRECTORY, ...paths);
+// const { FE_SUBDIRECTORY } = require(join(__dirname, '..', 'app', 'soapbox', 'build_config'));
+// const joinPublicPath = (...paths) => join(FE_SUBDIRECTORY, ...paths);
module.exports = merge(sharedConfig, {
mode: 'production',
@@ -28,97 +28,97 @@ module.exports = merge(sharedConfig, {
openAnalyzer: false,
logLevel: 'silent',
}),
- new OfflinePlugin({
- caches: {
- main: [':rest:'],
- additional: [
- ':externals:',
- 'packs/images/32-*.png', // used in emoji-mart
- 'packs/icons/*.svg',
- ],
- optional: [
- '**/locale_*.js', // don't fetch every locale; the user only needs one
- '**/*_polyfills-*.js', // the user may not need polyfills
- '**/*.chunk.js', // only cache chunks when needed
- '**/*.chunk.css',
- '**/*.woff2', // the user may have system-fonts enabled
- // images can be cached on-demand
- '**/*.png',
- '**/*.svg',
- ],
- },
- externals: [
- joinPublicPath('packs/emoji/1f602.svg'), // used for emoji picker dropdown
-
- // Default emoji reacts
- joinPublicPath('packs/emoji/1f44d.svg'), // Thumbs up
- joinPublicPath('packs/emoji/2764.svg'), // Heart
- joinPublicPath('packs/emoji/1f606.svg'), // Laughing
- joinPublicPath('packs/emoji/1f62e.svg'), // Surprised
- joinPublicPath('packs/emoji/1f622.svg'), // Crying
- joinPublicPath('packs/emoji/1f629.svg'), // Weary
- joinPublicPath('packs/emoji/1f621.svg'), // Angry (Spinster)
- ],
- excludes: [
- '**/*.gz',
- '**/*.map',
- '**/*.LICENSE.txt',
- 'stats.json',
- 'report.html',
- 'instance/**/*',
- // any browser that supports ServiceWorker will support woff2
- '**/*.eot',
- '**/*.ttf',
- '**/*-webfont-*.svg',
- '**/*.woff',
- // Sounds return a 206 causing sw.js to crash
- // https://stackoverflow.com/a/66335638
- '**/*.ogg',
- '**/*.oga',
- '**/*.mp3',
- '404.html',
- 'assets-manifest.json',
- // It would be nice to serve these, but they bloat up sw.js
- 'packs/images/crypto/**/*',
- 'packs/emoji/**/*',
- ],
- ServiceWorker: {
- cacheName: 'soapbox',
- entry: join(__dirname, '../app/soapbox/service_worker/entry.js'),
- minify: true,
- },
- cacheMaps: [{
- match: requestUrl => {
- const backendRoutes = [
- '/api',
- '/pleroma',
- '/nodeinfo',
- '/socket',
- '/oauth',
- '/auth/password',
- '/.well-known/webfinger',
- '/static',
- '/instance',
- '/main/ostatus',
- '/ostatus_subscribe',
- '/pghero',
- '/sidekiq',
- ];
-
- const isBackendRoute = ({ pathname }) => {
- if (pathname) {
- return backendRoutes.some(pathname.startsWith);
- } else {
- return false;
- }
- };
-
- return isBackendRoute(requestUrl) && requestUrl;
- },
- requestTypes: ['navigate'],
- }],
- safeToUseOptionalCaches: true,
- appShell: join(FE_SUBDIRECTORY, '/'),
- }),
+ // new OfflinePlugin({
+ // caches: {
+ // main: [':rest:'],
+ // additional: [
+ // ':externals:',
+ // 'packs/images/32-*.png', // used in emoji-mart
+ // 'packs/icons/*.svg',
+ // ],
+ // optional: [
+ // '**/locale_*.js', // don't fetch every locale; the user only needs one
+ // '**/*_polyfills-*.js', // the user may not need polyfills
+ // '**/*.chunk.js', // only cache chunks when needed
+ // '**/*.chunk.css',
+ // '**/*.woff2', // the user may have system-fonts enabled
+ // // images can be cached on-demand
+ // '**/*.png',
+ // '**/*.svg',
+ // ],
+ // },
+ // externals: [
+ // joinPublicPath('packs/emoji/1f602.svg'), // used for emoji picker dropdown
+ //
+ // // Default emoji reacts
+ // joinPublicPath('packs/emoji/1f44d.svg'), // Thumbs up
+ // joinPublicPath('packs/emoji/2764.svg'), // Heart
+ // joinPublicPath('packs/emoji/1f606.svg'), // Laughing
+ // joinPublicPath('packs/emoji/1f62e.svg'), // Surprised
+ // joinPublicPath('packs/emoji/1f622.svg'), // Crying
+ // joinPublicPath('packs/emoji/1f629.svg'), // Weary
+ // joinPublicPath('packs/emoji/1f621.svg'), // Angry (Spinster)
+ // ],
+ // excludes: [
+ // '**/*.gz',
+ // '**/*.map',
+ // '**/*.LICENSE.txt',
+ // 'stats.json',
+ // 'report.html',
+ // 'instance/**/*',
+ // // any browser that supports ServiceWorker will support woff2
+ // '**/*.eot',
+ // '**/*.ttf',
+ // '**/*-webfont-*.svg',
+ // '**/*.woff',
+ // // Sounds return a 206 causing sw.js to crash
+ // // https://stackoverflow.com/a/66335638
+ // '**/*.ogg',
+ // '**/*.oga',
+ // '**/*.mp3',
+ // '404.html',
+ // 'assets-manifest.json',
+ // // It would be nice to serve these, but they bloat up sw.js
+ // 'packs/images/crypto/**/*',
+ // 'packs/emoji/**/*',
+ // ],
+ // ServiceWorker: {
+ // cacheName: 'soapbox',
+ // entry: join(__dirname, '../app/soapbox/service_worker/entry.js'),
+ // minify: true,
+ // },
+ // cacheMaps: [{
+ // match: requestUrl => {
+ // const backendRoutes = [
+ // '/api',
+ // '/pleroma',
+ // '/nodeinfo',
+ // '/socket',
+ // '/oauth',
+ // '/.well-known/webfinger',
+ // '/static',
+ // '/instance',
+ // '/main/ostatus',
+ // '/ostatus_subscribe',
+ // '/pghero',
+ // '/sidekiq',
+ // '/open-source',
+ // ];
+ //
+ // const isBackendRoute = ({ pathname }) => {
+ // if (pathname) {
+ // return backendRoutes.some(pathname.startsWith);
+ // } else {
+ // return false;
+ // }
+ // };
+ //
+ // return isBackendRoute(requestUrl) && requestUrl;
+ // },
+ // requestTypes: ['navigate'],
+ // }],
+ // safeToUseOptionalCaches: true,
+ // appShell: join(FE_SUBDIRECTORY, '/'),
+ // }),
],
});
diff --git a/webpack/shared.js b/webpack/shared.js
index 2daba677a..7a2822b7e 100644
--- a/webpack/shared.js
+++ b/webpack/shared.js
@@ -13,7 +13,7 @@ const AssetsManifestPlugin = require('webpack-assets-manifest');
const { env, settings, output } = require('./configuration');
const rules = require('./rules');
-const { FE_SUBDIRECTORY } = require(join(__dirname, '..', 'app', 'soapbox', 'build_config'));
+const { FE_SUBDIRECTORY, FE_INSTANCE_SOURCE_DIR } = require(join(__dirname, '..', 'app', 'soapbox', 'build_config'));
const makeHtmlConfig = (params = {}) => {
return Object.assign({
@@ -95,7 +95,7 @@ module.exports = {
from: join(__dirname, '../node_modules/twemoji/assets/svg'),
to: join(output.path, 'packs/emoji'),
}, {
- from: join(__dirname, '../app/instance'),
+ from: join(__dirname, '..', 'app', FE_INSTANCE_SOURCE_DIR),
to: join(output.path, 'instance'),
}, {
from: join(__dirname, '../custom/instance'),
diff --git a/yarn.lock b/yarn.lock
index 6a8b8f0e4..baddb08b4 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1142,9 +1142,16 @@
regenerator-runtime "^0.13.4"
"@babel/runtime@^7.17.0":
- version "7.17.7"
- resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.7.tgz#a5f3328dc41ff39d803f311cfe17703418cf9825"
- integrity sha512-L6rvG9GDxaLgFjg41K+5Yv9OMrU98sWe+Ykmc6FDJW/+vYZMhdOMKkISgzptMaERHvS2Y2lw9MDRm2gHhlQQoA==
+ version "7.17.8"
+ resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.8.tgz#3e56e4aff81befa55ac3ac6a0967349fd1c5bca2"
+ integrity sha512-dQpEpK0O9o6lj6oPu0gRDbbnk+4LeHlNcBpspf6Olzt3GIX4P1lWF1gS+pHLDFlaJvbR6q7jCfQ08zA4QJBnmA==
+ dependencies:
+ regenerator-runtime "^0.13.4"
+
+"@babel/runtime@^7.7.6":
+ version "7.17.2"
+ resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.2.tgz#66f68591605e59da47523c631416b18508779941"
+ integrity sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw==
dependencies:
regenerator-runtime "^0.13.4"
@@ -1238,10 +1245,10 @@
minimatch "^3.0.4"
strip-json-comments "^3.1.1"
-"@fontsource/montserrat@^4.5.1":
+"@fontsource/inter@^4.5.1":
version "4.5.1"
- resolved "https://registry.yarnpkg.com/@fontsource/montserrat/-/montserrat-4.5.1.tgz#64a33ffdb77bbc63484c0321710bed272cc5b16f"
- integrity sha512-xdMkzsnFlzDt5Vj9+AWuUp4Vd9F3hYN2I0GTZZYscWN/bQ20wVOGtdWLO8Okfv7SZ9t/z39/EayAAt+f/8tAvw==
+ resolved "https://registry.yarnpkg.com/@fontsource/inter/-/inter-4.5.1.tgz#058d8a02354f3c78e369d452c15d33557ec1b705"
+ integrity sha512-mvtOvXNNVLlF1p/UbLgLrmz2RCOl6Ow+TqyiK10SosoLKX7edsXYiHFHb7XIZdjII6F2sJVPPsJXWhBnbXT2DQ==
"@fontsource/roboto@^4.5.0":
version "4.5.0"
@@ -1649,6 +1656,122 @@
resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.10.1.tgz#728ecd95ab207aab8a9a4e421f0422db329232be"
integrity sha512-HnUhk1Sy9IuKrxEMdIRCxpIqPw6BFsbYSEUO9p/hNw5sMld/+3OLMWQP80F8/db9qsv3qUjs7ZR5bS/R+iinXw==
+"@reach/auto-id@0.16.0":
+ version "0.16.0"
+ resolved "https://registry.yarnpkg.com/@reach/auto-id/-/auto-id-0.16.0.tgz#dfabc3227844e8c04f8e6e45203a8e14a8edbaed"
+ integrity sha512-5ssbeP5bCkM39uVsfQCwBBL+KT8YColdnMN5/Eto6Rj7929ql95R3HZUOkKIvj7mgPtEb60BLQxd1P3o6cjbmg==
+ dependencies:
+ "@reach/utils" "0.16.0"
+ tslib "^2.3.0"
+
+"@reach/descendants@0.16.1":
+ version "0.16.1"
+ resolved "https://registry.yarnpkg.com/@reach/descendants/-/descendants-0.16.1.tgz#fa3d89c0503565369707f32985d87eef61985d9f"
+ integrity sha512-3WZgRnD9O4EORKE31rrduJDiPFNMOjUkATx0zl192ZxMq3qITe4tUj70pS5IbJl/+v9zk78JwyQLvA1pL7XAPA==
+ dependencies:
+ "@reach/utils" "0.16.0"
+ tslib "^2.3.0"
+
+"@reach/dropdown@0.16.2":
+ version "0.16.2"
+ resolved "https://registry.yarnpkg.com/@reach/dropdown/-/dropdown-0.16.2.tgz#4aa7df0f716cb448d01bc020d54df595303d5fa6"
+ integrity sha512-l4nNiX6iUpMdHQNbZMhgW5APtw0AUwJuRnkqE93vkjvdtrYl/sNJy1Jr6cGG7TrZIABLSOsfwbXU3C+qwJ3ftQ==
+ dependencies:
+ "@reach/auto-id" "0.16.0"
+ "@reach/descendants" "0.16.1"
+ "@reach/popover" "0.16.2"
+ "@reach/utils" "0.16.0"
+ tslib "^2.3.0"
+
+"@reach/menu-button@^0.16.2":
+ version "0.16.2"
+ resolved "https://registry.yarnpkg.com/@reach/menu-button/-/menu-button-0.16.2.tgz#664e33e70de431f88abf1f8537c48b1b6ce87e88"
+ integrity sha512-p4n6tFVaJZHJZEznHWy0YH2Xr3I+W7tsQWAT72PqKGT+uryGRdtgEQqi76f/8cRaw/00ueazBk5lwLG7UKGFaA==
+ dependencies:
+ "@reach/dropdown" "0.16.2"
+ "@reach/popover" "0.16.2"
+ "@reach/utils" "0.16.0"
+ prop-types "^15.7.2"
+ tiny-warning "^1.0.3"
+ tslib "^2.3.0"
+
+"@reach/observe-rect@1.2.0":
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/@reach/observe-rect/-/observe-rect-1.2.0.tgz#d7a6013b8aafcc64c778a0ccb83355a11204d3b2"
+ integrity sha512-Ba7HmkFgfQxZqqaeIWWkNK0rEhpxVQHIoVyW1YDSkGsGIXzcaW4deC8B0pZrNSSyLTdIk7y+5olKt5+g0GmFIQ==
+
+"@reach/popover@0.16.2", "@reach/popover@^0.16.2":
+ version "0.16.2"
+ resolved "https://registry.yarnpkg.com/@reach/popover/-/popover-0.16.2.tgz#71d7af3002ca49d791476b22dee1840dd1719c19"
+ integrity sha512-IwkRrHM7Vt33BEkSXneovymJv7oIToOfTDwRKpuYEB/BWYMAuNfbsRL7KVe6MjkgchDeQzAk24cYY1ztQj5HQQ==
+ dependencies:
+ "@reach/portal" "0.16.2"
+ "@reach/rect" "0.16.0"
+ "@reach/utils" "0.16.0"
+ tabbable "^4.0.0"
+ tslib "^2.3.0"
+
+"@reach/portal@0.16.2", "@reach/portal@^0.16.2":
+ version "0.16.2"
+ resolved "https://registry.yarnpkg.com/@reach/portal/-/portal-0.16.2.tgz#ca83696215ee03acc2bb25a5ae5d8793eaaf2f64"
+ integrity sha512-9ur/yxNkuVYTIjAcfi46LdKUvH0uYZPfEp4usWcpt6PIp+WDF57F/5deMe/uGi/B/nfDweQu8VVwuMVrCb97JQ==
+ dependencies:
+ "@reach/utils" "0.16.0"
+ tiny-warning "^1.0.3"
+ tslib "^2.3.0"
+
+"@reach/rect@0.16.0", "@reach/rect@^0.16.0":
+ version "0.16.0"
+ resolved "https://registry.yarnpkg.com/@reach/rect/-/rect-0.16.0.tgz#78cf6acefe2e83d3957fa84f938f6e1fc5700f16"
+ integrity sha512-/qO9jQDzpOCdrSxVPR6l674mRHNTqfEjkaxZHluwJ/2qGUtYsA0GSZiF/+wX/yOWeBif1ycxJDa6HusAMJZC5Q==
+ dependencies:
+ "@reach/observe-rect" "1.2.0"
+ "@reach/utils" "0.16.0"
+ prop-types "^15.7.2"
+ tiny-warning "^1.0.3"
+ tslib "^2.3.0"
+
+"@reach/tabs@^0.16.4":
+ version "0.16.4"
+ resolved "https://registry.yarnpkg.com/@reach/tabs/-/tabs-0.16.4.tgz#7da85e46f64052bdd1c0f9582f900e379b098ac5"
+ integrity sha512-4EK+1U0OoLfg2tJ1BSZf6/tx0hF5vlXKxY7qB//bPWtlIh9Xfp/aSDIdspFf3xS8MjtKeb6IVmo5UAxDMq85ZA==
+ dependencies:
+ "@reach/auto-id" "0.16.0"
+ "@reach/descendants" "0.16.1"
+ "@reach/utils" "0.16.0"
+ prop-types "^15.7.2"
+ tslib "^2.3.0"
+
+"@reach/tooltip@^0.16.2":
+ version "0.16.2"
+ resolved "https://registry.yarnpkg.com/@reach/tooltip/-/tooltip-0.16.2.tgz#8448cee341476e4f795fa7192f7a0864f06b8085"
+ integrity sha512-wtJPnbJ6l4pmudMpQHGU9v1NS4ncDgcwRNi9re9KsIdsM525zccZvHQLteBKYiaW4ib7k09t2dbwhyNU9oa0Iw==
+ dependencies:
+ "@reach/auto-id" "0.16.0"
+ "@reach/portal" "0.16.2"
+ "@reach/rect" "0.16.0"
+ "@reach/utils" "0.16.0"
+ "@reach/visually-hidden" "0.16.0"
+ prop-types "^15.7.2"
+ tiny-warning "^1.0.3"
+ tslib "^2.3.0"
+
+"@reach/utils@0.16.0":
+ version "0.16.0"
+ resolved "https://registry.yarnpkg.com/@reach/utils/-/utils-0.16.0.tgz#5b0777cf16a7cab1ddd4728d5d02762df0ba84ce"
+ integrity sha512-PCggBet3qaQmwFNcmQ/GqHSefadAFyNCUekq9RrWoaU9hh/S4iaFgf2MBMdM47eQj5i/Bk0Mm07cP/XPFlkN+Q==
+ dependencies:
+ tiny-warning "^1.0.3"
+ tslib "^2.3.0"
+
+"@reach/visually-hidden@0.16.0":
+ version "0.16.0"
+ resolved "https://registry.yarnpkg.com/@reach/visually-hidden/-/visually-hidden-0.16.0.tgz#2a5e834af9e93c554065ff8cbb0907fbeb26ad02"
+ integrity sha512-IIayZ3jzJtI5KfcfRVtOMFkw2ef/1dMT8D9BUuFcU2ORZAWLNvnzj1oXNoIfABKl5wtsLjY6SGmkYQ+tMPN8TA==
+ dependencies:
+ prop-types "^15.7.2"
+ tslib "^2.3.0"
+
"@redux-devtools/extension@^3.2.2":
version "3.2.2"
resolved "https://registry.yarnpkg.com/@redux-devtools/extension/-/extension-3.2.2.tgz#2d6da4df2c4d32a0aac54d824e46f52b1fd9fc4d"
@@ -1773,16 +1896,16 @@
integrity sha512-Skk1BqXEOEhiRsXJgZBYtjFa/+4dMSFA5UyzTUW20oyyUSd3iizhEWrYt0jT87iFu771gWoqVV2/OGobBcGjgQ==
"@tailwindcss/forms@^0.4.0":
- version "0.4.1"
- resolved "https://registry.yarnpkg.com/@tailwindcss/forms/-/forms-0.4.1.tgz#5a47ccd60490cbba84e662f2b9cf3d71a5126d17"
- integrity sha512-gS9xjCmJjUBz/eP12QlENPLnf0tCx68oYE3mri0GMP5jdtVwLbGUNSRpjsp6NzLAZzZy3ueOwrcqB78Ax6Z84A==
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/@tailwindcss/forms/-/forms-0.4.0.tgz#a46715e347a32d216a3973eb67473bd29ae3798e"
+ integrity sha512-DeaQBx6EgEeuZPQACvC+mKneJsD8am1uiJugjgQK1+/Vt+Ai0GpFBC2T2fqnUad71WgOxyrZPE6BG1VaI6YqfQ==
dependencies:
mini-svg-data-uri "^1.2.3"
"@tailwindcss/typography@^0.5.1":
- version "0.5.2"
- resolved "https://registry.yarnpkg.com/@tailwindcss/typography/-/typography-0.5.2.tgz#24b069dab24d7a2467d01aca0dd432cb4b29f0ee"
- integrity sha512-coq8DBABRPFcVhVIk6IbKyyHUt7YTEC/C992tatFB+yEx5WGBQrCgsSFjxHUr8AWXphWckadVJbominEduYBqw==
+ version "0.5.1"
+ resolved "https://registry.yarnpkg.com/@tailwindcss/typography/-/typography-0.5.1.tgz#486248a9426501f11a9b0295f7cfc0eb29659c46"
+ integrity sha512-AmSzZSgLhHKlILKduU+PKBTHL6c+al82syZlRid1xgmlWwXagLigO+O++B4C0scpMfzW//f/3YCRcwwEHWoU3w==
dependencies:
lodash.castarray "^4.4.0"
lodash.isplainobject "^4.0.6"
@@ -1866,6 +1989,18 @@
dependencies:
"@types/node" "*"
+"@types/history@*":
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/@types/history/-/history-5.0.0.tgz#29f919f0c8e302763798118f45b19cab4a886f14"
+ integrity sha512-hy8b7Y1J8OGe6LbAjj3xniQrj3v6lsivCcrmf4TzSgPzLkhIeKgc5IZnT7ReIqmEuodjfO8EYAuoFvIrHi/+jQ==
+ dependencies:
+ history "*"
+
+"@types/history@^4.7.11":
+ version "4.7.11"
+ resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.11.tgz#56588b17ae8f50c53983a524fc3cc47437969d64"
+ integrity sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==
+
"@types/hoist-non-react-statics@^3.3.0", "@types/hoist-non-react-statics@^3.3.1":
version "3.3.1"
resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f"
@@ -1984,6 +2119,23 @@
hoist-non-react-statics "^3.3.0"
redux "^4.0.0"
+"@types/react-router-dom@^4.2.6":
+ version "4.3.5"
+ resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-4.3.5.tgz#72f229967690c890d00f96e6b85e9ee5780db31f"
+ integrity sha512-eFajSUASYbPHg2BDM1G8Btx+YqGgvROPIg6sBhl3O4kbDdYXdFdfrgQFf/pcBuQVObjfT9AL/dd15jilR5DIEA==
+ dependencies:
+ "@types/history" "*"
+ "@types/react" "*"
+ "@types/react-router" "*"
+
+"@types/react-router@*":
+ version "5.1.18"
+ resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-5.1.18.tgz#c8851884b60bc23733500d86c1266e1cfbbd9ef3"
+ integrity sha512-YYknwy0D0iOwKQgz9v8nOzt2J6l4gouBmDnWqUUznltOTaon+r8US8ky8HvN0tXvc38U9m6z/t2RsVsnd1zM0g==
+ dependencies:
+ "@types/history" "^4.7.11"
+ "@types/react" "*"
+
"@types/react@*", "@types/react@17":
version "17.0.21"
resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.21.tgz#069c43177cd419afaab5ce26bb4e9056549f7ea6"
@@ -2020,6 +2172,11 @@
resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d"
integrity sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==
+"@types/uuid@^8.3.4":
+ version "8.3.4"
+ resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.4.tgz#bd86a43617df0594787d38b735f55c805becf1bc"
+ integrity sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==
+
"@types/yargs-parser@*":
version "20.2.1"
resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-20.2.1.tgz#3b9ce2489919d9e4fea439b76916abc34b2df129"
@@ -2581,13 +2738,13 @@ at-least-node@^1.0.0:
integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==
autoprefixer@^10.4.2:
- version "10.4.4"
- resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.4.tgz#3e85a245b32da876a893d3ac2ea19f01e7ea5a1e"
- integrity sha512-Tm8JxsB286VweiZ5F0anmbyGiNI3v3wGv3mz9W+cxEDYB/6jbnj6GM9H9mK3wIL8ftgl+C07Lcwb8PG5PCCPzA==
+ version "10.4.2"
+ resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.2.tgz#25e1df09a31a9fba5c40b578936b90d35c9d4d3b"
+ integrity sha512-9fOPpHKuDW1w/0EKfRmVnxTDt8166MAnLI3mgZ1JCnhNtYWxcJ6Ud5CO/AVOZi/AvFa8DY9RTy3h3+tFBlrrdQ==
dependencies:
- browserslist "^4.20.2"
- caniuse-lite "^1.0.30001317"
- fraction.js "^4.2.0"
+ browserslist "^4.19.1"
+ caniuse-lite "^1.0.30001297"
+ fraction.js "^4.1.2"
normalize-range "^0.1.2"
picocolors "^1.0.0"
postcss-value-parser "^4.2.0"
@@ -2807,6 +2964,14 @@ babel-preset-jest@^27.2.0:
babel-plugin-jest-hoist "^27.2.0"
babel-preset-current-node-syntax "^1.0.0"
+babel-runtime@^6.26.0:
+ version "6.26.0"
+ resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
+ integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4=
+ dependencies:
+ core-js "^2.4.0"
+ regenerator-runtime "^0.11.0"
+
bail@^1.0.0:
version "1.0.5"
resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.5.tgz#b6fa133404a392cbc1f8c4bf63f5953351e7a776"
@@ -2926,15 +3091,15 @@ browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.14.5, browserslist@^4
escalade "^3.1.1"
node-releases "^1.1.75"
-browserslist@^4.20.2:
- version "4.20.2"
- resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.20.2.tgz#567b41508757ecd904dab4d1c646c612cd3d4f88"
- integrity sha512-CQOBCqp/9pDvDbx3xfMi+86pr4KXIf2FDkTTdeuYw8OxS9t898LA1Khq57gtufFILXpfgsSx5woNgsBgvGjpsA==
+browserslist@^4.19.1:
+ version "4.19.1"
+ resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.19.1.tgz#4ac0435b35ab655896c31d53018b6dd5e9e4c9a3"
+ integrity sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A==
dependencies:
- caniuse-lite "^1.0.30001317"
- electron-to-chromium "^1.4.84"
+ caniuse-lite "^1.0.30001286"
+ electron-to-chromium "^1.4.17"
escalade "^3.1.1"
- node-releases "^2.0.2"
+ node-releases "^2.0.1"
picocolors "^1.0.0"
bs-logger@0.x:
@@ -3046,14 +3211,14 @@ caniuse-api@^3.0.0:
lodash.uniq "^4.5.0"
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001254:
- version "1.0.30001317"
- resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001317.tgz"
- integrity sha512-xIZLh8gBm4dqNX0gkzrBeyI86J2eCjWzYAs40q88smG844YIrN4tVQl/RhquHvKEKImWWFIVh1Lxe5n1G/N+GQ==
+ version "1.0.30001257"
+ resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001257.tgz#150aaf649a48bee531104cfeda57f92ce587f6e5"
+ integrity sha512-JN49KplOgHSXpIsVSF+LUyhD8PUp6xPpAXeRrrcBh4KBeP7W864jHn6RvzJgDlrReyeVjMFJL3PLpPvKIxlIHA==
-caniuse-lite@^1.0.30001317:
- version "1.0.30001319"
- resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001319.tgz#eb4da4eb3ecdd409f7ba1907820061d56096e88f"
- integrity sha512-xjlIAFHucBRSMUo1kb5D4LYgcN1M45qdKP++lhqowDpwJwGkpIRTt5qQqnhxjj1vHcI7nrJxWhCC1ATrCEBTcw==
+caniuse-lite@^1.0.30001286, caniuse-lite@^1.0.30001297:
+ version "1.0.30001300"
+ resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001300.tgz#11ab6c57d3eb6f964cba950401fd00a146786468"
+ integrity sha512-cVjiJHWGcNlJi8TZVKNMnvMid3Z3TTdDHmLDzlOdIiZq138Exvo0G+G0wTdVYolxKb4AYwC+38pxodiInVtJSA==
catharsis@^0.9.0:
version "0.9.0"
@@ -3149,7 +3314,7 @@ cheerio@^1.0.0-rc.10, cheerio@^1.0.0-rc.3:
optionalDependencies:
fsevents "~2.3.2"
-chokidar@^3.4.2, chokidar@^3.5.3:
+chokidar@^3.4.2, chokidar@^3.5.2:
version "3.5.3"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd"
integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==
@@ -3422,6 +3587,11 @@ core-js-pure@^3.16.0:
resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.17.3.tgz#98ea3587188ab7ef4695db6518eeb71aec42604a"
integrity sha512-YusrqwiOTTn8058JDa0cv9unbXdIiIgcgI9gXso0ey4WgkFLd3lYlV9rp9n7nDCsYxXsMDTjA4m1h3T348mdlQ==
+core-js@^2.4.0:
+ version "2.6.12"
+ resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec"
+ integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==
+
core-js@^3.1.3, core-js@^3.15.2, core-js@^3.6.5:
version "3.18.0"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.18.0.tgz#9af3f4a6df9ba3428a3fb1b171f1503b3f40cc49"
@@ -4072,10 +4242,10 @@ electron-to-chromium@^1.3.830:
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.840.tgz#3f2a1df97015d9b1db5d86a4c6bd4cdb920adcbb"
integrity sha512-yRoUmTLDJnkIJx23xLY7GbSvnmDCq++NSuxHDQ0jiyDJ9YZBUGJcrdUqm+ZwZFzMbCciVzfem2N2AWiHJcWlbw==
-electron-to-chromium@^1.4.84:
- version "1.4.88"
- resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.88.tgz#ebe6a2573b563680c7a7bf3a51b9e465c9c501db"
- integrity sha512-oA7mzccefkvTNi9u7DXmT0LqvhnOiN2BhSrKerta7HeUC1cLoIwtbf2wL+Ah2ozh5KQd3/1njrGrwDBXx6d14Q==
+electron-to-chromium@^1.4.17:
+ version "1.4.49"
+ resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.49.tgz#5b6a3dc032590beef4be485a4b0b3fe7d0e3dfd7"
+ integrity sha512-k/0t1TRfonHIp8TJKfjBu2cKj8MqYTiEpOhci+q7CVEE5xnCQnx1pTa+V8b/sdhe4S3PR4p4iceEQWhGrKQORQ==
emittery@^0.8.1:
version "0.8.1"
@@ -4722,7 +4892,7 @@ fast-glob@^3.1.1, fast-glob@^3.2.5:
merge2 "^1.3.0"
micromatch "^4.0.4"
-fast-glob@^3.2.11, fast-glob@^3.2.9:
+fast-glob@^3.2.7, fast-glob@^3.2.9:
version "3.2.11"
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9"
integrity sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==
@@ -4884,10 +5054,10 @@ forwarded@0.2.0:
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811"
integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==
-fraction.js@^4.2.0:
- version "4.2.0"
- resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.2.0.tgz#448e5109a313a3527f5a3ab2119ec4cf0e0e2950"
- integrity sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==
+fraction.js@^4.1.2:
+ version "4.1.2"
+ resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.1.2.tgz#13e420a92422b6cf244dff8690ed89401029fbe8"
+ integrity sha512-o2RiJQ6DZaR/5+Si0qJUIy637QMRudSi9kU/FFzx9EZazrIdnBgpU+3sEWCxAVhH2RtxW2Oz+T4p2o8uOPVcgA==
fresh@0.5.2:
version "0.5.2"
@@ -5197,6 +5367,13 @@ hex-color-regex@^1.1.0:
resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e"
integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==
+history@*:
+ version "5.3.0"
+ resolved "https://registry.yarnpkg.com/history/-/history-5.3.0.tgz#1548abaa245ba47992f063a0783db91ef201c73b"
+ integrity sha512-ZqaKwjjrAYUYfLG+htGaIIZ4nioX2L70ZUMIFysS3xvBsSG4x/n1V6TXV3N8ZYNuFGlDirFg32T7B6WOUPDYcQ==
+ dependencies:
+ "@babel/runtime" "^7.7.6"
+
history@^4.10.1, history@^4.7.2:
version "4.10.1"
resolved "https://registry.yarnpkg.com/history/-/history-4.10.1.tgz#33371a65e3a83b267434e2b3f3b1b4c58aad4cf3"
@@ -5739,7 +5916,7 @@ is-core-module@^2.2.0, is-core-module@^2.5.0:
dependencies:
has "^1.0.3"
-is-core-module@^2.8.0, is-core-module@^2.8.1:
+is-core-module@^2.8.0:
version "2.8.1"
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211"
integrity sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==
@@ -6993,6 +7170,11 @@ loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3
dependencies:
js-tokens "^3.0.0 || ^4.0.0"
+lottie-web@^5.1.3:
+ version "5.7.13"
+ resolved "https://registry.yarnpkg.com/lottie-web/-/lottie-web-5.7.13.tgz#c4087e4742c485fc2c4034adad65d1f3fcd438b0"
+ integrity sha512-6iy93BGPkdk39b0jRgJ8Zosxi8QqcMP5XcDvg1f0XAvEkke6EMCl6BUO4Lu78dpgvfG2tzut4QJ+0vCrfbrldQ==
+
lower-case@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28"
@@ -7240,9 +7422,9 @@ mini-css-extract-plugin@^1.6.2:
webpack-sources "^1.1.0"
mini-svg-data-uri@^1.2.3:
- version "1.4.4"
- resolved "https://registry.yarnpkg.com/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz#8ab0aabcdf8c29ad5693ca595af19dd2ead09939"
- integrity sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==
+ version "1.4.3"
+ resolved "https://registry.yarnpkg.com/mini-svg-data-uri/-/mini-svg-data-uri-1.4.3.tgz#43177b2e93766ba338931a3e2a84a3dfd3a222b8"
+ integrity sha512-gSfqpMRC8IxghvMcxzzmMnWpXAChSA+vy4cia33RgerMS8Fex95akUyQZPbxJJmeBGiGmK7n/1OpUX8ksRjIdA==
minimalistic-assert@^1.0.0:
version "1.0.1"
@@ -7330,10 +7512,10 @@ nanoid@^3.1.23:
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.25.tgz#09ca32747c0e543f0e1814b7d3793477f9c8e152"
integrity sha512-rdwtIXaXCLFAQbnfqDRnI6jaRHp9fTcYBjtFKE8eezcZ7LuLjhUaQGNeMXf1HmRoCH32CLz6XwX0TtxEOS/A3Q==
-nanoid@^3.3.1:
- version "3.3.1"
- resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.1.tgz#6347a18cac88af88f58af0b3594b723d5e99bb35"
- integrity sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==
+nanoid@^3.1.30:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.2.0.tgz#62667522da6673971cca916a6d3eff3f415ff80c"
+ integrity sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA==
natural-compare@^1.4.0:
version "1.4.0"
@@ -7393,10 +7575,10 @@ node-releases@^1.1.75:
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.75.tgz#6dd8c876b9897a1b8e5a02de26afa79bb54ebbfe"
integrity sha512-Qe5OUajvqrqDSy6wrWFmMwfJ0jVgwiw4T3KqmbTcZ62qW0gQkheXYhcFM1+lOVcGUoRxcEcfyvFMAnDgaF1VWw==
-node-releases@^2.0.2:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.2.tgz#7139fe71e2f4f11b47d4d2986aaf8c48699e0c01"
- integrity sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==
+node-releases@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.1.tgz#3d1d395f204f1f2f29a54358b9fb678765ad2fc5"
+ integrity sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==
normalize-package-data@^2.5.0:
version "2.5.0"
@@ -7971,9 +8153,9 @@ postcss-less@^3.1.4:
postcss "^7.0.14"
postcss-load-config@^3.1.0:
- version "3.1.3"
- resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-3.1.3.tgz#21935b2c43b9a86e6581a576ca7ee1bde2bd1d23"
- integrity sha512-5EYgaM9auHGtO//ljHH+v/aC/TQ5LHXtL7bQajNAUBKUVKiYE8rYpFms7+V26D9FncaGe2zwCoPQsFKb5zF/Hw==
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-3.1.1.tgz#2f53a17f2f543d9e63864460af42efdac0d41f87"
+ integrity sha512-c/9XYboIbSEUZpiD1UQD0IKiUe8n9WHYV7YFe7X7J+ZwCsEKkUJSFWjS9hBU1RR9THR7jMXst8sxiqP0jjo2mg==
dependencies:
lilconfig "^2.0.4"
yaml "^1.10.2"
@@ -8254,7 +8436,7 @@ postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector
cssesc "^3.0.0"
util-deprecate "^1.0.2"
-postcss-selector-parser@^6.0.6, postcss-selector-parser@^6.0.9:
+postcss-selector-parser@^6.0.6, postcss-selector-parser@^6.0.8:
version "6.0.9"
resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz#ee71c3b9ff63d9cd130838876c13a2ec1a992b2f"
integrity sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ==
@@ -8328,14 +8510,14 @@ postcss@^8.2.15:
nanoid "^3.1.23"
source-map-js "^0.6.2"
-postcss@^8.4.5, postcss@^8.4.6:
- version "8.4.12"
- resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.12.tgz#1e7de78733b28970fa4743f7da6f3763648b1905"
- integrity sha512-lg6eITwYe9v6Hr5CncVbK70SoioNQIq81nsaG86ev5hAidQvmOeETBqs7jm43K2F5/Ley3ytDtriImV6TpNiSg==
+postcss@^8.4.5:
+ version "8.4.5"
+ resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.5.tgz#bae665764dfd4c6fcc24dc0fdf7e7aa00cc77f95"
+ integrity sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg==
dependencies:
- nanoid "^3.3.1"
+ nanoid "^3.1.30"
picocolors "^1.0.0"
- source-map-js "^1.0.2"
+ source-map-js "^1.0.1"
prelude-ls@^1.2.1:
version "1.2.1"
@@ -8551,9 +8733,9 @@ react-color@^2.18.1:
tinycolor2 "^1.4.1"
react-datepicker@^4.6.0:
- version "4.6.0"
- resolved "https://registry.yarnpkg.com/react-datepicker/-/react-datepicker-4.6.0.tgz#10fc7c5b9c72df5c3e29712d559cb3fe73fd9f62"
- integrity sha512-JGSQnQSQYUkS7zvSaZuyHv5lxp3wMrN7GXV0VA0E9Ax9fL3Bb6E1pSXjL6C3WoeuV8dt/mItQfRkPpRGCrl/OA==
+ version "4.7.0"
+ resolved "https://registry.yarnpkg.com/react-datepicker/-/react-datepicker-4.7.0.tgz#75e03b0a6718b97b84287933307faf2ed5f03cf4"
+ integrity sha512-FS8KgbwqpxmJBv/bUdA42MYqYZa+fEYcpc746DZiHvVE2nhjrW/dg7c5B5fIUuI8gZET6FOzuDgezNcj568Czw==
dependencies:
"@popperjs/core" "^2.9.2"
classnames "^2.2.6"
@@ -8673,6 +8855,14 @@ react-lifecycles-compat@^3.0.4:
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==
+react-lottie@^1.2.3:
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/react-lottie/-/react-lottie-1.2.3.tgz#8544b96939e088658072eea5e12d912cdaa3acc1"
+ integrity sha512-qLCERxUr8M+4mm1LU0Ruxw5Y5Fn/OmYkGfnA+JDM/dZb3oKwVAJCjwnjkj9TMHtzR2U6sMEUD3ZZ1RaHagM7kA==
+ dependencies:
+ babel-runtime "^6.26.0"
+ lottie-web "^5.1.3"
+
react-motion@^0.5.2:
version "0.5.2"
resolved "https://registry.yarnpkg.com/react-motion/-/react-motion-0.5.2.tgz#0dd3a69e411316567927917c6626551ba0607316"
@@ -8694,6 +8884,11 @@ react-onclickoutside@^6.12.0:
resolved "https://registry.yarnpkg.com/react-onclickoutside/-/react-onclickoutside-6.12.1.tgz#92dddd28f55e483a1838c5c2930e051168c1e96b"
integrity sha512-a5Q7CkWznBRUWPmocCvE8b6lEYw1s6+opp/60dCunhO+G6E4tDTO2Sd2jKE+leEnnrLAE2Wj5DlDHNqj5wPv1Q==
+react-otp-input@^2.4.0:
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/react-otp-input/-/react-otp-input-2.4.0.tgz#0f0a3de1d8c8d564e2e4fbe5d6b7b56e29e3a6e6"
+ integrity sha512-AIgl7u4sS9BTNCxX1xlaS5fPWay/Zml8Ho5LszXZKXrH1C/TiFsTQGmtl13UecQYO3mSF3HUzG2rrDf0sjEFmg==
+
react-overlays@^0.9.0:
version "0.9.3"
resolved "https://registry.yarnpkg.com/react-overlays/-/react-overlays-0.9.3.tgz#5bac8c1e9e7e057a125181dee2d784864dd62902"
@@ -8974,6 +9169,11 @@ regenerate@^1.4.2:
resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a"
integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==
+regenerator-runtime@^0.11.0:
+ version "0.11.1"
+ resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9"
+ integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==
+
regenerator-runtime@^0.12.0:
version "0.12.1"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz#fa1a71544764c036f8c49b13a08b2594c9f8a0de"
@@ -9144,12 +9344,12 @@ resolve@^1.10.0, resolve@^1.12.0, resolve@^1.14.2, resolve@^1.20.0, resolve@^1.9
is-core-module "^2.2.0"
path-parse "^1.0.6"
-resolve@^1.22.0:
- version "1.22.0"
- resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198"
- integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==
+resolve@^1.21.0:
+ version "1.21.0"
+ resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.21.0.tgz#b51adc97f3472e6a5cf4444d34bc9d6b9037591f"
+ integrity sha512-3wCbTpk5WJlyE4mSOtDLhqQmGFi0/TD9VPwmiolnk8U0wRgMEktqCXd3vy5buTO3tljvalNvKrjHEfrd2WpEKA==
dependencies:
- is-core-module "^2.8.1"
+ is-core-module "^2.8.0"
path-parse "^1.0.7"
supports-preserve-symlinks-flag "^1.0.0"
@@ -9520,7 +9720,7 @@ source-map-js@^0.6.2:
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-0.6.2.tgz#0bb5de631b41cfbda6cfba8bd05a80efdfd2385e"
integrity sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug==
-source-map-js@^1.0.2:
+source-map-js@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
@@ -9963,6 +10163,11 @@ symbol-tree@^3.2.4:
resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2"
integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==
+tabbable@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-4.0.0.tgz#5bff1d1135df1482cf0f0206434f15eadbeb9261"
+ integrity sha512-H1XoH1URcBOa/rZZWxLxHCtOdVUEev+9vo5YdYhC9tCY4wnybX+VQrCYuy9ubkg69fCBxCONJOSLGfw0DWMffQ==
+
table@^6.0.9, table@^6.6.0:
version "6.7.1"
resolved "https://registry.yarnpkg.com/table/-/table-6.7.1.tgz#ee05592b7143831a8c94f3cee6aae4c1ccef33e2"
@@ -9981,31 +10186,30 @@ taffydb@2.6.2:
integrity sha1-fLy2S1oUG2ou/CxdLGe04VCyomg=
tailwindcss@^3.0.15:
- version "3.0.23"
- resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.0.23.tgz#c620521d53a289650872a66adfcb4129d2200d10"
- integrity sha512-+OZOV9ubyQ6oI2BXEhzw4HrqvgcARY38xv3zKcjnWtMIZstEsXdI9xftd1iB7+RbOnj2HOEzkA0OyB5BaSxPQA==
+ version "3.0.15"
+ resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.0.15.tgz#e4db219771eb7678a3bfd97b3f6c8fe20be0a410"
+ integrity sha512-bT2iy7FtjwgsXik4ZoJnHXR+SRCiGR1W95fVqpLZebr64m4ahwUwRbIAc5w5+2fzr1YF4Ct2eI7dojMRRl8sVQ==
dependencies:
arg "^5.0.1"
chalk "^4.1.2"
- chokidar "^3.5.3"
+ chokidar "^3.5.2"
color-name "^1.1.4"
cosmiconfig "^7.0.1"
detective "^5.2.0"
didyoumean "^1.2.2"
dlv "^1.1.3"
- fast-glob "^3.2.11"
+ fast-glob "^3.2.7"
glob-parent "^6.0.2"
is-glob "^4.0.3"
normalize-path "^3.0.0"
object-hash "^2.2.0"
- postcss "^8.4.6"
postcss-js "^4.0.0"
postcss-load-config "^3.1.0"
postcss-nested "5.0.6"
- postcss-selector-parser "^6.0.9"
+ postcss-selector-parser "^6.0.8"
postcss-value-parser "^4.2.0"
quick-lru "^5.1.1"
- resolve "^1.22.0"
+ resolve "^1.21.0"
tapable@^1.0.0:
version "1.1.3"
@@ -10104,7 +10308,7 @@ tiny-queue@^0.2.1:
resolved "https://registry.yarnpkg.com/tiny-queue/-/tiny-queue-0.2.1.tgz#25a67f2c6e253b2ca941977b5ef7442ef97a6046"
integrity sha1-JaZ/LG4lOyypQZd7XvdELvl6YEY=
-tiny-warning@^1.0.0:
+tiny-warning@^1.0.0, tiny-warning@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754"
integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==
@@ -10211,7 +10415,7 @@ tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
-tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.2.0, tslib@^2.3.1:
+tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.2.0, tslib@^2.3.0, tslib@^2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01"
integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==