Improve visuals with branding
Co-authored-by: Alex Gleason <alex@alexgleason.me>
This commit is contained in:
parent
12cacf34e8
commit
20209c81ab
|
@ -243,7 +243,7 @@
|
||||||
"lists.edit": "Edit list",
|
"lists.edit": "Edit list",
|
||||||
"lists.edit.submit": "Change title",
|
"lists.edit.submit": "Change title",
|
||||||
"lists.new.create": "Add list",
|
"lists.new.create": "Add list",
|
||||||
"lists.new.create_title": "Create",
|
"lists.new.create_title": "Add list",
|
||||||
"lists.new.save_title": "Save Title",
|
"lists.new.save_title": "Save Title",
|
||||||
"lists.new.title_placeholder": "New list title",
|
"lists.new.title_placeholder": "New list title",
|
||||||
"lists.search": "Search among people you follow",
|
"lists.search": "Search among people you follow",
|
||||||
|
@ -721,7 +721,7 @@
|
||||||
"lists.edit": "Edit list",
|
"lists.edit": "Edit list",
|
||||||
"lists.edit.submit": "Change title",
|
"lists.edit.submit": "Change title",
|
||||||
"lists.new.create": "Add list",
|
"lists.new.create": "Add list",
|
||||||
"lists.new.create_title": "Create",
|
"lists.new.create_title": "Add list",
|
||||||
"lists.new.save_title": "Save Title",
|
"lists.new.save_title": "Save Title",
|
||||||
"lists.new.title_placeholder": "New list title",
|
"lists.new.title_placeholder": "New list title",
|
||||||
"lists.search": "Search among people you follow",
|
"lists.search": "Search among people you follow",
|
||||||
|
|
|
@ -218,8 +218,8 @@ export default class AutosuggestInput extends ImmutablePureComponent<IAutosugges
|
||||||
key={key}
|
key={key}
|
||||||
data-index={i}
|
data-index={i}
|
||||||
className={classNames({
|
className={classNames({
|
||||||
'px-4 py-2.5 text-sm text-gray-700 dark:text-gray-400 cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-700 group': true,
|
'px-4 py-2.5 text-sm text-gray-700 dark:text-gray-500 hover:bg-gray-100 dark:hover:bg-gray-800 focus:bg-gray-100 dark:focus:bg-primary-800 group': true,
|
||||||
'bg-gray-100 dark:bg-slate-700 hover:bg-gray-100 dark:hover:bg-gray-700': i === selectedSuggestion,
|
'bg-gray-100 dark:bg-gray-800 hover:bg-gray-100 dark:hover:bg-gray-800': i === selectedSuggestion,
|
||||||
})}
|
})}
|
||||||
onMouseDown={this.onSuggestionClick}
|
onMouseDown={this.onSuggestionClick}
|
||||||
onTouchEnd={this.onSuggestionClick}
|
onTouchEnd={this.onSuggestionClick}
|
||||||
|
@ -253,7 +253,7 @@ export default class AutosuggestInput extends ImmutablePureComponent<IAutosugges
|
||||||
|
|
||||||
return menu.map((item, i) => (
|
return menu.map((item, i) => (
|
||||||
<a
|
<a
|
||||||
className={classNames('flex items-center space-x-2 px-4 py-2.5 text-sm text-gray-700 dark:text-gray-400 cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-700', { selected: suggestions.size - selectedSuggestion === i })}
|
className={classNames('flex items-center space-x-2 px-4 py-2.5 text-sm cursor-pointer text-gray-700 dark:text-gray-500 hover:bg-gray-100 dark:hover:bg-gray-800 focus:bg-gray-100 dark:focus:bg-primary-800', { selected: suggestions.size - selectedSuggestion === i })}
|
||||||
href='#'
|
href='#'
|
||||||
role='button'
|
role='button'
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
|
@ -301,7 +301,7 @@ export default class AutosuggestInput extends ImmutablePureComponent<IAutosugges
|
||||||
<input
|
<input
|
||||||
type='text'
|
type='text'
|
||||||
className={classNames({
|
className={classNames({
|
||||||
'block w-full sm:text-sm border-gray-300 dark:border-gray-600 dark:bg-slate-800 dark:text-white dark:placeholder:text-gray-500 focus:ring-primary-500 focus:border-primary-500': true,
|
'block w-full sm:text-sm border-gray-200 dark:border-gray-800 bg-gray-200 dark:bg-gray-800 text-gray-900 dark:text-white placeholder:text-gray-600 dark:placeholder:text-gray-600 focus:border-gray-200 dark:focus-border-gray-800 focus:ring-primary-500 focus:ring-2': true,
|
||||||
}, className)}
|
}, className)}
|
||||||
ref={this.setInput}
|
ref={this.setInput}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
@ -324,7 +324,7 @@ export default class AutosuggestInput extends ImmutablePureComponent<IAutosugges
|
||||||
<div
|
<div
|
||||||
style={this.setPortalPosition()}
|
style={this.setPortalPosition()}
|
||||||
className={classNames({
|
className={classNames({
|
||||||
'fixed w-full z-[1001] shadow bg-white dark:bg-slate-800 rounded-lg py-1': true,
|
'fixed w-full z-[1001] shadow bg-white dark:bg-gray-900 rounded-lg py-1 dark:ring-2 dark:ring-primary-700 focus:outline-none': true,
|
||||||
hidden: !visible,
|
hidden: !visible,
|
||||||
block: visible,
|
block: visible,
|
||||||
})}
|
})}
|
||||||
|
|
|
@ -219,8 +219,8 @@ class AutosuggestTextarea extends ImmutablePureComponent<IAutosuggesteTextarea>
|
||||||
key={key}
|
key={key}
|
||||||
data-index={i}
|
data-index={i}
|
||||||
className={classNames({
|
className={classNames({
|
||||||
'px-4 py-2.5 text-sm text-gray-700 dark:text-gray-400 cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-700 group': true,
|
'px-4 py-2.5 text-sm text-gray-700 dark:text-gray-500 hover:bg-gray-100 dark:hover:bg-gray-800 focus:bg-gray-100 dark:focus:bg-primary-800 group': true,
|
||||||
'bg-gray-100 dark:bg-slate-700 hover:bg-gray-100 dark:hover:bg-slate-700': i === selectedSuggestion,
|
'bg-gray-100 dark:bg-gray-800 hover:bg-gray-100 dark:hover:bg-gray-800': i === selectedSuggestion,
|
||||||
})}
|
})}
|
||||||
onMouseDown={this.onSuggestionClick}
|
onMouseDown={this.onSuggestionClick}
|
||||||
>
|
>
|
||||||
|
@ -260,7 +260,7 @@ class AutosuggestTextarea extends ImmutablePureComponent<IAutosuggesteTextarea>
|
||||||
|
|
||||||
<Textarea
|
<Textarea
|
||||||
ref={this.setTextarea}
|
ref={this.setTextarea}
|
||||||
className={classNames('transition-[min-height] motion-reduce:transition-none dark:bg-slate-800 px-0 border-0 text-gray-800 dark:text-white placeholder:text-gray-400 dark:placeholder:text-gray-500 resize-none w-full focus:shadow-none focus:border-0 focus:ring-0', {
|
className={classNames('transition-[min-height] motion-reduce:transition-none dark:bg-transparent px-0 border-0 text-gray-800 dark:text-white placeholder:text-gray-600 dark:placeholder:text-gray-600 resize-none w-full focus:shadow-none focus:border-0 focus:ring-0', {
|
||||||
'min-h-[40px]': condensed,
|
'min-h-[40px]': condensed,
|
||||||
'min-h-[100px]': !condensed,
|
'min-h-[100px]': !condensed,
|
||||||
})}
|
})}
|
||||||
|
@ -288,7 +288,7 @@ class AutosuggestTextarea extends ImmutablePureComponent<IAutosuggesteTextarea>
|
||||||
<div
|
<div
|
||||||
style={this.setPortalPosition()}
|
style={this.setPortalPosition()}
|
||||||
className={classNames({
|
className={classNames({
|
||||||
'fixed z-1000 shadow bg-white dark:bg-slate-900 rounded-lg py-1 space-y-0': true,
|
'fixed z-1000 shadow bg-white dark:bg-gray-900 rounded-lg py-1 space-y-0 dark:ring-2 dark:ring-primary-700 focus:outline-none': true,
|
||||||
hidden: suggestionsHidden || suggestions.isEmpty(),
|
hidden: suggestionsHidden || suggestions.isEmpty(),
|
||||||
block: !suggestionsHidden && !suggestions.isEmpty(),
|
block: !suggestionsHidden && !suggestions.isEmpty(),
|
||||||
})}
|
})}
|
||||||
|
|
|
@ -15,7 +15,7 @@ const Badge: React.FC<IBadge> = ({ title, slug }) => (
|
||||||
'bg-yellow-500': slug === 'donor',
|
'bg-yellow-500': slug === 'donor',
|
||||||
'bg-black': slug === 'admin',
|
'bg-black': slug === 'admin',
|
||||||
'bg-cyan-600': slug === 'moderator',
|
'bg-cyan-600': slug === 'moderator',
|
||||||
'bg-gray-100 text-gray-900': slug === 'bot',
|
'bg-gray-100 dark:bg-gray-800 text-gray-900 dark:text-gray-100': slug === 'bot',
|
||||||
'bg-white bg-opacity-75 text-gray-900': slug === 'opaque',
|
'bg-white bg-opacity-75 text-gray-900': slug === 'opaque',
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
|
|
|
@ -384,8 +384,8 @@ class Dropdown extends React.PureComponent<IDropdown, IDropdownState> {
|
||||||
<IconButton
|
<IconButton
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
className={classNames({
|
className={classNames({
|
||||||
'text-gray-400 hover:text-gray-600': true,
|
'text-gray-600 hover:text-gray-700 dark:hover:text-gray-500': true,
|
||||||
'text-gray-600': open,
|
'text-gray-700 dark:text-gray-500': open,
|
||||||
})}
|
})}
|
||||||
title={title}
|
title={title}
|
||||||
src={src}
|
src={src}
|
||||||
|
|
|
@ -111,7 +111,7 @@ class EmojiSelector extends ImmutablePureComponent<IEmojiSelector> {
|
||||||
return (
|
return (
|
||||||
<HotKeys handlers={this.handlers}>
|
<HotKeys handlers={this.handlers}>
|
||||||
{/*<div
|
{/*<div
|
||||||
className={classNames('flex absolute bg-white dark:bg-slate-500 px-2 py-3 rounded-full shadow-md opacity-0 pointer-events-none duration-100 w-max', { 'opacity-100 pointer-events-auto z-[999]': visible || focused })}
|
className={classNames('flex absolute bg-white dark:bg-gray-500 px-2 py-3 rounded-full shadow-md opacity-0 pointer-events-none duration-100 w-max', { 'opacity-100 pointer-events-auto z-[999]': visible || focused })}
|
||||||
onBlur={this.handleBlur}
|
onBlur={this.handleBlur}
|
||||||
ref={this.setRef}
|
ref={this.setRef}
|
||||||
>
|
>
|
||||||
|
|
|
@ -5,11 +5,12 @@ import { connect } from 'react-redux';
|
||||||
import { getSoapboxConfig } from 'soapbox/actions/soapbox';
|
import { getSoapboxConfig } from 'soapbox/actions/soapbox';
|
||||||
import * as BuildConfig from 'soapbox/build_config';
|
import * as BuildConfig from 'soapbox/build_config';
|
||||||
import { Text, Stack } from 'soapbox/components/ui';
|
import { Text, Stack } from 'soapbox/components/ui';
|
||||||
import SvgIcon from 'soapbox/components/ui/icon/svg-icon';
|
|
||||||
import { captureException } from 'soapbox/monitoring';
|
import { captureException } from 'soapbox/monitoring';
|
||||||
import KVStore from 'soapbox/storage/kv_store';
|
import KVStore from 'soapbox/storage/kv_store';
|
||||||
import sourceCode from 'soapbox/utils/code';
|
import sourceCode from 'soapbox/utils/code';
|
||||||
|
|
||||||
|
import SiteLogo from './site-logo';
|
||||||
|
|
||||||
import type { RootState } from 'soapbox/store';
|
import type { RootState } from 'soapbox/store';
|
||||||
|
|
||||||
const goHome = () => location.href = '/';
|
const goHome = () => location.href = '/';
|
||||||
|
@ -103,7 +104,7 @@ class ErrorBoundary extends React.PureComponent<Props, State> {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { browser, hasError } = this.state;
|
const { browser, hasError } = this.state;
|
||||||
const { children, siteTitle, logo, links } = this.props;
|
const { children, links } = this.props;
|
||||||
|
|
||||||
if (!hasError) {
|
if (!hasError) {
|
||||||
return children;
|
return children;
|
||||||
|
@ -114,35 +115,33 @@ class ErrorBoundary extends React.PureComponent<Props, State> {
|
||||||
const errorText = this.getErrorText();
|
const errorText = this.getErrorText();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='h-screen pt-16 pb-12 flex flex-col bg-white'>
|
<div className='h-screen pt-16 pb-12 flex flex-col bg-white dark:bg-primary-900'>
|
||||||
<main className='flex-grow flex flex-col justify-center max-w-7xl w-full mx-auto px-4 sm:px-6 lg:px-8'>
|
<main className='flex-grow flex flex-col justify-center max-w-7xl w-full mx-auto px-4 sm:px-6 lg:px-8'>
|
||||||
<div className='flex-shrink-0 flex justify-center'>
|
<div className='flex-shrink-0 flex justify-center'>
|
||||||
<a href='/' className='inline-flex'>
|
<a href='/' className='inline-flex'>
|
||||||
{logo ? (
|
<SiteLogo alt='Logo' className='h-12 w-auto cursor-pointer' />
|
||||||
<img className='h-12' src={logo} alt={siteTitle} />
|
|
||||||
) : (
|
|
||||||
<SvgIcon className='h-12 w-12' src={require('@tabler/icons/home.svg')} alt={siteTitle} />
|
|
||||||
)}
|
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='py-8'>
|
<div className='py-8'>
|
||||||
<div className='text-center max-w-xl mx-auto space-y-2'>
|
<div className='text-center max-w-xl mx-auto space-y-2'>
|
||||||
<h1 className='text-3xl font-extrabold text-gray-900 tracking-tight sm:text-4xl'>
|
<h1 className='text-3xl font-extrabold text-gray-900 dark:text-gray-500 tracking-tight sm:text-4xl'>
|
||||||
<FormattedMessage id='alert.unexpected.message' defaultMessage='Something went wrong.' />
|
<FormattedMessage id='alert.unexpected.message' defaultMessage='Something went wrong.' />
|
||||||
</h1>
|
</h1>
|
||||||
<p className='text-lg text-gray-500'>
|
<p className='text-lg text-gray-700 dark:text-gray-600'>
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='alert.unexpected.body'
|
id='alert.unexpected.body'
|
||||||
defaultMessage="We're sorry for the interruption. If the problem persists, please reach out to our support team. You may also try to {clearCookies} (this will log you out)."
|
defaultMessage="We're sorry for the interruption. If the problem persists, please reach out to our support team. You may also try to {clearCookies} (this will log you out)."
|
||||||
values={{ clearCookies: (
|
values={{
|
||||||
<a href='/' onClick={this.clearCookies} className='text-gray-700 hover:underline'>
|
clearCookies: (
|
||||||
|
<a href='/' onClick={this.clearCookies} className='text-primary-600 dark:text-accent-blue hover:underline'>
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='alert.unexpected.clear_cookies'
|
id='alert.unexpected.clear_cookies'
|
||||||
defaultMessage='clear cookies and browser data'
|
defaultMessage='clear cookies and browser data'
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
) }}
|
),
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
@ -153,7 +152,7 @@ class ErrorBoundary extends React.PureComponent<Props, State> {
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
<div className='mt-10'>
|
<div className='mt-10'>
|
||||||
<a href='/' className='text-base font-medium text-primary-600 hover:text-primary-500'>
|
<a href='/' className='text-base font-medium text-primary-600 dark:text-accent-blue hover:underline'>
|
||||||
<FormattedMessage id='alert.unexpected.return_home' defaultMessage='Return Home' />
|
<FormattedMessage id='alert.unexpected.return_home' defaultMessage='Return Home' />
|
||||||
<span aria-hidden='true'> →</span>
|
<span aria-hidden='true'> →</span>
|
||||||
</a>
|
</a>
|
||||||
|
@ -165,7 +164,7 @@ class ErrorBoundary extends React.PureComponent<Props, State> {
|
||||||
{errorText && (
|
{errorText && (
|
||||||
<textarea
|
<textarea
|
||||||
ref={this.setTextareaRef}
|
ref={this.setTextareaRef}
|
||||||
className='h-48 p-4 shadow-sm focus:ring-primary-500 focus:border-primary-500 block w-full sm:text-sm border-gray-300 rounded-md font-mono'
|
className='h-48 p-4 shadow-sm bg-gray-100 text-gray-900 dark:text-gray-100 dark:bg-gray-800 focus:ring-2 focus:ring-primary-500 focus:border-primary-500 block w-full sm:text-sm border-gray-300 dark:border-gray-700 rounded-md font-mono'
|
||||||
value={errorText}
|
value={errorText}
|
||||||
onClick={this.handleCopy}
|
onClick={this.handleCopy}
|
||||||
readOnly
|
readOnly
|
||||||
|
@ -187,7 +186,7 @@ class ErrorBoundary extends React.PureComponent<Props, State> {
|
||||||
<nav className='flex justify-center space-x-4'>
|
<nav className='flex justify-center space-x-4'>
|
||||||
{links.get('status') && (
|
{links.get('status') && (
|
||||||
<>
|
<>
|
||||||
<a href={links.get('status')} className='text-sm font-medium text-gray-500 hover:text-gray-600'>
|
<a href={links.get('status')} className='text-sm font-medium text-gray-700 dark:text-gray-600 hover:underline'>
|
||||||
<FormattedMessage id='alert.unexpected.links.status' defaultMessage='Status' />
|
<FormattedMessage id='alert.unexpected.links.status' defaultMessage='Status' />
|
||||||
</a>
|
</a>
|
||||||
</>
|
</>
|
||||||
|
@ -196,7 +195,7 @@ class ErrorBoundary extends React.PureComponent<Props, State> {
|
||||||
{links.get('help') && (
|
{links.get('help') && (
|
||||||
<>
|
<>
|
||||||
<span className='inline-block border-l border-gray-300' aria-hidden='true' />
|
<span className='inline-block border-l border-gray-300' aria-hidden='true' />
|
||||||
<a href={links.get('help')} className='text-sm font-medium text-gray-500 hover:text-gray-600'>
|
<a href={links.get('help')} className='text-sm font-medium text-gray-700 dark:text-gray-600 hover:underline'>
|
||||||
<FormattedMessage id='alert.unexpected.links.help' defaultMessage='Help Center' />
|
<FormattedMessage id='alert.unexpected.links.help' defaultMessage='Help Center' />
|
||||||
</a>
|
</a>
|
||||||
</>
|
</>
|
||||||
|
@ -205,7 +204,7 @@ class ErrorBoundary extends React.PureComponent<Props, State> {
|
||||||
{links.get('support') && (
|
{links.get('support') && (
|
||||||
<>
|
<>
|
||||||
<span className='inline-block border-l border-gray-300' aria-hidden='true' />
|
<span className='inline-block border-l border-gray-300' aria-hidden='true' />
|
||||||
<a href={links.get('support')} className='text-sm font-medium text-gray-500 hover:text-gray-600'>
|
<a href={links.get('support')} className='text-sm font-medium text-gray-700 dark:text-gray-600 hover:underline'>
|
||||||
<FormattedMessage id='alert.unexpected.links.support' defaultMessage='Support' />
|
<FormattedMessage id='alert.unexpected.links.support' defaultMessage='Support' />
|
||||||
</a>
|
</a>
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -2,9 +2,6 @@ import React from 'react';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
import { Sparklines, SparklinesCurve } from 'react-sparklines';
|
import { Sparklines, SparklinesCurve } from 'react-sparklines';
|
||||||
|
|
||||||
import { getSoapboxConfig } from 'soapbox/actions/soapbox';
|
|
||||||
import { useAppSelector } from 'soapbox/hooks';
|
|
||||||
|
|
||||||
import { shortNumberFormat } from '../utils/numbers';
|
import { shortNumberFormat } from '../utils/numbers';
|
||||||
|
|
||||||
import Permalink from './permalink';
|
import Permalink from './permalink';
|
||||||
|
@ -18,7 +15,6 @@ interface IHashtag {
|
||||||
|
|
||||||
const Hashtag: React.FC<IHashtag> = ({ hashtag }) => {
|
const Hashtag: React.FC<IHashtag> = ({ hashtag }) => {
|
||||||
const count = Number(hashtag.history?.get(0)?.accounts);
|
const count = Number(hashtag.history?.get(0)?.accounts);
|
||||||
const brandColor = useAppSelector((state) => getSoapboxConfig(state).brandColor);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<HStack alignItems='center' justifyContent='between' data-testid='hashtag'>
|
<HStack alignItems='center' justifyContent='between' data-testid='hashtag'>
|
||||||
|
@ -48,7 +44,7 @@ const Hashtag: React.FC<IHashtag> = ({ hashtag }) => {
|
||||||
height={28}
|
height={28}
|
||||||
data={hashtag.history.reverse().map((day) => +day.uses).toArray()}
|
data={hashtag.history.reverse().map((day) => +day.uses).toArray()}
|
||||||
>
|
>
|
||||||
<SparklinesCurve style={{ fill: 'none' }} color={brandColor} />
|
<SparklinesCurve style={{ fill: 'none' }} color='#818cf8' />
|
||||||
</Sparklines>
|
</Sparklines>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -2,7 +2,7 @@ import React from 'react';
|
||||||
|
|
||||||
/** Fullscreen gradient used as a backdrop to public pages. */
|
/** Fullscreen gradient used as a backdrop to public pages. */
|
||||||
const LandingGradient: React.FC = () => (
|
const LandingGradient: React.FC = () => (
|
||||||
<div className='fixed h-screen w-full bg-gradient-to-tr from-primary-50 dark:from-slate-900/50 via-white dark:via-slate-900 to-gradient-end/10 dark:to-slate-900/50' />
|
<div className='fixed h-screen w-full bg-gradient-to-tr from-primary-50 dark:from-primary-900/50 via-white dark:via-primary-900 to-gradient-end/10 dark:to-primary-800/50' />
|
||||||
);
|
);
|
||||||
|
|
||||||
export default LandingGradient;
|
export default LandingGradient;
|
||||||
|
|
|
@ -2,7 +2,10 @@ import classNames from 'classnames';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
|
||||||
|
import { SelectDropdown } from '../features/forms';
|
||||||
|
|
||||||
import Icon from './icon';
|
import Icon from './icon';
|
||||||
|
import { Select } from './ui';
|
||||||
|
|
||||||
const List: React.FC = ({ children }) => (
|
const List: React.FC = ({ children }) => (
|
||||||
<div className='space-y-0.5'>{children}</div>
|
<div className='space-y-0.5'>{children}</div>
|
||||||
|
@ -22,36 +25,41 @@ const ListItem: React.FC<IListItem> = ({ label, hint, children, onClick }) => {
|
||||||
const LabelComp = onClick ? 'span' : 'label';
|
const LabelComp = onClick ? 'span' : 'label';
|
||||||
const linkProps = onClick ? { onClick } : {};
|
const linkProps = onClick ? { onClick } : {};
|
||||||
|
|
||||||
const renderChildren = React.useCallback(() =>
|
const renderChildren = React.useCallback(() => {
|
||||||
React.Children.map(children, (child) => {
|
return React.Children.map(children, (child) => {
|
||||||
if (React.isValidElement(child)) {
|
if (React.isValidElement(child)) {
|
||||||
|
const isSelect = child.type === SelectDropdown || child.type === Select;
|
||||||
|
|
||||||
return React.cloneElement(child, {
|
return React.cloneElement(child, {
|
||||||
id: domId,
|
id: domId,
|
||||||
|
className: classNames({
|
||||||
|
'w-auto': isSelect,
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
})
|
});
|
||||||
, [children, domId]);
|
}, [children, domId]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Comp
|
<Comp
|
||||||
className={classNames({
|
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-start/10 to-gradient-end/10 dark:from-slate-900/25 dark:to-slate-900/50': true,
|
'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': 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',
|
'cursor-pointer hover:from-gradient-start/20 hover:to-gradient-end/20 dark:hover:from-gradient-start/5 dark:hover:to-gradient-end/5': typeof onClick !== 'undefined',
|
||||||
})}
|
})}
|
||||||
{...linkProps}
|
{...linkProps}
|
||||||
>
|
>
|
||||||
<div className='flex flex-col py-1.5 pr-4'>
|
<div className='flex flex-col py-1.5 pr-4'>
|
||||||
<LabelComp className='text-black dark:text-white' htmlFor={domId}>{label}</LabelComp>
|
<LabelComp className='text-gray-900 dark:text-gray-100' htmlFor={domId}>{label}</LabelComp>
|
||||||
|
|
||||||
{hint ? (
|
{hint ? (
|
||||||
<span className='text-sm text-gray-500 dark:text-gray-400'>{hint}</span>
|
<span className='text-sm text-gray-700 dark:text-gray-600'>{hint}</span>
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{onClick ? (
|
{onClick ? (
|
||||||
<div className='flex flex-row items-center text-gray-500 dark:text-gray-400'>
|
<div className='flex flex-row items-center text-gray-700 dark:text-gray-600'>
|
||||||
{children}
|
{children}
|
||||||
|
|
||||||
<Icon src={require('@tabler/icons/chevron-right.svg')} className='ml-1' />
|
<Icon src={require('@tabler/icons/chevron-right.svg')} className='ml-1' />
|
||||||
|
|
|
@ -609,7 +609,7 @@ class MediaGallery extends React.PureComponent {
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<button type='button' onClick={this.handleOpen} className='bg-transparent w-full h-full border-0'>
|
<button type='button' onClick={this.handleOpen} className='bg-transparent w-full h-full border-0'>
|
||||||
<div className='p-4 rounded-xl shadow-xl backdrop-blur-sm bg-white/75 dark:bg-slate-800/75 text-center inline-block space-y-4 max-w-[280px]'>
|
<div className='p-4 rounded-xl shadow-xl backdrop-blur-sm bg-white/75 dark:bg-gray-900/75 text-center inline-block space-y-4 max-w-[280px]'>
|
||||||
<div className='space-y-1'>
|
<div className='space-y-1'>
|
||||||
<Text weight='semibold'>{warning}</Text>
|
<Text weight='semibold'>{warning}</Text>
|
||||||
<Text size='sm'>
|
<Text size='sm'>
|
||||||
|
|
|
@ -212,7 +212,7 @@ class ModalRoot extends React.PureComponent {
|
||||||
<div
|
<div
|
||||||
role='presentation'
|
role='presentation'
|
||||||
id='modal-overlay'
|
id='modal-overlay'
|
||||||
className='fixed inset-0 bg-gray-600 bg-opacity-90'
|
className='fixed inset-0 bg-gray-500/90 dark:bg-gray-700/90'
|
||||||
onClick={this.handleOnClose}
|
onClick={this.handleOnClose}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ const ProgressCircle: React.FC<IProgressCircle> = ({ progress, radius = 12, stro
|
||||||
viewBox={`0 0 ${actualRadius * 2} ${actualRadius * 2}`}
|
viewBox={`0 0 ${actualRadius * 2} ${actualRadius * 2}`}
|
||||||
>
|
>
|
||||||
<circle
|
<circle
|
||||||
className='stroke-gray-400'
|
className='stroke-gray-500 dark:stroke-white/20'
|
||||||
cx={actualRadius}
|
cx={actualRadius}
|
||||||
cy={actualRadius}
|
cy={actualRadius}
|
||||||
r={radius}
|
r={radius}
|
||||||
|
@ -30,8 +30,8 @@ const ProgressCircle: React.FC<IProgressCircle> = ({ progress, radius = 12, stro
|
||||||
strokeWidth={stroke}
|
strokeWidth={stroke}
|
||||||
/>
|
/>
|
||||||
<circle
|
<circle
|
||||||
className={classNames('stroke-primary-800', {
|
className={classNames('stroke-primary-500', {
|
||||||
'stroke-danger-600': progress > 1,
|
'stroke-secondary-500': progress > 1,
|
||||||
})}
|
})}
|
||||||
style={{
|
style={{
|
||||||
strokeDashoffset: dashoffset,
|
strokeDashoffset: dashoffset,
|
||||||
|
|
|
@ -126,8 +126,8 @@ const QuotedStatus: React.FC<IQuotedStatus> = ({ status, onCancel, compose }) =>
|
||||||
<Stack
|
<Stack
|
||||||
data-testid='quoted-status'
|
data-testid='quoted-status'
|
||||||
space={2}
|
space={2}
|
||||||
className={classNames('mt-3 p-4 rounded-lg border border-solid border-gray-100 dark:border-slate-700 cursor-pointer', {
|
className={classNames('mt-3 p-4 rounded-lg border border-solid border-gray-100 dark:border-gray-800 cursor-pointer', {
|
||||||
'hover:bg-gray-50 dark:hover:bg-slate-700': !compose,
|
'hover:bg-gray-50 dark:hover:bg-gray-800': !compose,
|
||||||
})}
|
})}
|
||||||
onClick={handleExpandClick}
|
onClick={handleExpandClick}
|
||||||
>
|
>
|
||||||
|
|
|
@ -37,18 +37,16 @@ const SidebarNavigationLink = React.forwardRef((props: ISidebarNavigationLink, r
|
||||||
ref={ref}
|
ref={ref}
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
className={classNames({
|
className={classNames({
|
||||||
'flex items-center p-3 text-sm font-semibold space-x-4 rounded-full group hover:bg-primary-200/80 dark:hover:bg-primary-900/60 hover:text-primary-600 dark:hover:text-gray-200': true,
|
'flex items-center px-4 py-3.5 text-base font-semibold space-x-4 rounded-full group text-gray-600 hover:text-primary-600 dark:text-gray-500 dark:hover:text-gray-100 hover:bg-primary-100 dark:hover:bg-primary-700': true,
|
||||||
'text-gray-500 dark:text-gray-400': !isActive,
|
'dark:text-gray-100 text-primary-600': isActive,
|
||||||
'text-primary-600 dark:text-white': isActive,
|
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<span className='relative'>
|
<span className='relative'>
|
||||||
<Icon
|
<Icon
|
||||||
src={icon}
|
src={icon}
|
||||||
count={count}
|
count={count}
|
||||||
className={classNames({
|
className={classNames('h-5 w-5 group-hover:text-primary-500', {
|
||||||
'h-6 w-6 dark:group-hover:text-primary-500': true,
|
'text-primary-500': isActive,
|
||||||
'dark:text-primary-500': isActive,
|
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -8,13 +8,12 @@ import { fetchOwnAccounts, logOut, switchAccount } from 'soapbox/actions/auth';
|
||||||
import { getSettings } from 'soapbox/actions/settings';
|
import { getSettings } from 'soapbox/actions/settings';
|
||||||
import { closeSidebar } from 'soapbox/actions/sidebar';
|
import { closeSidebar } from 'soapbox/actions/sidebar';
|
||||||
import Account from 'soapbox/components/account';
|
import Account from 'soapbox/components/account';
|
||||||
import SiteLogo from 'soapbox/components/site-logo';
|
|
||||||
import { Stack } from 'soapbox/components/ui';
|
import { Stack } from 'soapbox/components/ui';
|
||||||
import ProfileStats from 'soapbox/features/ui/components/profile_stats';
|
import ProfileStats from 'soapbox/features/ui/components/profile_stats';
|
||||||
import { useAppSelector, useFeatures } from 'soapbox/hooks';
|
import { useAppSelector, useFeatures } from 'soapbox/hooks';
|
||||||
import { makeGetAccount, makeGetOtherAccounts } from 'soapbox/selectors';
|
import { makeGetAccount, makeGetOtherAccounts } from 'soapbox/selectors';
|
||||||
|
|
||||||
import { HStack, Icon, IconButton, Text } from './ui';
|
import { Divider, HStack, Icon, IconButton, Text } from './ui';
|
||||||
|
|
||||||
import type { List as ImmutableList } from 'immutable';
|
import type { List as ImmutableList } from 'immutable';
|
||||||
import type { Account as AccountEntity } from 'soapbox/types/entities';
|
import type { Account as AccountEntity } from 'soapbox/types/entities';
|
||||||
|
@ -51,24 +50,24 @@ interface ISidebarLink {
|
||||||
const SidebarLink: React.FC<ISidebarLink> = ({ href, to, icon, text, onClick }) => {
|
const SidebarLink: React.FC<ISidebarLink> = ({ href, to, icon, text, onClick }) => {
|
||||||
const body = (
|
const body = (
|
||||||
<HStack space={2} alignItems='center'>
|
<HStack space={2} alignItems='center'>
|
||||||
<div className='bg-primary-50 dark:bg-slate-700 relative rounded inline-flex p-2'>
|
<div className='bg-primary-50 dark:bg-gray-800 relative rounded-full inline-flex p-2'>
|
||||||
<Icon src={icon} className='text-primary-600 h-5 w-5' />
|
<Icon src={icon} className='text-primary-500 h-5 w-5' />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Text tag='span' weight='medium' theme='muted' className='group-hover:text-gray-800 dark:group-hover:text-gray-200'>{text}</Text>
|
<Text tag='span' weight='medium' theme='inherit'>{text}</Text>
|
||||||
</HStack>
|
</HStack>
|
||||||
);
|
);
|
||||||
|
|
||||||
if (to) {
|
if (to) {
|
||||||
return (
|
return (
|
||||||
<NavLink className='group py-1 rounded-md' to={to} onClick={onClick}>
|
<NavLink className='group rounded-full text-gray-900 dark:text-gray-100 hover:bg-gray-50 dark:hover:bg-gray-800' to={to} onClick={onClick}>
|
||||||
{body}
|
{body}
|
||||||
</NavLink>
|
</NavLink>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<a className='group py-1 rounded-md' href={href} target='_blank' onClick={onClick}>
|
<a className='group rounded-full text-gray-900 dark:text-gray-100 hover:bg-gray-50 dark:hover:bg-gray-800' href={href} target='_blank' onClick={onClick}>
|
||||||
{body}
|
{body}
|
||||||
</a>
|
</a>
|
||||||
);
|
);
|
||||||
|
@ -139,72 +138,37 @@ const SidebarMenu: React.FC = (): JSX.Element | null => {
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className={classNames({
|
className={classNames({
|
||||||
'fixed inset-0 bg-gray-600 bg-opacity-90 z-1000': true,
|
'fixed inset-0 bg-gray-500/90 dark:bg-gray-700/90 z-1000': true,
|
||||||
'hidden': !sidebarOpen,
|
'hidden': !sidebarOpen,
|
||||||
})}
|
})}
|
||||||
role='button'
|
role='button'
|
||||||
onClick={handleClose}
|
onClick={handleClose}
|
||||||
/>
|
>
|
||||||
|
|
||||||
<div className='sidebar-menu'>
|
|
||||||
<div className='relative overflow-y-scroll overflow-auto h-full w-full'>
|
|
||||||
<div className='p-4'>
|
|
||||||
<Stack space={4}>
|
|
||||||
<HStack alignItems='center' justifyContent='between'>
|
|
||||||
<Link to='/' onClick={onClose}>
|
|
||||||
<SiteLogo alt='Logo' className='h-5 w-auto cursor-pointer' />
|
|
||||||
</Link>
|
|
||||||
|
|
||||||
<IconButton
|
<IconButton
|
||||||
title='close'
|
title='close'
|
||||||
onClick={handleClose}
|
onClick={handleClose}
|
||||||
src={require('@tabler/icons/x.svg')}
|
src={require('@tabler/icons/x.svg')}
|
||||||
ref={closeButtonRef}
|
ref={closeButtonRef}
|
||||||
className='text-gray-400 hover:text-gray-600'
|
iconClassName='h-6 w-6'
|
||||||
|
className='fixed top-5 right-5 text-gray-600 dark:text-gray-400 hover:text-gray-600 dark:hover:text-gray-300'
|
||||||
/>
|
/>
|
||||||
</HStack>
|
</div>
|
||||||
|
|
||||||
<Stack space={1}>
|
<div className='sidebar-menu'>
|
||||||
|
<div className='relative overflow-y-scroll overflow-auto h-full w-full'>
|
||||||
|
<div className='p-4'>
|
||||||
|
<Stack space={4}>
|
||||||
<Link to={`/@${account.acct}`} onClick={onClose}>
|
<Link to={`/@${account.acct}`} onClick={onClose}>
|
||||||
<Account account={account} showProfileHoverCard={false} withLinkToProfile={false} />
|
<Account account={account} showProfileHoverCard={false} withLinkToProfile={false} />
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
<Stack>
|
|
||||||
<button type='button' onClick={handleSwitcherClick} className='py-1'>
|
|
||||||
<HStack alignItems='center' justifyContent='between'>
|
|
||||||
<Text tag='span' size='sm' weight='medium'>
|
|
||||||
<FormattedMessage id='profile_dropdown.switch_account' defaultMessage='Switch accounts' />
|
|
||||||
</Text>
|
|
||||||
|
|
||||||
<Icon
|
|
||||||
src={require('@tabler/icons/chevron-down.svg')}
|
|
||||||
className={classNames('text-black dark:text-white transition-transform', {
|
|
||||||
'rotate-180': switcher,
|
|
||||||
})}
|
|
||||||
/>
|
|
||||||
</HStack>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
{switcher && (
|
|
||||||
<div className='border-t border-solid border-gray-200'>
|
|
||||||
{otherAccounts.map(account => renderAccount(account))}
|
|
||||||
|
|
||||||
<NavLink className='flex py-2 space-x-1' to='/login/add' onClick={handleClose}>
|
|
||||||
<Icon className='dark:text-white' src={require('@tabler/icons/plus.svg')} />
|
|
||||||
<Text>{intl.formatMessage(messages.addAccount)}</Text>
|
|
||||||
</NavLink>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</Stack>
|
|
||||||
</Stack>
|
|
||||||
|
|
||||||
<ProfileStats
|
<ProfileStats
|
||||||
account={account}
|
account={account}
|
||||||
onClickHandler={handleClose}
|
onClickHandler={handleClose}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Stack space={2}>
|
<Stack space={4}>
|
||||||
<hr />
|
<Divider />
|
||||||
|
|
||||||
<SidebarLink
|
<SidebarLink
|
||||||
to={`/@${account.acct}`}
|
to={`/@${account.acct}`}
|
||||||
|
@ -241,7 +205,7 @@ const SidebarMenu: React.FC = (): JSX.Element | null => {
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{features.publicTimeline && <>
|
{features.publicTimeline && <>
|
||||||
<hr className='dark:border-slate-700' />
|
<Divider />
|
||||||
|
|
||||||
<SidebarLink
|
<SidebarLink
|
||||||
to='/timeline/local'
|
to='/timeline/local'
|
||||||
|
@ -260,7 +224,7 @@ const SidebarMenu: React.FC = (): JSX.Element | null => {
|
||||||
)}
|
)}
|
||||||
</>}
|
</>}
|
||||||
|
|
||||||
<hr />
|
<Divider />
|
||||||
|
|
||||||
<SidebarLink
|
<SidebarLink
|
||||||
to='/blocks'
|
to='/blocks'
|
||||||
|
@ -319,7 +283,7 @@ const SidebarMenu: React.FC = (): JSX.Element | null => {
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<hr />
|
<Divider />
|
||||||
|
|
||||||
<SidebarLink
|
<SidebarLink
|
||||||
to='/logout'
|
to='/logout'
|
||||||
|
@ -327,6 +291,36 @@ const SidebarMenu: React.FC = (): JSX.Element | null => {
|
||||||
text={intl.formatMessage(messages.logout)}
|
text={intl.formatMessage(messages.logout)}
|
||||||
onClick={onClickLogOut}
|
onClick={onClickLogOut}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<Divider />
|
||||||
|
|
||||||
|
<Stack space={4}>
|
||||||
|
<button type='button' onClick={handleSwitcherClick} className='py-1'>
|
||||||
|
<HStack alignItems='center' justifyContent='between'>
|
||||||
|
<Text tag='span'>
|
||||||
|
<FormattedMessage id='profile_dropdown.switch_account' defaultMessage='Switch accounts' />
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<Icon
|
||||||
|
src={require('@tabler/icons/chevron-down.svg')}
|
||||||
|
className={classNames('w-4 h-4 text-gray-900 dark:text-gray-100 transition-transform', {
|
||||||
|
'rotate-180': switcher,
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
</HStack>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{switcher && (
|
||||||
|
<div className='border-t-2 border-gray-100 dark:border-gray-800 border-solid'>
|
||||||
|
{otherAccounts.map(account => renderAccount(account))}
|
||||||
|
|
||||||
|
<NavLink className='flex items-center py-2 space-x-1' to='/login/add' onClick={handleClose}>
|
||||||
|
<Icon className='text-primary-500 w-4 h-4' src={require('@tabler/icons/plus.svg')} />
|
||||||
|
<Text size='sm' weight='medium'>{intl.formatMessage(messages.addAccount)}</Text>
|
||||||
|
</NavLink>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Stack>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Stack>
|
</Stack>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -43,7 +43,7 @@ const StatusActionButton = React.forwardRef<HTMLButtonElement, IStatusActionButt
|
||||||
type='button'
|
type='button'
|
||||||
className={classNames(
|
className={classNames(
|
||||||
'flex items-center p-1 space-x-0.5 rounded-full',
|
'flex items-center p-1 space-x-0.5 rounded-full',
|
||||||
'text-gray-400 hover:text-gray-600 dark:hover:text-white',
|
'text-gray-600 hover:text-gray-600 dark:hover:text-white',
|
||||||
'bg-white dark:bg-transparent',
|
'bg-white dark:bg-transparent',
|
||||||
'focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500 dark:ring-offset-0',
|
'focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500 dark:ring-offset-0',
|
||||||
{
|
{
|
||||||
|
|
|
@ -361,7 +361,7 @@ class Status extends ImmutablePureComponent<IStatus, IStatusState> {
|
||||||
<NavLink
|
<NavLink
|
||||||
to={`/@${status.getIn(['account', 'acct'])}`}
|
to={`/@${status.getIn(['account', 'acct'])}`}
|
||||||
onClick={(event) => event.stopPropagation()}
|
onClick={(event) => event.stopPropagation()}
|
||||||
className='hidden sm:flex items-center text-gray-500 text-xs font-medium space-x-1 hover:underline'
|
className='hidden sm:flex items-center text-gray-700 dark:text-gray-600 text-xs font-medium space-x-1 hover:underline'
|
||||||
>
|
>
|
||||||
<Icon src={require('@tabler/icons/repeat.svg')} className='text-green-600' />
|
<Icon src={require('@tabler/icons/repeat.svg')} className='text-green-600' />
|
||||||
|
|
||||||
|
@ -384,7 +384,7 @@ class Status extends ImmutablePureComponent<IStatus, IStatusState> {
|
||||||
<NavLink
|
<NavLink
|
||||||
to={`/@${status.getIn(['account', 'acct'])}`}
|
to={`/@${status.getIn(['account', 'acct'])}`}
|
||||||
onClick={(event) => event.stopPropagation()}
|
onClick={(event) => event.stopPropagation()}
|
||||||
className='flex items-center text-gray-500 text-xs font-medium space-x-1 hover:underline'
|
className='flex items-center text-gray-700 dark:text-gray-600 text-xs font-medium space-x-1 hover:underline'
|
||||||
>
|
>
|
||||||
<Icon src={require('@tabler/icons/repeat.svg')} className='text-green-600' />
|
<Icon src={require('@tabler/icons/repeat.svg')} className='text-green-600' />
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,7 @@ const SpoilerButton: React.FC<ISpoilerButton> = ({ onClick, hidden, tabIndex })
|
||||||
tabIndex={tabIndex}
|
tabIndex={tabIndex}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
'inline-block rounded-md px-1.5 py-0.5 ml-[0.5em]',
|
'inline-block rounded-md px-1.5 py-0.5 ml-[0.5em]',
|
||||||
'text-black dark:text-white',
|
'text-gray-900 dark:text-gray-100',
|
||||||
'font-bold text-[11px] uppercase',
|
'font-bold text-[11px] uppercase',
|
||||||
'bg-primary-100 dark:bg-primary-900',
|
'bg-primary-100 dark:bg-primary-900',
|
||||||
'hover:bg-primary-300 dark:hover:bg-primary-600',
|
'hover:bg-primary-300 dark:hover:bg-primary-600',
|
||||||
|
@ -279,7 +279,7 @@ const StatusContent: React.FC<IStatusContent> = ({ status, expanded = false, onE
|
||||||
output.push(<Poll id={status.poll} key='poll' status={status.url} />);
|
output.push(<Poll id={status.poll} key='poll' status={status.url} />);
|
||||||
}
|
}
|
||||||
|
|
||||||
return <div className={classNames({ 'bg-gray-100 dark:bg-primary-900 rounded-md p-4': hasPoll })}>{output}</div>;
|
return <div className={classNames({ 'bg-gray-100 dark:bg-primary-800 rounded-md p-4': hasPoll })}>{output}</div>;
|
||||||
} else {
|
} else {
|
||||||
const output = [
|
const output = [
|
||||||
<div
|
<div
|
||||||
|
|
|
@ -206,7 +206,7 @@ const StatusList: React.FC<IStatusList> = ({
|
||||||
placeholderComponent={PlaceholderStatus}
|
placeholderComponent={PlaceholderStatus}
|
||||||
placeholderCount={20}
|
placeholderCount={20}
|
||||||
ref={node}
|
ref={node}
|
||||||
className={classNames('divide-y divide-solid divide-gray-200 dark:divide-slate-700', {
|
className={classNames('divide-y divide-solid divide-gray-200 dark:divide-gray-800', {
|
||||||
'divide-none': divideType !== 'border',
|
'divide-none': divideType !== 'border',
|
||||||
})}
|
})}
|
||||||
itemClassName={classNames({
|
itemClassName={classNames({
|
||||||
|
|
|
@ -34,8 +34,8 @@ const ThumbNavigationLink: React.FC<IThumbNavigationLink> = ({ count, src, text,
|
||||||
src={src}
|
src={src}
|
||||||
className={classNames({
|
className={classNames({
|
||||||
'h-5 w-5': true,
|
'h-5 w-5': true,
|
||||||
'text-gray-600 dark:text-gray-300': !active,
|
'text-gray-600': !active,
|
||||||
'text-primary-600': active,
|
'text-primary-500': active,
|
||||||
})}
|
})}
|
||||||
count={count}
|
count={count}
|
||||||
/>
|
/>
|
||||||
|
@ -44,13 +44,21 @@ const ThumbNavigationLink: React.FC<IThumbNavigationLink> = ({ count, src, text,
|
||||||
src={src}
|
src={src}
|
||||||
className={classNames({
|
className={classNames({
|
||||||
'h-5 w-5': true,
|
'h-5 w-5': true,
|
||||||
'text-gray-600 dark:text-gray-300': !active,
|
'text-gray-600': !active,
|
||||||
'text-primary-600': active,
|
'text-primary-500': active,
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Text tag='span' size='xs'>
|
<Text
|
||||||
|
tag='span'
|
||||||
|
size='xs'
|
||||||
|
weight='medium'
|
||||||
|
className={classNames({
|
||||||
|
'text-gray-600': !active,
|
||||||
|
'text-primary-500': active,
|
||||||
|
})}
|
||||||
|
>
|
||||||
{text}
|
{text}
|
||||||
</Text>
|
</Text>
|
||||||
</NavLink>
|
</NavLink>
|
||||||
|
|
|
@ -19,7 +19,7 @@ const Tombstone: React.FC<ITombstone> = ({ id, onMoveUp, onMoveDown }) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<HotKeys handlers={handlers}>
|
<HotKeys handlers={handlers}>
|
||||||
<div className='p-9 flex items-center justify-center sm:rounded-xl bg-gray-100 border border-solid border-gray-200 dark:bg-slate-900 dark:border-slate-700 focusable' tabIndex={0}>
|
<div className='p-9 flex items-center justify-center sm:rounded-xl bg-gray-100 border border-solid border-gray-200 dark:bg-gray-900 dark:border-gray-800 focusable' tabIndex={0}>
|
||||||
<Text>
|
<Text>
|
||||||
<FormattedMessage id='statuses.tombstone' defaultMessage='One or more posts are unavailable.' />
|
<FormattedMessage id='statuses.tombstone' defaultMessage='One or more posts are unavailable.' />
|
||||||
</Text>
|
</Text>
|
||||||
|
|
|
@ -13,8 +13,8 @@ const Banner: React.FC<IBanner> = ({ theme, children, className }) => {
|
||||||
<div
|
<div
|
||||||
data-testid='banner'
|
data-testid='banner'
|
||||||
className={classNames('fixed bottom-0 left-0 right-0 py-8 z-50', {
|
className={classNames('fixed bottom-0 left-0 right-0 py-8 z-50', {
|
||||||
'backdrop-blur bg-primary-900/80': theme === 'frosted',
|
'backdrop-blur bg-primary-800/80 dark:bg-primary-900/80': theme === 'frosted',
|
||||||
'bg-white dark:bg-slate-800 text-black dark:text-white shadow-3xl dark:shadow-inset': theme === 'opaque',
|
'bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 shadow-3xl dark:shadow-inset': theme === 'opaque',
|
||||||
}, className)}
|
}, className)}
|
||||||
>
|
>
|
||||||
<div className='max-w-4xl mx-auto px-4'>
|
<div className='max-w-4xl mx-auto px-4'>
|
||||||
|
|
|
@ -55,9 +55,9 @@ describe('<Button />', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handles Theme properly', () => {
|
it('handles Theme properly', () => {
|
||||||
render(<Button theme='secondary' />);
|
render(<Button theme='tertiary' />);
|
||||||
|
|
||||||
expect(screen.getByRole('button')).toHaveClass('bg-primary-100');
|
expect(screen.getByRole('button')).toHaveClass('bg-transparent border-gray-400');
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('to prop', () => {
|
describe('to prop', () => {
|
||||||
|
|
|
@ -44,7 +44,7 @@ const Button = React.forwardRef<HTMLButtonElement, IButton>((props, ref): JSX.El
|
||||||
onClick,
|
onClick,
|
||||||
size = 'md',
|
size = 'md',
|
||||||
text,
|
text,
|
||||||
theme = 'accent',
|
theme = 'secondary',
|
||||||
to,
|
to,
|
||||||
type = 'button',
|
type = 'button',
|
||||||
} = props;
|
} = props;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
type ButtonThemes = 'primary' | 'secondary' | 'ghost' | 'accent' | 'danger' | 'transparent' | 'link' | 'danger-link'
|
type ButtonThemes = 'primary' | 'secondary' | 'tertiary' | 'accent' | 'danger' | 'transparent'
|
||||||
type ButtonSizes = 'sm' | 'md' | 'lg'
|
type ButtonSizes = 'sm' | 'md' | 'lg'
|
||||||
|
|
||||||
type IButtonStyles = {
|
type IButtonStyles = {
|
||||||
|
@ -19,15 +19,14 @@ const useButtonStyles = ({
|
||||||
}: IButtonStyles) => {
|
}: IButtonStyles) => {
|
||||||
const themes = {
|
const themes = {
|
||||||
primary:
|
primary:
|
||||||
'border-primary-600 text-white bg-primary-600 hover:bg-primary-700 focus:ring-primary-500 focus:ring-2 focus:ring-offset-2',
|
'bg-primary-500 hover:bg-primary-400 dark:hover:bg-primary-600 border-transparent focus:bg-primary-500 text-gray-100 focus:ring-primary-300',
|
||||||
secondary:
|
secondary:
|
||||||
'border-transparent text-primary-700 bg-primary-100 hover:bg-primary-200 focus:ring-primary-500 focus:ring-2 focus:ring-offset-2',
|
'border-transparent bg-primary-100 dark:bg-primary-800 hover:bg-primary-50 dark:hover:bg-primary-700 focus:bg-primary-100 dark:focus:bg-primary-800 text-primary-500 dark:text-primary-200',
|
||||||
ghost: 'shadow-none border-gray-200 text-gray-700 bg-white dark:border-slate-700 dark:bg-slate-800 dark:text-slate-200 focus:ring-primary-500 focus:ring-2 focus:ring-offset-2',
|
tertiary:
|
||||||
accent: 'border-transparent text-white bg-accent-500 hover:bg-accent-300 focus:ring-pink-500 focus:ring-2 focus:ring-offset-2',
|
'bg-transparent border-gray-400 dark:border-gray-800 hover:border-primary-300 dark:hover:border-primary-700 focus:border-primary-500 text-gray-900 dark:text-gray-100 focus:ring-primary-500',
|
||||||
danger: 'border-transparent text-danger-700 bg-danger-100 hover:bg-danger-200 focus:ring-danger-500 focus:ring-2 focus:ring-offset-2',
|
accent: 'border-transparent bg-secondary-500 hover:bg-secondary-300 focus:bg-secondary-500 text-gray-100 focus:ring-secondary-300',
|
||||||
'danger-link': 'border-transparent text-accent-500 hover:bg-accent-500 hover:bg-opacity-10',
|
danger: 'border-transparent bg-danger-600 text-gray-100 hover:bg-danger-500 dark:hover:bg-danger-700 focus:bg-danger-600 dark:focus:bg-danger-600',
|
||||||
transparent: 'border-transparent text-gray-800 backdrop-blur-sm bg-white/75 hover:bg-white/80',
|
transparent: 'border-transparent text-gray-800 backdrop-blur-sm bg-white/75 hover:bg-white/80',
|
||||||
link: 'border-transparent text-primary-600 dark:text-primary-400 hover:bg-primary-100 hover:text-primary-700 dark:hover:bg-slate-900/50',
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const sizes = {
|
const sizes = {
|
||||||
|
@ -38,8 +37,8 @@ const useButtonStyles = ({
|
||||||
};
|
};
|
||||||
|
|
||||||
const buttonStyle = classNames({
|
const buttonStyle = classNames({
|
||||||
'inline-flex items-center border font-medium rounded-full focus:outline-none appearance-none transition-all': true,
|
'inline-flex items-center border font-medium rounded-full focus:outline-none focus:ring-2 focus:ring-offset-2 appearance-none transition-all': true,
|
||||||
'select-none disabled:opacity-50 disabled:cursor-default': disabled,
|
'select-none disabled:opacity-75 disabled:cursor-default': disabled,
|
||||||
[`${themes[theme]}`]: true,
|
[`${themes[theme]}`]: true,
|
||||||
[`${sizes[size]}`]: true,
|
[`${sizes[size]}`]: true,
|
||||||
'flex w-full justify-center': block,
|
'flex w-full justify-center': block,
|
||||||
|
|
|
@ -34,7 +34,7 @@ const Card = React.forwardRef<HTMLDivElement, ICard>(({ children, variant, size
|
||||||
{...filteredProps}
|
{...filteredProps}
|
||||||
className={classNames({
|
className={classNames({
|
||||||
'space-y-4': true,
|
'space-y-4': true,
|
||||||
'bg-white dark:bg-slate-800 text-black dark:text-white shadow-lg dark:shadow-inset overflow-hidden': variant === 'rounded',
|
'bg-white dark:bg-primary-900 text-gray-900 dark:text-gray-100 shadow-lg dark:shadow-none overflow-hidden': variant === 'rounded',
|
||||||
[sizes[size]]: variant === 'rounded',
|
[sizes[size]]: variant === 'rounded',
|
||||||
}, className)}
|
}, className)}
|
||||||
>
|
>
|
||||||
|
|
|
@ -9,7 +9,7 @@ const Checkbox = React.forwardRef<HTMLInputElement, ICheckbox>((props, ref) => {
|
||||||
{...props}
|
{...props}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
type='checkbox'
|
type='checkbox'
|
||||||
className='dark:bg-slate-800 dark:border-gray-600 focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded'
|
className='border-2 dark:bg-gray-900 dark:border-gray-800 focus:ring-primary-500 h-4 w-4 text-primary-600 border-gray-300 rounded'
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
@ -10,7 +10,7 @@ interface ICounter {
|
||||||
/** A simple counter for notifications, etc. */
|
/** A simple counter for notifications, etc. */
|
||||||
const Counter: React.FC<ICounter> = ({ count }) => {
|
const Counter: React.FC<ICounter> = ({ count }) => {
|
||||||
return (
|
return (
|
||||||
<span className='block px-1.5 py-0.5 bg-accent-500 text-xs text-white rounded-full ring-2 ring-white dark:ring-slate-800'>
|
<span className='block px-1.5 py-0.5 bg-secondary-500 text-xs text-white rounded-full ring-2 ring-white dark:ring-gray-800'>
|
||||||
{shortNumberFormat(count)}
|
{shortNumberFormat(count)}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
|
|
|
@ -8,7 +8,7 @@ interface IDivider {
|
||||||
const Divider = ({ text }: IDivider) => (
|
const Divider = ({ text }: IDivider) => (
|
||||||
<div className='relative' data-testid='divider'>
|
<div className='relative' data-testid='divider'>
|
||||||
<div className='absolute inset-0 flex items-center' aria-hidden='true'>
|
<div className='absolute inset-0 flex items-center' aria-hidden='true'>
|
||||||
<div className='w-full border-t-2 border-gray-100 dark:border-slate-700 border-solid' />
|
<div className='w-full border-t-2 border-gray-100 dark:border-gray-800 border-solid' />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{text && (
|
{text && (
|
||||||
|
|
|
@ -48,7 +48,7 @@ const EmojiSelector: React.FC<IEmojiSelector> = ({ emojis, onReact, visible = fa
|
||||||
return (
|
return (
|
||||||
<HStack
|
<HStack
|
||||||
space={2}
|
space={2}
|
||||||
className={classNames('bg-white dark:bg-slate-900 p-3 rounded-full shadow-md z-[999] w-max')}
|
className={classNames('bg-white dark:bg-gray-900 p-3 rounded-full shadow-md z-[999] w-max')}
|
||||||
>
|
>
|
||||||
{Array.from(emojis).map((emoji, i) => (
|
{Array.from(emojis).map((emoji, i) => (
|
||||||
<EmojiButton
|
<EmojiButton
|
||||||
|
|
|
@ -8,7 +8,7 @@ const FileInput = forwardRef<HTMLInputElement, IFileInput>((props, ref) => {
|
||||||
{...props}
|
{...props}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
type='file'
|
type='file'
|
||||||
className='block w-full text-sm text-gray-800 dark:text-slate-200 file:cursor-pointer file:mr-2 file:py-1.5 file:px-3 file:rounded-full file:text-xs file:leading-4 file:font-medium file:border-gray-200 file:border file:border-solid file:bg-white file:text-gray-700 hover:file:bg-gray-100 dark:file:border-slate-700 dark:file:bg-slate-800 dark:file:text-slate-200'
|
className='block w-full text-sm text-gray-800 dark:text-gray-200 file:cursor-pointer file:mr-2 file:py-1.5 file:px-3 file:rounded-full file:text-xs file:leading-4 file:font-medium file:border-gray-200 file:border file:border-solid file:bg-white file:text-gray-700 hover:file:bg-gray-100 dark:file:border-gray-800 dark:file:bg-gray-900 dark:file:hover:bg-gray-800 dark:file:text-gray-500'
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
@ -42,7 +42,7 @@ const FormGroup: React.FC<IFormGroup> = (props) => {
|
||||||
<label
|
<label
|
||||||
htmlFor={formFieldId}
|
htmlFor={formFieldId}
|
||||||
data-testid='form-group-label'
|
data-testid='form-group-label'
|
||||||
className='-mt-0.5 block text-sm font-medium text-gray-700 dark:text-gray-400'
|
className='-mt-0.5 block text-sm font-medium text-gray-900 dark:text-gray-100'
|
||||||
title={labelTitle}
|
title={labelTitle}
|
||||||
>
|
>
|
||||||
{labelText}
|
{labelText}
|
||||||
|
@ -61,7 +61,7 @@ const FormGroup: React.FC<IFormGroup> = (props) => {
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{hintText && (
|
{hintText && (
|
||||||
<p data-testid='form-group-hint' className='mt-0.5 text-xs text-gray-400'>
|
<p data-testid='form-group-hint' className='mt-0.5 text-xs text-gray-700 dark:text-gray-600'>
|
||||||
{hintText}
|
{hintText}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
|
@ -76,7 +76,7 @@ const FormGroup: React.FC<IFormGroup> = (props) => {
|
||||||
<label
|
<label
|
||||||
htmlFor={formFieldId}
|
htmlFor={formFieldId}
|
||||||
data-testid='form-group-label'
|
data-testid='form-group-label'
|
||||||
className='block text-sm font-medium text-gray-700 dark:text-gray-400'
|
className='block text-sm font-medium text-gray-900 dark:text-gray-100'
|
||||||
title={labelTitle}
|
title={labelTitle}
|
||||||
>
|
>
|
||||||
{labelText}
|
{labelText}
|
||||||
|
@ -97,7 +97,7 @@ const FormGroup: React.FC<IFormGroup> = (props) => {
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{hintText && (
|
{hintText && (
|
||||||
<p data-testid='form-group-hint' className='mt-0.5 text-xs text-gray-400'>
|
<p data-testid='form-group-hint' className='mt-0.5 text-xs text-gray-700 dark:text-gray-600'>
|
||||||
{hintText}
|
{hintText}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -33,7 +33,7 @@ const IconButton = React.forwardRef((props: IIconButton, ref: React.ForwardedRef
|
||||||
<SvgIcon src={src} className={iconClassName} />
|
<SvgIcon src={src} className={iconClassName} />
|
||||||
|
|
||||||
{text ? (
|
{text ? (
|
||||||
<Text tag='span' theme='muted' size='sm'>
|
<Text tag='span' theme='inherit' size='sm'>
|
||||||
{text}
|
{text}
|
||||||
</Text>
|
</Text>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
|
@ -57,7 +57,7 @@ const Input = React.forwardRef<HTMLInputElement, IInput>(
|
||||||
<div className={classNames('mt-1 relative rounded-md shadow-sm', outerClassName)}>
|
<div className={classNames('mt-1 relative rounded-md shadow-sm', outerClassName)}>
|
||||||
{icon ? (
|
{icon ? (
|
||||||
<div className='absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none'>
|
<div className='absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none'>
|
||||||
<Icon src={icon} className='h-4 w-4 text-gray-400' aria-hidden='true' />
|
<Icon src={icon} className='h-4 w-4 text-gray-700 dark:text-gray-600' aria-hidden='true' />
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ const Input = React.forwardRef<HTMLInputElement, IInput>(
|
||||||
type={revealed ? 'text' : type}
|
type={revealed ? 'text' : type}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={classNames({
|
className={classNames({
|
||||||
'dark:bg-slate-800 dark:text-white block w-full sm:text-sm border-gray-300 dark:border-gray-600 rounded-md focus:ring-primary-500 focus:border-primary-500':
|
'bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100 placeholder:text-gray-600 dark:placeholder:text-gray-600 block w-full sm:text-sm border-gray-400 dark:border-gray-800 dark:ring-1 dark:ring-gray-800 rounded-md focus:ring-primary-500 focus:border-primary-500 dark:focus:ring-primary-500 dark:focus:border-primary-500':
|
||||||
true,
|
true,
|
||||||
'pr-7': isPassword,
|
'pr-7': isPassword,
|
||||||
'text-red-600 border-red-600': hasError,
|
'text-red-600 border-red-600': hasError,
|
||||||
|
@ -94,7 +94,7 @@ const Input = React.forwardRef<HTMLInputElement, IInput>(
|
||||||
type='button'
|
type='button'
|
||||||
onClick={togglePassword}
|
onClick={togglePassword}
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
className='text-gray-400 dark:text-gray-500 hover:text-gray-500 dark:hover:text-gray-400 h-full px-2 focus:ring-primary-500 focus:ring-2'
|
className='text-gray-700 dark:text-gray-600 hover:text-gray-500 dark:hover:text-gray-400 h-full px-2 focus:ring-primary-500 focus:ring-2'
|
||||||
>
|
>
|
||||||
<SvgIcon
|
<SvgIcon
|
||||||
src={revealed ? require('@tabler/icons/eye-off.svg') : require('@tabler/icons/eye.svg')}
|
src={revealed ? require('@tabler/icons/eye-off.svg') : require('@tabler/icons/eye.svg')}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
[data-reach-menu-popover] {
|
[data-reach-menu-popover] {
|
||||||
@apply origin-top-right absolute right-0 mt-2 w-56 rounded-md shadow-lg bg-white dark:bg-slate-900 ring-1 ring-black ring-opacity-5 focus:outline-none;
|
@apply origin-top-right absolute right-0 mt-2 w-56 rounded-md shadow-lg bg-white dark:bg-gray-900 dark:ring-2 dark:ring-primary-700 focus:outline-none;
|
||||||
|
|
||||||
z-index: 1003;
|
z-index: 1003;
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ div:focus[data-reach-menu-list] {
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-reach-menu-item][data-selected] {
|
[data-reach-menu-item][data-selected] {
|
||||||
@apply bg-gray-100 dark:bg-slate-700;
|
@apply bg-gray-100 dark:bg-gray-800;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-reach-menu-list] {
|
[data-reach-menu-list] {
|
||||||
|
@ -22,11 +22,11 @@ div:focus[data-reach-menu-list] {
|
||||||
|
|
||||||
[data-reach-menu-item],
|
[data-reach-menu-item],
|
||||||
[data-reach-menu-link] {
|
[data-reach-menu-link] {
|
||||||
@apply block px-4 py-2.5 text-sm text-gray-700 dark:text-gray-400 cursor-pointer;
|
@apply block px-4 py-2.5 text-sm text-gray-700 dark:text-gray-500 cursor-pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-reach-menu-link] {
|
[data-reach-menu-link] {
|
||||||
@apply hover:bg-gray-100 dark:hover:bg-slate-700;
|
@apply hover:bg-gray-100 dark:hover:bg-gray-800;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-reach-menu-item][data-disabled],
|
[data-reach-menu-item][data-disabled],
|
||||||
|
@ -35,5 +35,5 @@ div:focus[data-reach-menu-list] {
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-reach-menu-popover] hr {
|
[data-reach-menu-popover] hr {
|
||||||
@apply my-1 mx-2 border-t border-gray-100 dark:border-slate-700;
|
@apply my-1 mx-2 border-t-2 border-gray-100 dark:border-gray-800;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ const MenuList: React.FC<IMenuList> = (props) => (
|
||||||
<MenuPopover position={props.position === 'left' ? positionDefault : positionRight}>
|
<MenuPopover position={props.position === 'left' ? positionDefault : positionRight}>
|
||||||
<MenuItems
|
<MenuItems
|
||||||
onKeyDown={(event) => event.nativeEvent.stopImmediatePropagation()}
|
onKeyDown={(event) => event.nativeEvent.stopImmediatePropagation()}
|
||||||
className='py-1 bg-white dark:bg-slate-900 rounded-lg shadow-menu'
|
className='py-1 bg-white dark:bg-primary-900 rounded-lg shadow-menu'
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
</MenuPopover>
|
</MenuPopover>
|
||||||
|
|
|
@ -83,7 +83,7 @@ const Modal: React.FC<IModal> = ({
|
||||||
}, [skipFocus, buttonRef]);
|
}, [skipFocus, buttonRef]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div data-testid='modal' className={classNames('block w-full p-6 mx-auto text-left align-middle transition-all transform bg-white dark:bg-slate-800 text-black dark:text-white shadow-xl rounded-2xl pointer-events-auto', widths[width])}>
|
<div data-testid='modal' className={classNames('block w-full p-6 mx-auto text-left align-middle transition-all transform bg-white dark:bg-primary-900 text-gray-900 dark:text-gray-100 shadow-xl rounded-2xl pointer-events-auto', widths[width])}>
|
||||||
<div className='sm:flex sm:items-start w-full justify-between'>
|
<div className='sm:flex sm:items-start w-full justify-between'>
|
||||||
<div className='w-full'>
|
<div className='w-full'>
|
||||||
{title && (
|
{title && (
|
||||||
|
@ -92,7 +92,7 @@ const Modal: React.FC<IModal> = ({
|
||||||
'flex-row-reverse': closePosition === 'left',
|
'flex-row-reverse': closePosition === 'left',
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<h3 className='flex-grow text-lg leading-6 font-medium text-gray-900 dark:text-white'>
|
<h3 className='flex-grow text-lg leading-6 font-bold text-gray-900 dark:text-white'>
|
||||||
{title}
|
{title}
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
|
@ -120,7 +120,7 @@ const Modal: React.FC<IModal> = ({
|
||||||
<div className='flex-grow'>
|
<div className='flex-grow'>
|
||||||
{cancelAction && (
|
{cancelAction && (
|
||||||
<Button
|
<Button
|
||||||
theme='ghost'
|
theme='tertiary'
|
||||||
onClick={cancelAction}
|
onClick={cancelAction}
|
||||||
>
|
>
|
||||||
{cancelText || 'Cancel'}
|
{cancelText || 'Cancel'}
|
||||||
|
|
|
@ -6,8 +6,8 @@ interface IProgressBar {
|
||||||
|
|
||||||
/** A horizontal meter filled to the given percentage. */
|
/** A horizontal meter filled to the given percentage. */
|
||||||
const ProgressBar: React.FC<IProgressBar> = ({ progress }) => (
|
const ProgressBar: React.FC<IProgressBar> = ({ progress }) => (
|
||||||
<div className='h-2.5 w-full rounded-full bg-gray-100 dark:bg-slate-900/50 overflow-hidden'>
|
<div className='h-2.5 w-full rounded-full bg-gray-300 dark:bg-primary-800 overflow-hidden'>
|
||||||
<div className='h-full bg-accent-500' style={{ width: `${Math.floor(progress * 100)}%` }} />
|
<div className='h-full bg-secondary-500' style={{ width: `${Math.floor(progress * 100)}%` }} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -6,12 +6,12 @@ interface ISelect extends React.SelectHTMLAttributes<HTMLSelectElement> {
|
||||||
|
|
||||||
/** Multiple-select dropdown. */
|
/** Multiple-select dropdown. */
|
||||||
const Select = React.forwardRef<HTMLSelectElement, ISelect>((props, ref) => {
|
const Select = React.forwardRef<HTMLSelectElement, ISelect>((props, ref) => {
|
||||||
const { children, ...filteredProps } = props;
|
const { children, className, ...filteredProps } = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<select
|
<select
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className='w-full pl-3 pr-10 py-2 text-base border-gray-300 dark:border-slate-700 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 dark:bg-slate-800 dark:text-white sm:text-sm rounded-md disabled:opacity-50'
|
className={`w-full pl-3 pr-10 py-2 text-base border-gray-300 dark:border-gray-800 focus:outline-none focus:ring-primary-500 focus:border-primary-500 dark:bg-gray-900 dark:text-gray-100 dark:ring-1 dark:ring-gray-800 dark:focus:ring-primary-500 dark:focus:border-primary-500 sm:text-sm rounded-md disabled:opacity-50 ${className}`}
|
||||||
{...filteredProps}
|
{...filteredProps}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.spinner > div::after {
|
.spinner > div::after {
|
||||||
@apply block absolute rounded-full bg-gray-600;
|
@apply block absolute rounded-full bg-gray-700 dark:bg-gray-400;
|
||||||
content: ' ';
|
content: ' ';
|
||||||
top: 3.75%;
|
top: 3.75%;
|
||||||
left: 46.25%;
|
left: 46.25%;
|
||||||
|
|
|
@ -89,7 +89,7 @@ const Streamfield: React.FC<IStreamfield> = ({
|
||||||
icon={require('@tabler/icons/plus.svg')}
|
icon={require('@tabler/icons/plus.svg')}
|
||||||
onClick={onAddItem}
|
onClick={onAddItem}
|
||||||
disabled={values.length >= maxItems}
|
disabled={values.length >= maxItems}
|
||||||
theme='ghost'
|
theme='secondary'
|
||||||
block
|
block
|
||||||
>
|
>
|
||||||
{intl.formatMessage(messages.add)}
|
{intl.formatMessage(messages.add)}
|
||||||
|
|
|
@ -12,11 +12,11 @@
|
||||||
|
|
||||||
[data-reach-tab] {
|
[data-reach-tab] {
|
||||||
@apply flex-1 flex justify-center items-center
|
@apply flex-1 flex justify-center items-center
|
||||||
py-4 px-1 text-center font-medium text-sm text-gray-500
|
py-4 px-1 text-center font-medium text-sm text-gray-700
|
||||||
dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200
|
dark:text-gray-600 hover:text-gray-800 dark:hover:text-gray-500
|
||||||
focus:ring-primary-500 focus:ring-2;
|
focus:ring-primary-300 focus:ring-2;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-reach-tab][data-selected] {
|
[data-reach-tab][data-selected] {
|
||||||
@apply text-gray-900 dark:text-white;
|
@apply text-gray-900 dark:text-gray-100;
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,11 +45,11 @@ const AnimatedTabs: React.FC<IAnimatedInterface> = ({ children, ...rest }) => {
|
||||||
ref={ref}
|
ref={ref}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className='w-full h-[3px] bg-primary-200 dark:bg-slate-700 absolute'
|
className='w-full h-[3px] bg-primary-200 dark:bg-primary-700 absolute'
|
||||||
style={{ top }}
|
style={{ top }}
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
className={classNames('absolute h-[3px] bg-primary-600 transition-all duration-200', {
|
className={classNames('absolute h-[3px] bg-primary-500 transition-all duration-200', {
|
||||||
'hidden': top <= 0,
|
'hidden': top <= 0,
|
||||||
})}
|
})}
|
||||||
style={{ left, top, width }}
|
style={{ left, top, width }}
|
||||||
|
|
|
@ -14,8 +14,8 @@ type Directions = 'ltr' | 'rtl'
|
||||||
const themes = {
|
const themes = {
|
||||||
default: 'text-gray-900 dark:text-gray-100',
|
default: 'text-gray-900 dark:text-gray-100',
|
||||||
danger: 'text-danger-600',
|
danger: 'text-danger-600',
|
||||||
primary: 'text-primary-600 dark:text-primary-400',
|
primary: 'text-primary-600 dark:text-accent-blue',
|
||||||
muted: 'text-gray-500 dark:text-gray-300',
|
muted: 'text-gray-700 dark:text-gray-600',
|
||||||
subtle: 'text-gray-400 dark:text-gray-500',
|
subtle: 'text-gray-400 dark:text-gray-500',
|
||||||
success: 'text-success-600',
|
success: 'text-success-600',
|
||||||
inherit: 'text-inherit',
|
inherit: 'text-inherit',
|
||||||
|
@ -32,7 +32,7 @@ const weights = {
|
||||||
const sizes = {
|
const sizes = {
|
||||||
xs: 'text-xs',
|
xs: 'text-xs',
|
||||||
sm: 'text-sm',
|
sm: 'text-sm',
|
||||||
md: 'text-base',
|
md: 'text-base leading-5',
|
||||||
lg: 'text-lg',
|
lg: 'text-lg',
|
||||||
xl: 'text-xl',
|
xl: 'text-xl',
|
||||||
'2xl': 'text-2xl',
|
'2xl': 'text-2xl',
|
||||||
|
|
|
@ -28,7 +28,7 @@ const Textarea = React.forwardRef(
|
||||||
{...props}
|
{...props}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={classNames({
|
className={classNames({
|
||||||
'dark:bg-slate-800 shadow-sm focus:ring-indigo-500 focus:border-indigo-500 block w-full sm:text-sm border-gray-300 dark:border-gray-600 rounded-md':
|
'bg-white dark:bg-transparent shadow-sm block w-full sm:text-sm rounded-md text-gray-900 dark:text-gray-100 placeholder:text-gray-600 dark:placeholder:text-gray-600 border-gray-400 dark:border-gray-800 dark:ring-1 dark:ring-gray-800 focus:ring-primary-500 focus:border-primary-500 dark:focus:ring-primary-500 dark:focus:border-primary-500':
|
||||||
true,
|
true,
|
||||||
'font-mono': isCodeEditor,
|
'font-mono': isCodeEditor,
|
||||||
'text-red-600 border-red-600': hasError,
|
'text-red-600 border-red-600': hasError,
|
||||||
|
|
|
@ -3,10 +3,10 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-reach-tooltip] {
|
[data-reach-tooltip] {
|
||||||
@apply pointer-events-none absolute px-2.5 py-1.5 rounded shadow whitespace-nowrap text-xs font-medium bg-gray-800 text-white;
|
@apply pointer-events-none absolute px-2.5 py-1.5 rounded shadow whitespace-nowrap text-xs font-medium bg-gray-800 text-gray-100 dark:bg-gray-100 dark:text-gray-900;
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-reach-tooltip-arrow] {
|
[data-reach-tooltip-arrow] {
|
||||||
@apply absolute z-50 w-0 h-0 border-l-8 border-solid border-l-transparent border-r-8 border-r-transparent border-b-8 border-b-gray-800;
|
@apply absolute z-50 w-0 h-0 border-l-8 border-solid border-l-transparent border-r-8 border-r-transparent border-b-8 border-b-gray-800 dark:border-b-gray-100;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ const ValidationCheckmark = ({ isValid, text }: IValidationCheckmark) => {
|
||||||
src={isValid ? require('@tabler/icons/check.svg') : require('@tabler/icons/point.svg')}
|
src={isValid ? require('@tabler/icons/check.svg') : require('@tabler/icons/point.svg')}
|
||||||
className={classNames({
|
className={classNames({
|
||||||
'w-4 h-4': true,
|
'w-4 h-4': true,
|
||||||
'text-gray-400 fill-gray-400': !isValid,
|
'text-gray-400 dark:text-gray-600 dark:fill-gray-600 fill-gray-400': !isValid,
|
||||||
'text-success-500': isValid,
|
'text-success-500': isValid,
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -255,7 +255,7 @@ const SoapboxHead: React.FC<ISoapboxHead> = ({ children }) => {
|
||||||
const darkMode = useTheme() === 'dark';
|
const darkMode = useTheme() === 'dark';
|
||||||
const themeCss = generateThemeCss(soapboxConfig);
|
const themeCss = generateThemeCss(soapboxConfig);
|
||||||
|
|
||||||
const bodyClass = classNames('bg-white dark:bg-slate-900 text-base h-full', {
|
const bodyClass = classNames('bg-white dark:bg-gray-800 text-base h-full', {
|
||||||
'no-reduce-motion': !settings.get('reduceMotion'),
|
'no-reduce-motion': !settings.get('reduceMotion'),
|
||||||
'underline-links': settings.get('underlineLinks'),
|
'underline-links': settings.get('underlineLinks'),
|
||||||
'dyslexic': settings.get('dyslexicFont'),
|
'dyslexic': settings.get('dyslexicFont'),
|
||||||
|
|
|
@ -515,8 +515,8 @@ class Header extends ImmutablePureComponent {
|
||||||
src={require('@tabler/icons/mail.svg')}
|
src={require('@tabler/icons/mail.svg')}
|
||||||
onClick={this.props.onDirect}
|
onClick={this.props.onDirect}
|
||||||
title={intl.formatMessage(messages.direct, { name: account.get('username') })}
|
title={intl.formatMessage(messages.direct, { name: account.get('username') })}
|
||||||
className='text-primary-700 bg-primary-100 hover:bg-primary-200 p-2'
|
className='px-2 border border-solid bg-transparent border-gray-400 dark:border-gray-800 hover:border-primary-300 dark:hover:border-primary-700 focus:border-primary-500 text-gray-900 dark:text-gray-100 focus:ring-primary-500'
|
||||||
iconClassName='w-5 h-5'
|
iconClassName='w-4 h-4'
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -535,8 +535,8 @@ class Header extends ImmutablePureComponent {
|
||||||
src={require('@tabler/icons/upload.svg')}
|
src={require('@tabler/icons/upload.svg')}
|
||||||
onClick={this.handleShare}
|
onClick={this.handleShare}
|
||||||
title={intl.formatMessage(messages.share, { name: account.get('username') })}
|
title={intl.formatMessage(messages.share, { name: account.get('username') })}
|
||||||
className='text-primary-700 bg-primary-100 dark:!bg-slate-700 dark:!text-white hover:bg-primary-200 p-2'
|
className='px-2 border border-solid bg-transparent border-gray-400 dark:border-gray-800 hover:border-primary-300 dark:hover:border-primary-700 focus:border-primary-500 text-gray-900 dark:text-gray-100 focus:ring-primary-500'
|
||||||
iconClassName='w-5 h-5'
|
iconClassName='w-4 h-4'
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -548,14 +548,14 @@ class Header extends ImmutablePureComponent {
|
||||||
return (
|
return (
|
||||||
<div className='-mt-4 -mx-4'>
|
<div className='-mt-4 -mx-4'>
|
||||||
<div>
|
<div>
|
||||||
<div className='relative h-32 w-full lg:h-48 md:rounded-t-xl bg-gray-200 dark:bg-slate-900/50' />
|
<div className='relative h-32 w-full lg:h-48 md:rounded-t-xl bg-gray-200 dark:bg-gray-900/50' />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='px-4 sm:px-6'>
|
<div className='px-4 sm:px-6'>
|
||||||
<div className='-mt-12 flex items-end space-x-5'>
|
<div className='-mt-12 flex items-end space-x-5'>
|
||||||
<div className='flex relative'>
|
<div className='flex relative'>
|
||||||
<div
|
<div
|
||||||
className='h-24 w-24 bg-gray-400 rounded-full ring-4 ring-white dark:ring-slate-800'
|
className='h-24 w-24 bg-gray-400 rounded-full ring-4 ring-white dark:ring-gray-800'
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -571,7 +571,7 @@ class Header extends ImmutablePureComponent {
|
||||||
return (
|
return (
|
||||||
<div className='-mt-4 -mx-4'>
|
<div className='-mt-4 -mx-4'>
|
||||||
<div>
|
<div>
|
||||||
<div className='relative h-32 w-full lg:h-48 md:rounded-t-xl bg-gray-200 dark:bg-slate-900/50'>
|
<div className='relative h-32 w-full lg:h-48 md:rounded-t-xl bg-gray-200 dark:bg-gray-900/50'>
|
||||||
{header && (
|
{header && (
|
||||||
<a href={account.get('header')} onClick={this.handleHeaderClick} target='_blank'>
|
<a href={account.get('header')} onClick={this.handleHeaderClick} target='_blank'>
|
||||||
<StillImage
|
<StillImage
|
||||||
|
@ -596,7 +596,7 @@ class Header extends ImmutablePureComponent {
|
||||||
<a href={account.get('avatar')} onClick={this.handleAvatarClick} target='_blank'>
|
<a href={account.get('avatar')} onClick={this.handleAvatarClick} target='_blank'>
|
||||||
<Avatar
|
<Avatar
|
||||||
account={account}
|
account={account}
|
||||||
className='h-24 w-24 rounded-full ring-4 ring-white dark:ring-slate-800'
|
className='h-24 w-24 rounded-full ring-4 ring-white dark:ring-primary-900'
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -610,8 +610,8 @@ class Header extends ImmutablePureComponent {
|
||||||
<MenuButton
|
<MenuButton
|
||||||
as={IconButton}
|
as={IconButton}
|
||||||
src={require('@tabler/icons/dots.svg')}
|
src={require('@tabler/icons/dots.svg')}
|
||||||
className='text-primary-700 bg-primary-100 dark:!bg-slate-700 dark:!text-white hover:bg-primary-200 p-2'
|
className='px-2 border border-solid bg-transparent border-gray-400 dark:border-gray-800 hover:border-primary-300 dark:hover:border-primary-700 focus:border-primary-500 text-gray-900 dark:text-gray-100 focus:ring-primary-500'
|
||||||
iconClassName='w-5 h-5'
|
iconClassName='w-4 h-4'
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<MenuList>
|
<MenuList>
|
||||||
|
|
|
@ -2,10 +2,9 @@ import React from 'react';
|
||||||
import { defineMessages, useIntl } from 'react-intl';
|
import { defineMessages, useIntl } from 'react-intl';
|
||||||
import { Switch, Route } from 'react-router-dom';
|
import { Switch, Route } from 'react-router-dom';
|
||||||
|
|
||||||
|
import { Column } from 'soapbox/components/ui';
|
||||||
import { useOwnAccount } from 'soapbox/hooks';
|
import { useOwnAccount } from 'soapbox/hooks';
|
||||||
|
|
||||||
import Column from '../ui/components/column';
|
|
||||||
|
|
||||||
import AdminTabs from './components/admin-tabs';
|
import AdminTabs from './components/admin-tabs';
|
||||||
import Waitlist from './tabs/awaiting-approval';
|
import Waitlist from './tabs/awaiting-approval';
|
||||||
import Dashboard from './tabs/dashboard';
|
import Dashboard from './tabs/dashboard';
|
||||||
|
|
|
@ -45,7 +45,7 @@ const Search: React.FC = () => {
|
||||||
<span style={{ display: 'none' }}>{intl.formatMessage(messages.search)}</span>
|
<span style={{ display: 'none' }}>{intl.formatMessage(messages.search)}</span>
|
||||||
|
|
||||||
<input
|
<input
|
||||||
className='block w-full sm:text-sm dark:bg-slate-800 dark:text-white dark:placeholder:text-gray-500 focus:ring-indigo-500 focus:border-indigo-500 rounded-full'
|
className='block w-full sm:text-sm dark:bg-gray-800 dark:text-white dark:placeholder:text-gray-500 focus:ring-primary-500 focus:border-primary-500 rounded-full'
|
||||||
type='text'
|
type='text'
|
||||||
value={value}
|
value={value}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
|
|
|
@ -54,7 +54,7 @@ const AuthLayout = () => {
|
||||||
{shouldShowRegisterLink && (
|
{shouldShowRegisterLink && (
|
||||||
<div className='relative z-10 ml-auto flex items-center'>
|
<div className='relative z-10 ml-auto flex items-center'>
|
||||||
<Button
|
<Button
|
||||||
theme='link'
|
theme='tertiary'
|
||||||
icon={require('@tabler/icons/user.svg')}
|
icon={require('@tabler/icons/user.svg')}
|
||||||
to='/signup'
|
to='/signup'
|
||||||
>
|
>
|
||||||
|
|
|
@ -25,7 +25,7 @@ const LoginForm: React.FC<ILoginForm> = ({ isLoading, handleSubmit }) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className='pb-4 sm:pb-10 mb-4 border-b border-gray-200 dark:border-gray-600 border-solid -mx-4 sm:-mx-10'>
|
<div className='pb-4 sm:pb-10 mb-4 border-b border-gray-200 dark:border-gray-800 border-solid -mx-4 sm:-mx-10'>
|
||||||
<h1 className='text-center font-bold text-2xl'><FormattedMessage id='login_form.header' defaultMessage='Sign In' /></h1>
|
<h1 className='text-center font-bold text-2xl'><FormattedMessage id='login_form.header' defaultMessage='Sign In' /></h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ const AuthToken: React.FC<IAuthToken> = ({ token }) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='p-4 rounded-lg bg-gray-100 dark:bg-slate-700'>
|
<div className='p-4 rounded-lg bg-gray-100 dark:bg-gray-700'>
|
||||||
<Stack space={2}>
|
<Stack space={2}>
|
||||||
<Stack>
|
<Stack>
|
||||||
<Text size='md' weight='medium'>{token.app_name}</Text>
|
<Text size='md' weight='medium'>{token.app_name}</Text>
|
||||||
|
|
|
@ -21,7 +21,12 @@ const ComposeFormButton: React.FC<IComposeFormButton> = ({
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<IconButton
|
<IconButton
|
||||||
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 })}
|
className={
|
||||||
|
classNames({
|
||||||
|
'text-gray-600 hover:text-gray-700 dark:hover:text-gray-500': !active,
|
||||||
|
'text-primary-500 hover:text-primary-600 dark:text-primary-500 dark:hover:text-primary-400': active,
|
||||||
|
})
|
||||||
|
}
|
||||||
src={icon}
|
src={icon}
|
||||||
title={title}
|
title={title}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
|
|
@ -371,7 +371,7 @@ class EmojiPickerDropdown extends React.PureComponent {
|
||||||
>
|
>
|
||||||
{button || <IconButton
|
{button || <IconButton
|
||||||
className={classNames({
|
className={classNames({
|
||||||
'text-gray-400 hover:text-gray-600': true,
|
'text-gray-600 hover:text-gray-700 dark:hover:text-gray-500': true,
|
||||||
'pulse-loading': active && loading,
|
'pulse-loading': active && loading,
|
||||||
})}
|
})}
|
||||||
alt='😀'
|
alt='😀'
|
||||||
|
|
|
@ -79,7 +79,7 @@ const Option = (props: IOption) => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<AutosuggestInput
|
<AutosuggestInput
|
||||||
className='rounded-md'
|
className='rounded-md dark:!bg-transparent !bg-transparent'
|
||||||
placeholder={intl.formatMessage(messages.option_placeholder, { number: index + 1 })}
|
placeholder={intl.formatMessage(messages.option_placeholder, { number: index + 1 })}
|
||||||
maxLength={maxChars}
|
maxLength={maxChars}
|
||||||
value={title}
|
value={title}
|
||||||
|
@ -190,9 +190,9 @@ const PollForm = () => {
|
||||||
|
|
||||||
{/* Remove Poll */}
|
{/* Remove Poll */}
|
||||||
<div className='text-center'>
|
<div className='text-center'>
|
||||||
<Button theme='danger-link' onClick={onRemovePoll}>
|
<button className='text-danger-500' onClick={onRemovePoll}>
|
||||||
{intl.formatMessage(messages.removePoll)}
|
{intl.formatMessage(messages.removePoll)}
|
||||||
</Button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
|
|
|
@ -237,7 +237,7 @@ const PrivacyDropdown: React.FC<IPrivacyDropdown> = ({
|
||||||
<div className={classNames('privacy-dropdown', placement, { active: open })} onKeyDown={handleKeyDown} ref={node}>
|
<div className={classNames('privacy-dropdown', placement, { active: open })} onKeyDown={handleKeyDown} ref={node}>
|
||||||
<div className={classNames('privacy-dropdown__value', { active: valueOption && options.indexOf(valueOption) === 0 })}>
|
<div className={classNames('privacy-dropdown__value', { active: valueOption && options.indexOf(valueOption) === 0 })}>
|
||||||
<IconButton
|
<IconButton
|
||||||
className='text-gray-400 hover:text-gray-600'
|
className='text-gray-600 hover:text-gray-700 dark:hover:text-gray-500'
|
||||||
src={valueOption?.icon}
|
src={valueOption?.icon}
|
||||||
title={intl.formatMessage(messages.change_privacy)}
|
title={intl.formatMessage(messages.change_privacy)}
|
||||||
onClick={handleToggle}
|
onClick={handleToggle}
|
||||||
|
|
|
@ -33,7 +33,7 @@ const ReplyIndicator: React.FC<IReplyIndicator> = ({ status, hideActions, onCanc
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack space={2} className='p-4 rounded-lg bg-gray-100 dark:bg-slate-700'>
|
<Stack space={2} className='p-4 rounded-lg bg-gray-100 dark:bg-gray-800'>
|
||||||
<AccountContainer
|
<AccountContainer
|
||||||
{...actions}
|
{...actions}
|
||||||
id={status.getIn(['account', 'id']) as string}
|
id={status.getIn(['account', 'id']) as string}
|
||||||
|
|
|
@ -119,7 +119,7 @@ const Search = (props: ISearch) => {
|
||||||
|
|
||||||
<div className='relative'>
|
<div className='relative'>
|
||||||
<Component
|
<Component
|
||||||
className='block w-full pl-3 pr-10 py-2 border border-gray-100 dark:border-slate-600 rounded-full leading-5 bg-gray-100 dark:text-white placeholder-gray-500 dark:placeholder-gray-300 dark:bg-slate-900 focus:bg-white focus:outline-none focus:placeholder-gray-400 focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm'
|
className='block w-full pl-3 pr-10 py-2 border border-gray-200 dark:border-gray-800 rounded-full leading-5 bg-gray-200 dark:bg-gray-800 dark:text-white placeholder:text-gray-600 dark:placeholder:text-gray-600 focus:outline-none focus:ring-2 focus:ring-primary-500 sm:text-sm'
|
||||||
type='text'
|
type='text'
|
||||||
id='search'
|
id='search'
|
||||||
placeholder={intl.formatMessage(messages.placeholder)}
|
placeholder={intl.formatMessage(messages.placeholder)}
|
||||||
|
@ -141,12 +141,12 @@ const Search = (props: ISearch) => {
|
||||||
>
|
>
|
||||||
<SvgIcon
|
<SvgIcon
|
||||||
src={require('@tabler/icons/search.svg')}
|
src={require('@tabler/icons/search.svg')}
|
||||||
className={classNames('h-4 w-4 text-gray-400', { hidden: hasValue })}
|
className={classNames('h-4 w-4 text-gray-600', { hidden: hasValue })}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<SvgIcon
|
<SvgIcon
|
||||||
src={require('@tabler/icons/x.svg')}
|
src={require('@tabler/icons/x.svg')}
|
||||||
className={classNames('h-4 w-4 text-gray-400', { hidden: !hasValue })}
|
className={classNames('h-4 w-4 text-gray-600', { hidden: !hasValue })}
|
||||||
aria-label={intl.formatMessage(messages.placeholder)}
|
aria-label={intl.formatMessage(messages.placeholder)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -204,7 +204,7 @@ const SearchResults = () => {
|
||||||
placeholderComponent={placeholderComponent}
|
placeholderComponent={placeholderComponent}
|
||||||
placeholderCount={20}
|
placeholderCount={20}
|
||||||
className={classNames({
|
className={classNames({
|
||||||
'divide-gray-200 dark:divide-slate-700 divide-solid divide-y': selectedFilter === 'statuses',
|
'divide-gray-200 dark:divide-gray-800 divide-solid divide-y': selectedFilter === 'statuses',
|
||||||
})}
|
})}
|
||||||
itemClassName={classNames({
|
itemClassName={classNames({
|
||||||
'pb-4': selectedFilter === 'accounts',
|
'pb-4': selectedFilter === 'accounts',
|
||||||
|
|
|
@ -11,9 +11,9 @@ const TextCharacterCounter: React.FC<ITextCharacterCounter> = ({ text, max }) =>
|
||||||
const checkRemainingText = (diff: number) => {
|
const checkRemainingText = (diff: number) => {
|
||||||
return (
|
return (
|
||||||
<span
|
<span
|
||||||
className={classNames('text-sm font-semibold', {
|
className={classNames('text-sm font-medium', {
|
||||||
'text-gray-400': diff >= 0,
|
'text-gray-700': diff >= 0,
|
||||||
'text-danger-600': diff < 0,
|
'text-secondary-600': diff < 0,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
{diff}
|
{diff}
|
||||||
|
|
|
@ -55,7 +55,7 @@ const UploadButton: React.FC<IUploadButton> = ({
|
||||||
<div>
|
<div>
|
||||||
<IconButton
|
<IconButton
|
||||||
src={src}
|
src={src}
|
||||||
className='text-gray-400 hover:text-gray-600'
|
className='text-gray-600 hover:text-gray-700 dark:hover:text-gray-500'
|
||||||
title={intl.formatMessage(messages.upload)}
|
title={intl.formatMessage(messages.upload)}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { defineMessages, useIntl } from 'react-intl';
|
||||||
|
|
||||||
import { deleteAccount } from 'soapbox/actions/security';
|
import { deleteAccount } from 'soapbox/actions/security';
|
||||||
import snackbar from 'soapbox/actions/snackbar';
|
import snackbar from 'soapbox/actions/snackbar';
|
||||||
import { Button, Card, CardBody, CardHeader, CardTitle, Form, FormActions, FormGroup, Input } from 'soapbox/components/ui';
|
import { Button, Card, CardBody, CardHeader, CardTitle, Form, FormActions, FormGroup, Input, Stack, Text } from 'soapbox/components/ui';
|
||||||
import { useAppDispatch, useFeatures } from 'soapbox/hooks';
|
import { useAppDispatch, useFeatures } from 'soapbox/hooks';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
|
@ -50,9 +50,11 @@ const DeleteAccount = () => {
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
|
|
||||||
<CardBody>
|
<CardBody>
|
||||||
<p className='text-gray-400 mb-4'>
|
<Stack space={4}>
|
||||||
|
<Text theme='muted'>
|
||||||
|
|
||||||
{intl.formatMessage(features.federating ? messages.deleteText : messages.localDeleteText)}
|
{intl.formatMessage(features.federating ? messages.deleteText : messages.localDeleteText)}
|
||||||
</p>
|
</Text>
|
||||||
|
|
||||||
<Form onSubmit={handleSubmit}>
|
<Form onSubmit={handleSubmit}>
|
||||||
<FormGroup labelText={intl.formatMessage(messages.passwordFieldLabel)}>
|
<FormGroup labelText={intl.formatMessage(messages.passwordFieldLabel)}>
|
||||||
|
@ -71,6 +73,7 @@ const DeleteAccount = () => {
|
||||||
|
|
||||||
</FormActions>
|
</FormActions>
|
||||||
</Form>
|
</Form>
|
||||||
|
</Stack>
|
||||||
</CardBody>
|
</CardBody>
|
||||||
</Card >
|
</Card >
|
||||||
);
|
);
|
||||||
|
|
|
@ -49,7 +49,8 @@ const DevelopersChallenge = () => {
|
||||||
values={{ function: <span className='font-mono'>soapbox()</span> }}
|
values={{ function: <span className='font-mono'>soapbox()</span> }}
|
||||||
/>
|
/>
|
||||||
</Text>
|
</Text>
|
||||||
<Text tag='pre' family='mono'>
|
|
||||||
|
<Text tag='pre' family='mono' theme='muted'>
|
||||||
{challenge}
|
{challenge}
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ interface IDashWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
const DashWidget: React.FC<IDashWidget> = ({ to, onClick, children }) => {
|
const DashWidget: React.FC<IDashWidget> = ({ to, onClick, children }) => {
|
||||||
const className = 'bg-gray-200 dark:bg-gray-600 p-4 rounded flex flex-col items-center justify-center space-y-2 hover:-translate-y-1 transition-transform';
|
const className = 'bg-gray-200 dark:bg-gray-800 hover:bg-gray-300 dark:hover:bg-gray-800/75 p-4 rounded flex flex-col items-center justify-center space-y-2';
|
||||||
|
|
||||||
if (to) {
|
if (to) {
|
||||||
return <Link className={className} to={to}>{children}</Link>;
|
return <Link className={className} to={to}>{children}</Link>;
|
||||||
|
@ -50,7 +50,7 @@ const Developers: React.FC = () => {
|
||||||
<Column label={intl.formatMessage(messages.heading)}>
|
<Column label={intl.formatMessage(messages.heading)}>
|
||||||
<div className='grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-2'>
|
<div className='grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-2'>
|
||||||
<DashWidget to='/developers/apps/create'>
|
<DashWidget to='/developers/apps/create'>
|
||||||
<SvgIcon src={require('@tabler/icons/apps.svg')} className='dark:text-gray-100' />
|
<SvgIcon src={require('@tabler/icons/apps.svg')} className='text-gray-700 dark:text-gray-600' />
|
||||||
|
|
||||||
<Text>
|
<Text>
|
||||||
<FormattedMessage id='developers.navigation.app_create_label' defaultMessage='Create an app' />
|
<FormattedMessage id='developers.navigation.app_create_label' defaultMessage='Create an app' />
|
||||||
|
@ -58,7 +58,7 @@ const Developers: React.FC = () => {
|
||||||
</DashWidget>
|
</DashWidget>
|
||||||
|
|
||||||
<DashWidget to='/developers/settings_store'>
|
<DashWidget to='/developers/settings_store'>
|
||||||
<SvgIcon src={require('@tabler/icons/code-plus.svg')} className='dark:text-gray-100' />
|
<SvgIcon src={require('@tabler/icons/code-plus.svg')} className='text-gray-700 dark:text-gray-600' />
|
||||||
|
|
||||||
<Text>
|
<Text>
|
||||||
<FormattedMessage id='developers.navigation.settings_store_label' defaultMessage='Settings store' />
|
<FormattedMessage id='developers.navigation.settings_store_label' defaultMessage='Settings store' />
|
||||||
|
@ -66,7 +66,7 @@ const Developers: React.FC = () => {
|
||||||
</DashWidget>
|
</DashWidget>
|
||||||
|
|
||||||
<DashWidget to='/developers/timeline'>
|
<DashWidget to='/developers/timeline'>
|
||||||
<SvgIcon src={require('@tabler/icons/home.svg')} className='dark:text-gray-100' />
|
<SvgIcon src={require('@tabler/icons/home.svg')} className='text-gray-700 dark:text-gray-600' />
|
||||||
|
|
||||||
<Text>
|
<Text>
|
||||||
<FormattedMessage id='developers.navigation.test_timeline_label' defaultMessage='Test timeline' />
|
<FormattedMessage id='developers.navigation.test_timeline_label' defaultMessage='Test timeline' />
|
||||||
|
@ -74,7 +74,7 @@ const Developers: React.FC = () => {
|
||||||
</DashWidget>
|
</DashWidget>
|
||||||
|
|
||||||
<DashWidget to='/error'>
|
<DashWidget to='/error'>
|
||||||
<SvgIcon src={require('@tabler/icons/mood-sad.svg')} className='dark:text-gray-100' />
|
<SvgIcon src={require('@tabler/icons/mood-sad.svg')} className='text-gray-700 dark:text-gray-600' />
|
||||||
|
|
||||||
<Text>
|
<Text>
|
||||||
<FormattedMessage id='developers.navigation.intentional_error_label' defaultMessage='Trigger an error' />
|
<FormattedMessage id='developers.navigation.intentional_error_label' defaultMessage='Trigger an error' />
|
||||||
|
@ -82,7 +82,7 @@ const Developers: React.FC = () => {
|
||||||
</DashWidget>
|
</DashWidget>
|
||||||
|
|
||||||
<DashWidget to='/error/network'>
|
<DashWidget to='/error/network'>
|
||||||
<SvgIcon src={require('@tabler/icons/refresh.svg')} className='dark:text-gray-100' />
|
<SvgIcon src={require('@tabler/icons/refresh.svg')} className='text-gray-700 dark:text-gray-600' />
|
||||||
|
|
||||||
<Text>
|
<Text>
|
||||||
<FormattedMessage id='developers.navigation.network_error_label' defaultMessage='Network error' />
|
<FormattedMessage id='developers.navigation.network_error_label' defaultMessage='Network error' />
|
||||||
|
@ -90,7 +90,7 @@ const Developers: React.FC = () => {
|
||||||
</DashWidget>
|
</DashWidget>
|
||||||
|
|
||||||
<DashWidget onClick={leaveDevelopers}>
|
<DashWidget onClick={leaveDevelopers}>
|
||||||
<SvgIcon src={require('@tabler/icons/logout.svg')} className='dark:text-gray-100' />
|
<SvgIcon src={require('@tabler/icons/logout.svg')} className='text-gray-700 dark:text-gray-600' />
|
||||||
|
|
||||||
<Text>
|
<Text>
|
||||||
<FormattedMessage id='developers.navigation.leave_developers_label' defaultMessage='Leave developers' />
|
<FormattedMessage id='developers.navigation.leave_developers_label' defaultMessage='Leave developers' />
|
||||||
|
|
|
@ -83,7 +83,7 @@ const EditEmail = () => {
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
|
|
||||||
<FormActions>
|
<FormActions>
|
||||||
<Button to='/settings' theme='ghost'>{intl.formatMessage(messages.cancel)}</Button>
|
<Button to='/settings' theme='tertiary'>{intl.formatMessage(messages.cancel)}</Button>
|
||||||
<Button type='submit' theme='primary' disabled={isLoading}>{intl.formatMessage(messages.submit)}</Button>
|
<Button type='submit' theme='primary' disabled={isLoading}>{intl.formatMessage(messages.submit)}</Button>
|
||||||
</FormActions>
|
</FormActions>
|
||||||
</Form>
|
</Form>
|
||||||
|
|
|
@ -95,7 +95,7 @@ const EditPassword = () => {
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
|
|
||||||
<FormActions>
|
<FormActions>
|
||||||
<Button to='/settings' theme='ghost'>
|
<Button to='/settings' theme='tertiary'>
|
||||||
{intl.formatMessage(messages.cancel)}
|
{intl.formatMessage(messages.cancel)}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
|
|
|
@ -16,9 +16,9 @@ const ProfilePreview: React.FC<IProfilePreview> = ({ account }) => {
|
||||||
const { displayFqn } = useSoapboxConfig();
|
const { displayFqn } = useSoapboxConfig();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='bg-white dark:bg-slate-800 rounded-lg text-black dark:text-white sm:shadow dark:sm:shadow-inset overflow-hidden'>
|
<div className='bg-white dark:bg-gray-800 rounded-lg text-black dark:text-white sm:shadow dark:sm:shadow-inset overflow-hidden'>
|
||||||
<div>
|
<div>
|
||||||
<div className='relative w-full h-32 md:rounded-t-lg bg-gray-200 dark:bg-slate-900/50'>
|
<div className='relative w-full h-32 md:rounded-t-lg bg-gray-200 dark:bg-gray-900/50'>
|
||||||
<StillImage alt='' src={account.header} className='absolute inset-0 object-cover md:rounded-t-lg' />
|
<StillImage alt='' src={account.header} className='absolute inset-0 object-cover md:rounded-t-lg' />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -368,19 +368,19 @@ const EditProfile: React.FC = () => {
|
||||||
<ProfilePreview account={previewAccount} />
|
<ProfilePreview account={previewAccount} />
|
||||||
|
|
||||||
<div className='space-y-4'>
|
<div className='space-y-4'>
|
||||||
<FormGroup
|
|
||||||
labelText={<FormattedMessage id='edit_profile.fields.header_label' defaultMessage='Choose Background Picture' />}
|
|
||||||
hintText={<FormattedMessage id='edit_profile.hints.header' defaultMessage='PNG, GIF or JPG. Will be downscaled to {size}' values={{ size: '1920x1080px' }} />}
|
|
||||||
>
|
|
||||||
<FileInput onChange={handleFileChange('header', 1920 * 1080)} />
|
|
||||||
</FormGroup>
|
|
||||||
|
|
||||||
<FormGroup
|
<FormGroup
|
||||||
labelText={<FormattedMessage id='edit_profile.fields.avatar_label' defaultMessage='Choose Profile Picture' />}
|
labelText={<FormattedMessage id='edit_profile.fields.avatar_label' defaultMessage='Choose Profile Picture' />}
|
||||||
hintText={<FormattedMessage id='edit_profile.hints.avatar' defaultMessage='PNG, GIF or JPG. Will be downscaled to {size}' values={{ size: '400x400px' }} />}
|
hintText={<FormattedMessage id='edit_profile.hints.avatar' defaultMessage='PNG, GIF or JPG. Will be downscaled to {size}' values={{ size: '400x400px' }} />}
|
||||||
>
|
>
|
||||||
<FileInput onChange={handleFileChange('avatar', 400 * 400)} />
|
<FileInput onChange={handleFileChange('avatar', 400 * 400)} />
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
|
|
||||||
|
<FormGroup
|
||||||
|
labelText={<FormattedMessage id='edit_profile.fields.header_label' defaultMessage='Choose Background Picture' />}
|
||||||
|
hintText={<FormattedMessage id='edit_profile.hints.header' defaultMessage='PNG, GIF or JPG. Will be downscaled to {size}' values={{ size: '1920x1080px' }} />}
|
||||||
|
>
|
||||||
|
<FileInput onChange={handleFileChange('header', 1920 * 1080)} />
|
||||||
|
</FormGroup>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -472,7 +472,7 @@ const EditProfile: React.FC = () => {
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<FormActions>
|
<FormActions>
|
||||||
<Button to='/settings' theme='ghost'>
|
<Button to='/settings' theme='tertiary'>
|
||||||
{intl.formatMessage(messages.cancel)}
|
{intl.formatMessage(messages.cancel)}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,7 @@ const CarouselItem = ({ avatar }: { avatar: any }) => {
|
||||||
<img
|
<img
|
||||||
src={avatar.account_avatar}
|
src={avatar.account_avatar}
|
||||||
className={classNames({
|
className={classNames({
|
||||||
'w-14 h-14 min-w-[56px] rounded-full ring-2 ring-offset-4 dark:ring-offset-slate-800': true,
|
'w-14 h-14 min-w-[56px] rounded-full ring-2 ring-offset-4 dark:ring-offset-primary-900': true,
|
||||||
'ring-transparent': !isSelected,
|
'ring-transparent': !isSelected,
|
||||||
'ring-primary-600': isSelected,
|
'ring-primary-600': isSelected,
|
||||||
})}
|
})}
|
||||||
|
|
|
@ -19,7 +19,7 @@ const SuggestionItem = ({ accountId }: { accountId: string }) => {
|
||||||
const account = useAccount(accountId) as Account;
|
const account = useAccount(accountId) as Account;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack space={3} className='p-4 md:p-0 rounded-md border border-solid border-gray-100 dark:border-slate-700 dark:md:border-transparent md:border-transparent w-52 shrink-0 md:shrink md:w-full'>
|
<Stack space={3} className='p-4 md:p-0 rounded-md border border-solid border-gray-300 dark:border-gray-800 dark:md:border-transparent md:border-transparent w-52 shrink-0 md:shrink md:w-full'>
|
||||||
<Link
|
<Link
|
||||||
to={`/@${account.acct}`}
|
to={`/@${account.acct}`}
|
||||||
title={account.acct}
|
title={account.acct}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import { useAppSelector } from 'soapbox/hooks';
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
label: { id: 'lists.new.title_placeholder', defaultMessage: 'New list title' },
|
label: { id: 'lists.new.title_placeholder', defaultMessage: 'New list title' },
|
||||||
title: { id: 'lists.new.create', defaultMessage: 'Add list' },
|
title: { id: 'lists.new.create', defaultMessage: 'Add list' },
|
||||||
create: { id: 'lists.new.create_title', defaultMessage: 'Create' },
|
create: { id: 'lists.new.create_title', defaultMessage: 'Add list' },
|
||||||
});
|
});
|
||||||
|
|
||||||
const NewListForm: React.FC = () => {
|
const NewListForm: React.FC = () => {
|
||||||
|
@ -49,6 +49,7 @@ const NewListForm: React.FC = () => {
|
||||||
<Button
|
<Button
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
onClick={handleSubmit}
|
onClick={handleSubmit}
|
||||||
|
theme='primary'
|
||||||
>
|
>
|
||||||
{create}
|
{create}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
@ -8,11 +8,9 @@ import { deleteList, fetchLists } from 'soapbox/actions/lists';
|
||||||
import { openModal } from 'soapbox/actions/modals';
|
import { openModal } from 'soapbox/actions/modals';
|
||||||
import Icon from 'soapbox/components/icon';
|
import Icon from 'soapbox/components/icon';
|
||||||
import ScrollableList from 'soapbox/components/scrollable_list';
|
import ScrollableList from 'soapbox/components/scrollable_list';
|
||||||
import { CardHeader, CardTitle, IconButton, Spinner } from 'soapbox/components/ui';
|
import { Column, IconButton, Spinner } from 'soapbox/components/ui';
|
||||||
import { useAppSelector } from 'soapbox/hooks';
|
import { useAppSelector } from 'soapbox/hooks';
|
||||||
|
|
||||||
import Column from '../ui/components/column';
|
|
||||||
|
|
||||||
import NewListForm from './components/new_list_form';
|
import NewListForm from './components/new_list_form';
|
||||||
|
|
||||||
import type { RootState } from 'soapbox/store';
|
import type { RootState } from 'soapbox/store';
|
||||||
|
@ -76,32 +74,27 @@ const Lists: React.FC = () => {
|
||||||
const emptyMessage = <FormattedMessage id='empty_column.lists' defaultMessage="You don't have any lists yet. When you create one, it will show up here." />;
|
const emptyMessage = <FormattedMessage id='empty_column.lists' defaultMessage="You don't have any lists yet. When you create one, it will show up here." />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column icon='list-ul' label={intl.formatMessage(messages.heading)}>
|
<Column label={intl.formatMessage(messages.heading)}>
|
||||||
<br />
|
<div className='space-y-4'>
|
||||||
<CardHeader>
|
|
||||||
<CardTitle title={intl.formatMessage(messages.add)} />
|
|
||||||
</CardHeader>
|
|
||||||
<NewListForm />
|
<NewListForm />
|
||||||
<br />
|
|
||||||
<CardHeader>
|
|
||||||
<CardTitle title={intl.formatMessage(messages.subheading)} />
|
|
||||||
</CardHeader>
|
|
||||||
<ScrollableList
|
<ScrollableList
|
||||||
scrollKey='lists'
|
scrollKey='lists'
|
||||||
emptyMessage={emptyMessage}
|
emptyMessage={emptyMessage}
|
||||||
itemClassName='py-2'
|
itemClassName='py-2'
|
||||||
>
|
>
|
||||||
{lists.map((list: any) => (
|
{lists.map((list: any) => (
|
||||||
<Link key={list.id} to={`/list/${list.id}`} className='flex items-center gap-1.5 p-2 text-black dark:text-white hover:bg-gray-100 dark:hover:bg-slate-700 rounded-lg'>
|
<Link key={list.id} to={`/list/${list.id}`} className='flex items-center gap-1.5 p-2 text-gray-900 dark:text-gray-100 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-lg'>
|
||||||
<Icon src={require('@tabler/icons/list.svg')} fixedWidth />
|
<Icon src={require('@tabler/icons/list.svg')} fixedWidth />
|
||||||
<span className='flex-grow'>
|
<span className='flex-grow'>
|
||||||
{list.title}
|
{list.title}
|
||||||
</span>
|
</span>
|
||||||
<IconButton iconClassName='h-5 w-5' src={require('@tabler/icons/pencil.svg')} onClick={handleEditClick(list.id)} title={intl.formatMessage(messages.editList)} />
|
<IconButton iconClassName='h-5 w-5 text-gray-700 dark:text-gray-600 hover:text-gray-800 dark:hover:text-gray-500' src={require('@tabler/icons/pencil.svg')} onClick={handleEditClick(list.id)} title={intl.formatMessage(messages.editList)} />
|
||||||
<IconButton iconClassName='h-5 w-5' src={require('@tabler/icons/trash.svg')} onClick={handleDeleteClick(list.id)} title={intl.formatMessage(messages.deleteList)} />
|
<IconButton iconClassName='h-5 w-5 text-gray-700 dark:text-gray-600 hover:text-gray-800 dark:hover:text-gray-500' src={require('@tabler/icons/trash.svg')} onClick={handleDeleteClick(list.id)} title={intl.formatMessage(messages.deleteList)} />
|
||||||
</Link>
|
</Link>
|
||||||
))}
|
))}
|
||||||
</ScrollableList>
|
</ScrollableList>
|
||||||
|
</div>
|
||||||
</Column>
|
</Column>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -165,7 +165,7 @@ const Notifications = () => {
|
||||||
onScrollToTop={handleScrollToTop}
|
onScrollToTop={handleScrollToTop}
|
||||||
onScroll={handleScroll}
|
onScroll={handleScroll}
|
||||||
className={classNames({
|
className={classNames({
|
||||||
'divide-y divide-gray-200 dark:divide-gray-600 divide-solid': notifications.size > 0,
|
'divide-y divide-gray-200 dark:divide-primary-800 divide-solid': notifications.size > 0,
|
||||||
'space-y-2': notifications.size === 0,
|
'space-y-2': notifications.size === 0,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
|
|
|
@ -97,7 +97,7 @@ const OnboardingWizard = () => {
|
||||||
onClick={() => handleDotClick(i)}
|
onClick={() => handleDotClick(i)}
|
||||||
className={classNames({
|
className={classNames({
|
||||||
'w-5 h-5 rounded-full focus:ring-primary-600 focus:ring-2 focus:ring-offset-2': true,
|
'w-5 h-5 rounded-full focus:ring-primary-600 focus:ring-2 focus:ring-offset-2': true,
|
||||||
'bg-gray-200 hover:bg-gray-300': i !== currentStep,
|
'bg-gray-300 dark:bg-gray-700 dark:hover:bg-gray-700/75 hover:bg-gray-400': i !== currentStep,
|
||||||
'bg-primary-600': i === currentStep,
|
'bg-primary-600': i === currentStep,
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -74,7 +74,7 @@ const AvatarSelectionStep = ({ onNext }: { onNext: () => void }) => {
|
||||||
<Card variant='rounded' size='xl'>
|
<Card variant='rounded' size='xl'>
|
||||||
<CardBody>
|
<CardBody>
|
||||||
<div>
|
<div>
|
||||||
<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'>
|
<div className='pb-4 sm:pb-10 mb-4 border-b border-gray-200 dark:border-gray-900/50 border-solid -mx-4 sm:-mx-10'>
|
||||||
<Stack space={2}>
|
<Stack space={2}>
|
||||||
<Text size='2xl' align='center' weight='bold'>
|
<Text size='2xl' align='center' weight='bold'>
|
||||||
<FormattedMessage id='onboarding.avatar.title' defaultMessage='Choose a profile picture' />
|
<FormattedMessage id='onboarding.avatar.title' defaultMessage='Choose a profile picture' />
|
||||||
|
@ -94,7 +94,7 @@ const AvatarSelectionStep = ({ onNext }: { onNext: () => void }) => {
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{isSubmitting && (
|
{isSubmitting && (
|
||||||
<div className='absolute inset-0 rounded-full flex justify-center items-center bg-white/80'>
|
<div className='absolute inset-0 rounded-full flex justify-center items-center bg-white/80 dark:bg-primary-900/80'>
|
||||||
<Spinner withText={false} />
|
<Spinner withText={false} />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
@ -103,7 +103,7 @@ const AvatarSelectionStep = ({ onNext }: { onNext: () => void }) => {
|
||||||
onClick={openFilePicker}
|
onClick={openFilePicker}
|
||||||
type='button'
|
type='button'
|
||||||
className={classNames({
|
className={classNames({
|
||||||
'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,
|
'absolute bottom-3 right-2 p-1 bg-primary-600 rounded-full ring-2 ring-white dark:ring-primary-900 hover:bg-primary-700': true,
|
||||||
'opacity-50 pointer-events-none': isSubmitting,
|
'opacity-50 pointer-events-none': isSubmitting,
|
||||||
})}
|
})}
|
||||||
disabled={isSubmitting}
|
disabled={isSubmitting}
|
||||||
|
@ -124,7 +124,7 @@ const AvatarSelectionStep = ({ onNext }: { onNext: () => void }) => {
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
{isDisabled && (
|
{isDisabled && (
|
||||||
<Button block theme='link' type='button' onClick={onNext}>
|
<Button block theme='tertiary' type='button' onClick={onNext}>
|
||||||
<FormattedMessage id='onboarding.skip' defaultMessage='Skip for now' />
|
<FormattedMessage id='onboarding.skip' defaultMessage='Skip for now' />
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -45,7 +45,7 @@ const BioStep = ({ onNext }: { onNext: () => void }) => {
|
||||||
<Card variant='rounded' size='xl'>
|
<Card variant='rounded' size='xl'>
|
||||||
<CardBody>
|
<CardBody>
|
||||||
<div>
|
<div>
|
||||||
<div className='pb-4 sm:pb-10 mb-4 border-b border-gray-200 dark:border-gray-600 border-solid -mx-4 sm:-mx-10'>
|
<div className='pb-4 sm:pb-10 mb-4 border-b border-gray-200 dark:border-gray-800 border-solid -mx-4 sm:-mx-10'>
|
||||||
<Stack space={2}>
|
<Stack space={2}>
|
||||||
<Text size='2xl' align='center' weight='bold'>
|
<Text size='2xl' align='center' weight='bold'>
|
||||||
<FormattedMessage id='onboarding.note.title' defaultMessage='Write a short bio' />
|
<FormattedMessage id='onboarding.note.title' defaultMessage='Write a short bio' />
|
||||||
|
@ -89,7 +89,7 @@ const BioStep = ({ onNext }: { onNext: () => void }) => {
|
||||||
)}
|
)}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Button block theme='link' type='button' onClick={onNext}>
|
<Button block theme='tertiary' type='button' onClick={onNext}>
|
||||||
<FormattedMessage id='onboarding.skip' defaultMessage='Skip for now' />
|
<FormattedMessage id='onboarding.skip' defaultMessage='Skip for now' />
|
||||||
</Button>
|
</Button>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|
|
@ -75,7 +75,7 @@ const CoverPhotoSelectionStep = ({ onNext }: { onNext: () => void }) => {
|
||||||
<Card variant='rounded' size='xl'>
|
<Card variant='rounded' size='xl'>
|
||||||
<CardBody>
|
<CardBody>
|
||||||
<div>
|
<div>
|
||||||
<div className='pb-4 sm:pb-10 mb-4 border-b border-gray-200 dark:border-gray-600 border-solid -mx-4 sm:-mx-10'>
|
<div className='pb-4 sm:pb-10 mb-4 border-b border-gray-200 dark:border-gray-800 border-solid -mx-4 sm:-mx-10'>
|
||||||
<Stack space={2}>
|
<Stack space={2}>
|
||||||
<Text size='2xl' align='center' weight='bold'>
|
<Text size='2xl' align='center' weight='bold'>
|
||||||
<FormattedMessage id='onboarding.header.title' defaultMessage='Pick a cover image' />
|
<FormattedMessage id='onboarding.header.title' defaultMessage='Pick a cover image' />
|
||||||
|
@ -89,11 +89,11 @@ const CoverPhotoSelectionStep = ({ onNext }: { onNext: () => void }) => {
|
||||||
|
|
||||||
<div className='sm:pt-10 sm:w-2/3 md:w-1/2 mx-auto'>
|
<div className='sm:pt-10 sm:w-2/3 md:w-1/2 mx-auto'>
|
||||||
<Stack space={10}>
|
<Stack space={10}>
|
||||||
<div className='border border-solid border-gray-200 rounded-lg'>
|
<div className='border border-solid border-gray-200 dark:border-gray-800 rounded-lg'>
|
||||||
{/* eslint-disable-next-line jsx-a11y/interactive-supports-focus */}
|
{/* eslint-disable-next-line jsx-a11y/interactive-supports-focus */}
|
||||||
<div
|
<div
|
||||||
role='button'
|
role='button'
|
||||||
className='relative h-24 bg-primary-100 rounded-t-md flex items-center justify-center'
|
className='relative h-24 bg-gray-200 dark:bg-gray-800 rounded-t-md flex items-center justify-center'
|
||||||
>
|
>
|
||||||
{selectedFile || account?.header && (
|
{selectedFile || account?.header && (
|
||||||
<StillImage
|
<StillImage
|
||||||
|
@ -105,7 +105,7 @@ const CoverPhotoSelectionStep = ({ onNext }: { onNext: () => void }) => {
|
||||||
|
|
||||||
{isSubmitting && (
|
{isSubmitting && (
|
||||||
<div
|
<div
|
||||||
className='absolute inset-0 rounded-t-md flex justify-center items-center bg-white/80'
|
className='absolute inset-0 rounded-t-md flex justify-center items-center bg-white/80 dark:bg-primary-900/80'
|
||||||
>
|
>
|
||||||
<Spinner withText={false} />
|
<Spinner withText={false} />
|
||||||
</div>
|
</div>
|
||||||
|
@ -115,7 +115,7 @@ const CoverPhotoSelectionStep = ({ onNext }: { onNext: () => void }) => {
|
||||||
onClick={openFilePicker}
|
onClick={openFilePicker}
|
||||||
type='button'
|
type='button'
|
||||||
className={classNames({
|
className={classNames({
|
||||||
'absolute -top-3 -right-3 p-1 bg-primary-600 rounded-full ring-2 ring-white hover:bg-primary-700': true,
|
'absolute -top-3 -right-3 p-1 bg-primary-600 rounded-full ring-2 ring-white dark:ring-primary-900 hover:bg-primary-700': true,
|
||||||
'opacity-50 pointer-events-none': isSubmitting,
|
'opacity-50 pointer-events-none': isSubmitting,
|
||||||
})}
|
})}
|
||||||
disabled={isSubmitting}
|
disabled={isSubmitting}
|
||||||
|
@ -128,7 +128,7 @@ const CoverPhotoSelectionStep = ({ onNext }: { onNext: () => void }) => {
|
||||||
|
|
||||||
<div className='flex flex-col px-4 pb-4'>
|
<div className='flex flex-col px-4 pb-4'>
|
||||||
{account && (
|
{account && (
|
||||||
<Avatar src={account.avatar} size={64} className='ring-2 ring-white -mt-8 mb-2' />
|
<Avatar src={account.avatar} size={64} className='ring-2 dark:ring-primary-800 ring-white -mt-8 mb-2' />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Text weight='bold' size='sm'>{account?.display_name}</Text>
|
<Text weight='bold' size='sm'>{account?.display_name}</Text>
|
||||||
|
@ -142,7 +142,7 @@ const CoverPhotoSelectionStep = ({ onNext }: { onNext: () => void }) => {
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
{isDisabled && (
|
{isDisabled && (
|
||||||
<Button block theme='link' type='button' onClick={onNext}>
|
<Button block theme='tertiary' type='button' onClick={onNext}>
|
||||||
<FormattedMessage id='onboarding.skip' defaultMessage='Skip for now' />
|
<FormattedMessage id='onboarding.skip' defaultMessage='Skip for now' />
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -52,7 +52,7 @@ const DisplayNameStep = ({ onNext }: { onNext: () => void }) => {
|
||||||
<Card variant='rounded' size='xl'>
|
<Card variant='rounded' size='xl'>
|
||||||
<CardBody>
|
<CardBody>
|
||||||
<div>
|
<div>
|
||||||
<div className='pb-4 sm:pb-10 mb-4 border-b border-gray-200 dark:border-gray-600 border-solid -mx-4 sm:-mx-10'>
|
<div className='pb-4 sm:pb-10 mb-4 border-b border-gray-200 dark:border-gray-800 border-solid -mx-4 sm:-mx-10'>
|
||||||
<Stack space={2}>
|
<Stack space={2}>
|
||||||
<Text size='2xl' align='center' weight='bold'>
|
<Text size='2xl' align='center' weight='bold'>
|
||||||
<FormattedMessage id='onboarding.display_name.title' defaultMessage='Choose a display name' />
|
<FormattedMessage id='onboarding.display_name.title' defaultMessage='Choose a display name' />
|
||||||
|
@ -91,7 +91,7 @@ const DisplayNameStep = ({ onNext }: { onNext: () => void }) => {
|
||||||
{isSubmitting ? 'Saving…' : 'Next'}
|
{isSubmitting ? 'Saving…' : 'Next'}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Button block theme='link' type='button' onClick={onNext}>
|
<Button block theme='tertiary' type='button' onClick={onNext}>
|
||||||
<FormattedMessage id='onboarding.skip' defaultMessage='Skip for now' />
|
<FormattedMessage id='onboarding.skip' defaultMessage='Skip for now' />
|
||||||
</Button>
|
</Button>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|
|
@ -56,7 +56,7 @@ const SuggestedAccountsStep = ({ onNext }: { onNext: () => void }) => {
|
||||||
|
|
||||||
const renderEmpty = () => {
|
const renderEmpty = () => {
|
||||||
return (
|
return (
|
||||||
<div className='bg-primary-50 dark:bg-slate-700 my-2 rounded-lg text-center p-8'>
|
<div className='bg-primary-50 dark:bg-gray-800 my-2 rounded-lg text-center p-8'>
|
||||||
<Text>
|
<Text>
|
||||||
<FormattedMessage id='empty_column.follow_recommendations' defaultMessage='Looks like no suggestions could be generated for you. You can try using search to look for people you might know or explore trending hashtags.' />
|
<FormattedMessage id='empty_column.follow_recommendations' defaultMessage='Looks like no suggestions could be generated for you. You can try using search to look for people you might know or explore trending hashtags.' />
|
||||||
</Text>
|
</Text>
|
||||||
|
@ -76,7 +76,7 @@ const SuggestedAccountsStep = ({ onNext }: { onNext: () => void }) => {
|
||||||
<Card variant='rounded' size='xl'>
|
<Card variant='rounded' size='xl'>
|
||||||
<CardBody>
|
<CardBody>
|
||||||
<div>
|
<div>
|
||||||
<div className='pb-4 sm:pb-10 mb-4 border-b border-gray-200 dark:border-gray-600 border-solid -mx-4 sm:-mx-10'>
|
<div className='pb-4 sm:pb-10 mb-4 border-b border-gray-200 dark:border-gray-800 border-solid -mx-4 sm:-mx-10'>
|
||||||
<Stack space={2}>
|
<Stack space={2}>
|
||||||
<Text size='2xl' align='center' weight='bold'>
|
<Text size='2xl' align='center' weight='bold'>
|
||||||
<FormattedMessage id='onboarding.suggestions.title' defaultMessage='Suggested accounts' />
|
<FormattedMessage id='onboarding.suggestions.title' defaultMessage='Suggested accounts' />
|
||||||
|
@ -101,7 +101,7 @@ const SuggestedAccountsStep = ({ onNext }: { onNext: () => void }) => {
|
||||||
<FormattedMessage id='onboarding.done' defaultMessage='Done' />
|
<FormattedMessage id='onboarding.done' defaultMessage='Done' />
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Button block theme='link' type='button' onClick={onNext}>
|
<Button block theme='tertiary' type='button' onClick={onNext}>
|
||||||
<FormattedMessage id='onboarding.skip' defaultMessage='Skip for now' />
|
<FormattedMessage id='onboarding.skip' defaultMessage='Skip for now' />
|
||||||
</Button>
|
</Button>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|
|
@ -23,12 +23,12 @@ const PlaceholderAvatar: React.FC<IPlaceholderAvatar> = ({ size, withText = fals
|
||||||
return (
|
return (
|
||||||
<Stack space={3} className='animate-pulse text-center'>
|
<Stack space={3} className='animate-pulse text-center'>
|
||||||
<div
|
<div
|
||||||
className='block mx-auto rounded-full bg-slate-200 dark:bg-slate-700'
|
className='block mx-auto rounded-full bg-primary-50 dark:bg-primary-800'
|
||||||
style={style}
|
style={style}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{withText && (
|
{withText && (
|
||||||
<div style={{ width: size, height: 20 }} className='rounded-full bg-slate-200 dark:bg-slate-700' />
|
<div style={{ width: size, height: 20 }} className='rounded-full bg-primary-50 dark:bg-primary-800' />
|
||||||
)}
|
)}
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
|
|
|
@ -9,9 +9,9 @@ const PlaceholderCard: React.FC = () => (
|
||||||
'animate-pulse': true,
|
'animate-pulse': true,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<div className='w-2/5 bg-slate-200 rounded-l'> </div>
|
<div className='w-2/5 primary-500 rounded-l'> </div>
|
||||||
|
|
||||||
<div className='w-3/5 p-4 flex flex-col justify-between text-slate-200 break-words'>
|
<div className='w-3/5 p-4 flex flex-col justify-between text-primary-50 break-words'>
|
||||||
<p>{generateText(randomIntFromInterval(5, 25))}</p>
|
<p>{generateText(randomIntFromInterval(5, 25))}</p>
|
||||||
<p>{generateText(randomIntFromInterval(5, 75))}</p>
|
<p>{generateText(randomIntFromInterval(5, 75))}</p>
|
||||||
<p>{generateText(randomIntFromInterval(5, 15))}</p>
|
<p>{generateText(randomIntFromInterval(5, 15))}</p>
|
||||||
|
|
|
@ -13,7 +13,7 @@ const PlaceholderDisplayName: React.FC<IPlaceholderDisplayName> = ({ minLength,
|
||||||
const acctLength = randomIntFromInterval(maxLength, minLength);
|
const acctLength = randomIntFromInterval(maxLength, minLength);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='flex flex-col text-slate-200 dark:text-slate-700'>
|
<div className='flex flex-col text-primary-50 dark:text-primary-800'>
|
||||||
<p>{generateText(length)}</p>
|
<p>{generateText(length)}</p>
|
||||||
<p>{generateText(acctLength)}</p>
|
<p>{generateText(acctLength)}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -6,7 +6,7 @@ import PlaceholderStatusContent from './placeholder_status_content';
|
||||||
|
|
||||||
/** Fake notification to display while data is loading. */
|
/** Fake notification to display while data is loading. */
|
||||||
const PlaceholderNotification = () => (
|
const PlaceholderNotification = () => (
|
||||||
<div className='bg-white dark:bg-slate-800 px-4 py-6 sm:p-6'>
|
<div className='bg-white dark:bg-primary-900 px-4 py-6 sm:p-6'>
|
||||||
<div className='w-full animate-pulse'>
|
<div className='w-full animate-pulse'>
|
||||||
<div className='mb-2'>
|
<div className='mb-2'>
|
||||||
<PlaceholderStatusContent minLength={20} maxLength={20} />
|
<PlaceholderStatusContent minLength={20} maxLength={20} />
|
||||||
|
|
|
@ -13,8 +13,8 @@ interface IPlaceholderStatus {
|
||||||
const PlaceholderStatus: React.FC<IPlaceholderStatus> = ({ thread = false }) => (
|
const PlaceholderStatus: React.FC<IPlaceholderStatus> = ({ thread = false }) => (
|
||||||
<div
|
<div
|
||||||
className={classNames({
|
className={classNames({
|
||||||
'status-placeholder bg-white dark:bg-slate-800': true,
|
'status-placeholder bg-white dark:bg-primary-900': true,
|
||||||
'shadow-xl dark:shadow-inset sm:rounded-xl px-4 py-6 sm:p-5': !thread,
|
'shadow-xl dark:shadow-none sm:rounded-xl px-4 py-6 sm:p-5': !thread,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<div className='w-full animate-pulse overflow-hidden'>
|
<div className='w-full animate-pulse overflow-hidden'>
|
||||||
|
|
|
@ -12,7 +12,7 @@ const PlaceholderStatusContent: React.FC<IPlaceholderStatusContent> = ({ minLeng
|
||||||
const length = randomIntFromInterval(maxLength, minLength);
|
const length = randomIntFromInterval(maxLength, minLength);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='flex flex-col text-slate-200 dark:text-slate-700'>
|
<div className='flex flex-col text-primary-50 dark:text-primary-800'>
|
||||||
<p className='break-words'>{generateText(length)}</p>
|
<p className='break-words'>{generateText(length)}</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -31,8 +31,8 @@ const Footer = () => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={idx} className='px-5 py-2'>
|
<div key={idx} className='px-5 py-2'>
|
||||||
<Comp {...compProps} className='hover:underline'>
|
<Comp {...compProps} className='text-primary-600 dark:text-primary-400 hover:underline'>
|
||||||
<Text tag='span' theme='primary' size='sm'>
|
<Text tag='span' theme='inherit' size='sm'>
|
||||||
{(link.getIn(['titleLocales', locale]) || link.get('title')) as string}
|
{(link.getIn(['titleLocales', locale]) || link.get('title')) as string}
|
||||||
</Text>
|
</Text>
|
||||||
</Comp>
|
</Comp>
|
||||||
|
|
|
@ -101,7 +101,7 @@ const Header = () => {
|
||||||
<a
|
<a
|
||||||
href={links.get('help')}
|
href={links.get('help')}
|
||||||
target='_blank'
|
target='_blank'
|
||||||
className='text-sm font-medium text-gray-500 hover:text-gray-900'
|
className='text-sm font-medium text-gray-700 dark:text-gray-600 hover:underline'
|
||||||
>
|
>
|
||||||
<FormattedMessage id='landing_page_modal.helpCenter' defaultMessage='Help Center' />
|
<FormattedMessage id='landing_page_modal.helpCenter' defaultMessage='Help Center' />
|
||||||
</a>
|
</a>
|
||||||
|
@ -109,7 +109,7 @@ const Header = () => {
|
||||||
</HStack>
|
</HStack>
|
||||||
|
|
||||||
<HStack space={2} className='xl:hidden shrink-0'>
|
<HStack space={2} className='xl:hidden shrink-0'>
|
||||||
<Button to='/login' theme='secondary'>
|
<Button to='/login' theme='tertiary'>
|
||||||
{intl.formatMessage(messages.login)}
|
{intl.formatMessage(messages.login)}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
|
@ -152,8 +152,9 @@ const Header = () => {
|
||||||
<Tooltip text={intl.formatMessage(messages.forgotPassword)}>
|
<Tooltip text={intl.formatMessage(messages.forgotPassword)}>
|
||||||
<IconButton
|
<IconButton
|
||||||
src={require('@tabler/icons/help.svg')}
|
src={require('@tabler/icons/help.svg')}
|
||||||
className='bg-transparent text-gray-400 dark:text-gray-500 hover:text-gray-700 dark:hover:text-gray-200 cursor-pointer'
|
className='bg-transparent text-gray-700 dark:text-gray-600 hover:text-gray-800 dark:hover:text-gray-500 cursor-pointer'
|
||||||
iconClassName='w-5 h-5'
|
iconClassName='w-5 h-5'
|
||||||
|
transparent
|
||||||
/>
|
/>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</Link>
|
</Link>
|
||||||
|
|
|
@ -3,12 +3,12 @@ import React from 'react';
|
||||||
const Sonar = () => (
|
const Sonar = () => (
|
||||||
<div className='relative'>
|
<div className='relative'>
|
||||||
<div className='relative w-48 h-48'>
|
<div className='relative w-48 h-48'>
|
||||||
<div className='animate-sonar-scale-4 absolute top-0 left-0 w-full h-full rounded-full bg-primary-600/25 dark:bg-primary-400/25 opacity-0 pointer-events-none' />
|
<div className='animate-sonar-scale-4 absolute top-0 left-0 w-full h-full rounded-full bg-primary-600/25 dark:bg-primary-600/25 opacity-0 pointer-events-none' />
|
||||||
<div className='animate-sonar-scale-3 absolute top-0 left-0 w-full h-full rounded-full bg-primary-600/25 dark:bg-primary-400/25 opacity-0 pointer-events-none' />
|
<div className='animate-sonar-scale-3 absolute top-0 left-0 w-full h-full rounded-full bg-primary-600/25 dark:bg-primary-600/25 opacity-0 pointer-events-none' />
|
||||||
<div className='animate-sonar-scale-2 absolute top-0 left-0 w-full h-full rounded-full bg-primary-600/25 dark:bg-primary-400/25 opacity-0 pointer-events-none' />
|
<div className='animate-sonar-scale-2 absolute top-0 left-0 w-full h-full rounded-full bg-primary-600/25 dark: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 dark:bg-primary-400/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 dark:bg-primary-600/25 opacity-0 pointer-events-none' />
|
||||||
|
|
||||||
<div className='absolute top-0 left-0 w-48 h-48 bg-white dark:bg-slate-900 rounded-full' />
|
<div className='absolute top-0 left-0 w-48 h-48 bg-white dark:bg-primary-900 rounded-full' />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -36,12 +36,12 @@ const EnableOtpForm: React.FC<IEnableOtpForm> = ({ displayOtpForm, handleSetupPr
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack space={4}>
|
<Stack space={4}>
|
||||||
<Stack space={2}>
|
<Stack space={4}>
|
||||||
<Text theme='muted'>
|
<Text theme='muted'>
|
||||||
<FormattedMessage id='mfa.setup_warning' defaultMessage="Write these codes down or save them somewhere secure - otherwise you won't see them again. If you lose access to your 2FA app and recovery codes you'll be locked out of your account." />
|
<FormattedMessage id='mfa.setup_warning' defaultMessage="Write these codes down or save them somewhere secure - otherwise you won't see them again. If you lose access to your 2FA app and recovery codes you'll be locked out of your account." />
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
<div className='bg-gray-100 dark:bg-slate-900/50 rounded-lg p-4'>
|
<div className='border-2 border-solid border-gray-200 dark:border-gray-800 rounded-lg p-4'>
|
||||||
<Stack space={3}>
|
<Stack space={3}>
|
||||||
<Text weight='medium' align='center'>
|
<Text weight='medium' align='center'>
|
||||||
<FormattedMessage id='mfa.setup_recoverycodes' defaultMessage='Recovery codes' />
|
<FormattedMessage id='mfa.setup_recoverycodes' defaultMessage='Recovery codes' />
|
||||||
|
@ -65,7 +65,7 @@ const EnableOtpForm: React.FC<IEnableOtpForm> = ({ displayOtpForm, handleSetupPr
|
||||||
{!displayOtpForm && (
|
{!displayOtpForm && (
|
||||||
<FormActions>
|
<FormActions>
|
||||||
<Button
|
<Button
|
||||||
theme='ghost'
|
theme='tertiary'
|
||||||
text={intl.formatMessage(messages.mfaCancelButton)}
|
text={intl.formatMessage(messages.mfaCancelButton)}
|
||||||
onClick={() => history.push('../auth/edit')}
|
onClick={() => history.push('../auth/edit')}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -64,8 +64,6 @@ const OtpConfirmForm: React.FC = () => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack space={4}>
|
<Stack space={4}>
|
||||||
<hr className='mt-4 dark:border-slate-700' />
|
|
||||||
|
|
||||||
<Form onSubmit={handleSubmit}>
|
<Form onSubmit={handleSubmit}>
|
||||||
<Stack>
|
<Stack>
|
||||||
<Text weight='semibold' size='lg'>
|
<Text weight='semibold' size='lg'>
|
||||||
|
@ -118,7 +116,7 @@ const OtpConfirmForm: React.FC = () => {
|
||||||
<FormActions>
|
<FormActions>
|
||||||
<Button
|
<Button
|
||||||
type='button'
|
type='button'
|
||||||
theme='ghost'
|
theme='tertiary'
|
||||||
text={intl.formatMessage(messages.mfaCancelButton)}
|
text={intl.formatMessage(messages.mfaCancelButton)}
|
||||||
onClick={() => history.push('../auth/edit')}
|
onClick={() => history.push('../auth/edit')}
|
||||||
disabled={state.isLoading}
|
disabled={state.isLoading}
|
||||||
|
|
|
@ -2,7 +2,7 @@ import React, { useEffect, useState } from 'react';
|
||||||
import { useIntl, defineMessages } from 'react-intl';
|
import { useIntl, defineMessages } from 'react-intl';
|
||||||
|
|
||||||
import { fetchMfa } from 'soapbox/actions/mfa';
|
import { fetchMfa } from 'soapbox/actions/mfa';
|
||||||
import { Card, CardBody, CardHeader, CardTitle, Column } from 'soapbox/components/ui';
|
import { Card, CardBody, CardHeader, CardTitle, Column, Stack } from 'soapbox/components/ui';
|
||||||
import { useAppSelector, useAppDispatch } from 'soapbox/hooks';
|
import { useAppSelector, useAppDispatch } from 'soapbox/hooks';
|
||||||
|
|
||||||
import DisableOtpForm from './mfa/disable_otp_form';
|
import DisableOtpForm from './mfa/disable_otp_form';
|
||||||
|
@ -47,10 +47,10 @@ const MfaForm: React.FC = () => {
|
||||||
{mfa.getIn(['settings', 'totp']) ? (
|
{mfa.getIn(['settings', 'totp']) ? (
|
||||||
<DisableOtpForm />
|
<DisableOtpForm />
|
||||||
) : (
|
) : (
|
||||||
<>
|
<Stack space={4}>
|
||||||
<EnableOtpForm displayOtpForm={displayOtpForm} handleSetupProceedClick={handleSetupProceedClick} />
|
<EnableOtpForm displayOtpForm={displayOtpForm} handleSetupProceedClick={handleSetupProceedClick} />
|
||||||
{displayOtpForm && <OtpConfirmForm />}
|
{displayOtpForm && <OtpConfirmForm />}
|
||||||
</>
|
</Stack>
|
||||||
)}
|
)}
|
||||||
</CardBody>
|
</CardBody>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
|
@ -9,7 +9,7 @@ interface IIconPicker {
|
||||||
|
|
||||||
const IconPicker: React.FC<IIconPicker> = ({ value, onChange }) => {
|
const IconPicker: React.FC<IIconPicker> = ({ value, onChange }) => {
|
||||||
return (
|
return (
|
||||||
<div className='mt-1 relative rounded-md shadow-sm dark:bg-slate-800 border border-solid border-gray-300 dark:border-gray-600 rounded-md'>
|
<div className='mt-1 relative rounded-md shadow-sm dark:bg-gray-800 border border-solid border-gray-300 dark:border-gray-600'>
|
||||||
<IconPickerDropdown value={value} onPickEmoji={onChange} />
|
<IconPickerDropdown value={value} onPickEmoji={onChange} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -27,11 +27,11 @@ const SitePreview: React.FC<ISitePreview> = ({ soapbox }) => {
|
||||||
const bodyClass = classNames(
|
const bodyClass = classNames(
|
||||||
'site-preview',
|
'site-preview',
|
||||||
'relative flex justify-center align-center text-base',
|
'relative flex justify-center align-center text-base',
|
||||||
'border border-solid border-gray-200 dark:border-slate-600',
|
'border border-solid border-gray-200 dark:border-gray-600',
|
||||||
'h-40 rounded-lg overflow-hidden',
|
'h-40 rounded-lg overflow-hidden',
|
||||||
{
|
{
|
||||||
'bg-white': !dark,
|
'bg-white': !dark,
|
||||||
'bg-slate-900': dark,
|
'bg-gray-900': dark,
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -45,7 +45,7 @@ const SitePreview: React.FC<ISitePreview> = ({ soapbox }) => {
|
||||||
|
|
||||||
<div className={classNames('flex absolute inset-0 shadow z-10 h-12 lg:h-16', {
|
<div className={classNames('flex absolute inset-0 shadow z-10 h-12 lg:h-16', {
|
||||||
'bg-white': !dark,
|
'bg-white': !dark,
|
||||||
'bg-slate-800': dark,
|
'bg-gray-800': dark,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<SiteLogo alt='Logo' className='h-5 lg:h-6 w-auto self-center px-2' theme={dark ? 'dark' : 'light'} />
|
<SiteLogo alt='Logo' className='h-5 lg:h-6 w-auto self-center px-2' theme={dark ? 'dark' : 'light'} />
|
||||||
|
|
|
@ -549,7 +549,7 @@ class ActionBar extends React.PureComponent<IActionBar, IActionBarState> {
|
||||||
<IconButton
|
<IconButton
|
||||||
disabled={reblog_disabled}
|
disabled={reblog_disabled}
|
||||||
className={classNames({
|
className={classNames({
|
||||||
'text-gray-400 hover:text-gray-600': !status.reblogged,
|
'text-gray-600 hover:text-gray-700 dark:hover:text-gray-500': !status.reblogged,
|
||||||
'text-success-600 hover:text-success-600': status.reblogged,
|
'text-success-600 hover:text-success-600': status.reblogged,
|
||||||
})}
|
})}
|
||||||
title={reblog_disabled ? intl.formatMessage(messages.cannot_reblog) : intl.formatMessage(messages.reblog)}
|
title={reblog_disabled ? intl.formatMessage(messages.cannot_reblog) : intl.formatMessage(messages.reblog)}
|
||||||
|
@ -564,7 +564,7 @@ class ActionBar extends React.PureComponent<IActionBar, IActionBarState> {
|
||||||
<IconButton
|
<IconButton
|
||||||
title={intl.formatMessage(messages.reply)}
|
title={intl.formatMessage(messages.reply)}
|
||||||
src={require('@tabler/icons/message-circle-2.svg')}
|
src={require('@tabler/icons/message-circle-2.svg')}
|
||||||
className='text-gray-400 hover:text-gray-600'
|
className='text-gray-600 hover:text-gray-700 dark:hover:text-gray-500'
|
||||||
onClick={this.handleReplyClick}
|
onClick={this.handleReplyClick}
|
||||||
text={intl.formatMessage(messages.reply)}
|
text={intl.formatMessage(messages.reply)}
|
||||||
/>
|
/>
|
||||||
|
@ -601,7 +601,7 @@ class ActionBar extends React.PureComponent<IActionBar, IActionBarState> {
|
||||||
) : (
|
) : (
|
||||||
<IconButton
|
<IconButton
|
||||||
className={classNames({
|
className={classNames({
|
||||||
'text-gray-400 hover:text-gray-600': !meEmojiReact,
|
'text-gray-600 hover:text-gray-700 dark:hover:text-gray-500': !meEmojiReact,
|
||||||
'text-accent-300 hover:text-accent-300': Boolean(meEmojiReact),
|
'text-accent-300 hover:text-accent-300': Boolean(meEmojiReact),
|
||||||
})}
|
})}
|
||||||
title={meEmojiTitle}
|
title={meEmojiTitle}
|
||||||
|
@ -616,7 +616,7 @@ class ActionBar extends React.PureComponent<IActionBar, IActionBarState> {
|
||||||
) : (
|
) : (
|
||||||
<IconButton
|
<IconButton
|
||||||
className={classNames({
|
className={classNames({
|
||||||
'text-gray-400 hover:text-gray-600': !meEmojiReact,
|
'text-gray-600 hover:text-gray-700 dark:hover:text-gray-500': !meEmojiReact,
|
||||||
'text-accent-300 hover:text-accent-300': Boolean(meEmojiReact),
|
'text-accent-300 hover:text-accent-300': Boolean(meEmojiReact),
|
||||||
})}
|
})}
|
||||||
title={meEmojiTitle}
|
title={meEmojiTitle}
|
||||||
|
@ -633,7 +633,7 @@ class ActionBar extends React.PureComponent<IActionBar, IActionBarState> {
|
||||||
<IconButton
|
<IconButton
|
||||||
title={intl.formatMessage(messages.share)}
|
title={intl.formatMessage(messages.share)}
|
||||||
src={require('@tabler/icons/upload.svg')}
|
src={require('@tabler/icons/upload.svg')}
|
||||||
className='text-gray-400 hover:text-gray-600'
|
className='text-gray-600 hover:text-gray-700 dark:hover:text-gray-500'
|
||||||
onClick={this.handleShare}
|
onClick={this.handleShare}
|
||||||
text={intl.formatMessage(messages.share)}
|
text={intl.formatMessage(messages.share)}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -153,7 +153,7 @@ const Card: React.FC<ICard> = ({
|
||||||
);
|
);
|
||||||
|
|
||||||
const description = (
|
const description = (
|
||||||
<div className='status-card__content cursor-default'>
|
<div className='status-card__content'>
|
||||||
<span className='status-card__title'>{title}</span>
|
<span className='status-card__title'>{title}</span>
|
||||||
<p className='status-card__description'>{trimmedDescription}</p>
|
<p className='status-card__description'>{trimmedDescription}</p>
|
||||||
<span className='status-card__host'><Icon src={require('@tabler/icons/link.svg')} /> {card.provider_name}</span>
|
<span className='status-card__host'><Icon src={require('@tabler/icons/link.svg')} /> {card.provider_name}</span>
|
||||||
|
@ -196,12 +196,12 @@ const Card: React.FC<ICard> = ({
|
||||||
{thumbnail}
|
{thumbnail}
|
||||||
|
|
||||||
<div className='absolute inset-0 flex items-center justify-center'>
|
<div className='absolute inset-0 flex items-center justify-center'>
|
||||||
<div className='bg-white shadow-md rounded-md p-2 flex items-center justify-center'>
|
<div className='bg-gray-500/90 dark:bg-gray-700/90 shadow-md rounded-full px-4 py-3 flex items-center justify-center'>
|
||||||
<HStack space={3} alignItems='center'>
|
<HStack space={3} alignItems='center'>
|
||||||
<button onClick={handleEmbedClick} className='appearance-none text-gray-400 hover:text-gray-600'>
|
<button onClick={handleEmbedClick} className='appearance-none text-gray-700 dark:text-gray-500 hover:text-gray-900 dark:hover:text-gray-100'>
|
||||||
<Icon
|
<Icon
|
||||||
src={iconVariant}
|
src={iconVariant}
|
||||||
className='w-5 h-5 text-inherit'
|
className='w-6 h-6 text-inherit'
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
@ -211,11 +211,11 @@ const Card: React.FC<ICard> = ({
|
||||||
href={card.url}
|
href={card.url}
|
||||||
target='_blank'
|
target='_blank'
|
||||||
rel='noopener'
|
rel='noopener'
|
||||||
className='text-gray-400 hover:text-gray-600'
|
className='text-gray-700 dark:text-gray-500 hover:text-gray-900 dark:hover:text-gray-100'
|
||||||
>
|
>
|
||||||
<Icon
|
<Icon
|
||||||
src={require('@tabler/icons/external-link.svg')}
|
src={require('@tabler/icons/external-link.svg')}
|
||||||
className='w-5 h-5 text-inherit'
|
className='w-6 h-6 text-inherit'
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -16,7 +16,6 @@ interface IStatusInteractionBar {
|
||||||
}
|
}
|
||||||
|
|
||||||
const StatusInteractionBar: React.FC<IStatusInteractionBar> = ({ status }): JSX.Element | null => {
|
const StatusInteractionBar: React.FC<IStatusInteractionBar> = ({ status }): JSX.Element | null => {
|
||||||
|
|
||||||
const me = useAppSelector(({ me }) => me);
|
const me = useAppSelector(({ me }) => me);
|
||||||
const { allowedEmoji } = useSoapboxConfig();
|
const { allowedEmoji } = useSoapboxConfig();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
@ -163,9 +162,9 @@ const StatusInteractionBar: React.FC<IStatusInteractionBar> = ({ status }): JSX.
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<HStack space={3}>
|
<HStack space={3}>
|
||||||
{features.emojiReacts ? getEmojiReacts() : getFavourites()}
|
|
||||||
|
|
||||||
{getReposts()}
|
{getReposts()}
|
||||||
|
|
||||||
|
{features.emojiReacts ? getEmojiReacts() : getFavourites()}
|
||||||
</HStack>
|
</HStack>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,7 +22,7 @@ const ThreadLoginCta: React.FC = () => {
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|
||||||
<Stack space={4} className='max-w-xs mx-auto'>
|
<Stack space={4} className='max-w-xs mx-auto'>
|
||||||
<Button theme='secondary' to='/login' block>
|
<Button theme='tertiary' to='/login' block>
|
||||||
<FormattedMessage id='thread_login.login' defaultMessage='Log in' />
|
<FormattedMessage id='thread_login.login' defaultMessage='Log in' />
|
||||||
</Button>
|
</Button>
|
||||||
<Button to='/signup' block>
|
<Button to='/signup' block>
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue