Merge remote-tracking branch 'origin/develop' into registration
This commit is contained in:
commit
3c08326806
43 changed files with 218 additions and 81 deletions
|
@ -1 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 0 0 2.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 0 0 1.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 0 0-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 0 0-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 0 0-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 0 0-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 0 0 1.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"/><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0z"/></svg>
|
Before Width: | Height: | Size: 781 B |
|
@ -1 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m3 8 7.89 5.26a2 2 0 0 0 2.22 0L21 8M5 19h14a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2z"/></svg>
|
Before Width: | Height: | Size: 284 B |
|
@ -12,7 +12,7 @@
|
|||
<%= snippets %>
|
||||
</head>
|
||||
<body class="theme-mode-light no-reduce-motion">
|
||||
<div id="soapbox">
|
||||
<div id="soapbox" class="h-full">
|
||||
<div class="loading-indicator-wrapper">
|
||||
<div class="loading-indicator">
|
||||
<div class="loading-indicator__container">
|
||||
|
|
Binary file not shown.
Binary file not shown.
38
app/soapbox/components/avatar.tsx
Normal file
38
app/soapbox/components/avatar.tsx
Normal file
|
@ -0,0 +1,38 @@
|
|||
import classNames from 'classnames';
|
||||
import React from 'react';
|
||||
|
||||
import StillImage from 'soapbox/components/still_image';
|
||||
|
||||
import type { Account } from 'soapbox/types/entities';
|
||||
|
||||
interface IAvatar {
|
||||
account?: Account | null,
|
||||
size?: number,
|
||||
className?: string,
|
||||
}
|
||||
|
||||
/**
|
||||
* Legacy avatar component.
|
||||
* @see soapbox/components/ui/avatar/avatar.tsx
|
||||
* @deprecated
|
||||
*/
|
||||
const Avatar: React.FC<IAvatar> = ({ account, size, className }) => {
|
||||
if (!account) return null;
|
||||
|
||||
// : TODO : remove inline and change all avatars to be sized using css
|
||||
const style: React.CSSProperties = !size ? {} : {
|
||||
width: `${size}px`,
|
||||
height: `${size}px`,
|
||||
};
|
||||
|
||||
return (
|
||||
<StillImage
|
||||
className={classNames('rounded-full overflow-hidden', className)}
|
||||
style={style}
|
||||
src={account.avatar}
|
||||
alt=''
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default Avatar;
|
8
app/soapbox/components/landing-gradient.tsx
Normal file
8
app/soapbox/components/landing-gradient.tsx
Normal file
|
@ -0,0 +1,8 @@
|
|||
import React from 'react';
|
||||
|
||||
/** Fullscreen gradient used as a backdrop to public pages. */
|
||||
const LandingGradient: React.FC = () => (
|
||||
<div className='fixed h-screen w-full bg-gradient-to-tr from-primary-50 dark:from-slate-700 via-white dark:via-slate-900 to-gradient-end/10 dark:to-slate-900' />
|
||||
);
|
||||
|
||||
export default LandingGradient;
|
|
@ -37,8 +37,8 @@ const ListItem: React.FC<IListItem> = ({ label, hint, children, onClick }) => {
|
|||
return (
|
||||
<Comp
|
||||
className={classNames({
|
||||
'flex items-center justify-between px-3 py-2 first:rounded-t-lg last:rounded-b-lg bg-gradient-to-r from-gradient-purple/20 to-gradient-blue/20 dark:from-slate-900/25 dark:to-slate-900/50': true,
|
||||
'cursor-pointer hover:from-gradient-purple/30 hover:to-gradient-blue/30 dark:hover:from-slate-900/40 dark:hover:to-slate-900/75': typeof onClick !== 'undefined',
|
||||
'flex items-center justify-between px-3 py-2 first:rounded-t-lg last:rounded-b-lg bg-gradient-to-r from-gradient-start/10 to-gradient-end/10 dark:from-slate-900/25 dark:to-slate-900/50': true,
|
||||
'cursor-pointer hover:from-gradient-start/20 hover:to-gradient-end/20 dark:hover:from-slate-900/40 dark:hover:to-slate-900/75': typeof onClick !== 'undefined',
|
||||
})}
|
||||
{...linkProps}
|
||||
>
|
||||
|
|
|
@ -123,7 +123,7 @@ const SidebarNavigation = () => {
|
|||
return (
|
||||
<SidebarNavigationLink
|
||||
to='/messages'
|
||||
icon={require('icons/mail.svg')}
|
||||
icon={require('@tabler/icons/icons/mail.svg')}
|
||||
text={<FormattedMessage id='navigation.direct_messages' defaultMessage='Messages' />}
|
||||
/>
|
||||
);
|
||||
|
@ -158,7 +158,7 @@ const SidebarNavigation = () => {
|
|||
|
||||
<SidebarNavigationLink
|
||||
to='/settings'
|
||||
icon={require('icons/cog.svg')}
|
||||
icon={require('@tabler/icons/icons/settings.svg')}
|
||||
text={<FormattedMessage id='tabs_bar.settings' defaultMessage='Settings' />}
|
||||
/>
|
||||
</>
|
||||
|
|
Binary file not shown.
46
app/soapbox/components/still_image.tsx
Normal file
46
app/soapbox/components/still_image.tsx
Normal file
|
@ -0,0 +1,46 @@
|
|||
import classNames from 'classnames';
|
||||
import React, { useRef } from 'react';
|
||||
|
||||
import { useSettings } from 'soapbox/hooks';
|
||||
|
||||
interface IStillImage {
|
||||
/** Image alt text. */
|
||||
alt?: string,
|
||||
/** Extra class names for the outer <div> container. */
|
||||
className?: string,
|
||||
/** URL to the image */
|
||||
src: string,
|
||||
/** Extra CSS styles on the outer <div> element. */
|
||||
style?: React.CSSProperties,
|
||||
}
|
||||
|
||||
/** Renders images on a canvas, only playing GIFs if autoPlayGif is enabled. */
|
||||
const StillImage: React.FC<IStillImage> = ({ alt, className, src, style }) => {
|
||||
const settings = useSettings();
|
||||
const autoPlayGif = settings.get('autoPlayGif');
|
||||
|
||||
const canvas = useRef<HTMLCanvasElement>(null);
|
||||
const img = useRef<HTMLImageElement>(null);
|
||||
|
||||
const hoverToPlay = (
|
||||
src && !autoPlayGif && (src.endsWith('.gif') || src.startsWith('blob:'))
|
||||
);
|
||||
|
||||
const handleImageLoad = () => {
|
||||
if (hoverToPlay && canvas.current && img.current) {
|
||||
canvas.current.width = img.current.naturalWidth;
|
||||
canvas.current.height = img.current.naturalHeight;
|
||||
canvas.current.getContext('2d')?.drawImage(img.current, 0, 0);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<div data-testid='still-image-container' className={classNames(className, 'still-image', { 'still-image--play-on-hover': hoverToPlay })} style={style}>
|
||||
<img src={src} alt={alt} ref={img} onLoad={handleImageLoad} />
|
||||
{hoverToPlay && <canvas ref={canvas} />}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default StillImage;
|
|
@ -25,7 +25,7 @@ const Avatar = (props: IAvatar) => {
|
|||
|
||||
return (
|
||||
<StillImage
|
||||
className={classNames('rounded-full', className)}
|
||||
className={classNames('rounded-full overflow-hidden', className)}
|
||||
style={style}
|
||||
src={src}
|
||||
alt='Avatar'
|
||||
|
|
|
@ -25,7 +25,7 @@ const useButtonStyles = ({
|
|||
accent: 'border-transparent text-white bg-accent-500 hover:bg-accent-300 focus:ring-pink-500 focus:ring-2 focus:ring-offset-2',
|
||||
danger: 'border-transparent text-danger-700 bg-danger-100 hover:bg-danger-200 focus:ring-danger-500 focus:ring-2 focus:ring-offset-2',
|
||||
transparent: 'border-transparent text-gray-800 backdrop-blur-sm bg-white/75 hover:bg-white/80',
|
||||
link: 'border-transparent text-primary-600 hover:bg-gray-100 hover:text-primary-700',
|
||||
link: 'border-transparent text-primary-600 dark:text-primary-400 hover:bg-gray-100 hover:text-primary-700 dark:hover:bg-slate-900/50',
|
||||
};
|
||||
|
||||
const sizes = {
|
||||
|
|
|
@ -62,7 +62,7 @@ const CardHeader: React.FC<ICardHeader> = ({ children, backHref, onBackClick }):
|
|||
return (
|
||||
<Comp {...backAttributes} className='mr-2 text-gray-900 dark:text-gray-100' aria-label={intl.formatMessage(messages.back)}>
|
||||
<SvgIcon src={require('@tabler/icons/icons/arrow-left.svg')} className='h-6 w-6' />
|
||||
<span className='sr-only' data-testid='back-button'>Back</span>
|
||||
<span className='sr-only' data-testid='back-button'>{intl.formatMessage(messages.back)}</span>
|
||||
</Comp>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -13,7 +13,7 @@ type Tags = 'abbr' | 'p' | 'span' | 'pre' | 'time' | 'h1' | 'h2' | 'h3' | 'h4' |
|
|||
const themes = {
|
||||
default: 'text-gray-900 dark:text-gray-100',
|
||||
danger: 'text-danger-600',
|
||||
primary: 'text-primary-600',
|
||||
primary: 'text-primary-600 dark:text-primary-400',
|
||||
muted: 'text-gray-500 dark:text-gray-400',
|
||||
subtle: 'text-gray-400 dark:text-gray-500',
|
||||
success: 'text-success-600',
|
||||
|
|
|
@ -132,7 +132,7 @@ const SoapboxMount = () => {
|
|||
|
||||
const waitlisted = account && !account.source.get('approved', true);
|
||||
|
||||
const bodyClass = classNames('bg-white dark:bg-slate-900 text-base', {
|
||||
const bodyClass = classNames('bg-white dark:bg-slate-900 text-base h-full', {
|
||||
'no-reduce-motion': !settings.get('reduceMotion'),
|
||||
'underline-links': settings.get('underlineLinks'),
|
||||
'dyslexic': settings.get('dyslexicFont'),
|
||||
|
@ -162,7 +162,7 @@ const SoapboxMount = () => {
|
|||
return (
|
||||
<IntlProvider locale={locale} messages={messages}>
|
||||
<Helmet>
|
||||
<html lang={locale} className={classNames({ dark: darkMode })} />
|
||||
<html lang={locale} className={classNames('h-full', { dark: darkMode })} />
|
||||
<body className={bodyClass} />
|
||||
{themeCss && <style id='theme' type='text/css'>{`:root{${themeCss}}`}</style>}
|
||||
<meta name='theme-color' content={soapboxConfig.brandColor} />
|
||||
|
@ -185,13 +185,14 @@ const SoapboxMount = () => {
|
|||
<Route exact path='/about/:slug?' component={PublicLayout} />
|
||||
<Route exact path='/beta/:slug?' component={PublicLayout} />
|
||||
<Route exact path='/mobile/:slug?' component={PublicLayout} />
|
||||
<Route exact path='/login' component={AuthLayout} />
|
||||
<Route path='/login' component={AuthLayout} />
|
||||
{(features.accountCreation && instance.registrations) && (
|
||||
<Route exact path='/signup' component={AuthLayout} />
|
||||
)}
|
||||
<Route path='/verify' component={AuthLayout} />
|
||||
<Route path='/reset-password' component={AuthLayout} />
|
||||
<Route path='/edit-password' component={AuthLayout} />
|
||||
<Route path='/invite/:token' component={AuthLayout} />
|
||||
|
||||
<Route path='/' component={UI} />
|
||||
</Switch>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import React from 'react';
|
||||
import { Link, Redirect, Route, Switch } from 'react-router-dom';
|
||||
|
||||
import LandingGradient from 'soapbox/components/landing-gradient';
|
||||
import SvgIcon from 'soapbox/components/ui/icon/svg-icon';
|
||||
import BundleContainer from 'soapbox/features/ui/containers/bundle_container';
|
||||
import { NotificationsContainer } from 'soapbox/features/ui/util/async-components';
|
||||
|
@ -11,6 +12,8 @@ import LoginPage from '../auth_login/components/login_page';
|
|||
import PasswordReset from '../auth_login/components/password_reset';
|
||||
import PasswordResetConfirm from '../auth_login/components/password_reset_confirm';
|
||||
import RegistrationForm from '../auth_login/components/registration_form';
|
||||
import ExternalLoginForm from '../external_login/components/external-login-form';
|
||||
import RegisterInvite from '../register_invite';
|
||||
import Verification from '../verification';
|
||||
import EmailPassthru from '../verification/email_passthru';
|
||||
|
||||
|
@ -19,44 +22,47 @@ const AuthLayout = () => {
|
|||
const siteTitle = useAppSelector(state => state.instance.title);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className='fixed h-screen w-full bg-gradient-to-tr from-primary-50 dark:from-slate-700 via-white dark:via-slate-900 to-cyan-50 dark:to-cyan-900' />
|
||||
<div className='h-full'>
|
||||
<LandingGradient />
|
||||
|
||||
<main className='relative flex flex-col h-screen'>
|
||||
<header className='py-10 flex justify-center relative'>
|
||||
<Link to='/' className='cursor-pointer'>
|
||||
{logo ? (
|
||||
<img src={logo} alt={siteTitle} className='h-7' />
|
||||
) : (
|
||||
<SvgIcon
|
||||
className='w-7 h-7 dark:text-white'
|
||||
alt={siteTitle}
|
||||
src={require('@tabler/icons/icons/home.svg')}
|
||||
/>
|
||||
)}
|
||||
</Link>
|
||||
</header>
|
||||
<main className='relative min-h-full sm:flex sm:items-center sm:justify-center py-12'>
|
||||
<div className='w-full sm:max-w-lg md:max-w-2xl space-y-8'>
|
||||
<header className='flex justify-center relative'>
|
||||
<Link to='/' className='cursor-pointer'>
|
||||
{logo ? (
|
||||
<img src={logo} alt={siteTitle} className='h-7' />
|
||||
) : (
|
||||
<SvgIcon
|
||||
className='w-7 h-7 dark:text-white'
|
||||
alt={siteTitle}
|
||||
src={require('@tabler/icons/icons/home.svg')}
|
||||
/>
|
||||
)}
|
||||
</Link>
|
||||
</header>
|
||||
|
||||
<div className='flex flex-col justify-center items-center'>
|
||||
<div className='pb-10 sm:mx-auto w-full sm:max-w-lg md:max-w-2xl'>
|
||||
<Card variant='rounded' size='xl'>
|
||||
<CardBody>
|
||||
<Switch>
|
||||
<Route exact path='/verify' component={Verification} />
|
||||
<Route exact path='/verify/email/:token' component={EmailPassthru} />
|
||||
<Route exact path='/login' component={LoginPage} />
|
||||
<Route exact path='/signup' component={RegistrationForm} />
|
||||
<Route exact path='/reset-password' component={PasswordReset} />
|
||||
<Route exact path='/edit-password' component={PasswordResetConfirm} />
|
||||
<div className='flex flex-col justify-center items-center'>
|
||||
<div className='pb-10 sm:mx-auto w-full sm:max-w-lg md:max-w-2xl'>
|
||||
<Card variant='rounded' size='xl'>
|
||||
<CardBody>
|
||||
<Switch>
|
||||
<Route exact path='/verify' component={Verification} />
|
||||
<Route exact path='/verify/email/:token' component={EmailPassthru} />
|
||||
<Route exact path='/login/external' component={ExternalLoginForm} />
|
||||
<Route exact path='/login' component={LoginPage} />
|
||||
<Route exact path='/signup' component={RegistrationForm} />
|
||||
<Route exact path='/reset-password' component={PasswordReset} />
|
||||
<Route exact path='/edit-password' component={PasswordResetConfirm} />
|
||||
<Route path='/invite/:token' component={RegisterInvite} />
|
||||
|
||||
<Redirect from='/auth/password/new' to='/reset-password' />
|
||||
<Redirect from='/auth/password/edit' to='/edit-password' />
|
||||
</Switch>
|
||||
</CardBody>
|
||||
</Card>
|
||||
<Redirect from='/auth/password/new' to='/reset-password' />
|
||||
<Redirect from='/auth/password/edit' to='/edit-password' />
|
||||
</Switch>
|
||||
</CardBody>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</main>
|
||||
|
||||
<BundleContainer fetchComponent={NotificationsContainer}>
|
||||
|
|
|
@ -21,7 +21,7 @@ const ComposeFormButton: React.FC<IComposeFormButton> = ({
|
|||
return (
|
||||
<div>
|
||||
<IconButton
|
||||
className={classNames('text-gray-400 hover:text-gray-600', { 'text-primary-600 hover:text-primary-500': active })}
|
||||
className={classNames('text-gray-400 hover:text-gray-600', { 'text-primary-600 hover:text-primary-500 dark:text-primary-400 dark:hover:text-primary-300': active })}
|
||||
src={icon}
|
||||
title={title}
|
||||
disabled={disabled}
|
||||
|
|
Binary file not shown.
|
@ -72,7 +72,7 @@ const LandingPage = () => {
|
|||
<div className='px-4 sm:px-6 sm:text-center md:max-w-2xl md:mx-auto lg:col-span-6 lg:text-left lg:flex'>
|
||||
<div>
|
||||
<Stack space={3}>
|
||||
<h1 className='text-5xl font-extrabold text-transparent bg-clip-text bg-gradient-to-br from-pink-600 via-primary-500 to-blue-600 sm:mt-5 sm:leading-none lg:mt-6 lg:text-6xl xl:text-7xl'>
|
||||
<h1 className='text-5xl font-extrabold text-transparent bg-clip-text bg-gradient-to-br from-accent-500 via-primary-500 to-gradient-end sm:mt-5 sm:leading-none lg:mt-6 lg:text-6xl xl:text-7xl'>
|
||||
{instance.title}
|
||||
</h1>
|
||||
<Text size='lg'>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import { HotKeys } from 'react-hotkeys';
|
||||
import { FormattedMessage, useIntl } from 'react-intl';
|
||||
import { FormattedMessage, useIntl } from 'react-intl';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
|
||||
import Icon from '../../../components/icon';
|
||||
|
@ -204,7 +204,7 @@ const Notification: React.FC<INotificaton> = (props) => {
|
|||
return (
|
||||
<Icon
|
||||
src={icons[type]}
|
||||
className='text-primary-600 flex-none'
|
||||
className='text-primary-600 dark:text-primary-400 flex-none'
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
|
@ -286,10 +286,11 @@ const Notification: React.FC<INotificaton> = (props) => {
|
|||
<HStack alignItems='center' space={1.5}>
|
||||
{renderIcon()}
|
||||
|
||||
<div>
|
||||
<div className='truncate'>
|
||||
<Text
|
||||
theme='muted'
|
||||
size='sm'
|
||||
truncate
|
||||
>
|
||||
{message}
|
||||
</Text>
|
||||
|
|
|
@ -4,6 +4,7 @@ import { useDispatch } from 'react-redux';
|
|||
import ReactSwipeableViews from 'react-swipeable-views';
|
||||
|
||||
import { endOnboarding } from 'soapbox/actions/onboarding';
|
||||
import LandingGradient from 'soapbox/components/landing-gradient';
|
||||
import { HStack } from 'soapbox/components/ui';
|
||||
|
||||
import AvatarSelectionStep from './steps/avatar-selection-step';
|
||||
|
@ -68,7 +69,7 @@ const OnboardingWizard = () => {
|
|||
|
||||
return (
|
||||
<div data-testid='onboarding-wizard'>
|
||||
<div className='fixed h-screen w-full bg-gradient-to-tr from-primary-50 dark:from-slate-700 via-white dark:via-slate-900 to-cyan-50 dark:to-cyan-900' />
|
||||
<LandingGradient />
|
||||
|
||||
<main className='h-screen flex flex-col overflow-x-hidden'>
|
||||
<div className='flex flex-col justify-center items-center h-full'>
|
||||
|
|
|
@ -73,7 +73,7 @@ const AvatarSelectionStep = ({ onNext }: { onNext: () => void }) => {
|
|||
<Card variant='rounded' size='xl'>
|
||||
<CardBody>
|
||||
<div>
|
||||
<div className='pb-4 sm:pb-10 mb-4 border-b border-gray-200 border-solid -mx-4 sm:-mx-10'>
|
||||
<div className='pb-4 sm:pb-10 mb-4 border-b border-gray-200 dark:border-slate-900/50 border-solid -mx-4 sm:-mx-10'>
|
||||
<Stack space={2}>
|
||||
<Text size='2xl' align='center' weight='bold'>
|
||||
<FormattedMessage id='onboarding.avatar.title' defaultMessage='Choose a profile picture' />
|
||||
|
@ -102,7 +102,7 @@ const AvatarSelectionStep = ({ onNext }: { onNext: () => void }) => {
|
|||
onClick={openFilePicker}
|
||||
type='button'
|
||||
className={classNames({
|
||||
'absolute bottom-3 right-2 p-1 bg-primary-600 rounded-full ring-2 ring-white hover:bg-primary-700': true,
|
||||
'absolute bottom-3 right-2 p-1 bg-primary-600 rounded-full ring-2 ring-white dark:ring-slate-800 hover:bg-primary-700': true,
|
||||
'opacity-50 pointer-events-none': isSubmitting,
|
||||
})}
|
||||
disabled={isSubmitting}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import * as React from 'react';
|
||||
import { FormattedMessage } from'react-intl';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import { Button, Card, CardBody, Icon, Stack, Text } from 'soapbox/components/ui';
|
||||
|
||||
|
@ -7,7 +7,7 @@ const CompletedStep = ({ onComplete }: { onComplete: () => void }) => (
|
|||
<Card variant='rounded' size='xl'>
|
||||
<CardBody>
|
||||
<Stack space={2}>
|
||||
<Icon strokeWidth={1} src={require('@tabler/icons/icons/confetti.svg')} className='w-16 h-16 mx-auto text-primary-600' />
|
||||
<Icon strokeWidth={1} src={require('@tabler/icons/icons/confetti.svg')} className='w-16 h-16 mx-auto text-primary-600 dark:text-primary-400' />
|
||||
|
||||
<Text size='2xl' align='center' weight='bold'>
|
||||
<FormattedMessage id='onboarding.finished.title' defaultMessage='Onboarding complete' />
|
||||
|
|
|
@ -8,7 +8,7 @@ const Sonar = () => (
|
|||
<div className='animate-sonar-scale-2 absolute top-0 left-0 w-full h-full rounded-full bg-primary-600/25 opacity-0 pointer-events-none' />
|
||||
<div className='animate-sonar-scale-1 absolute top-0 left-0 w-full h-full rounded-full bg-primary-600/25 opacity-0 pointer-events-none' />
|
||||
|
||||
<div className='absolute top-0 left-0 w-48 h-48 bg-white rounded-full' />
|
||||
<div className='absolute top-0 left-0 w-48 h-48 bg-white dark:bg-slate-900 rounded-full' />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
Binary file not shown.
Binary file not shown.
44
app/soapbox/features/register_invite/index.tsx
Normal file
44
app/soapbox/features/register_invite/index.tsx
Normal file
|
@ -0,0 +1,44 @@
|
|||
import React from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { useParams } from 'react-router-dom';
|
||||
|
||||
import { Stack, CardTitle, Text } from 'soapbox/components/ui';
|
||||
import RegistrationForm from 'soapbox/features/auth_login/components/registration_form';
|
||||
import { useAppSelector } from 'soapbox/hooks';
|
||||
|
||||
interface RegisterInviteParams {
|
||||
token: string,
|
||||
}
|
||||
|
||||
/** Page to register with an invitation. */
|
||||
const RegisterInvite: React.FC = () => {
|
||||
const { token } = useParams<RegisterInviteParams>();
|
||||
const siteTitle = useAppSelector(state => state.instance.title);
|
||||
|
||||
const title = (
|
||||
<FormattedMessage
|
||||
id='register_invite.title'
|
||||
defaultMessage="You've been invited to join {siteTitle}!"
|
||||
values={{ siteTitle }}
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<Stack space={3}>
|
||||
<Stack className='mb-4'>
|
||||
<CardTitle title={title} />
|
||||
|
||||
<Text theme='muted'>
|
||||
<FormattedMessage
|
||||
id='register_invite.lead'
|
||||
defaultMessage='Complete the form below to create an account.'
|
||||
/>
|
||||
</Text>
|
||||
</Stack>
|
||||
|
||||
<RegistrationForm inviteToken={token} />
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
export default RegisterInvite;
|
|
@ -25,8 +25,8 @@ const BackgroundShapes: React.FC<IBackgroundShapes> = ({ position = 'fixed' }) =
|
|||
<use xlinkHref='#a' />
|
||||
</mask>
|
||||
<g mask='url(#b)'>
|
||||
<path className='fill-bg-shape-1' d='M1257.79 335.852C1262 527.117 897.55 530.28 792.32 977.19 600.48 981.41 435.29 545.31 431.08 354.046 426.871 162.782 578.976 4.31 770.815.088c191.844-4.222 482.764 144.5 486.974 335.764Z' fillRule='nonzero' filter='url(#c)' transform='translate(309.54 -367.538)' opacity='.1' />
|
||||
<path className='fill-bg-shape-2' d='M71.127 1126.654c206.164 179.412 502.452 211.232 661.777 71.072 159.325-140.163 295.165-510.155 8.23-504.412-320.079 6.405-381.35-817.422-540.675-677.258-31 368-335.497 931.182-129.332 1110.598Z' fillRule='nonzero' filter='url(#d)' transform='translate(309.54 -141.056)' opacity='.1' />
|
||||
<path className='fill-gradient-end opacity-10 dark:fill-gradient-end dark:opacity-5' d='M1257.79 335.852C1262 527.117 897.55 530.28 792.32 977.19 600.48 981.41 435.29 545.31 431.08 354.046 426.871 162.782 578.976 4.31 770.815.088c191.844-4.222 482.764 144.5 486.974 335.764Z' fillRule='nonzero' filter='url(#c)' transform='translate(309.54 -367.538)' />
|
||||
<path className='fill-gradient-start opacity-10 dark:fill-gradient-start dark:opacity-5' d='M71.127 1126.654c206.164 179.412 502.452 211.232 661.777 71.072 159.325-140.163 295.165-510.155 8.23-504.412-320.079 6.405-381.35-817.422-540.675-677.258-31 368-335.497 931.182-129.332 1110.598Z' fillRule='nonzero' filter='url(#d)' transform='translate(309.54 -141.056)' />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
|
@ -120,7 +120,7 @@ const ReasonStep = (_props: IReasonStep) => {
|
|||
value={rule.id}
|
||||
checked={isSelected}
|
||||
readOnly
|
||||
className='h-4 w-4 cursor-pointer text-primary-600 border-gray-300 rounded focus:ring-primary-500'
|
||||
className='h-4 w-4 cursor-pointer text-primary-600 dark:text-primary-400 border-gray-300 rounded focus:ring-primary-500'
|
||||
/>
|
||||
</button>
|
||||
);
|
||||
|
|
|
@ -76,7 +76,6 @@ import {
|
|||
// GroupRemovedAccounts,
|
||||
// GroupCreate,
|
||||
// GroupEdit,
|
||||
ExternalLogin,
|
||||
Settings,
|
||||
MediaDisplay,
|
||||
EditProfile,
|
||||
|
@ -108,7 +107,6 @@ import {
|
|||
NotificationsContainer,
|
||||
ModalContainer,
|
||||
ProfileHoverCard,
|
||||
RegisterInvite,
|
||||
Share,
|
||||
NewStatus,
|
||||
IntentionalError,
|
||||
|
@ -173,7 +171,6 @@ const SwitchingColumnsArea: React.FC = ({ children }) => {
|
|||
// Ex: use /login instead of /auth, but redirect /auth to /login
|
||||
return (
|
||||
<Switch>
|
||||
<WrappedRoute path='/login/external' page={EmptyPage} component={ExternalLogin} content={children} publicRoute exact />
|
||||
<WrappedRoute path='/email-confirmation' page={EmptyPage} component={EmailConfirmation} publicRoute exact />
|
||||
<WrappedRoute path='/logout' page={EmptyPage} component={LogoutPage} publicRoute exact />
|
||||
|
||||
|
@ -290,8 +287,6 @@ const SwitchingColumnsArea: React.FC = ({ children }) => {
|
|||
<WrappedRoute path='/statuses/:statusId' exact component={Status} content={children} />
|
||||
{features.scheduledStatuses && <WrappedRoute path='/scheduled_statuses' page={DefaultPage} component={ScheduledStatuses} content={children} />}
|
||||
|
||||
<WrappedRoute path='/invite/:token' page={DefaultPage} component={RegisterInvite} content={children} publicRoute />
|
||||
|
||||
<WrappedRoute path='/settings/profile' page={DefaultPage} component={EditProfile} content={children} />
|
||||
<WrappedRoute path='/settings/export' page={DefaultPage} component={ExportData} content={children} />
|
||||
<WrappedRoute path='/settings/import' page={DefaultPage} component={ImportData} content={children} />
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -52,8 +52,6 @@ const DEFAULT_COLORS = ImmutableMap<string, any>({
|
|||
800: '#991b1b',
|
||||
900: '#7f1d1d',
|
||||
}),
|
||||
'gradient-purple': '#b8a3f9',
|
||||
'gradient-blue': '#9bd5ff',
|
||||
'sea-blue': '#2feecc',
|
||||
});
|
||||
|
||||
|
@ -158,8 +156,8 @@ const maybeAddMissingColors = (soapboxConfig: SoapboxConfigMap): SoapboxConfigMa
|
|||
const colors = soapboxConfig.get('colors');
|
||||
|
||||
const missing = ImmutableMap({
|
||||
'bg-shape-1': colors.getIn(['accent', '500']),
|
||||
'bg-shape-2': colors.getIn(['primary', '500']),
|
||||
'gradient-start': colors.getIn(['primary', '500']),
|
||||
'gradient-end': colors.getIn(['accent', '500']),
|
||||
});
|
||||
|
||||
return soapboxConfig.set('colors', missing.mergeDeep(colors));
|
||||
|
|
|
@ -8,13 +8,11 @@ import {
|
|||
SignUpPanel,
|
||||
} from 'soapbox/features/ui/util/async-components';
|
||||
import { useAppSelector, useFeatures } from 'soapbox/hooks';
|
||||
import { isStandalone } from 'soapbox/utils/state';
|
||||
|
||||
import { Layout } from '../components/ui';
|
||||
|
||||
const DefaultPage: React.FC = ({ children }) => {
|
||||
const me = useAppSelector(state => state.me);
|
||||
const standalone = useAppSelector(isStandalone);
|
||||
const features = useFeatures();
|
||||
|
||||
return (
|
||||
|
@ -24,7 +22,7 @@ const DefaultPage: React.FC = ({ children }) => {
|
|||
</Layout.Main>
|
||||
|
||||
<Layout.Aside>
|
||||
{!me && !standalone && (
|
||||
{!me && (
|
||||
<BundleContainer fetchComponent={SignUpPanel}>
|
||||
{Component => <Component key='sign-up-panel' />}
|
||||
</BundleContainer>
|
||||
|
|
|
@ -771,7 +771,7 @@
|
|||
}
|
||||
|
||||
a {
|
||||
@apply text-primary-600 no-underline hover:underline;
|
||||
@apply text-primary-600 dark:text-primary-400 no-underline hover:underline;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -113,5 +113,5 @@
|
|||
.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;
|
||||
@apply bg-primary-50 hover:bg-primary-100 text-primary-600 dark:text-primary-400;
|
||||
}
|
||||
|
|
|
@ -291,6 +291,7 @@
|
|||
}
|
||||
|
||||
&__current {
|
||||
@apply bg-accent-500;
|
||||
display: block;
|
||||
position: absolute;
|
||||
height: 4px;
|
||||
|
@ -298,10 +299,10 @@
|
|||
left: 0;
|
||||
top: 50%;
|
||||
transform: translate(0, -50%);
|
||||
background: var(--accent-color);
|
||||
}
|
||||
|
||||
&__handle {
|
||||
@apply bg-accent-500;
|
||||
position: absolute;
|
||||
z-index: 3;
|
||||
border-radius: 50%;
|
||||
|
@ -311,7 +312,6 @@
|
|||
left: 0;
|
||||
margin-left: -6px;
|
||||
transform: translate(0, -50%);
|
||||
background: var(--accent-color);
|
||||
box-shadow: 1px 2px 6px rgba($base-shadow-color, 0.2);
|
||||
opacity: 0;
|
||||
|
||||
|
@ -365,7 +365,10 @@
|
|||
height: 4px;
|
||||
border-radius: 4px;
|
||||
top: 14px;
|
||||
background: var(--accent-color);
|
||||
}
|
||||
|
||||
&__progress {
|
||||
@apply bg-accent-500;
|
||||
}
|
||||
|
||||
&__buffer {
|
||||
|
@ -373,6 +376,7 @@
|
|||
}
|
||||
|
||||
&__handle {
|
||||
@apply bg-accent-500;
|
||||
position: absolute;
|
||||
z-index: 3;
|
||||
opacity: 0;
|
||||
|
@ -381,7 +385,6 @@
|
|||
height: 12px;
|
||||
top: 10px;
|
||||
margin-left: -6px;
|
||||
background: var(--accent-color);
|
||||
box-shadow: 1px 2px 6px rgba($base-shadow-color, 0.2);
|
||||
|
||||
.no-reduce-motion & {
|
||||
|
|
|
@ -193,7 +193,7 @@
|
|||
}
|
||||
|
||||
.button.button-secondary {
|
||||
@apply h-auto py-1.5 px-2.5 text-primary-600 border-primary-600;
|
||||
@apply h-auto py-1.5 px-2.5 text-primary-600 dark:text-primary-400 border-primary-600;
|
||||
}
|
||||
|
||||
li {
|
||||
|
|
|
@ -13,5 +13,5 @@
|
|||
}
|
||||
|
||||
.mention {
|
||||
@apply text-primary-600 hover:underline;
|
||||
@apply text-primary-600 dark:text-primary-400 hover:underline;
|
||||
}
|
||||
|
|
Binary file not shown.
Binary file not shown.
Loading…
Reference in a new issue