Convert rating stars to inline SVGs (#7576)

This commit is contained in:
Kumar McMillan 2019-02-11 13:33:43 -06:00 коммит произвёл GitHub
Родитель 0d3bbc272a
Коммит bb9277eeff
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
17 изменённых файлов: 293 добавлений и 145 удалений

Просмотреть файл

@ -248,6 +248,7 @@
"mozilla-version-comparator": "1.0.2", "mozilla-version-comparator": "1.0.2",
"nano-time": "1.0.0", "nano-time": "1.0.0",
"normalize.css": "8.0.1", "normalize.css": "8.0.1",
"photon-colors": "3.3.1",
"pino": "5.11.1", "pino": "5.11.1",
"pino-mozlog": "2.0.0", "pino-mozlog": "2.0.0",
"prop-types": "15.7.1", "prop-types": "15.7.1",
@ -342,7 +343,6 @@
"node-sass": "^4.9.1", "node-sass": "^4.9.1",
"object.values": "^1.0.4", "object.values": "^1.0.4",
"optimize-css-assets-webpack-plugin": "^5.0.1", "optimize-css-assets-webpack-plugin": "^5.0.1",
"photon-colors": "^3.0.1",
"pino-devtools": "^2.1.0", "pino-devtools": "^2.1.0",
"pino-pretty": "^2.0.1", "pino-pretty": "^2.0.1",
"piping": "^1.0.0-rc.4", "piping": "^1.0.0-rc.4",

Просмотреть файл

@ -11,7 +11,7 @@ import { reviewListURL } from 'amo/reducers/reviews';
import { withFixedErrorHandler } from 'core/errorHandler'; import { withFixedErrorHandler } from 'core/errorHandler';
import translate from 'core/i18n/translate'; import translate from 'core/i18n/translate';
import LoadingText from 'ui/components/LoadingText'; import LoadingText from 'ui/components/LoadingText';
import Icon from 'ui/components/Icon'; import IconStar from 'ui/components/IconStar';
import type { GroupedRatingsType } from 'amo/api/reviews'; import type { GroupedRatingsType } from 'amo/api/reviews';
import type { AppState } from 'amo/store'; import type { AppState } from 'amo/store';
import type { AddonType } from 'core/types/addons'; import type { AddonType } from 'core/types/addons';
@ -141,7 +141,7 @@ export class RatingsByStarBase extends React.Component<InternalProps> {
) : ( ) : (
createLink(i18n.formatNumber(star)) createLink(i18n.formatNumber(star))
)} )}
<Icon name="star-yellow" /> <IconStar selected />
</div> </div>
<div className="RatingsByStar-barContainer"> <div className="RatingsByStar-barContainer">
<div className="RatingsByStar-bar RatingsByStar-barFrame"> <div className="RatingsByStar-bar RatingsByStar-barFrame">

Просмотреть файл

@ -146,10 +146,6 @@ $icon-default-size: 32px;
.Rating { .Rating {
justify-content: flex-start; justify-content: flex-start;
margin: 0; margin: 0;
@include respond-to(large) {
margin-top: 2px;
}
} }
.SearchResult--theme & { .SearchResult--theme & {

Просмотреть файл

@ -0,0 +1,126 @@
/* @flow */
import * as React from 'react';
import makeClassName from 'classnames';
import photon from 'photon-colors';
import uuidv4 from 'uuid/v4';
import Icon from 'ui/components/Icon';
import type { Props as IconProps } from 'ui/components/Icon';
export const CLOSED_STYLE = 'closed';
export const DIM_CLOSED_STYLE = 'dimClosed';
export const HALF_STYLE = 'half';
export const OPEN_STYLE = 'open';
export const getSvgPath = (starStyle: string) => {
switch (starStyle) {
case CLOSED_STYLE:
case DIM_CLOSED_STYLE:
return 'M154.994575,670.99995 C153.704598,671.000763 152.477615,670.442079 151.630967,669.468394 C150.784319,668.49471 150.401158,667.201652 150.580582,665.923653 L153.046749,648.259919 L141.193762,635.514481 C140.080773,634.318044 139.711733,632.608076 140.232152,631.058811 C140.752571,629.509546 142.078939,628.369589 143.688275,628.088421 L160.214424,625.130961 L168.013827,609.468577 C168.767364,607.955994 170.3113,607 172.000594,607 C173.689888,607 175.233824,607.955994 175.98736,609.468577 L183.790813,625.130961 L200.329111,628.08437 C201.934946,628.371492 203.25546,629.513805 203.771316,631.062053 C204.287172,632.610301 203.915846,634.316807 202.803377,635.51043 L190.954439,648.26397 L193.420606,665.923653 C193.652457,667.578241 192.93975,669.223573 191.574418,670.185702 C190.209085,671.147831 188.420524,671.265104 186.941351,670.489485 L172.002619,662.698806 L157.047688,670.50569 C156.413201,670.833752 155.708782,671.003331 154.994575,670.99995 Z';
case HALF_STYLE:
return 'M1216.67559,197.013479 C1216.54115,196.628667 1216.19883,196.344304 1215.78203,196.271203 L1211.45804,195.530952 L1209.42135,191.617039 C1209.22458,191.238958 1208.8214,191 1208.38027,191 C1207.93914,191 1207.53597,191.238958 1207.33919,191.617039 L1205.30145,195.530952 L1200.98592,196.269177 C1200.56542,196.339521 1200.21894,196.624766 1200.08323,197.012329 C1199.94751,197.399891 1200.04437,197.827503 1200.33557,198.126387 L1203.43079,201.313214 L1202.78679,205.728392 C1202.72624,206.141968 1202.91235,206.553231 1203.26889,206.793722 C1203.62542,207.034213 1204.09248,207.063526 1204.47874,206.869654 L1208.37974,204.921305 L1212.28181,206.872692 C1212.66807,207.066564 1213.13512,207.037251 1213.49166,206.79676 C1213.84819,206.556269 1214.0343,206.145006 1213.97376,205.73143 L1213.3287,201.313214 L1216.42286,198.1274 C1216.71414,197.828621 1216.81115,197.401068 1216.67559,197.013479 Z';
case OPEN_STYLE:
default:
return 'M317.994575,670.99995 C316.704598,671.000763 315.477615,670.442079 314.630967,669.468394 C313.784319,668.49471 313.401158,667.201652 313.580582,665.923653 L316.046749,648.259919 L304.193762,635.514481 C303.080773,634.318044 302.711733,632.608076 303.232152,631.058811 C303.752571,629.509546 305.078939,628.369589 306.688275,628.088421 L323.214424,625.130961 L331.013827,609.468577 C331.767364,607.955994 333.3113,607 335.000594,607 C336.689888,607 338.233824,607.955994 338.98736,609.468577 L346.790813,625.130961 L363.329111,628.08437 C364.934946,628.371492 366.25546,629.513805 366.771316,631.062053 C367.287172,632.610301 366.915846,634.316807 365.803377,635.51043 L353.954439,648.26397 L356.420606,665.923653 C356.652457,667.578241 355.93975,669.223573 354.574418,670.185702 C353.209085,671.147831 351.420524,671.265104 349.941351,670.489485 L335.002619,662.698806 L320.047688,670.50569 C319.413201,670.833752 318.708782,671.003331 317.994575,670.99995 Z M314.678006,634.89463 L324.603415,645.569846 L322.578647,660.041143 L335.002619,653.56309 L347.42254,660.045194 L345.397773,645.573897 L355.323182,634.89463 L341.352288,632.39902 L335.002619,619.637378 L328.648899,632.39902 L314.678006,634.89463 Z';
}
};
export type Props = {|
alt?: $PropertyType<IconProps, 'alt'>,
className?: string,
half?: boolean,
selected?: boolean,
readOnly?: boolean,
yellow?: boolean,
|};
const IconStar = ({
className,
half = false,
selected = false,
readOnly = false,
yellow = true,
...iconProps
}: Props) => {
let color = photon.YELLOW_50;
if (!yellow) {
color = photon.GREY_50;
}
let starStyle = selected ? CLOSED_STYLE : OPEN_STYLE;
if (readOnly) {
if (half) {
starStyle = HALF_STYLE;
} else if (!selected) {
starStyle = DIM_CLOSED_STYLE;
}
}
let defs;
let gProps = {
fill: color,
fillRule: 'nonzero',
};
switch (starStyle) {
case CLOSED_STYLE:
case DIM_CLOSED_STYLE:
gProps = {
...gProps,
transform: 'translate(-140.000000, -607.000000)',
fillOpacity: starStyle === DIM_CLOSED_STYLE ? 0.25 : 1,
};
break;
case HALF_STYLE: {
// This id is needed in case there are multiple IconStars on 1 page.
const id = `half${uuidv4()}`;
defs = (
<defs>
<linearGradient id={id} x1="0" x2="100%" y1="0" y2="0">
<stop offset="50%" stopColor={color} />
<stop offset="50%" stopColor={color} stopOpacity="0.25" />
</linearGradient>
</defs>
);
gProps = {
...gProps,
fill: `url(#${id})`,
transform: 'scale(3.75) translate(-1200.000000, -191.000000)',
};
break;
}
case OPEN_STYLE:
default:
gProps = {
...gProps,
fillOpacity: readOnly ? 0.25 : 1,
transform: 'translate(-303.000000, -607.000000)',
};
break;
}
return (
<Icon
className={makeClassName('IconStar', className)}
name="inline-content"
{...iconProps}
>
<svg
viewBox="0 0 64 64"
className="IconStar-svg"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlnsXlink="http://www.w3.org/1999/xlink"
>
{defs}
<g {...gProps}>
<path d={getSvgPath(starStyle)} />
</g>
</svg>
</Icon>
);
};
export default IconStar;

Просмотреть файл

@ -1,12 +0,0 @@
<svg width="17px" height="16px" viewBox="0 0 17 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 47.1 (45422) - http://www.bohemiancoding.com/sketch -->
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Screens" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Extension-Detail---1366px" transform="translate(-1268.000000, -191.000000)" fill-rule="nonzero" fill="#D7D7DB">
<g id="Icon/Star/Off" transform="translate(1268.093458, 191.000000)">
<path d="M16.9387231,6.0134792 C16.8019739,5.62866693 16.4537759,5.34430427 16.0298163,5.27120279 L11.6315676,4.53095169 L9.55990532,0.617038533 C9.35975238,0.238957594 8.94965505,-8.43205013e-17 8.50094816,0 C8.05224128,5.62136675e-17 7.64214395,0.238957594 7.44199101,0.617038533 L5.36925312,4.53095169 L0.979609481,5.26917748 C0.55189384,5.33952054 0.199461709,5.62476632 0.0614173919,6.01232884 C-0.0766269256,6.39989135 0.0218952463,6.82750347 0.318097391,7.1263875 L3.46646469,10.3132141 L2.81140637,14.7283917 C2.74982246,15.1419679 2.93913032,15.5532305 3.30178728,15.7937216 C3.66444423,16.0342127 4.13951821,16.0635259 4.53241344,15.8696543 L8.50041035,13.9213053 L12.4694829,15.8726923 C12.8623781,16.0665639 13.3374521,16.0372507 13.7001091,15.7967596 C14.062766,15.5562685 14.2520739,15.1450059 14.19049,14.7314296 L13.534356,10.3132141 L16.6816477,7.12740015 C16.9779332,6.82862115 17.0766057,6.40106827 16.9387231,6.0134792 Z" id="Star-Copy"></path>
</g>
</g>
</g>
</svg>

До

Ширина:  |  Высота:  |  Размер: 1.6 KiB

Просмотреть файл

@ -1,9 +0,0 @@
<svg width="64px" height="64px" viewBox="0 0 64 64" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 50.2 (55047) - http://www.bohemiancoding.com/sketch -->
<desc>Created with Sketch.</desc>
<g id="Screens" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" fill-opacity="0.25">
<g transform="translate(-382.000000, -286.000000)" fill="#FFE900" fill-rule="nonzero">
<path d="M445.769311,310.053917 C445.25449,308.514668 443.943627,307.377217 442.347544,307.084811 L425.789431,304.123807 L417.990232,288.468154 C417.236715,286.95583 415.692819,286 414.00357,286 C412.31432,286 410.770424,286.95583 410.016907,288.468154 L402.213659,304.123807 L385.687942,307.07671 C384.077718,307.358082 382.750915,308.499065 382.231218,310.049315 C381.711522,311.599565 382.082429,313.310014 383.197543,314.50555 L395.05022,327.252856 L392.584118,344.913567 C392.352273,346.567872 393.064961,348.212922 394.430258,349.174886 C395.795555,350.136851 397.584069,350.254104 399.063204,349.478617 L414.001545,341.685221 L428.943936,349.490769 C430.423071,350.266256 432.211584,350.149003 433.576881,349.187038 C434.942178,348.225074 435.654866,346.580024 435.423021,344.925718 L432.95287,327.252856 L444.801497,314.509601 C445.916925,313.314485 446.288398,311.604273 445.769311,310.053917 Z" id="Star"></path>
</g>
</g>
</svg>

До

Ширина:  |  Высота:  |  Размер: 1.4 KiB

Просмотреть файл

@ -1,10 +0,0 @@
<svg width="17px" height="16px" viewBox="0 0 17 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 47.1 (45422) - http://www.bohemiancoding.com/sketch -->
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Screens" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Extension-Detail---1366px" transform="translate(-1200.000000, -191.000000)" fill-rule="nonzero" fill="#737373">
<path d="M1216.67559,197.013479 C1216.54115,196.628667 1216.19883,196.344304 1215.78203,196.271203 L1211.45804,195.530952 L1209.42135,191.617039 C1209.22458,191.238958 1208.8214,191 1208.38027,191 C1207.93914,191 1207.53597,191.238958 1207.33919,191.617039 L1205.30145,195.530952 L1200.98592,196.269177 C1200.56542,196.339521 1200.21894,196.624766 1200.08323,197.012329 C1199.94751,197.399891 1200.04437,197.827503 1200.33557,198.126387 L1203.43079,201.313214 L1202.78679,205.728392 C1202.72624,206.141968 1202.91235,206.553231 1203.26889,206.793722 C1203.62542,207.034213 1204.09248,207.063526 1204.47874,206.869654 L1208.37974,204.921305 L1212.28181,206.872692 C1212.66807,207.066564 1213.13512,207.037251 1213.49166,206.79676 C1213.84819,206.556269 1214.0343,206.145006 1213.97376,205.73143 L1213.3287,201.313214 L1216.42286,198.1274 C1216.71414,197.828621 1216.81115,197.401068 1216.67559,197.013479 Z" id="Star"></path>
</g>
</g>
</svg>

До

Ширина:  |  Высота:  |  Размер: 1.4 KiB

Просмотреть файл

@ -1,10 +0,0 @@
<svg width="64px" height="64px" viewBox="0 0 64 64" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 48.2 (47327) - http://www.bohemiancoding.com/sketch -->
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Screens" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Extension-Detail---1366px" transform="translate(-140.000000, -607.000000)" fill="#FFE900" fill-rule="nonzero">
<path d="M154.994575,670.99995 C153.704598,671.000763 152.477615,670.442079 151.630967,669.468394 C150.784319,668.49471 150.401158,667.201652 150.580582,665.923653 L153.046749,648.259919 L141.193762,635.514481 C140.080773,634.318044 139.711733,632.608076 140.232152,631.058811 C140.752571,629.509546 142.078939,628.369589 143.688275,628.088421 L160.214424,625.130961 L168.013827,609.468577 C168.767364,607.955994 170.3113,607 172.000594,607 C173.689888,607 175.233824,607.955994 175.98736,609.468577 L183.790813,625.130961 L200.329111,628.08437 C201.934946,628.371492 203.25546,629.513805 203.771316,631.062053 C204.287172,632.610301 203.915846,634.316807 202.803377,635.51043 L190.954439,648.26397 L193.420606,665.923653 C193.652457,667.578241 192.93975,669.223573 191.574418,670.185702 C190.209085,671.147831 188.420524,671.265104 186.941351,670.489485 L172.002619,662.698806 L157.047688,670.50569 C156.413201,670.833752 155.708782,671.003331 154.994575,670.99995 Z" id="Star-outline"></path>
</g>
</g>
</svg>

До

Ширина:  |  Высота:  |  Размер: 1.5 KiB

Просмотреть файл

@ -1,15 +0,0 @@
<svg width="17px" height="16px" viewBox="0 0 17 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 47.1 (45422) - http://www.bohemiancoding.com/sketch -->
<desc>Created with Sketch.</desc>
<defs>
<linearGradient id="half" x1="0" x2="100%" y1="0" y2="0">
<stop offset="50%" stop-color="#737373"/>
<stop offset="50%" stop-color="#D7D7DB"/>
</linearGradient>
</defs>
<g id="Screens" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Extension-Detail---1366px" transform="translate(-1200.000000, -191.000000)" fill-rule="nonzero" fill="url(#half)">
<path d="M1216.67559,197.013479 C1216.54115,196.628667 1216.19883,196.344304 1215.78203,196.271203 L1211.45804,195.530952 L1209.42135,191.617039 C1209.22458,191.238958 1208.8214,191 1208.38027,191 C1207.93914,191 1207.53597,191.238958 1207.33919,191.617039 L1205.30145,195.530952 L1200.98592,196.269177 C1200.56542,196.339521 1200.21894,196.624766 1200.08323,197.012329 C1199.94751,197.399891 1200.04437,197.827503 1200.33557,198.126387 L1203.43079,201.313214 L1202.78679,205.728392 C1202.72624,206.141968 1202.91235,206.553231 1203.26889,206.793722 C1203.62542,207.034213 1204.09248,207.063526 1204.47874,206.869654 L1208.37974,204.921305 L1212.28181,206.872692 C1212.66807,207.066564 1213.13512,207.037251 1213.49166,206.79676 C1213.84819,206.556269 1214.0343,206.145006 1213.97376,205.73143 L1213.3287,201.313214 L1216.42286,198.1274 C1216.71414,197.828621 1216.81115,197.401068 1216.67559,197.013479 Z" id="Star"></path>
</g>
</g>
</svg>

До

Ширина:  |  Высота:  |  Размер: 1.6 KiB

Просмотреть файл

@ -1,15 +0,0 @@
<svg width="17px" height="16px" viewBox="0 0 17 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 47.1 (45422) - http://www.bohemiancoding.com/sketch -->
<desc>Created with Sketch.</desc>
<defs>
<linearGradient id="half" x1="0" x2="100%" y1="0" y2="0">
<stop offset="50%" stop-color="#FFE900"/>
<stop offset="50%" stop-color="#FFE900" stop-opacity="0.25" />
</linearGradient>
</defs>
<g id="Screens" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Extension-Detail---1366px" transform="translate(-1200.000000, -191.000000)" fill-rule="nonzero" fill="url(#half)">
<path d="M1216.67559,197.013479 C1216.54115,196.628667 1216.19883,196.344304 1215.78203,196.271203 L1211.45804,195.530952 L1209.42135,191.617039 C1209.22458,191.238958 1208.8214,191 1208.38027,191 C1207.93914,191 1207.53597,191.238958 1207.33919,191.617039 L1205.30145,195.530952 L1200.98592,196.269177 C1200.56542,196.339521 1200.21894,196.624766 1200.08323,197.012329 C1199.94751,197.399891 1200.04437,197.827503 1200.33557,198.126387 L1203.43079,201.313214 L1202.78679,205.728392 C1202.72624,206.141968 1202.91235,206.553231 1203.26889,206.793722 C1203.62542,207.034213 1204.09248,207.063526 1204.47874,206.869654 L1208.37974,204.921305 L1212.28181,206.872692 C1212.66807,207.066564 1213.13512,207.037251 1213.49166,206.79676 C1213.84819,206.556269 1214.0343,206.145006 1213.97376,205.73143 L1213.3287,201.313214 L1216.42286,198.1274 C1216.71414,197.828621 1216.81115,197.401068 1216.67559,197.013479 Z" id="Star"></path>
</g>
</g>
</svg>

До

Ширина:  |  Высота:  |  Размер: 1.6 KiB

Просмотреть файл

@ -1,10 +0,0 @@
<svg width="64px" height="64px" viewBox="0 0 64 64" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 48.2 (47327) - http://www.bohemiancoding.com/sketch -->
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Screens" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Extension-Detail---1366px" transform="translate(-303.000000, -607.000000)" fill="#FFE900" fill-rule="nonzero">
<path d="M317.994575,670.99995 C316.704598,671.000763 315.477615,670.442079 314.630967,669.468394 C313.784319,668.49471 313.401158,667.201652 313.580582,665.923653 L316.046749,648.259919 L304.193762,635.514481 C303.080773,634.318044 302.711733,632.608076 303.232152,631.058811 C303.752571,629.509546 305.078939,628.369589 306.688275,628.088421 L323.214424,625.130961 L331.013827,609.468577 C331.767364,607.955994 333.3113,607 335.000594,607 C336.689888,607 338.233824,607.955994 338.98736,609.468577 L346.790813,625.130961 L363.329111,628.08437 C364.934946,628.371492 366.25546,629.513805 366.771316,631.062053 C367.287172,632.610301 366.915846,634.316807 365.803377,635.51043 L353.954439,648.26397 L356.420606,665.923653 C356.652457,667.578241 355.93975,669.223573 354.574418,670.185702 C353.209085,671.147831 351.420524,671.265104 349.941351,670.489485 L335.002619,662.698806 L320.047688,670.50569 C319.413201,670.833752 318.708782,671.003331 317.994575,670.99995 Z M314.678006,634.89463 L324.603415,645.569846 L322.578647,660.041143 L335.002619,653.56309 L347.42254,660.045194 L345.397773,645.573897 L355.323182,634.89463 L341.352288,632.39902 L335.002619,619.637378 L328.648899,632.39902 L314.678006,634.89463 Z" id="Star-outline"></path>
</g>
</g>
</svg>

До

Ширина:  |  Высота:  |  Размер: 1.7 KiB

Просмотреть файл

@ -8,6 +8,8 @@ import { compose } from 'redux';
import log from 'core/logger'; import log from 'core/logger';
import translate from 'core/i18n/translate'; import translate from 'core/i18n/translate';
import { type I18nType } from 'core/types/i18n'; import { type I18nType } from 'core/types/i18n';
import IconStar from 'ui/components/IconStar';
import type { Props as IconStarProps } from 'ui/components/IconStar';
import './styles.scss'; import './styles.scss';
@ -121,7 +123,7 @@ export class RatingBase extends React.Component<InternalProps, StateType> {
}; };
renderRatings(): Array<React.Node> { renderRatings(): Array<React.Node> {
const { readOnly } = this.props; const { readOnly, yellowStars } = this.props;
const { hoveringOverStar } = this.state; const { hoveringOverStar } = this.state;
// Accept falsey values as if they are zeroes. // Accept falsey values as if they are zeroes.
const rating = this.props.rating || 0; const rating = this.props.rating || 0;
@ -134,11 +136,13 @@ export class RatingBase extends React.Component<InternalProps, StateType> {
const title = this.renderTitle(rating, readOnly, thisRating); const title = this.renderTitle(rating, readOnly, thisRating);
const halfStar =
thisRating - rating > 0.25 && thisRating - rating <= 0.75;
const props = { const props = {
className: makeClassName('Rating-star', `Rating-rating-${thisRating}`, { className: makeClassName('Rating-star', `Rating-rating-${thisRating}`, {
'Rating-selected-star': isSelected, 'Rating-selected-star': isSelected,
'Rating-half-star': 'Rating-half-star': halfStar,
thisRating - rating > 0.25 && thisRating - rating <= 0.75,
}), }),
key: `rating-${thisRating}`, key: `rating-${thisRating}`,
onClick: undefined, onClick: undefined,
@ -147,7 +151,16 @@ export class RatingBase extends React.Component<InternalProps, StateType> {
}; };
if (readOnly) { if (readOnly) {
return <div {...props} />; return (
<div {...props}>
{this.renderStar({
half: halfStar,
selected: isSelected,
readOnly,
yellow: yellowStars,
})}
</div>
);
} }
if (!this.isLoading()) { if (!this.isLoading()) {
@ -164,15 +177,21 @@ export class RatingBase extends React.Component<InternalProps, StateType> {
type="button" type="button"
value={thisRating} value={thisRating}
{...props} {...props}
/> >
<span id={id} className="visually-hidden"> <span id={id} className="visually-hidden">
{title} {title}
</span> </span>
{this.renderStar({ selected: isSelected, yellow: true })}
</button>
</React.Fragment> </React.Fragment>
); );
}); });
} }
renderStar(props: IconStarProps) {
return <IconStar {...props} />;
}
isLoading() { isLoading() {
// When rating is undefined, the rating is still loading. // When rating is undefined, the rating is still loading.
// When rating is null, the rating has been loaded but it's empty. // When rating is null, the rating has been loaded but it's empty.
@ -180,7 +199,7 @@ export class RatingBase extends React.Component<InternalProps, StateType> {
} }
render() { render() {
const { className, rating, readOnly, styleSize, yellowStars } = this.props; const { className, rating, readOnly, styleSize } = this.props;
if (!styleSize || !RATING_STYLE_SIZES.includes(styleSize)) { if (!styleSize || !RATING_STYLE_SIZES.includes(styleSize)) {
throw new Error( throw new Error(
oneLine`styleSize=${styleSize || '[empty string]'} is not a valid oneLine`styleSize=${styleSize || '[empty string]'} is not a valid
@ -201,7 +220,6 @@ export class RatingBase extends React.Component<InternalProps, StateType> {
{ {
'Rating--editable': !readOnly, 'Rating--editable': !readOnly,
'Rating--loading': this.isLoading(), 'Rating--loading': this.isLoading(),
'Rating--yellowStars': yellowStars,
}, },
); );

Просмотреть файл

@ -1,4 +1,7 @@
@import '~ui/css/styles'; @import '~ui/css/styles';
$icon-large: 64px;
$icon-medium: 19px;
$icon-small: 13px;
.Rating { .Rating {
align-content: center; align-content: center;
@ -10,21 +13,48 @@
// The width of small rating stars are controlled by .Rating-star. // The width of small rating stars are controlled by .Rating-star.
&.Rating--small { &.Rating--small {
grid-column-gap: 4px; grid-column-gap: 4px;
min-height: 13px; min-height: $icon-small;
width: min-content; width: min-content;
.IconStar {
display: flex;
height: $icon-medium;
width: $icon-small;
svg {
width: inherit;
}
}
&.Rating--editable {
.IconStar {
width: $icon-medium;
// stylelint-disable max-nesting-depth
@include respond-to(large) {
width: $icon-small;
}
}
}
} }
// The width of large rating stars are controlled by the container. // The width of large rating stars are controlled by the container.
&.Rating--large { &.Rating--large {
grid-column-gap: 6px; grid-column-gap: 6px;
max-width: 300px;
min-height: 48px; min-height: 48px;
width: 100%; width: 100%;
.IconStar {
height: 100%;
width: 100%;
}
} }
@include respond-to(extraExtraLarge) { @include respond-to(extraExtraLarge) {
&.Rating--large { &.Rating--large {
grid-column-gap: 12px; grid-column-gap: 12px;
min-height: 64px; max-width: none;
} }
} }
} }
@ -53,7 +83,9 @@
} }
.Rating-star { .Rating-star {
background: url('./img/closed-star-dim-gray.svg') center/contain no-repeat; align-items: center;
display: flex;
justify-content: center;
padding: 0; padding: 0;
&:not(.focus-visible) { &:not(.focus-visible) {
@ -61,7 +93,7 @@
} }
.Rating--small & { .Rating--small & {
min-width: 13px; min-width: $icon-small;
} }
.Rating--loading & { .Rating--loading & {
@ -71,7 +103,6 @@
.Rating--editable { .Rating--editable {
.Rating-star { .Rating-star {
background-image: url('./img/open-star-dim-yellow.svg');
cursor: pointer; cursor: pointer;
} }
@ -79,44 +110,12 @@
animation-name: pulseOpaqueRatingStars; animation-name: pulseOpaqueRatingStars;
// Ensure editable rating stars always render as open stars while // Ensure editable rating stars always render as open stars while
// loading, even if some are selected (e.g. while hovering). // loading, even if some are selected (e.g. while hovering).
background-image: url('./img/open-star-dim-yellow.svg');
cursor: initial; cursor: initial;
} }
} }
.Rating-selected-star {
background-image: url('./img/closed-star-gray.svg');
}
.Rating--editable .Rating-selected-star {
background-image: url('./img/closed-star-yellow.svg');
}
.Rating-half-star { .Rating-half-star {
background-image: url('./img/half-star-gray.svg');
[dir='rtl'] & { [dir='rtl'] & {
transform: scaleX(-1); transform: scaleX(-1);
} }
} }
.Rating--yellowStars {
// When stars are read-only, they are closed. Otherwise, they are open.
.Rating-star {
background-image: url('./img/closed-star-dim-yellow.svg');
}
&.Rating--editable .Rating-star {
background-image: url('./img/open-star-dim-yellow.svg');
}
.Rating-selected-star,
&.Rating--editable .Rating-selected-star {
background-image: url('./img/closed-star-yellow.svg');
}
// This doesn't define an editable half-star because that's not possible.
.Rating-half-star {
background-image: url('./img/half-star-yellow.svg');
}
}

Просмотреть файл

@ -16,6 +16,7 @@ import {
shallowUntilTarget, shallowUntilTarget,
} from 'tests/unit/helpers'; } from 'tests/unit/helpers';
import ErrorList from 'ui/components/ErrorList'; import ErrorList from 'ui/components/ErrorList';
import IconStar from 'ui/components/IconStar';
import LoadingText from 'ui/components/LoadingText'; import LoadingText from 'ui/components/LoadingText';
describe(__filename, () => { describe(__filename, () => {
@ -186,6 +187,13 @@ describe(__filename, () => {
validateLink(counts.at(4), '1', 'Read all one-star reviews'); validateLink(counts.at(4), '1', 'Read all one-star reviews');
}); });
it('renders IconStar', () => {
const root = render();
const star = root.find(IconStar).at(0);
expect(star).toHaveLength(1);
expect(star).toHaveProp('selected');
});
it('renders bar value widths based on total ratings', () => { it('renders bar value widths based on total ratings', () => {
// Set up an add-on with one 5-star rating and one 4-star rating. // Set up an add-on with one 5-star rating and one 4-star rating.
const grouping = { const grouping = {

Просмотреть файл

@ -0,0 +1,60 @@
import * as React from 'react';
import { shallow } from 'enzyme';
import photon from 'photon-colors';
import Icon from 'ui/components/Icon';
import IconStar, {
getSvgPath,
CLOSED_STYLE,
DIM_CLOSED_STYLE,
HALF_STYLE,
OPEN_STYLE,
} from 'ui/components/IconStar';
describe(__filename, () => {
it('sets the default color to YELLOW', () => {
const star = shallow(<IconStar />);
expect(star.find('g')).toHaveProp('fill', photon.YELLOW_50);
});
it('changes the color to GRAY if yellow is false', () => {
const star = shallow(<IconStar yellow={false} />);
expect(star.find('g')).toHaveProp('fill', photon.GREY_50);
});
it('sets the star style to HALF_STYLE if half and readOnly are true', () => {
const star = shallow(<IconStar readOnly half />);
expect(star.find('defs')).toHaveLength(1);
expect(star.find('path')).toHaveProp('d', getSvgPath(HALF_STYLE));
});
it("sets the star style to CLOSED_STYLE if the star is selected and it's not readOnly", () => {
const star = shallow(<IconStar readOnly={false} selected />);
expect(star.find('g')).toHaveProp('fillOpacity', 1);
expect(star.find('path')).toHaveProp('d', getSvgPath(CLOSED_STYLE));
});
it("sets the star style to DIM_CLOSED_STYLE if the star is not selected and it's readOnly", () => {
const star = shallow(<IconStar readOnly selected={false} />);
expect(star.find('g')).toHaveProp('fillOpacity', 0.25);
expect(star.find('path')).toHaveProp('d', getSvgPath(DIM_CLOSED_STYLE));
});
it("sets the star style to OPEN_STYLE if the star is not selected and it's not readOnly ", () => {
const star = shallow(<IconStar readOnly={false} selected={false} />);
expect(star.find('g')).toHaveProp('fillOpacity', 1);
expect(star.find('path')).toHaveProp('d', getSvgPath(OPEN_STYLE));
});
it('passes a className to the Icon component', () => {
const star = shallow(<IconStar className="twinkle" />);
expect(star.find(Icon)).toHaveClassName('twinkle');
});
});

Просмотреть файл

@ -5,6 +5,7 @@ import {
fakeI18n, fakeI18n,
shallowUntilTarget, shallowUntilTarget,
} from 'tests/unit/helpers'; } from 'tests/unit/helpers';
import IconStar from 'ui/components/IconStar';
import Rating, { RatingBase } from 'ui/components/Rating'; import Rating, { RatingBase } from 'ui/components/Rating';
describe(__filename, () => { describe(__filename, () => {
@ -51,9 +52,10 @@ describe(__filename, () => {
expect(root).toHaveClassName('Rating--small'); expect(root).toHaveClassName('Rating--small');
}); });
it('can be classified as yellowStars', () => { it('can be classified as yellow stars', () => {
const root = render({ yellowStars: true }); const root = render({ yellowStars: true });
expect(root).toHaveClassName('Rating--yellowStars'); const star = root.find(IconStar).at(0);
expect(star).toHaveProp('yellow');
}); });
it('classifies as yellowStars=false by default', () => { it('classifies as yellowStars=false by default', () => {
@ -411,13 +413,34 @@ describe(__filename, () => {
); );
}); });
}); });
it("only passes the selected and yellow prop to the IconStar component when it's not readOnly", () => {
const root = render({ readOnly: false });
const star = root.find(IconStar).at(0);
expect(star).toHaveProp('selected');
expect(star).not.toHaveProp('half');
});
it("passes several props to the IconStar component when it's readOnly", () => {
const root = render({ readOnly: true });
const star = root.find(IconStar).at(0);
expect(star).toHaveProp('selected');
expect(star).toHaveProp('half');
expect(star).toHaveProp('yellow');
expect(star).toHaveProp('readOnly', true);
});
}); });
describe('rating counts', () => { describe('rating counts', () => {
it('renders the average rating', () => { it('renders the average rating', () => {
expect(render({ rating: 3.5, readOnly: true })).toHaveText( const rating = 3.5;
'Rated 3.5 out of 5', const root = render({ rating, readOnly: true });
);
expect(root).toHaveProp('title', `Rated ${rating} out of 5`);
}); });
it('localizes average rating', () => { it('localizes average rating', () => {
@ -428,9 +451,9 @@ describe(__filename, () => {
}); });
it('renders empty ratings', () => { it('renders empty ratings', () => {
expect(renderWithEmptyRating({ readOnly: true })).toHaveText( const root = renderWithEmptyRating({ readOnly: true });
'There are no ratings yet',
); expect(root).toHaveProp('title', 'There are no ratings yet');
}); });
}); });

Просмотреть файл

@ -2342,7 +2342,6 @@ babel-eslint@^10.0.1:
"babel-gettext-extractor@github:mozilla/babel-gettext-extractor#babel-7": "babel-gettext-extractor@github:mozilla/babel-gettext-extractor#babel-7":
version "4.0.0" version "4.0.0"
uid "78ff104e669edb731e979e36fbf4fe261a569924"
resolved "https://codeload.github.com/mozilla/babel-gettext-extractor/tar.gz/78ff104e669edb731e979e36fbf4fe261a569924" resolved "https://codeload.github.com/mozilla/babel-gettext-extractor/tar.gz/78ff104e669edb731e979e36fbf4fe261a569924"
dependencies: dependencies:
"@babel/core" "^7.0.0" "@babel/core" "^7.0.0"
@ -10338,7 +10337,7 @@ performance-now@^2.1.0:
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
photon-colors@^3.0.1: photon-colors@3.3.1:
version "3.3.1" version "3.3.1"
resolved "https://registry.yarnpkg.com/photon-colors/-/photon-colors-3.3.1.tgz#74d8322ca459a1bb12f769d2669ef62d20992285" resolved "https://registry.yarnpkg.com/photon-colors/-/photon-colors-3.3.1.tgz#74d8322ca459a1bb12f769d2669ef62d20992285"
integrity sha512-xE+6KKudiSuoGV1YaVLnYMeKyUpqsVeQUvrUUPAOy4s9YuIdGOVdJ07+YQAZVm7R1cQpi0cm0pcq+DcyTVFVyg== integrity sha512-xE+6KKudiSuoGV1YaVLnYMeKyUpqsVeQUvrUUPAOy4s9YuIdGOVdJ07+YQAZVm7R1cQpi0cm0pcq+DcyTVFVyg==