Add ProgressBar and dark mode support
This commit is contained in:
parent
6baec89484
commit
86fb9bf704
10 changed files with 53 additions and 37 deletions
|
@ -1,13 +0,0 @@
|
|||
import React from 'react';
|
||||
|
||||
interface IProgressBar {
|
||||
progress: number,
|
||||
}
|
||||
|
||||
const ProgressBar: React.FC<IProgressBar> = ({ progress }) => (
|
||||
<div className='h-2 w-full rounded-md bg-gray-300 dark:bg-slate-700 overflow-hidden'>
|
||||
<div className='h-full bg-primary-500' style={{ width: `${Math.floor(progress*100)}%` }} />
|
||||
</div>
|
||||
);
|
||||
|
||||
export default ProgressBar;
|
|
@ -56,7 +56,6 @@ const StatusActionButton = React.forwardRef((props: IStatusActionButton, ref: Re
|
|||
<Icon
|
||||
src={icon}
|
||||
className={classNames(
|
||||
'rounded-full',
|
||||
{
|
||||
'fill-accent-300 hover:fill-accent-300': active && filled && color === COLORS.accent,
|
||||
},
|
||||
|
|
|
@ -23,6 +23,7 @@ export {
|
|||
MenuList,
|
||||
} from './menu/menu';
|
||||
export { default as Modal } from './modal/modal';
|
||||
export { default as ProgressBar } from './progress-bar/progress-bar';
|
||||
export { default as Select } from './select/select';
|
||||
export { default as Spinner } from './spinner/spinner';
|
||||
export { default as Stack } from './stack/stack';
|
||||
|
|
13
app/soapbox/components/ui/progress-bar/progress-bar.tsx
Normal file
13
app/soapbox/components/ui/progress-bar/progress-bar.tsx
Normal file
|
@ -0,0 +1,13 @@
|
|||
import React from 'react';
|
||||
|
||||
interface IProgressBar {
|
||||
progress: number,
|
||||
}
|
||||
|
||||
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-full bg-accent-500' style={{ width: `${Math.floor(progress * 100)}%` }} />
|
||||
</div>
|
||||
);
|
||||
|
||||
export default ProgressBar;
|
|
@ -2,11 +2,9 @@ import React, { useEffect } from 'react';
|
|||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import { fetchPatronInstance } from 'soapbox/actions/patron';
|
||||
import { Widget, Button, Text } from 'soapbox/components/ui';
|
||||
import { Widget, Button, ProgressBar, Text } from 'soapbox/components/ui';
|
||||
import { useAppSelector, useAppDispatch } from 'soapbox/hooks';
|
||||
|
||||
import ProgressBar from '../../../components/progress_bar';
|
||||
|
||||
/** Open link in a new tab. */
|
||||
// https://stackoverflow.com/a/28374344/8811886
|
||||
const openInNewTab = (href: string): void => {
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import { AxiosError } from 'axios';
|
||||
import { Set as ImmutableSet } from 'immutable';
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
||||
|
||||
import { blockAccount } from 'soapbox/actions/accounts';
|
||||
import { submitReport, cancelReport, submitReportSuccess, submitReportFail } from 'soapbox/actions/reports';
|
||||
import { expandAccountTimeline } from 'soapbox/actions/timelines';
|
||||
import { Modal } from 'soapbox/components/ui';
|
||||
import { Modal, ProgressBar, Stack } from 'soapbox/components/ui';
|
||||
import { useAccount, useAppDispatch, useAppSelector } from 'soapbox/hooks';
|
||||
|
||||
import ConfirmationStep from './steps/confirmation-step';
|
||||
|
@ -103,6 +103,19 @@ const ReportModal = ({ onClose }: IReportModal) => {
|
|||
return isSubmitting || (shouldRequireRule && !ruleId) || selectedStatusIds.size === 0;
|
||||
}, [currentStep, isSubmitting, shouldRequireRule, ruleId, selectedStatusIds.size]);
|
||||
|
||||
const calculateProgress = useCallback(() => {
|
||||
switch (currentStep) {
|
||||
case Steps.ONE:
|
||||
return 0.33;
|
||||
case Steps.TWO:
|
||||
return 0.66;
|
||||
case Steps.THREE:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}, [currentStep]);
|
||||
|
||||
useEffect(() => {
|
||||
if (account) {
|
||||
dispatch(expandAccountTimeline(account.id, { withReplies: true, maxId: null }));
|
||||
|
@ -119,13 +132,17 @@ const ReportModal = ({ onClose }: IReportModal) => {
|
|||
<Modal
|
||||
title={<FormattedMessage id='report.target' defaultMessage='Reporting {target}' values={{ target: <strong>@{account.acct}</strong> }} />}
|
||||
onClose={handleClose}
|
||||
cancelAction={onClose}
|
||||
cancelAction={currentStep === Steps.THREE ? undefined : onClose}
|
||||
confirmationAction={handleNextStep}
|
||||
confirmationText={confirmationText}
|
||||
confirmationDisabled={isConfirmationButtonDisabled}
|
||||
skipFocus
|
||||
>
|
||||
<StepToRender account={account} />
|
||||
<Stack space={4}>
|
||||
<ProgressBar progress={calculateProgress()} />
|
||||
|
||||
<StepToRender account={account} />
|
||||
</Stack>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -11,7 +11,7 @@ interface IOtherActionsStep {
|
|||
const ConfirmationStep = ({ account }: IOtherActionsStep) => {
|
||||
return (
|
||||
<Stack space={1}>
|
||||
<Text weight='medium'>
|
||||
<Text weight='semibold' tag='h1' size='xl'>
|
||||
Thanks for submitting your report.
|
||||
</Text>
|
||||
|
||||
|
|
|
@ -97,7 +97,7 @@ const OtherActionsStep = ({ account }: IOtherActionsStep) => {
|
|||
|
||||
{features.reportMultipleStatuses && (
|
||||
<Stack space={2}>
|
||||
<Text size='xl' weight='semibold'>Include other statuses?</Text>
|
||||
<Text tag='h1' size='xl' weight='semibold'>Include other statuses?</Text>
|
||||
|
||||
<FormGroup
|
||||
labelText='Would you like to add additional statuses to this report?'
|
||||
|
@ -134,7 +134,7 @@ const OtherActionsStep = ({ account }: IOtherActionsStep) => {
|
|||
)}
|
||||
|
||||
<Stack space={2}>
|
||||
<Text size='xl' weight='semibold'>Further actions:</Text>
|
||||
<Text tag='h1' size='xl' weight='semibold'>Further actions:</Text>
|
||||
|
||||
<FormGroup
|
||||
labelText={<FormattedMessage id='report.block_hint' defaultMessage='Do you also want to block this account?' />}
|
||||
|
|
|
@ -8,7 +8,7 @@ import { changeReportComment, changeReportRule } from 'soapbox/actions/reports';
|
|||
import { fetchRules } from 'soapbox/actions/rules';
|
||||
import AttachmentThumbs from 'soapbox/components/attachment_thumbs';
|
||||
import StatusContent from 'soapbox/components/status_content';
|
||||
import { FormGroup, Stack, Text, Textarea } from 'soapbox/components/ui';
|
||||
import { FormGroup, HStack, Stack, Text, Textarea } from 'soapbox/components/ui';
|
||||
import AccountContainer from 'soapbox/containers/account_container';
|
||||
import { useAppSelector } from 'soapbox/hooks';
|
||||
|
||||
|
@ -115,11 +115,11 @@ const ReasonStep = (_props: IReasonStep) => {
|
|||
|
||||
{shouldRequireRule && (
|
||||
<Stack space={2}>
|
||||
<Text size='xl' weight='semibold'>Reason for reporting</Text>
|
||||
<Text size='xl' weight='semibold' tag='h1'>Reason for reporting</Text>
|
||||
|
||||
<div className='relative'>
|
||||
<div
|
||||
className='bg-white rounded-lg -space-y-px max-h-96 overflow-y-auto'
|
||||
className='rounded-lg -space-y-px max-h-96 overflow-y-auto'
|
||||
onScroll={handleRulesScrolling}
|
||||
ref={rulesListRef}
|
||||
>
|
||||
|
@ -132,21 +132,20 @@ const ReasonStep = (_props: IReasonStep) => {
|
|||
data-testid={`rule-${rule.id}`}
|
||||
onClick={() => dispatch(changeReportRule(rule.id))}
|
||||
className={classNames({
|
||||
'relative border border-solid border-gray-200 hover:bg-gray-50 text-left w-full p-4 flex justify-between items-center cursor-pointer': true,
|
||||
'relative border border-solid border-gray-200 dark:border-slate-900/75 hover:bg-gray-50 dark:hover:bg-slate-900/50 text-left w-full p-4 flex justify-between items-center cursor-pointer': true,
|
||||
'rounded-tl-lg rounded-tr-lg': idx === 0,
|
||||
'rounded-bl-lg rounded-br-lg': idx === rules.length - 1,
|
||||
'bg-gray-50': isSelected,
|
||||
'bg-gray-50 dark:bg-slate-900': isSelected,
|
||||
})}
|
||||
>
|
||||
<div className='mr-3 flex flex-col'>
|
||||
<span
|
||||
className={classNames('block text-sm font-medium', {
|
||||
'text-primary-800': isSelected,
|
||||
'text-gray-800': !isSelected,
|
||||
})}
|
||||
<Text
|
||||
size='sm'
|
||||
weight='medium'
|
||||
theme={isSelected ? 'primary' : 'default'}
|
||||
>
|
||||
{rule.text}
|
||||
</span>
|
||||
</Text>
|
||||
<Text theme='muted' size='sm'>{rule.subtext}</Text>
|
||||
</div>
|
||||
|
||||
|
@ -164,13 +163,13 @@ const ReasonStep = (_props: IReasonStep) => {
|
|||
</div>
|
||||
|
||||
<div
|
||||
className={classNames('inset-x-0 top-0 flex justify-center bg-gradient-to-b from-white pb-12 pt-8 pointer-events-none dark:from-slate-900 absolute transition-opacity duration-500', {
|
||||
className={classNames('inset-x-0 top-0 flex rounded-t-lg justify-center bg-gradient-to-b from-white pb-12 pt-8 pointer-events-none dark:from-slate-900 absolute transition-opacity duration-500', {
|
||||
'opacity-0': isNearTop,
|
||||
'opacity-100': !isNearTop,
|
||||
})}
|
||||
/>
|
||||
<div
|
||||
className={classNames('inset-x-0 bottom-0 flex justify-center bg-gradient-to-t from-white pt-12 pb-8 pointer-events-none dark:from-slate-900 absolute transition-opacity duration-500', {
|
||||
className={classNames('inset-x-0 bottom-0 flex rounded-b-lg justify-center bg-gradient-to-t from-white pt-12 pb-8 pointer-events-none dark:from-slate-900 absolute transition-opacity duration-500', {
|
||||
'opacity-0': isNearBottom,
|
||||
'opacity-100': !isNearBottom,
|
||||
})}
|
||||
|
|
|
@ -66,6 +66,8 @@ export default function reports(state = initialState, action) {
|
|||
map.setIn(['new', 'status_ids'], ImmutableSet());
|
||||
map.setIn(['new', 'comment'], '');
|
||||
map.setIn(['new', 'isSubmitting'], false);
|
||||
map.setIn(['new', 'rule_id'], null);
|
||||
map.setIn(['new', 'block'], false);
|
||||
});
|
||||
default:
|
||||
return state;
|
||||
|
|
Loading…
Reference in a new issue