Skip to content

Commit 40e91e9

Browse files
Update Backup Media download progress indicator for narrow left panes
Co-authored-by: Jamie Kyle <[email protected]>
1 parent cdfd608 commit 40e91e9

File tree

7 files changed

+117
-73
lines changed

7 files changed

+117
-73
lines changed

stylesheets/components/BackupMediaDownloadProgress.scss

Lines changed: 18 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -4,34 +4,17 @@
44
@use '../mixins';
55
@use '../variables';
66

7-
.BackupMediaDownloadProgress {
8-
border-radius: 12px;
7+
.BackupMediaDownloadProgress__content {
98
display: flex;
10-
gap: 10px;
11-
padding: 11px;
12-
padding-inline-end: 16px;
13-
margin-inline: 10px;
14-
margin-block-end: 6px;
15-
margin-block-start: 2px;
16-
user-select: none;
17-
position: relative;
18-
19-
&__title {
20-
@include mixins.font-body-2-bold;
21-
}
22-
23-
@include mixins.light-theme {
24-
background-color: variables.$color-white;
25-
border: 1px solid variables.$color-gray-20;
26-
}
27-
@include mixins.dark-theme {
28-
background: variables.$color-gray-75;
29-
border: 1px solid variables.$color-gray-60;
30-
}
9+
flex-direction: column;
10+
justify-content: center;
11+
min-height: 36px;
12+
margin-inline-end: 20px;
13+
gap: 2px;
3114
}
3215

33-
.BackupMediaDownloadProgress__icon {
34-
margin-top: 6px;
16+
.BackupMediaDownloadProgress__title {
17+
@include mixins.font-body-2-bold;
3518
}
3619

3720
.BackupMediaDownloadProgress__icon--complete {
@@ -89,10 +72,12 @@ button.BackupMediaDownloadProgress__button {
8972
}
9073

9174
button.BackupMediaDownloadProgress__button-more {
92-
position: absolute;
93-
inset-inline-end: 14px;
94-
inset-block-start: 10px;
9575
@include mixins.button-reset;
76+
& {
77+
position: absolute;
78+
inset-block-start: 8px;
79+
inset-inline-end: 14px;
80+
}
9681
&::after {
9782
content: '';
9883
display: block;
@@ -113,10 +98,12 @@ button.BackupMediaDownloadProgress__button-more {
11398
}
11499
}
115100
button.BackupMediaDownloadProgress__button-close {
116-
position: absolute;
117-
inset-inline-end: 14px;
118-
inset-block-start: 10px;
119101
@include mixins.button-reset;
102+
& {
103+
position: absolute;
104+
inset-block-start: 12px;
105+
inset-inline-end: 12px;
106+
}
120107
&::after {
121108
content: '';
122109
display: block;
@@ -137,14 +124,6 @@ button.BackupMediaDownloadProgress__button-close {
137124
}
138125
}
139126

140-
.BackupMediaDownloadProgress__content {
141-
display: flex;
142-
flex-direction: column;
143-
justify-content: center;
144-
gap: 2px;
145-
min-height: 36px;
146-
}
147-
148127
.BackupMediaDownloadProgress__description {
149128
@include mixins.font-subtitle;
150129

stylesheets/components/LeftPaneDialog.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
padding-inline: 16px 14px;
3131
user-select: none;
3232
width: 100%;
33+
position: relative;
3334

3435
font-size: 13px;
3536
line-height: 18px;

ts/components/BackupMediaDownloadProgress.stories.tsx

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,40 @@ import { action } from '@storybook/addon-actions';
77

88
import { BackupMediaDownloadProgress } from './BackupMediaDownloadProgress';
99
import { KIBIBYTE } from '../types/AttachmentSize';
10+
import { WidthBreakpoint } from './_util';
1011

1112
const { i18n } = window.SignalContext;
1213

1314
type PropsType = ComponentProps<typeof BackupMediaDownloadProgress>;
1415

16+
function Template(args: PropsType): JSX.Element {
17+
return (
18+
<>
19+
<div style={{ width: 350 }}>
20+
<p>Wide</p>
21+
<BackupMediaDownloadProgress
22+
{...args}
23+
widthBreakpoint={WidthBreakpoint.Wide}
24+
/>
25+
</div>
26+
<div style={{ width: 280 }}>
27+
<p>Medium</p>
28+
<BackupMediaDownloadProgress
29+
{...args}
30+
widthBreakpoint={WidthBreakpoint.Medium}
31+
/>
32+
</div>
33+
<div style={{ width: 130 }}>
34+
<p>Narrow</p>
35+
<BackupMediaDownloadProgress
36+
{...args}
37+
widthBreakpoint={WidthBreakpoint.Narrow}
38+
/>
39+
</div>
40+
</>
41+
);
42+
}
43+
1544
export default {
1645
title: 'Components/BackupMediaDownloadProgress',
1746
args: {
@@ -27,34 +56,27 @@ export default {
2756
} satisfies Meta<PropsType>;
2857

2958
export function InProgress(args: PropsType): JSX.Element {
30-
return <BackupMediaDownloadProgress {...args} />;
59+
return <Template {...args} />;
3160
}
3261

3362
export function Increasing(args: PropsType): JSX.Element {
34-
return (
35-
<BackupMediaDownloadProgress
36-
{...args}
37-
{...useIncreasingFractionComplete()}
38-
/>
39-
);
63+
return <Template {...args} {...useIncreasingFractionComplete()} />;
4064
}
4165

4266
export function Paused(args: PropsType): JSX.Element {
43-
return <BackupMediaDownloadProgress {...args} isPaused />;
67+
return <Template {...args} isPaused />;
4468
}
4569

4670
export function Idle(args: PropsType): JSX.Element {
47-
return <BackupMediaDownloadProgress {...args} isIdle />;
71+
return <Template {...args} isIdle />;
4872
}
4973

5074
export function PausedAndIdle(args: PropsType): JSX.Element {
51-
return <BackupMediaDownloadProgress {...args} isPaused isIdle />;
75+
return <Template {...args} isPaused isIdle />;
5276
}
5377

5478
export function Complete(args: PropsType): JSX.Element {
55-
return (
56-
<BackupMediaDownloadProgress {...args} downloadedBytes={args.totalBytes} />
57-
);
79+
return <Template {...args} downloadedBytes={args.totalBytes} />;
5880
}
5981

6082
function useIncreasingFractionComplete() {

ts/components/BackupMediaDownloadProgress.tsx

Lines changed: 49 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,16 @@ import { roundFractionForProgressBar } from '../util/numbers';
99
import { ProgressCircle } from './ProgressCircle';
1010
import { ContextMenu } from './ContextMenu';
1111
import { BackupMediaDownloadCancelConfirmationDialog } from './BackupMediaDownloadCancelConfirmationDialog';
12+
import { LeftPaneDialog } from './LeftPaneDialog';
13+
import { WidthBreakpoint } from './_util';
1214

1315
export type PropsType = Readonly<{
1416
i18n: LocalizerType;
1517
downloadedBytes: number;
1618
totalBytes: number;
1719
isIdle: boolean;
1820
isPaused: boolean;
21+
widthBreakpoint: WidthBreakpoint;
1922
handleCancel: VoidFunction;
2023
handleClose: VoidFunction;
2124
handleResume: VoidFunction;
@@ -32,6 +35,7 @@ export function BackupMediaDownloadProgress({
3235
handleClose,
3336
handleResume,
3437
handlePause,
38+
widthBreakpoint,
3539
}: PropsType): JSX.Element | null {
3640
const [isShowingCancelConfirmation, setIsShowingCancelConfirmation] =
3741
useState(false);
@@ -62,7 +66,10 @@ export function BackupMediaDownloadProgress({
6266
let actionButton: JSX.Element | undefined;
6367
if (fractionComplete === 1) {
6468
icon = (
65-
<div className="BackupMediaDownloadProgress__icon BackupMediaDownloadProgress__icon--complete" />
69+
<div
70+
className="BackupMediaDownloadProgress__icon BackupMediaDownloadProgress__icon--complete"
71+
aria-label={i18n('icu:BackupMediaDownloadProgress__title-complete')}
72+
/>
6673
);
6774
content = (
6875
<>
@@ -77,7 +84,10 @@ export function BackupMediaDownloadProgress({
7784
actionButton = closeButton;
7885
} else if (isIdle && !isPaused) {
7986
icon = (
80-
<div className="BackupMediaDownloadProgress__icon BackupMediaDownloadProgress__icon--idle" />
87+
<div
88+
className="BackupMediaDownloadProgress__icon BackupMediaDownloadProgress__icon--idle"
89+
aria-label={i18n('icu:BackupMediaDownloadProgress__description-idle')}
90+
/>
8191
);
8292
content = (
8393
<>
@@ -94,28 +104,34 @@ export function BackupMediaDownloadProgress({
94104
);
95105
actionButton = closeButton;
96106
} else {
97-
icon = (
98-
<div className="BackupMediaDownloadProgress__icon">
99-
<ProgressCircle fractionComplete={fractionComplete} />
100-
</div>
101-
);
102-
103107
if (isPaused) {
104108
content = (
105109
<>
106110
<div className="BackupMediaDownloadProgress__title">
107111
{i18n('icu:BackupMediaDownloadProgress__title-paused')}
108112
</div>
109-
<button
110-
type="button"
111-
onClick={handleResume}
112-
className="BackupMediaDownloadProgress__button"
113-
aria-label={i18n('icu:BackupMediaDownloadProgress__button-resume')}
114-
>
115-
{i18n('icu:BackupMediaDownloadProgress__button-resume')}
116-
</button>
113+
{widthBreakpoint !== WidthBreakpoint.Narrow ? (
114+
<button
115+
type="button"
116+
onClick={handleResume}
117+
className="BackupMediaDownloadProgress__button"
118+
aria-label={i18n(
119+
'icu:BackupMediaDownloadProgress__button-resume'
120+
)}
121+
>
122+
{i18n('icu:BackupMediaDownloadProgress__button-resume')}
123+
</button>
124+
) : null}
117125
</>
118126
);
127+
icon = (
128+
<div className="BackupMediaDownloadProgress__icon">
129+
<ProgressCircle
130+
fractionComplete={fractionComplete}
131+
ariaLabel={i18n('icu:BackupMediaDownloadProgress__title-paused')}
132+
/>
133+
</div>
134+
);
119135
} else {
120136
content = (
121137
<>
@@ -131,6 +147,16 @@ export function BackupMediaDownloadProgress({
131147
</div>
132148
</>
133149
);
150+
icon = (
151+
<div className="BackupMediaDownloadProgress__icon">
152+
<ProgressCircle
153+
fractionComplete={fractionComplete}
154+
ariaLabel={i18n(
155+
'icu:BackupMediaDownloadProgress__title-in-progress'
156+
)}
157+
/>
158+
</div>
159+
);
134160
}
135161

136162
actionButton = (
@@ -173,17 +199,20 @@ export function BackupMediaDownloadProgress({
173199
}
174200

175201
return (
176-
<div className="BackupMediaDownloadProgress">
177-
{icon}
202+
<LeftPaneDialog
203+
type="info"
204+
containerWidthBreakpoint={widthBreakpoint}
205+
icon={icon}
206+
>
178207
<div className="BackupMediaDownloadProgress__content">{content}</div>
179-
{actionButton}
208+
{widthBreakpoint !== WidthBreakpoint.Narrow ? actionButton : null}
180209
{isShowingCancelConfirmation ? (
181210
<BackupMediaDownloadCancelConfirmationDialog
182211
i18n={i18n}
183212
handleDialogClose={() => setIsShowingCancelConfirmation(false)}
184213
handleConfirmCancel={handleConfirmedCancel}
185214
/>
186215
) : null}
187-
</div>
216+
</LeftPaneDialog>
188217
);
189218
}

ts/components/LeftPane.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -801,6 +801,7 @@ export function LeftPane({
801801
{showBackupMediaDownloadProgress ? (
802802
<BackupMediaDownloadProgress
803803
i18n={i18n}
804+
widthBreakpoint={widthBreakpoint}
804805
{...backupMediaDownloadProgress}
805806
handleClose={dismissBackupMediaDownloadBanner}
806807
handlePause={pauseBackupMediaDownload}

ts/components/ProgressCircle.stories.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,12 @@ type Props = React.ComponentProps<typeof ProgressCircle>;
1010
export default {
1111
title: 'Components/ProgressCircle',
1212
component: ProgressCircle,
13-
args: { fractionComplete: 0, width: undefined, strokeWidth: undefined },
13+
args: {
14+
fractionComplete: 0,
15+
width: undefined,
16+
strokeWidth: undefined,
17+
ariaLabel: undefined,
18+
},
1419
} satisfies ComponentMeta<Props>;
1520

1621
export function Zero(args: Props): JSX.Element {

ts/components/ProgressCircle.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@ export function ProgressCircle({
77
fractionComplete,
88
width = 24,
99
strokeWidth = 3,
10+
ariaLabel,
1011
}: {
1112
fractionComplete: number;
1213
width?: number;
1314
strokeWidth?: number;
15+
ariaLabel?: string;
1416
}): JSX.Element {
1517
const radius = width / 2 - strokeWidth / 2;
1618
const circumference = radius * 2 * Math.PI;
@@ -21,6 +23,11 @@ export function ProgressCircle({
2123
className="ProgressCircle"
2224
width={widthInPixels}
2325
height={widthInPixels}
26+
role="progressbar"
27+
aria-label={ariaLabel}
28+
aria-valuenow={Math.trunc(fractionComplete * 100)}
29+
aria-valuemin={0}
30+
aria-valuemax={100}
2431
>
2532
<circle
2633
className="ProgressCircle__background"

0 commit comments

Comments
 (0)