Bug 1554322 - Add accessible content, static clamping and bug fixes to Activity Stream r=k88hudson

Differential Revision: https://phabricator.services.mozilla.com/D32540

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Ed Lee 2019-05-25 00:38:53 +00:00
parent 9180d72bfa
commit e3ec6b73eb
235 changed files with 1123 additions and 1236 deletions

View File

@ -17,6 +17,7 @@ export class _CollapsibleSection extends React.PureComponent {
super(props);
this.onBodyMount = this.onBodyMount.bind(this);
this.onHeaderClick = this.onHeaderClick.bind(this);
this.onKeyPress = this.onKeyPress.bind(this);
this.onTransitionEnd = this.onTransitionEnd.bind(this);
this.enableOrDisableAnimation = this.enableOrDisableAnimation.bind(this);
this.onMenuButtonClick = this.onMenuButtonClick.bind(this);
@ -91,6 +92,12 @@ export class _CollapsibleSection extends React.PureComponent {
}));
}
onKeyPress(event) {
if (event.key === "Enter" || event.key === " ") {
this.onHeaderClick();
}
}
_getSectionBodyHeight() {
const div = this.sectionBody;
if (div.style.display === "none") {
@ -148,16 +155,18 @@ export class _CollapsibleSection extends React.PureComponent {
return (
<section
className={`collapsible-section ${this.props.className}${enableAnimation ? " animation-enabled" : ""}${collapsed ? " collapsed" : ""}${active ? " active" : ""}`}
aria-expanded={!collapsed}
// Note: data-section-id is used for web extension api tests in mozilla central
data-section-id={id}>
<div className="section-top-bar">
<h3 className="section-title">
<span className="click-target-container">
<span className="click-target" onClick={this.onHeaderClick}>
{/* Click-targets that toggle a collapsible section should have an aria-expanded attribute; see bug 1553234 */}
<span className="click-target" role="button" tabIndex="0" onKeyPress={this.onKeyPress} onClick={this.onHeaderClick}>
{this.renderIcon()}
{getFormattedMessage(title)}
</span>
<span className="click-target" onClick={this.onHeaderClick}>
<span className="click-target" role="button" tabIndex="0" onKeyPress={this.onKeyPress} onClick={this.onHeaderClick}>
{isCollapsible && <span className={`collapsible-arrow icon ${collapsed ? "icon-arrowhead-forward-small" : "icon-arrowhead-down-small"}`} />}
</span>
<span className="learn-more-link-wrapper">

View File

@ -56,7 +56,7 @@ export class _ConfirmDialog extends React.PureComponent {
}
return (<div className="confirmation-dialog">
<div className="modal-overlay" onClick={this._handleCancelBtn} />
<div className="modal-overlay" onClick={this._handleCancelBtn} role="presentation" />
<div className="modal">
<section className="modal-message">
{this.props.data.icon && <span className={`icon icon-spacer icon-${this.props.data.icon}`} />}

View File

@ -37,11 +37,11 @@ export class ContextMenu extends React.PureComponent {
}
render() {
return (<span className="context-menu" onClick={this.onClick}>
<ul role="menu" className="context-menu-list">
return (<span role="menu" className="context-menu" onClick={this.onClick} onKeyDown={this.onClick} tabIndex="0" >
<ul className="context-menu-list">
{this.props.options.map((option, i) => (option.type === "separator" ?
(<li key={i} className="separator" />) :
(option.type !== "empty" && <ContextMenuItem key={i} option={option} hideContext={this.hideContext} />)
(option.type !== "empty" && <ContextMenuItem key={i} option={option} hideContext={this.hideContext} tabIndex="0" />)
))}
</ul>
</span>);
@ -81,11 +81,11 @@ export class ContextMenuItem extends React.PureComponent {
render() {
const {option} = this.props;
return (
<li role="menuitem" className="context-menu-item">
<a onClick={this.onClick} onKeyDown={this.onKeyDown} tabIndex="0" className={option.disabled ? "disabled" : ""}>
<li role="menuitem" className="context-menu-item" >
<button className={option.disabled ? "disabled" : ""} onClick={this.onClick} onKeyDown={this.onKeyDown} tabIndex="0" >
{option.icon && <span className={`icon icon-spacer icon-${option.icon}`} />}
{option.label}
</a>
</button>
</li>);
}
}

View File

@ -24,13 +24,16 @@
margin: $context-menu-outer-padding 0;
}
> a {
> a,
> button {
align-items: center;
color: inherit;
cursor: pointer;
display: flex;
width: 100%;
line-height: 16px;
outline: none;
border: 0;
padding: $context-menu-item-padding;
white-space: nowrap;

View File

@ -66,6 +66,10 @@ $col4-header-font-size: 14;
font-size: 17px;
line-height: 24px;
}
.excerpt {
@include limit-visibile-lines(3, 24, 15);
}
}
&.ds-card-grid-divisible-by-4 .title {

View File

@ -1,5 +1,4 @@
import {actionCreators as ac} from "common/Actions.jsm";
import {clampTotalLines} from "content-src/lib/clamp-total-lines";
import {DSImage} from "../DSImage/DSImage.jsx";
import {DSLinkMenu} from "../DSLinkMenu/DSLinkMenu";
import {ImpressionStats} from "../../DiscoveryStreamImpressionStats/ImpressionStats";
@ -41,11 +40,9 @@ export class DSCard extends React.PureComponent {
<DSImage extraClassNames="img" source={this.props.image_src} rawSource={this.props.raw_image_src} />
</div>
<div className="meta">
<div className="info-wrap"
data-total-lines="7"
ref={clampTotalLines}>
<p className="source clamp" data-clamp="1">{this.props.source}</p>
<header className="title clamp" data-clamp="4">{this.props.title}</header>
<div className="info-wrap">
<p className="source clamp">{this.props.source}</p>
<header className="title clamp">{this.props.title}</header>
{this.props.excerpt && <p className="excerpt clamp">{this.props.excerpt}</p>}
</div>
{this.props.context && (

View File

@ -39,9 +39,6 @@ $excerpt-line-height: 20;
}
.ds-card-link {
display: flex;
flex-direction: column;
justify-content: space-between;
height: 100%;
&:focus {
@ -85,8 +82,7 @@ $excerpt-line-height: 20;
.meta {
display: flex;
flex-direction: column;
flex-grow: 1;
padding: 12px;
padding: 12px 16px;
.info-wrap {
flex-grow: 1;
@ -105,6 +101,7 @@ $excerpt-line-height: 20;
}
.source {
-webkit-line-clamp: 1;
margin-bottom: 2px;
}

View File

@ -78,13 +78,13 @@ export class DSImage extends React.PureComponent {
this.state.containerHeight * 2
);
img = (<img crossOrigin="anonymous"
img = (<img alt="" crossOrigin="anonymous"
onError={this.onOptimizedImageError}
src={source}
srcSet={`${source2x} 2x`} />);
}
} else if (!this.state.nonOptimizedImageFailed) {
img = (<img crossOrigin="anonymous"
img = (<img alt="" crossOrigin="anonymous"
onError={this.onNonOptimizedImageError}
src={this.props.source} />);
} else {

View File

@ -1,6 +1,5 @@
import {DSCard, PlaceholderDSCard} from "../DSCard/DSCard.jsx";
import {actionCreators as ac} from "common/Actions.jsm";
import {clampTotalLines} from "content-src/lib/clamp-total-lines";
import {DSEmptyState} from "../DSEmptyState/DSEmptyState.jsx";
import {DSImage} from "../DSImage/DSImage.jsx";
import {DSLinkMenu} from "../DSLinkMenu/DSLinkMenu";
@ -77,15 +76,13 @@ export class Hero extends React.PureComponent {
<DSImage extraClassNames="img" source={heroRec.image_src} rawSource={heroRec.raw_image_src} />
</div>
<div className="meta">
<div className="header-and-excerpt"
data-total-lines="7"
ref={clampTotalLines}>
<div className="header-and-excerpt">
{heroRec.context ? (
<p className="context">{heroRec.context}</p>
) : (
<p className="source clamp" data-clamp="1">{heroRec.domain}</p>
<p className="source clamp">{heroRec.domain}</p>
)}
<header className="clamp" data-clamp="4">{heroRec.title}</header>
<header className="clamp">{heroRec.title}</header>
<p className="excerpt clamp">{heroRec.excerpt}</p>
</div>
</div>

View File

@ -14,7 +14,7 @@ $card-header-in-hero-line-height: 20;
}
.excerpt {
@include limit-visibile-lines(3, 20, 14);
@include limit-visibile-lines(3, 24, 15);
@include dark-theme-only {
color: $grey-10;
}
@ -147,6 +147,7 @@ $card-header-in-hero-line-height: 20;
font-size: 13px;
color: $grey-50;
-webkit-line-clamp: 1;
margin-bottom: 0;
}
}

View File

@ -1,5 +1,4 @@
import {actionCreators as ac} from "common/Actions.jsm";
import {clampTotalLines} from "content-src/lib/clamp-total-lines";
import {connect} from "react-redux";
import {DSEmptyState} from "../DSEmptyState/DSEmptyState.jsx";
import {DSImage} from "../DSImage/DSImage.jsx";
@ -44,15 +43,14 @@ export class ListItem extends React.PureComponent {
onLinkClick={!this.props.placeholder ? this.onLinkClick : undefined}
url={this.props.url}>
<div className="ds-list-item-text">
<div data-total-lines="4"
ref={clampTotalLines}>
<div>
<div className="ds-list-item-title clamp">{this.props.title}</div>
{this.props.excerpt && <div className="ds-list-item-excerpt clamp">{this.props.excerpt}</div>}
</div>
<p>
{this.props.context && (
<span>
<span className="ds-list-item-context">{this.props.context}</span>
<span className="ds-list-item-context clamp">{this.props.context}</span>
<br />
</span>
)}

View File

@ -228,7 +228,6 @@ $item-line-height: 20;
color: $grey-50;
font-size: 13px;
-webkit-line-clamp: 1;
}
.ds-list-item-title {

View File

@ -1,3 +1,4 @@
import {A11yLinkButton} from "content-src/components/A11yLinkButton/A11yLinkButton";
import {FormattedMessage} from "react-intl";
import React from "react";
@ -25,7 +26,7 @@ export class ErrorBoundaryFallback extends React.PureComponent {
className = defaultClass;
}
// href="#" to force normal link styling stuff (eg cursor on hover)
// "A11yLinkButton" to force normal link styling stuff (eg cursor on hover)
return (
<div className={className}>
<div>
@ -34,11 +35,11 @@ export class ErrorBoundaryFallback extends React.PureComponent {
id="error_fallback_default_info" />
</div>
<span>
<a href="#" className="reload-button" onClick={this.onClick}>
<A11yLinkButton className="reload-button" onClick={this.onClick}>
<FormattedMessage
defaultMessage="Refresh page to try again."
id="error_fallback_default_refresh_suggestion" />
</a>
</A11yLinkButton>
</span>
</div>
);

View File

@ -1,32 +0,0 @@
/**
* Adjusts line-clamps of a node's children to fill a desired number of lines.
*
* This is a React callback ref that should be set on a parent node that also
* has a data-total-lines attribute. Children with "clamp" class name are
* clamped to allow as many lines to earlier children while making sure every
* child gets at least one line. Each child can be explicitly clamped to a max
* lines with a data-clamp attribute.
*/
export function clampTotalLines(parentNode) {
// Nothing to do if the node is removed or didn't configure how many lines
if (!parentNode || !parentNode.dataset.totalLines) {
return;
}
// Only handle clamp-able children that are displayed (not hidden)
const toClamp = Array.from(parentNode.querySelectorAll(".clamp"))
.filter(child => child.scrollHeight);
// Start with total allowed lines while reserving 1 line for each child
let maxLines = parentNode.dataset.totalLines - toClamp.length + 1;
toClamp.forEach(child => {
// Clamp to the remaining allowed, explicit limit or the natural line count
const lines = Math.min(maxLines,
child.dataset.clamp || Infinity,
child.scrollHeight / parseInt(global.getComputedStyle(child).lineHeight, 10));
child.style.webkitLineClamp = `${lines}`;
// Update the remaining line allowance less the already reserved 1 line
maxLines -= lines - 1;
});
}

View File

@ -9,9 +9,10 @@
}
// Note: lineHeight and fontSize should be unitless but can be derived from pixel values
// Bug 1550624 to clean up / remove this mixin that no longer limits lines
// Bug 1550624 to clean up / remove this mixin to avoid duplicate styles
@mixin limit-visibile-lines($line-count, $line-height, $font-size) {
font-size: $font-size * 1px;
-webkit-line-clamp: $line-count;
line-height: $line-height * 1px;
}

View File

@ -1265,20 +1265,26 @@ main {
.context-menu > ul > li.separator {
border-bottom: 1px solid var(--newtab-border-secondary-color);
margin: 5px 0; }
.context-menu > ul > li > a {
.context-menu > ul > li > a,
.context-menu > ul > li > button {
align-items: center;
color: inherit;
cursor: pointer;
display: flex;
width: 100%;
line-height: 16px;
outline: none;
border: 0;
padding: 3px 12px;
white-space: nowrap; }
.context-menu > ul > li > a:-moz-any(:focus, :hover) {
.context-menu > ul > li > a:-moz-any(:focus, :hover),
.context-menu > ul > li > button:-moz-any(:focus, :hover) {
background: var(--newtab-element-hover-color); }
.context-menu > ul > li > a:active {
.context-menu > ul > li > a:active,
.context-menu > ul > li > button:active {
background: var(--newtab-element-active-color); }
.context-menu > ul > li > a.disabled {
.context-menu > ul > li > a.disabled,
.context-menu > ul > li > button.disabled {
opacity: 0.4;
pointer-events: none; }
@ -1951,11 +1957,19 @@ main {
.ds-column-12 .ds-card-grid.ds-card-grid-divisible-by-3 .title {
font-size: 17px;
line-height: 24px; }
.ds-column-9 .ds-card-grid.ds-card-grid-divisible-by-3 .excerpt,
.ds-column-10 .ds-card-grid.ds-card-grid-divisible-by-3 .excerpt,
.ds-column-11 .ds-card-grid.ds-card-grid-divisible-by-3 .excerpt,
.ds-column-12 .ds-card-grid.ds-card-grid-divisible-by-3 .excerpt {
font-size: 15px;
-webkit-line-clamp: 3;
line-height: 24px; }
.ds-column-9 .ds-card-grid.ds-card-grid-divisible-by-4 .title,
.ds-column-10 .ds-card-grid.ds-card-grid-divisible-by-4 .title,
.ds-column-11 .ds-card-grid.ds-card-grid-divisible-by-4 .title,
.ds-column-12 .ds-card-grid.ds-card-grid-divisible-by-4 .title {
font-size: 15px;
-webkit-line-clamp: 3;
line-height: 20px; }
.ds-card-grid.empty {
grid-template-columns: auto; }
@ -1968,8 +1982,9 @@ main {
line-height: 1.538;
margin: 8px 0; }
.ds-hero .excerpt {
font-size: 14px;
line-height: 20px;
font-size: 15px;
-webkit-line-clamp: 3;
line-height: 24px;
color: #0C0C0D;
margin: 0 0 10px; }
[lwt-newtab-brighttext] .ds-hero .excerpt {
@ -2036,6 +2051,7 @@ main {
justify-content: space-between; }
.ds-hero .wrapper .meta header {
font-size: 22px;
-webkit-line-clamp: 4;
line-height: 28px;
color: #0C0C0D;
margin-bottom: 0; }
@ -2051,6 +2067,7 @@ main {
.ds-hero .wrapper .meta .source {
font-size: 13px;
color: #737373;
-webkit-line-clamp: 1;
margin-bottom: 0; }
[lwt-newtab-brighttext] .ds-hero .wrapper .meta .source {
color: #B1B1B3; }
@ -2152,6 +2169,7 @@ main {
.ds-column-11 .ds-hero .wrapper .meta header,
.ds-column-12 .ds-hero .wrapper .meta header {
font-size: 22px;
-webkit-line-clamp: 3;
line-height: 28px; }
.ds-column-9 .ds-hero .wrapper .meta .source,
.ds-column-10 .ds-hero .wrapper .meta .source,
@ -2186,6 +2204,7 @@ main {
.ds-column-11 .ds-hero .cards .ds-card .title,
.ds-column-12 .ds-hero .cards .ds-card .title {
font-size: 14px;
-webkit-line-clamp: 3;
line-height: 20px; }
[lwt-newtab-brighttext] .ds-column-9 .ds-hero .cards .ds-card .title, [lwt-newtab-brighttext]
.ds-column-10 .ds-hero .cards .ds-card .title, [lwt-newtab-brighttext]
@ -2213,6 +2232,7 @@ main {
position: relative; }
.ds-list:not(.ds-list-full-width) .ds-list-item-title {
font-size: 14px;
-webkit-line-clamp: 3;
line-height: 20px; }
.ds-list:not(.ds-list-full-width) .ds-list-image {
min-width: 80px;
@ -2325,6 +2345,7 @@ main {
.ds-list-full-width .ds-list-item-title {
font-size: 17px;
-webkit-line-clamp: 3;
line-height: 24px; }
.ds-list-full-width .ds-list-image {
@ -2350,6 +2371,7 @@ main {
height: 100%; }
.ds-list-item .ds-list-item-excerpt {
font-size: 14px;
-webkit-line-clamp: 2;
line-height: 20px;
color: #737373;
margin: 4px 0 8px; }
@ -2362,10 +2384,10 @@ main {
.ds-list-item .ds-list-item-info,
.ds-list-item .ds-list-item-context {
font-size: 14px;
-webkit-line-clamp: 1;
line-height: 20px;
color: #737373;
font-size: 13px;
-webkit-line-clamp: 1; }
font-size: 13px; }
[lwt-newtab-brighttext] .ds-list-item .ds-list-item-info, [lwt-newtab-brighttext]
.ds-list-item .ds-list-item-context {
color: #B1B1B3; }
@ -2601,9 +2623,6 @@ main {
border-radius: 4px;
box-shadow: inset 0 0 0 0.5px rgba(0, 0, 0, 0.15); }
.ds-card .ds-card-link {
display: flex;
flex-direction: column;
justify-content: space-between;
height: 100%; }
.ds-card .ds-card-link:focus {
box-shadow: 0 0 0 5px rgba(10, 132, 255, 0.3);
@ -2636,19 +2655,21 @@ main {
.ds-card .meta {
display: flex;
flex-direction: column;
flex-grow: 1;
padding: 12px; }
padding: 12px 16px; }
.ds-card .meta .info-wrap {
flex-grow: 1;
margin: 0 0 12px; }
.ds-card .meta .title {
font-size: 17px;
-webkit-line-clamp: 3;
line-height: 24px;
font-weight: 600; }
.ds-card .meta .excerpt {
font-size: 14px;
-webkit-line-clamp: 3;
line-height: 20px; }
.ds-card .meta .source {
-webkit-line-clamp: 1;
margin-bottom: 2px; }
.ds-card .meta .context,
.ds-card .meta .source {

View File

@ -1268,20 +1268,26 @@ main {
.context-menu > ul > li.separator {
border-bottom: 1px solid var(--newtab-border-secondary-color);
margin: 5px 0; }
.context-menu > ul > li > a {
.context-menu > ul > li > a,
.context-menu > ul > li > button {
align-items: center;
color: inherit;
cursor: pointer;
display: flex;
width: 100%;
line-height: 16px;
outline: none;
border: 0;
padding: 3px 12px;
white-space: nowrap; }
.context-menu > ul > li > a:-moz-any(:focus, :hover) {
.context-menu > ul > li > a:-moz-any(:focus, :hover),
.context-menu > ul > li > button:-moz-any(:focus, :hover) {
background: var(--newtab-element-hover-color); }
.context-menu > ul > li > a:active {
.context-menu > ul > li > a:active,
.context-menu > ul > li > button:active {
background: var(--newtab-element-active-color); }
.context-menu > ul > li > a.disabled {
.context-menu > ul > li > a.disabled,
.context-menu > ul > li > button.disabled {
opacity: 0.4;
pointer-events: none; }
@ -1954,11 +1960,19 @@ main {
.ds-column-12 .ds-card-grid.ds-card-grid-divisible-by-3 .title {
font-size: 17px;
line-height: 24px; }
.ds-column-9 .ds-card-grid.ds-card-grid-divisible-by-3 .excerpt,
.ds-column-10 .ds-card-grid.ds-card-grid-divisible-by-3 .excerpt,
.ds-column-11 .ds-card-grid.ds-card-grid-divisible-by-3 .excerpt,
.ds-column-12 .ds-card-grid.ds-card-grid-divisible-by-3 .excerpt {
font-size: 15px;
-webkit-line-clamp: 3;
line-height: 24px; }
.ds-column-9 .ds-card-grid.ds-card-grid-divisible-by-4 .title,
.ds-column-10 .ds-card-grid.ds-card-grid-divisible-by-4 .title,
.ds-column-11 .ds-card-grid.ds-card-grid-divisible-by-4 .title,
.ds-column-12 .ds-card-grid.ds-card-grid-divisible-by-4 .title {
font-size: 15px;
-webkit-line-clamp: 3;
line-height: 20px; }
.ds-card-grid.empty {
grid-template-columns: auto; }
@ -1971,8 +1985,9 @@ main {
line-height: 1.538;
margin: 8px 0; }
.ds-hero .excerpt {
font-size: 14px;
line-height: 20px;
font-size: 15px;
-webkit-line-clamp: 3;
line-height: 24px;
color: #0C0C0D;
margin: 0 0 10px; }
[lwt-newtab-brighttext] .ds-hero .excerpt {
@ -2039,6 +2054,7 @@ main {
justify-content: space-between; }
.ds-hero .wrapper .meta header {
font-size: 22px;
-webkit-line-clamp: 4;
line-height: 28px;
color: #0C0C0D;
margin-bottom: 0; }
@ -2054,6 +2070,7 @@ main {
.ds-hero .wrapper .meta .source {
font-size: 13px;
color: #737373;
-webkit-line-clamp: 1;
margin-bottom: 0; }
[lwt-newtab-brighttext] .ds-hero .wrapper .meta .source {
color: #B1B1B3; }
@ -2155,6 +2172,7 @@ main {
.ds-column-11 .ds-hero .wrapper .meta header,
.ds-column-12 .ds-hero .wrapper .meta header {
font-size: 22px;
-webkit-line-clamp: 3;
line-height: 28px; }
.ds-column-9 .ds-hero .wrapper .meta .source,
.ds-column-10 .ds-hero .wrapper .meta .source,
@ -2189,6 +2207,7 @@ main {
.ds-column-11 .ds-hero .cards .ds-card .title,
.ds-column-12 .ds-hero .cards .ds-card .title {
font-size: 14px;
-webkit-line-clamp: 3;
line-height: 20px; }
[lwt-newtab-brighttext] .ds-column-9 .ds-hero .cards .ds-card .title, [lwt-newtab-brighttext]
.ds-column-10 .ds-hero .cards .ds-card .title, [lwt-newtab-brighttext]
@ -2216,6 +2235,7 @@ main {
position: relative; }
.ds-list:not(.ds-list-full-width) .ds-list-item-title {
font-size: 14px;
-webkit-line-clamp: 3;
line-height: 20px; }
.ds-list:not(.ds-list-full-width) .ds-list-image {
min-width: 80px;
@ -2328,6 +2348,7 @@ main {
.ds-list-full-width .ds-list-item-title {
font-size: 17px;
-webkit-line-clamp: 3;
line-height: 24px; }
.ds-list-full-width .ds-list-image {
@ -2353,6 +2374,7 @@ main {
height: 100%; }
.ds-list-item .ds-list-item-excerpt {
font-size: 14px;
-webkit-line-clamp: 2;
line-height: 20px;
color: #737373;
margin: 4px 0 8px; }
@ -2365,10 +2387,10 @@ main {
.ds-list-item .ds-list-item-info,
.ds-list-item .ds-list-item-context {
font-size: 14px;
-webkit-line-clamp: 1;
line-height: 20px;
color: #737373;
font-size: 13px;
-webkit-line-clamp: 1; }
font-size: 13px; }
[lwt-newtab-brighttext] .ds-list-item .ds-list-item-info, [lwt-newtab-brighttext]
.ds-list-item .ds-list-item-context {
color: #B1B1B3; }
@ -2604,9 +2626,6 @@ main {
border-radius: 4px;
box-shadow: inset 0 0 0 0.5px rgba(0, 0, 0, 0.15); }
.ds-card .ds-card-link {
display: flex;
flex-direction: column;
justify-content: space-between;
height: 100%; }
.ds-card .ds-card-link:focus {
box-shadow: 0 0 0 5px rgba(10, 132, 255, 0.3);
@ -2639,19 +2658,21 @@ main {
.ds-card .meta {
display: flex;
flex-direction: column;
flex-grow: 1;
padding: 12px; }
padding: 12px 16px; }
.ds-card .meta .info-wrap {
flex-grow: 1;
margin: 0 0 12px; }
.ds-card .meta .title {
font-size: 17px;
-webkit-line-clamp: 3;
line-height: 24px;
font-weight: 600; }
.ds-card .meta .excerpt {
font-size: 14px;
-webkit-line-clamp: 3;
line-height: 20px; }
.ds-card .meta .source {
-webkit-line-clamp: 1;
margin-bottom: 2px; }
.ds-card .meta .context,
.ds-card .meta .source {

View File

@ -1265,20 +1265,26 @@ main {
.context-menu > ul > li.separator {
border-bottom: 1px solid var(--newtab-border-secondary-color);
margin: 5px 0; }
.context-menu > ul > li > a {
.context-menu > ul > li > a,
.context-menu > ul > li > button {
align-items: center;
color: inherit;
cursor: pointer;
display: flex;
width: 100%;
line-height: 16px;
outline: none;
border: 0;
padding: 3px 12px;
white-space: nowrap; }
.context-menu > ul > li > a:-moz-any(:focus, :hover) {
.context-menu > ul > li > a:-moz-any(:focus, :hover),
.context-menu > ul > li > button:-moz-any(:focus, :hover) {
background: var(--newtab-element-hover-color); }
.context-menu > ul > li > a:active {
.context-menu > ul > li > a:active,
.context-menu > ul > li > button:active {
background: var(--newtab-element-active-color); }
.context-menu > ul > li > a.disabled {
.context-menu > ul > li > a.disabled,
.context-menu > ul > li > button.disabled {
opacity: 0.4;
pointer-events: none; }
@ -1951,11 +1957,19 @@ main {
.ds-column-12 .ds-card-grid.ds-card-grid-divisible-by-3 .title {
font-size: 17px;
line-height: 24px; }
.ds-column-9 .ds-card-grid.ds-card-grid-divisible-by-3 .excerpt,
.ds-column-10 .ds-card-grid.ds-card-grid-divisible-by-3 .excerpt,
.ds-column-11 .ds-card-grid.ds-card-grid-divisible-by-3 .excerpt,
.ds-column-12 .ds-card-grid.ds-card-grid-divisible-by-3 .excerpt {
font-size: 15px;
-webkit-line-clamp: 3;
line-height: 24px; }
.ds-column-9 .ds-card-grid.ds-card-grid-divisible-by-4 .title,
.ds-column-10 .ds-card-grid.ds-card-grid-divisible-by-4 .title,
.ds-column-11 .ds-card-grid.ds-card-grid-divisible-by-4 .title,
.ds-column-12 .ds-card-grid.ds-card-grid-divisible-by-4 .title {
font-size: 15px;
-webkit-line-clamp: 3;
line-height: 20px; }
.ds-card-grid.empty {
grid-template-columns: auto; }
@ -1968,8 +1982,9 @@ main {
line-height: 1.538;
margin: 8px 0; }
.ds-hero .excerpt {
font-size: 14px;
line-height: 20px;
font-size: 15px;
-webkit-line-clamp: 3;
line-height: 24px;
color: #0C0C0D;
margin: 0 0 10px; }
[lwt-newtab-brighttext] .ds-hero .excerpt {
@ -2036,6 +2051,7 @@ main {
justify-content: space-between; }
.ds-hero .wrapper .meta header {
font-size: 22px;
-webkit-line-clamp: 4;
line-height: 28px;
color: #0C0C0D;
margin-bottom: 0; }
@ -2051,6 +2067,7 @@ main {
.ds-hero .wrapper .meta .source {
font-size: 13px;
color: #737373;
-webkit-line-clamp: 1;
margin-bottom: 0; }
[lwt-newtab-brighttext] .ds-hero .wrapper .meta .source {
color: #B1B1B3; }
@ -2152,6 +2169,7 @@ main {
.ds-column-11 .ds-hero .wrapper .meta header,
.ds-column-12 .ds-hero .wrapper .meta header {
font-size: 22px;
-webkit-line-clamp: 3;
line-height: 28px; }
.ds-column-9 .ds-hero .wrapper .meta .source,
.ds-column-10 .ds-hero .wrapper .meta .source,
@ -2186,6 +2204,7 @@ main {
.ds-column-11 .ds-hero .cards .ds-card .title,
.ds-column-12 .ds-hero .cards .ds-card .title {
font-size: 14px;
-webkit-line-clamp: 3;
line-height: 20px; }
[lwt-newtab-brighttext] .ds-column-9 .ds-hero .cards .ds-card .title, [lwt-newtab-brighttext]
.ds-column-10 .ds-hero .cards .ds-card .title, [lwt-newtab-brighttext]
@ -2213,6 +2232,7 @@ main {
position: relative; }
.ds-list:not(.ds-list-full-width) .ds-list-item-title {
font-size: 14px;
-webkit-line-clamp: 3;
line-height: 20px; }
.ds-list:not(.ds-list-full-width) .ds-list-image {
min-width: 80px;
@ -2325,6 +2345,7 @@ main {
.ds-list-full-width .ds-list-item-title {
font-size: 17px;
-webkit-line-clamp: 3;
line-height: 24px; }
.ds-list-full-width .ds-list-image {
@ -2350,6 +2371,7 @@ main {
height: 100%; }
.ds-list-item .ds-list-item-excerpt {
font-size: 14px;
-webkit-line-clamp: 2;
line-height: 20px;
color: #737373;
margin: 4px 0 8px; }
@ -2362,10 +2384,10 @@ main {
.ds-list-item .ds-list-item-info,
.ds-list-item .ds-list-item-context {
font-size: 14px;
-webkit-line-clamp: 1;
line-height: 20px;
color: #737373;
font-size: 13px;
-webkit-line-clamp: 1; }
font-size: 13px; }
[lwt-newtab-brighttext] .ds-list-item .ds-list-item-info, [lwt-newtab-brighttext]
.ds-list-item .ds-list-item-context {
color: #B1B1B3; }
@ -2601,9 +2623,6 @@ main {
border-radius: 4px;
box-shadow: inset 0 0 0 0.5px rgba(0, 0, 0, 0.15); }
.ds-card .ds-card-link {
display: flex;
flex-direction: column;
justify-content: space-between;
height: 100%; }
.ds-card .ds-card-link:focus {
box-shadow: 0 0 0 5px rgba(10, 132, 255, 0.3);
@ -2636,19 +2655,21 @@ main {
.ds-card .meta {
display: flex;
flex-direction: column;
flex-grow: 1;
padding: 12px; }
padding: 12px 16px; }
.ds-card .meta .info-wrap {
flex-grow: 1;
margin: 0 0 12px; }
.ds-card .meta .title {
font-size: 17px;
-webkit-line-clamp: 3;
line-height: 24px;
font-weight: 600; }
.ds-card .meta .excerpt {
font-size: 14px;
-webkit-line-clamp: 3;
line-height: 20px; }
.ds-card .meta .source {
-webkit-line-clamp: 1;
margin-bottom: 2px; }
.ds-card .meta .context,
.ds-card .meta .source {

View File

@ -17,11 +17,6 @@ const DEFAULT_STATE = {
_devtoolsPref: DEVTOOLS_PREF,
};
const MIGRATE_PREFS = [
// Old pref, New pref
["browser.newtabpage.activity-stream.asrouter.userprefs.cfr", "browser.newtabpage.activity-stream.asrouter.userprefs.cfr.addons"],
];
const USER_PREFERENCES = {
snippets: "browser.newtabpage.activity-stream.feeds.snippets",
cfrAddons: "browser.newtabpage.activity-stream.asrouter.userprefs.cfr.addons",
@ -66,24 +61,6 @@ class _ASRouterPreferences {
}, []);
}
// XXX Bug 1531734
// Required for 67 when the pref change will happen
_migratePrefs() {
for (let [oldPref, newPref] of MIGRATE_PREFS) {
if (!Services.prefs.prefHasUserValue(oldPref)) {
continue;
}
if (Services.prefs.prefHasUserValue(newPref)) {
Services.prefs.clearUserPref(oldPref);
continue;
}
// If the pref was user modified we assume it was set to false
const oldValue = Services.prefs.getBoolPref(oldPref, false);
Services.prefs.clearUserPref(oldPref);
Services.prefs.setBoolPref(newPref, oldValue);
}
}
get providers() {
if (!this._initialized || this._providers === null) {
const config = this._getProviderConfig();
@ -168,7 +145,6 @@ class _ASRouterPreferences {
if (this._initialized) {
return;
}
this._migratePrefs();
Services.prefs.addObserver(this._providerPrefBranch, this);
Services.prefs.addObserver(this._devtoolsPref, this);
for (const id of Object.keys(USER_PREFERENCES)) {

View File

@ -368,7 +368,6 @@ this.ActivityStream = class ActivityStream {
init() {
try {
this._migratePrefs();
this._updateDynamicPrefs();
this._defaultPrefs.init();
@ -422,29 +421,6 @@ this.ActivityStream = class ActivityStream {
Services.prefs.clearUserPref(oldPrefName);
}
_migratePrefs() {
// Do a one time migration of Tiles about:newtab prefs that have been modified
this._migratePref("browser.newtabpage.rows", rows => {
// Just disable top sites if rows are not desired
if (rows <= 0) {
Services.prefs.setBoolPref("browser.newtabpage.activity-stream.feeds.topsites", false);
} else {
Services.prefs.setIntPref("browser.newtabpage.activity-stream.topSitesRows", rows);
}
});
this._migratePref("browser.newtabpage.activity-stream.showTopSites", value => {
if (value === false) {
Services.prefs.setBoolPref("browser.newtabpage.activity-stream.feeds.topsites", false);
}
});
// Old activity stream topSitesCount pref showed 6 per row
this._migratePref("browser.newtabpage.activity-stream.topSitesCount", count => {
Services.prefs.setIntPref("browser.newtabpage.activity-stream.topSitesRows", Math.ceil(count / 6));
});
}
uninit() {
if (this.geo === "") {
Services.prefs.removeObserver(GEO_PREF, this);

View File

@ -14,17 +14,6 @@ ChromeUtils.defineModuleGetter(this, "PrivateBrowsingUtils",
ChromeUtils.defineModuleGetter(this, "AppConstants",
"resource://gre/modules/AppConstants.jsm");
// List of prefs that require migration to indexedDB.
// Object key is the name of the pref in indexedDB, each will contain a
// map (key: name of preference to migrate, value: name of component).
const PREF_MIGRATION = {
collapsed: new Map([
["collapseTopSites", "topsites"],
["section.highlights.collapsed", "highlights"],
["section.topstories.collapsed", "topstories"],
]),
};
this.PrefsFeed = class PrefsFeed {
constructor(prefMap) {
this._prefMap = prefMap;
@ -54,20 +43,6 @@ this.PrefsFeed = class PrefsFeed {
this._checkPrerender(name);
}
_migratePrefs() {
for (const indexedDBPref of Object.keys(PREF_MIGRATION)) {
for (const migratePref of PREF_MIGRATION[indexedDBPref].keys()) {
// Check if pref exists (if the user changed the default)
if (this._prefs.get(migratePref, null) === true) {
const data = {id: PREF_MIGRATION[indexedDBPref].get(migratePref), value: {}};
data.value[indexedDBPref] = true;
this.store.dispatch(ac.OnlyToMain({type: at.UPDATE_SECTION_PREFS, data}));
this._prefs.reset(migratePref);
}
}
}
}
init() {
this._prefs.observeBranch(this);
this._storage = this.store.dbStorage.getDbTable("sectionPrefs");
@ -104,7 +79,6 @@ this.PrefsFeed = class PrefsFeed {
// Set the initial state of all prefs in redux
this.store.dispatch(ac.BroadcastToContent({type: at.PREFS_INITIAL_VALUES, data: values}));
this._migratePrefs();
this._setPrerenderPref();
}

View File

@ -93,6 +93,7 @@ prefs_home_header=เนื้อหาหน้าแรก Firefox
prefs_home_description=เลือกเนื้อหาที่คุณต้องการในหน้าจอหน้าแรก Firefox ของคุณ
prefs_content_discovery_header=Firefox Home
prefs_content_discovery_description=Content Discovery ใน Firefox Home ช่วยให้คุณค้นพบบทความที่มีคุณภาพและมีความเกี่ยวข้องสูงจากทั่วทั้งเว็บ
prefs_content_discovery_button=ปิดการค้นพบเนื้อหา
@ -153,7 +154,7 @@ pocket_how_it_works=วิธีการทำงาน
pocket_cta_button=รับ Pocket
pocket_cta_text=บันทึกเรื่องราวที่คุณรักลงใน Pocket และเติมเต็มสมองของคุณด้วยบทความที่น่าหลงใหล
highlights_empty_state=เริ่มการท่องเว็บและเราจะแสดงบทความ, วิดีโอ และหน้าอื่น ๆ บางส่วนที่ยอดเยี่ยมที่คุณได้เยี่ยมชมหรือเพิ่มที่คั่นหน้าไว้ล่าสุดที่นี่
highlights_empty_state=เริ่มการเรียกดูและเราจะแสดงบทความ, วิดีโอ และหน้าอื่น ๆ บางส่วนที่ยอดเยี่ยมที่คุณได้เยี่ยมชมหรือเพิ่มที่คั่นหน้าไว้ล่าสุดที่นี่
# LOCALIZATION NOTE (topstories_empty_state): When there are no recommendations,
# in the space that would have shown a few stories, this is shown instead.
# {provider} is replaced by the name of the content provider for this section.

View File

@ -91,6 +91,11 @@ section_disclaimer_topstories_buttontext=Sige, nakuha ko
# what is shown for the homepage, new windows, and new tabs.
prefs_home_header=Nilalaman ng Home ng Firefox
prefs_home_description=Piliin kung anong nilalaman ang gusto mo sa iyong screen ng Home ng Firefox.
prefs_content_discovery_header=Firefox Home
prefs_content_discovery_button=I-off ang Content Discovery
# LOCALIZATION NOTE (prefs_section_rows_option): This is a semi-colon list of
# plural forms used in a drop down of multiple row options (1 row, 2 rows).
# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
@ -143,7 +148,6 @@ pocket_read_more=Tanyag na mga paksa:
# end of the list of popular topic links.
pocket_read_even_more=Tignan ang higit pang mga kuwento
pocket_more_reccommendations=Karagdagang Rekomendasyon
pocket_learn_more=Alamin Pa
pocket_how_it_works=Paano gamitin
pocket_cta_button=Kunin ang Pocket
pocket_cta_text=I-save sa Pocket ang mga kwentong iyong nagustuhan, at palawigin ang iyong pagiisip sa mga nakabibighaning babasahin.

View File

@ -132,7 +132,7 @@
"debugcoverage": "open logs/coverage/index.html",
"lint": "npm-run-all lint:*",
"lint:eslint": "esw --ext=.js,.jsm,.json,.jsx .",
"lint:jsx-a11y": "esw --config=.eslintrc.jsx-a11y.js --ext=.jsx content-src/asrouter content-src/components/ASRouterAdmin content-src/components/TopSites",
"lint:jsx-a11y": "esw --config=.eslintrc.jsx-a11y.js --ext=.jsx content-src/",
"lint:sasslint": "sass-lint -v -q",
"strings-import": "node ./bin/strings-import.js",
"test": "npm run testmc",

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More