Merge remote-tracking branch 'origin/develop' into public-layout-improvements

This commit is contained in:
Alex Gleason 2022-05-09 11:06:56 -05:00
commit 75c4582ce6
No known key found for this signature in database
GPG key ID: 7211D1F99744FBB7
37 changed files with 161 additions and 69 deletions

View file

@ -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

View file

@ -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

View file

@ -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.

View 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;

View 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;

View file

@ -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}
>

View file

@ -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' />}
/>
</>

View 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;

View file

@ -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'

View file

@ -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 = {

View file

@ -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',

View file

@ -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} />

View file

@ -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';
@ -21,46 +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/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} />
<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}>

View file

@ -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}

View file

@ -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'>

View file

@ -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>

View file

@ -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'>

View file

@ -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}

View file

@ -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' />

View file

@ -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>
);

View file

@ -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>

View file

@ -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>
);

View file

@ -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));

View file

@ -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;
}
}

View file

@ -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;
}

View file

@ -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 {

View file

@ -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.