Skip to content

Commit b131675

Browse files
committed
copy
1 parent 93de6db commit b131675

File tree

6 files changed

+103
-10
lines changed

6 files changed

+103
-10
lines changed

special-pages/pages/new-tab/app/activity/components/Activity.js

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { useVisibility } from '../../widget-list/widget-config.provider.js';
88
import { useDocumentVisibility } from '../../utils.js';
99
import { useCustomizer } from '../../customizer/components/CustomizerMenu.js';
1010
import { usePlatformName } from '../../settings.provider.js';
11-
import { Heading } from '../../privacy-stats/components/PrivacyStats.js';
11+
import { ActivityHeading } from '../../privacy-stats/components/PrivacyStats.js';
1212
import { ChevronSmall } from '../../components/Icons.js';
1313
import { CompanyIcon } from '../../components/CompanyIcon.js';
1414
import { Trans } from '../../../../../shared/components/TranslationsProvider.js';
@@ -44,8 +44,8 @@ function ActivityConfigured({ expansion, toggle }) {
4444
return acc + item.totalCount;
4545
}, 0);
4646
});
47-
const canExpand = useComputed(() => {
48-
return Object.keys(activity.value.items).length > 0;
47+
const itemCount = useComputed(() => {
48+
return Object.keys(activity.value.items).length;
4949
});
5050

5151
// see: https://www.w3.org/WAI/ARIA/apg/patterns/accordion/examples/accordion/
@@ -55,17 +55,18 @@ function ActivityConfigured({ expansion, toggle }) {
5555

5656
return (
5757
<div class={styles.root}>
58-
<Heading
59-
recent={count.value}
58+
<ActivityHeading
59+
trackerCount={count.value}
60+
itemCount={itemCount.value}
6061
onToggle={toggle}
6162
expansion={expansion}
62-
canExpand={canExpand.value}
63+
canExpand={itemCount.value > 0}
6364
buttonAttrs={{
6465
'aria-controls': WIDGET_ID,
6566
id: TOGGLE_ID,
6667
}}
6768
/>
68-
{canExpand && expanded && <ActivityBody canBurn={canBurn} />}
69+
{itemCount.value > 0 && expanded && <ActivityBody canBurn={canBurn} />}
6970
</div>
7071
);
7172
}

special-pages/pages/new-tab/app/activity/integration-tests/activity.page.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,4 +291,23 @@ export class ActivityPage {
291291
- text: 2 hrs ago
292292
`);
293293
}
294+
295+
async hasEmptyTitle() {
296+
const { page } = this;
297+
await expect(page.getByTestId('ActivityHeading')).toMatchAriaSnapshot(`
298+
- img "Privacy Shield"
299+
- heading "No recent browsing activity" [level=2]
300+
- paragraph: Recently visited sites will appear here. Keep browsing to see how many trackers we block.
301+
`);
302+
}
303+
async hasPopuplatedTitle() {
304+
const { page } = this;
305+
await expect(page.getByTestId('ActivityHeading')).toMatchAriaSnapshot(`
306+
- img "Privacy Shield"
307+
- heading "0 tracking attempts blocked" [level=2]
308+
- button "Hide recent activity" [expanded] [pressed]:
309+
- img
310+
- paragraph: Past 7 days
311+
`);
312+
}
294313
}

special-pages/pages/new-tab/app/activity/integration-tests/activity.spec.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,15 @@ test.describe('activity widget', () => {
4242
await ntp.openPage({ additional: { feed: 'activity', activity: 'onlyTopLevel' } });
4343
await ap.cannotExpandListWhenEmpty();
4444
});
45+
test('titles', async ({ page }, workerInfo) => {
46+
const ntp = NewtabPage.create(page, workerInfo);
47+
const ap = new ActivityPage(page, ntp);
48+
await ntp.reducedMotion();
49+
await ntp.openPage({ additional: { feed: 'activity', activity: 'empty' } });
50+
await ap.hasEmptyTitle();
51+
await ntp.openPage({ additional: { feed: 'activity', activity: 'onlyTopLevel' } });
52+
await ap.hasPopuplatedTitle();
53+
});
4554
test('favorite item', async ({ page }, workerInfo) => {
4655
const ntp = NewtabPage.create(page, workerInfo);
4756
const ap = new ActivityPage(page, ntp);

special-pages/pages/new-tab/app/activity/strings.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
11
{
2+
"activity_noRecent_title": {
3+
"title": "No recent browsing activity",
4+
"note": "Placeholder to indicate that no browsing activity was seen in the last 7 days"
5+
},
6+
"activity_noRecent_subtitle": {
7+
"title": "Recently visited sites will appear here. Keep browsing to see how many trackers we block.",
8+
"note": "Shown in the place a list of browsing history entries will be displayed."
9+
},
210
"activity_no_trackers": {
311
"title": "No trackers found",
412
"note": "Placeholder message indicating that no trackers are detected"

special-pages/pages/new-tab/app/privacy-stats/components/PrivacyStats.js

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ import { CompanyIcon } from '../../components/CompanyIcon.js';
1515

1616
/**
1717
* @import enStrings from "../strings.json"
18+
* @import activityStrings from "../../activity/strings.json"
19+
* @typedef {enStrings & activityStrings} Strings
1820
* @typedef {import('../../../types/new-tab').TrackerCompany} TrackerCompany
1921
* @typedef {import('../../../types/new-tab').Expansion} Expansion
2022
* @typedef {import('../../../types/new-tab').Animation} Animation
@@ -104,7 +106,7 @@ function PrivacyStatsConfigured({ parentRef, expansion, data, toggle }) {
104106
* @param {import("preact").ComponentProps<'button'>} [props.buttonAttrs]
105107
*/
106108
export function Heading({ expansion, canExpand, recent, onToggle, buttonAttrs = {} }) {
107-
const { t } = useTypedTranslationWith(/** @type {enStrings} */ ({}));
109+
const { t } = useTypedTranslationWith(/** @type {Strings} */ ({}));
108110
const [formatter] = useState(() => new Intl.NumberFormat());
109111

110112
const none = recent === 0;
@@ -139,14 +141,60 @@ export function Heading({ expansion, canExpand, recent, onToggle, buttonAttrs =
139141
);
140142
}
141143

144+
/**
145+
* @param {object} props
146+
* @param {Expansion} props.expansion
147+
* @param {number} props.trackerCount
148+
* @param {number} props.itemCount
149+
* @param {boolean} props.canExpand
150+
* @param {() => void} props.onToggle
151+
* @param {import("preact").ComponentProps<'button'>} [props.buttonAttrs]
152+
*/
153+
export function ActivityHeading({ expansion, canExpand, itemCount, trackerCount, onToggle, buttonAttrs = {} }) {
154+
const { t } = useTypedTranslationWith(/** @type {Strings} */ ({}));
155+
const [formatter] = useState(() => new Intl.NumberFormat());
156+
157+
const none = itemCount === 0;
158+
const someItems = itemCount > 0;
159+
const trackerCountFormatted = formatter.format(trackerCount);
160+
const allTimeString =
161+
trackerCount === 1 ? t('stats_countBlockedSingular') : t('stats_countBlockedPlural', { count: trackerCountFormatted });
162+
163+
return (
164+
<div className={styles.heading} data-testid={'ActivityHeading'}>
165+
<span className={styles.headingIcon}>
166+
<img src="./icons/shield.svg" alt="Privacy Shield" />
167+
</span>
168+
{none && <h2 className={styles.title}>{t('activity_noRecent_title')}</h2>}
169+
{someItems && <h2 className={styles.title}>{allTimeString}</h2>}
170+
{canExpand && (
171+
<span className={styles.widgetExpander}>
172+
<ShowHideButton
173+
buttonAttrs={{
174+
...buttonAttrs,
175+
'aria-expanded': expansion === 'expanded',
176+
'aria-pressed': expansion === 'expanded',
177+
}}
178+
onClick={onToggle}
179+
text={expansion === 'expanded' ? t('stats_hideLabel') : t('stats_toggleLabel')}
180+
shape="round"
181+
/>
182+
</span>
183+
)}
184+
{itemCount === 0 && <p className={styles.subtitle}>{t('activity_noRecent_subtitle')}</p>}
185+
{itemCount > 0 && <p className={cn(styles.subtitle, styles.uppercase)}>{t('stats_feedCountBlockedPeriod')}</p>}
186+
</div>
187+
);
188+
}
189+
142190
/**
143191
* @param {object} props
144192
* @param {import("preact").ComponentProps<'ul'>} [props.listAttrs]
145193
* @param {TrackerCompany[]} props.trackerCompanies
146194
*/
147195

148196
export function PrivacyStatsBody({ trackerCompanies, listAttrs = {} }) {
149-
const { t } = useTypedTranslationWith(/** @type {enStrings} */ ({}));
197+
const { t } = useTypedTranslationWith(/** @type {Strings} */ ({}));
150198
const messaging = useMessaging();
151199
const [formatter] = useState(() => new Intl.NumberFormat());
152200
const defaultRowMax = 5;
@@ -221,7 +269,7 @@ export function PrivacyStatsBody({ trackerCompanies, listAttrs = {} }) {
221269
* whether to incur the side effects (data fetching).
222270
*/
223271
export function PrivacyStatsCustomized() {
224-
const { t } = useTypedTranslationWith(/** @type {enStrings} */ ({}));
272+
const { t } = useTypedTranslationWith(/** @type {Strings} */ ({}));
225273
const drawer = useCustomizerDrawerSettings();
226274

227275
/**

special-pages/pages/new-tab/public/locales/en/new-tab.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,14 @@
273273
"title": "Delete image {number}",
274274
"note": "Label text on a button that deletes an image. {number} will be replaced with a numeric reference of 1-8, eg: 'Delete image 1'"
275275
},
276+
"activity_noRecent_title": {
277+
"title": "No recent browsing activity",
278+
"note": "Placeholder to indicate that no browsing activity was seen in the last 7 days"
279+
},
280+
"activity_noRecent_subtitle": {
281+
"title": "Recently visited sites will appear here. Keep browsing to see how many trackers we block.",
282+
"note": "Shown in the place a list of browsing history entries will be displayed."
283+
},
276284
"activity_no_trackers": {
277285
"title": "No trackers found",
278286
"note": "Placeholder message indicating that no trackers are detected"

0 commit comments

Comments
 (0)