Skip to content
This repository was archived by the owner on Jul 9, 2025. It is now read-only.

Commit 92c8da1

Browse files
committed
Bug 1973214 - Newtab fix add shortcut tooltip r=home-newtab-reviewers,fluent-reviewers,npypchenko,bolsson
Differential Revision: https://phabricator.services.mozilla.com/D256146
1 parent f3ed9a1 commit 92c8da1

File tree

8 files changed

+139
-106
lines changed

8 files changed

+139
-106
lines changed

browser/extensions/newtab/content-src/components/TopSites/TopSite.jsx

Lines changed: 42 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -275,9 +275,12 @@ export class TopSiteLink extends React.PureComponent {
275275
selectedColor,
276276
} = this.calculateStyle();
277277

278-
let addButtonl10n = {
278+
const addButtonLabell10n = {
279279
"data-l10n-id": "newtab-topsites-add-shortcut-label",
280280
};
281+
const addButtonTitlel10n = {
282+
"data-l10n-id": "newtab-topsites-add-shortcut-title",
283+
};
281284

282285
let draggableProps = {};
283286
if (isDraggable) {
@@ -367,6 +370,7 @@ export class TopSiteLink extends React.PureComponent {
367370
data-is-sponsored-link={!!link.sponsored_tile_id}
368371
title={title}
369372
onFocus={this.props.onFocus}
373+
{...(isAddButton && { ...addButtonTitlel10n })}
370374
>
371375
{shortcutsRefresh && link.isPinned && (
372376
<div className="icon icon-pin-small" />
@@ -404,7 +408,7 @@ export class TopSiteLink extends React.PureComponent {
404408
<span
405409
className="title-label"
406410
dir="auto"
407-
{...(isAddButton && { ...addButtonl10n })}
411+
{...(isAddButton && { ...addButtonLabell10n })}
408412
>
409413
{!shortcutsRefresh && link.isPinned && (
410414
<div className="icon icon-pin-small" />
@@ -658,7 +662,7 @@ TopSite.defaultProps = {
658662
onActivate() {},
659663
};
660664

661-
export class TopSitePlaceholder extends React.PureComponent {
665+
export class TopSiteAddButton extends React.PureComponent {
662666
constructor(props) {
663667
super(props);
664668
this.onEditButtonClick = this.onEditButtonClick.bind(this);
@@ -672,21 +676,12 @@ export class TopSitePlaceholder extends React.PureComponent {
672676
}
673677

674678
render() {
675-
let addButtonProps = {};
676-
if (this.props.isAddButton) {
677-
addButtonProps = {
678-
title: "newtab-topsites-add-shortcut-label",
679-
onClick: this.onEditButtonClick,
680-
};
681-
}
682-
683679
return (
684680
<TopSiteLink
685681
{...this.props}
686-
{...(this.props.isAddButton ? { ...addButtonProps } : {})}
687-
className={`placeholder ${this.props.className || ""} ${
688-
this.props.isAddButton ? "add-button" : ""
689-
}`}
682+
isAddButton={true}
683+
className={`add-button ${this.props.className || ""}`}
684+
onClick={this.onEditButtonClick}
690685
setPref={this.props.setPref}
691686
isDraggable={false}
692687
tabIndex={this.props.tabIndex}
@@ -695,6 +690,18 @@ export class TopSitePlaceholder extends React.PureComponent {
695690
}
696691
}
697692

693+
export class TopSitePlaceholder extends React.PureComponent {
694+
render() {
695+
return (
696+
<TopSiteLink
697+
{...this.props}
698+
className={`placeholder ${this.props.className || ""}`}
699+
isDraggable={false}
700+
/>
701+
);
702+
}
703+
}
704+
698705
export class _TopSiteList extends React.PureComponent {
699706
static get DEFAULT_STATE() {
700707
return {
@@ -956,29 +963,29 @@ export class _TopSiteList extends React.PureComponent {
956963
// tile for the about:home startup cache.
957964
if (
958965
!link ||
959-
(props.App.isForStartupCache.TopSites && isSponsored(link)) ||
960-
topSites[i]?.isAddButton
966+
(props.App.isForStartupCache.TopSites && isSponsored(link))
961967
) {
962968
if (link) {
963-
topSiteLink = (
964-
<TopSitePlaceholder
965-
{...slotProps}
966-
{...commonProps}
967-
isAddButton={topSites[i] && topSites[i].isAddButton}
968-
setRef={
969-
i === this.state.focusedIndex
970-
? el => {
971-
this.focusedRef = el;
972-
}
973-
: () => {}
974-
}
975-
tabIndex={i === this.state.focusedIndex ? 0 : -1}
976-
onFocus={() => {
977-
this.onTopsiteFocus(i);
978-
}}
979-
/>
980-
);
969+
topSiteLink = <TopSitePlaceholder {...slotProps} {...commonProps} />;
981970
}
971+
} else if (topSites[i]?.isAddButton) {
972+
topSiteLink = (
973+
<TopSiteAddButton
974+
{...slotProps}
975+
{...commonProps}
976+
setRef={
977+
i === this.state.focusedIndex
978+
? el => {
979+
this.focusedRef = el;
980+
}
981+
: () => {}
982+
}
983+
tabIndex={i === this.state.focusedIndex ? 0 : -1}
984+
onFocus={() => {
985+
this.onTopsiteFocus(i);
986+
}}
987+
/>
988+
);
982989
} else {
983990
topSiteLink = (
984991
<TopSite

browser/extensions/newtab/content-src/components/TopSites/_TopSites.scss

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -306,20 +306,22 @@ $calculated-max-width-twice-widest: $break-point-widest + 2 * $card-width;
306306
box-shadow: $shadow-card;
307307
cursor: default;
308308
}
309+
}
309310

310-
&.add-button {
311-
.tile {
312-
background-color: var(--button-background-color);
313-
314-
.icon-wrapper {
315-
background-image: url('chrome://global/skin/icons/plus-20.svg');
316-
background-size: cover;
317-
background-repeat: no-repeat;
318-
height: 20px;
319-
width: 20px;
320-
fill: var(--icon-color);
321-
-moz-context-properties: fill;
322-
}
311+
&.add-button {
312+
.tile {
313+
background-color: var(--button-background-color);
314+
box-shadow: $shadow-card;
315+
cursor: default;
316+
317+
.icon-wrapper {
318+
background-image: url('chrome://global/skin/icons/plus-20.svg');
319+
background-size: cover;
320+
background-repeat: no-repeat;
321+
height: 20px;
322+
width: 20px;
323+
fill: var(--icon-color);
324+
-moz-context-properties: fill;
323325
}
324326
}
325327
}
@@ -397,15 +399,15 @@ $calculated-max-width-twice-widest: $break-point-widest + 2 * $card-width;
397399
}
398400
}
399401

402+
.icon-wrapper {
403+
width: 40px;
404+
height: 40px;
405+
}
406+
400407
.tile {
401408
background: var(--newtab-background-card);
402409
border-radius: var(--border-radius-large);
403410

404-
.icon-wrapper {
405-
width: 40px;
406-
height: 40px;
407-
}
408-
409411
.top-site-icon {
410412
// Remove the white background colors on icons,
411413
// fully rely on the icon itself to make the decision on the background.

browser/extensions/newtab/css/activity-stream.css

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -978,10 +978,12 @@ main section {
978978
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
979979
cursor: default;
980980
}
981-
.top-site-outer.placeholder.add-button .tile {
981+
.top-site-outer.add-button .tile {
982982
background-color: var(--button-background-color);
983+
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
984+
cursor: default;
983985
}
984-
.top-site-outer.placeholder.add-button .tile .icon-wrapper {
986+
.top-site-outer.add-button .tile .icon-wrapper {
985987
background-image: url("chrome://global/skin/icons/plus-20.svg");
986988
background-size: cover;
987989
background-repeat: no-repeat;
@@ -1043,14 +1045,14 @@ main section {
10431045
.shortcuts-refresh .top-site-outer .top-site-button:focus + div .context-menu-button {
10441046
opacity: 1;
10451047
}
1048+
.shortcuts-refresh .top-site-outer .icon-wrapper {
1049+
width: 40px;
1050+
height: 40px;
1051+
}
10461052
.shortcuts-refresh .top-site-outer .tile {
10471053
background: var(--newtab-background-card);
10481054
border-radius: var(--border-radius-large);
10491055
}
1050-
.shortcuts-refresh .top-site-outer .tile .icon-wrapper {
1051-
width: 40px;
1052-
height: 40px;
1053-
}
10541056
.shortcuts-refresh .top-site-outer .tile .top-site-icon {
10551057
background-color: transparent;
10561058
border-radius: var(--border-radius-medium);

browser/extensions/newtab/data/content/activity-stream.bundle.js

Lines changed: 34 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -9154,9 +9154,12 @@ class TopSiteLink extends (external_React_default()).PureComponent {
91549154
imageClassName,
91559155
selectedColor
91569156
} = this.calculateStyle();
9157-
let addButtonl10n = {
9157+
const addButtonLabell10n = {
91589158
"data-l10n-id": "newtab-topsites-add-shortcut-label"
91599159
};
9160+
const addButtonTitlel10n = {
9161+
"data-l10n-id": "newtab-topsites-add-shortcut-title"
9162+
};
91609163
let draggableProps = {};
91619164
if (isDraggable) {
91629165
draggableProps = {
@@ -9223,7 +9226,7 @@ class TopSiteLink extends (external_React_default()).PureComponent {
92239226
ref: this.props.setRef
92249227
}, draggableProps), /*#__PURE__*/external_React_default().createElement("div", {
92259228
className: "top-site-inner"
9226-
}, /*#__PURE__*/external_React_default().createElement("a", {
9229+
}, /*#__PURE__*/external_React_default().createElement("a", TopSite_extends({
92279230
className: "top-site-button",
92289231
href: link.searchTopSite ? undefined : link.url,
92299232
tabIndex: this.props.tabIndex,
@@ -9233,7 +9236,9 @@ class TopSiteLink extends (external_React_default()).PureComponent {
92339236
"data-is-sponsored-link": !!link.sponsored_tile_id,
92349237
title: title,
92359238
onFocus: this.props.onFocus
9236-
}, shortcutsRefresh && link.isPinned && /*#__PURE__*/external_React_default().createElement("div", {
9239+
}, isAddButton && {
9240+
...addButtonTitlel10n
9241+
}), shortcutsRefresh && link.isPinned && /*#__PURE__*/external_React_default().createElement("div", {
92379242
className: "icon icon-pin-small"
92389243
}), /*#__PURE__*/external_React_default().createElement("div", {
92399244
className: "tile",
@@ -9259,7 +9264,7 @@ class TopSiteLink extends (external_React_default()).PureComponent {
92599264
className: "title-label",
92609265
dir: "auto"
92619266
}, isAddButton && {
9262-
...addButtonl10n
9267+
...addButtonLabell10n
92639268
}), !shortcutsRefresh && link.isPinned && /*#__PURE__*/external_React_default().createElement("div", {
92649269
className: "icon icon-pin-small"
92659270
}), shortcutsRefresh && link.searchTopSite && /*#__PURE__*/external_React_default().createElement("div", {
@@ -9482,7 +9487,7 @@ TopSite.defaultProps = {
94829487
link: {},
94839488
onActivate() {}
94849489
};
9485-
class TopSitePlaceholder extends (external_React_default()).PureComponent {
9490+
class TopSiteAddButton extends (external_React_default()).PureComponent {
94869491
constructor(props) {
94879492
super(props);
94889493
this.onEditButtonClick = this.onEditButtonClick.bind(this);
@@ -9496,23 +9501,24 @@ class TopSitePlaceholder extends (external_React_default()).PureComponent {
94969501
});
94979502
}
94989503
render() {
9499-
let addButtonProps = {};
9500-
if (this.props.isAddButton) {
9501-
addButtonProps = {
9502-
title: "newtab-topsites-add-shortcut-label",
9503-
onClick: this.onEditButtonClick
9504-
};
9505-
}
9506-
return /*#__PURE__*/external_React_default().createElement(TopSiteLink, TopSite_extends({}, this.props, this.props.isAddButton ? {
9507-
...addButtonProps
9508-
} : {}, {
9509-
className: `placeholder ${this.props.className || ""} ${this.props.isAddButton ? "add-button" : ""}`,
9504+
return /*#__PURE__*/external_React_default().createElement(TopSiteLink, TopSite_extends({}, this.props, {
9505+
isAddButton: true,
9506+
className: `add-button ${this.props.className || ""}`,
9507+
onClick: this.onEditButtonClick,
95109508
setPref: this.props.setPref,
95119509
isDraggable: false,
95129510
tabIndex: this.props.tabIndex
95139511
}));
95149512
}
95159513
}
9514+
class TopSitePlaceholder extends (external_React_default()).PureComponent {
9515+
render() {
9516+
return /*#__PURE__*/external_React_default().createElement(TopSiteLink, TopSite_extends({}, this.props, {
9517+
className: `placeholder ${this.props.className || ""}`,
9518+
isDraggable: false
9519+
}));
9520+
}
9521+
}
95169522
class _TopSiteList extends (external_React_default()).PureComponent {
95179523
static get DEFAULT_STATE() {
95189524
return {
@@ -9737,19 +9743,20 @@ class _TopSiteList extends (external_React_default()).PureComponent {
97379743
let topSiteLink;
97389744
// Use a placeholder if the link is empty or it's rendering a sponsored
97399745
// tile for the about:home startup cache.
9740-
if (!link || props.App.isForStartupCache.TopSites && isSponsored(link) || topSites[i]?.isAddButton) {
9746+
if (!link || props.App.isForStartupCache.TopSites && isSponsored(link)) {
97419747
if (link) {
9742-
topSiteLink = /*#__PURE__*/external_React_default().createElement(TopSitePlaceholder, TopSite_extends({}, slotProps, commonProps, {
9743-
isAddButton: topSites[i] && topSites[i].isAddButton,
9744-
setRef: i === this.state.focusedIndex ? el => {
9745-
this.focusedRef = el;
9746-
} : () => {},
9747-
tabIndex: i === this.state.focusedIndex ? 0 : -1,
9748-
onFocus: () => {
9749-
this.onTopsiteFocus(i);
9750-
}
9751-
}));
9748+
topSiteLink = /*#__PURE__*/external_React_default().createElement(TopSitePlaceholder, TopSite_extends({}, slotProps, commonProps));
97529749
}
9750+
} else if (topSites[i]?.isAddButton) {
9751+
topSiteLink = /*#__PURE__*/external_React_default().createElement(TopSiteAddButton, TopSite_extends({}, slotProps, commonProps, {
9752+
setRef: i === this.state.focusedIndex ? el => {
9753+
this.focusedRef = el;
9754+
} : () => {},
9755+
tabIndex: i === this.state.focusedIndex ? 0 : -1,
9756+
onFocus: () => {
9757+
this.onTopsiteFocus(i);
9758+
}
9759+
}));
97539760
} else {
97549761
topSiteLink = /*#__PURE__*/external_React_default().createElement(TopSite, TopSite_extends({
97559762
link: link,

browser/extensions/newtab/test/browser/browser_topsites_contextMenu_options.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ test_newtab({
4949
before: setDefaultTopSites,
5050
// Test verifies that the next top site in queue replaces a dismissed top site.
5151
test: async function defaultTopSites_dismiss() {
52-
const siteSelector = ".top-site-outer:not(.search-shortcut, .placeholder)";
52+
const siteSelector =
53+
".top-site-outer:not(.search-shortcut, .placeholder, .add-button)";
5354
await ContentTaskUtils.waitForCondition(
5455
() => content.document.querySelector(siteSelector),
5556
"Topsite tippytop icon not found"

0 commit comments

Comments
 (0)