Improve visuals with branding

Co-authored-by: Alex Gleason <alex@alexgleason.me>
This commit is contained in:
Justin 2022-07-22 13:30:16 -04:00
parent 12cacf34e8
commit 20209c81ab
208 changed files with 695 additions and 654 deletions

View File

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

View File

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

View File

@ -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(),
})} })}

View File

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

View File

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

View File

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

View File

@ -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'> &rarr;</span> <span aria-hidden='true'> &rarr;</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>
</> </>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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', () => {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -9,9 +9,9 @@ const PlaceholderCard: React.FC = () => (
'animate-pulse': true, 'animate-pulse': true,
})} })}
> >
<div className='w-2/5 bg-slate-200 rounded-l'>&nbsp;</div> <div className='w-2/5 primary-500 rounded-l'>&nbsp;</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>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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