Tighten up styles for the recommended badges (#8062)

This commit is contained in:
Kumar McMillan 2019-05-24 11:26:46 -05:00 коммит произвёл GitHub
Родитель 6412f24eeb
Коммит d2fb74c09a
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
17 изменённых файлов: 291 добавлений и 88 удалений

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

@ -70,7 +70,7 @@ export class AddonBadgesBase extends React.Component<InternalProps> {
_config.get('enableFeatureRecommendedBadges') &&
addon.is_recommended &&
clientApp !== CLIENT_APP_ANDROID ? (
<RecommendedBadge />
<RecommendedBadge size="large" />
) : null}
{showFeaturedBadge ? (
<Badge type="featured" label={getFeaturedText(addon.type)} />

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

@ -144,7 +144,7 @@ export class SearchResultBase extends React.Component<InternalProps> {
addon &&
addon.is_recommended &&
clientApp !== CLIENT_APP_ANDROID ? (
<RecommendedBadge />
<RecommendedBadge size="small" />
) : null}
</h2>
{summary}

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

@ -94,9 +94,12 @@ $icon-default-size: 32px;
.SearchResult-name {
@include font-medium();
align-items: flex-start;
color: $type-black;
display: flex;
flex-direction: column;
flex-grow: 1;
flex-wrap: wrap;
font-size: $font-size-m-smaller;
line-height: 1.2;
margin: 0;
@ -106,7 +109,19 @@ $icon-default-size: 32px;
word-wrap: break-word;
.RecommendedBadge {
@include margin-start(8px);
justify-content: flex-start;
margin-top: 6px;
}
@include respond-to(extraLarge) {
flex-direction: row;
margin-top: 0;
.RecommendedBadge {
@include margin-start(8px);
margin-top: 0;
}
}
.SearchResult-link:focus &,

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

@ -5,6 +5,7 @@ import makeClassName from 'classnames';
import translate from 'core/i18n/translate';
import Icon from 'ui/components/Icon';
import IconRecommendedBadge from 'ui/components/IconRecommendedBadge';
import LoadingText from 'ui/components/LoadingText';
import type { I18nType } from 'core/types/i18n';
@ -44,10 +45,10 @@ export const SearchSuggestionBase = ({
{loading ? <LoadingText minWidth={20} range={12} /> : name}
</span>
{_config.get('enableFeatureRecommendedBadges') && isRecommended && (
<Icon
<IconRecommendedBadge
alt={i18n.gettext('Recommended')}
className="SearchSuggestion-icon-recommended"
name="recommended-circle"
size="small"
/>
)}
<Icon

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

@ -1,11 +0,0 @@
<svg width="20" height="20" xmlns="http://www.w3.org/2000/svg">
<title>Group 16 Copy 2</title>
<!--
The color #ff9400 is equivalent to the photon color orange-50
https://design.firefox.com/photon/visuals/color.html#orange
-->
<circle cx="10" cy="10" fill="#ff9400" r="10"></circle>
<g fill="#FFFFFF" fill-rule="nonzero">
<path d="M15.449999809265137,3.999999523162842 H4.550000190734863 C4.25,3.999999523162842 4,4.219999313354492 4,4.499999523162842 V6.999999523162842 c0,1.100000023841858 0.9800000190734863,2 2.180000066757202,2 h0.05000000074505806 a3.6700000762939453,3.6700000762939453 0 0 0 3.2200000286102295,2.9600000381469727 V13.499999523162842 h1.100000023841858 V11.959999561309814 A3.6700000762939453,3.6700000762939453 0 0 0 13.770000457763672,8.999999523162842 h0.05000000074505806 C15.020000457763672,8.999999523162842 16,8.099998950958252 16,6.999999523162842 V4.499999523162842 c0,-0.2800000011920929 -0.23999999463558197,-0.5 -0.550000011920929,-0.5 zM5.099999904632568,6.999999523162842 V4.999999523162842 h1.100000023841858 v3 c-0.6100000143051147,0 -1.100000023841858,-0.44999998807907104 -1.100000023841858,-1 zm9.819999694824219,0 c0,0.550000011920929 -0.49000000953674316,1 -1.100000023841858,1 V4.999999523162842 h1.100000023841858 v2 zM11.100000381469727,13.999999523162842 H8.899999618530273 c-2.7200000286102295,0 -2.7200000286102295,2 -2.7200000286102295,2 h7.639999866485596 s0,-2 -2.7300000190734863,-2 z" id="svg_3"/>
</g>
</svg>

До

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

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

@ -1 +0,0 @@
<svg width="12" height="12" xmlns="http://www.w3.org/2000/svg"><title>Group 16 Copy 2</title><g fill="#FFFFFF" fill-rule="nonzero"><path d="M11.45 0H.55C.25 0 0 .22 0 .5V3c0 1.1.98 2 2.18 2h.05a3.67 3.67 0 0 0 3.22 2.96V9.5h1.1V7.96A3.67 3.67 0 0 0 9.77 5h.05C11.02 5 12 4.1 12 3V.5c0-.28-.24-.5-.55-.5zM1.1 3V1h1.1v3c-.61 0-1.1-.45-1.1-1zm9.82 0c0 .55-.49 1-1.1 1V1h1.1v2zM7.1 10H4.9c-2.72 0-2.72 2-2.72 2h7.64s0-2-2.73-2z"/></g></svg>

До

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

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

@ -327,14 +327,3 @@
height: 12px;
width: 12px;
}
.Icon-recommended {
@include icon($name: 'recommended');
height: 12px;
width: 12px;
}
.Icon-recommended-circle {
@include icon($name: 'recommended-circle');
}

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

@ -0,0 +1,51 @@
/* @flow */
import * as React from 'react';
import makeClassName from 'classnames';
import Icon from 'ui/components/Icon';
import type { Props as IconProps } from 'ui/components/Icon';
import './styles.scss';
export type RecommendedBadgeSize = 'large' | 'small';
type Props = {|
alt?: $PropertyType<IconProps, 'alt'>,
className?: string,
size: RecommendedBadgeSize,
|};
const IconRecommendedBadge = ({ className, size, ...iconProps }: Props) => {
return (
<Icon
{...iconProps}
className={makeClassName('IconRecommendedBadge', className, {
'IconRecommendedBadge-large': size === 'large',
'IconRecommendedBadge-small': size === 'small',
})}
name="inline-content"
>
<svg
className="IconRecommendedBadge-svg"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlnsXlink="http://www.w3.org/1999/xlink"
>
<circle
className="IconRecommendedBadge-shellPath"
cx="50%"
cy="50%"
r="50%"
/>
<g fillRule="nonzero">
<path
className="IconRecommendedBadge-iconPath"
d="M15.449999809265137,3.999999523162842 H4.550000190734863 C4.25,3.999999523162842 4,4.219999313354492 4,4.499999523162842 V6.999999523162842 c0,1.100000023841858 0.9800000190734863,2 2.180000066757202,2 h0.05000000074505806 a3.6700000762939453,3.6700000762939453 0 0 0 3.2200000286102295,2.9600000381469727 V13.499999523162842 h1.100000023841858 V11.959999561309814 A3.6700000762939453,3.6700000762939453 0 0 0 13.770000457763672,8.999999523162842 h0.05000000074505806 C15.020000457763672,8.999999523162842 16,8.099998950958252 16,6.999999523162842 V4.499999523162842 c0,-0.2800000011920929 -0.23999999463558197,-0.5 -0.550000011920929,-0.5 zM5.099999904632568,6.999999523162842 V4.999999523162842 h1.100000023841858 v3 c-0.6100000143051147,0 -1.100000023841858,-0.44999998807907104 -1.100000023841858,-1 zm9.819999694824219,0 c0,0.550000011920929 -0.49000000953674316,1 -1.100000023841858,1 V4.999999523162842 h1.100000023841858 v2 zM11.100000381469727,13.999999523162842 H8.899999618530273 c-2.7200000286102295,0 -2.7200000286102295,2 -2.7200000286102295,2 h7.639999866485596 s0,-2 -2.7300000190734863,-2 z"
/>
</g>
</svg>
</Icon>
);
};
export default IconRecommendedBadge;

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

@ -0,0 +1,51 @@
@import '~ui/css/styles';
@import '~ui/components/Icon/vars';
$icon-recommended-large-size: 24px;
$icon-recommended-small-size: 16px;
.IconRecommendedBadge {
box-sizing: border-box;
display: flex;
height: auto;
width: auto;
}
.IconRecommendedBadge-svg {
box-sizing: border-box;
height: $default-icon-size;
width: $default-icon-size;
}
.IconRecommendedBadge-shellPath {
fill: $orange-50;
}
.IconRecommendedBadge-iconPath {
fill: $white;
transform-origin: 50% 50%;
}
.IconRecommendedBadge-large {
.IconRecommendedBadge-svg {
height: $icon-recommended-large-size;
width: $icon-recommended-large-size;
}
.IconRecommendedBadge-iconPath {
// Nudge the trophy into the center of the circle.
transform: translate(2px, 2.5px) scale(1.1);
}
}
.IconRecommendedBadge-small {
.IconRecommendedBadge-svg {
height: $icon-recommended-small-size;
width: $icon-recommended-small-size;
}
.IconRecommendedBadge-iconPath {
// Nudge the trophy into the center of the circle.
transform: translate(-1.5px, -1.5px) scale(0.8);
}
}

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

@ -1,25 +1,34 @@
/* @flow */
import makeClassName from 'classnames';
import * as React from 'react';
import { compose } from 'redux';
import translate from 'core/i18n/translate';
import Icon from 'ui/components/Icon';
import IconRecommendedBadge from 'ui/components/IconRecommendedBadge';
import type { RecommendedBadgeSize } from 'ui/components/IconRecommendedBadge';
import type { I18nType } from 'core/types/i18n';
import './styles.scss';
type Props = {};
type Props = {|
size: RecommendedBadgeSize,
|};
type InternalProps = {|
...Props,
i18n: I18nType,
|};
export const RecommendedBadgeBase = (props: InternalProps) => {
const { i18n } = props;
export const RecommendedBadgeBase = ({ i18n, size }: InternalProps) => {
const label = i18n.gettext('Recommended');
return (
<div className="RecommendedBadge">
<div
className={makeClassName('RecommendedBadge', {
'RecommendedBadge-large': size === 'large',
'RecommendedBadge-small': size === 'small',
})}
>
<a
className="RecommendedBadge-link"
href="https://support.mozilla.org/"
@ -29,9 +38,7 @@ export const RecommendedBadgeBase = (props: InternalProps) => {
'Firefox only recommends extensions that meet our standards for security and performance.',
)}
>
<span className="RecommendedBadge-icon">
<Icon alt={label} name="recommended" />
</span>
<IconRecommendedBadge alt={label} size={size} />
<span className="RecommendedBadge-label">{label}</span>
</a>
</div>

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

@ -1,61 +1,63 @@
@import '~ui/css/styles';
$recommended-text-color: $orange-50;
$recommended-hover-color: $orange-60;
@import '~ui/components/IconRecommendedBadge/styles';
.RecommendedBadge {
align-items: center;
color: $recommended-text-color;
align-items: flex-start;
color: $orange-50;
display: flex;
font-size: $font-size-m-smaller;
font-size: $font-size-micro;
margin-bottom: 6px;
&.RecommendedBadge-large {
font-size: $font-size-m-smaller;
}
@include respond-to(large) {
justify-content: flex-end;
}
}
a,
a:link,
a:visited {
color: $recommended-text-color;
.RecommendedBadge-link {
align-items: center;
border: 1px solid $orange-50;
border-radius: 20px;
box-sizing: border-box;
display: flex;
flex-grow: 0;
flex-shrink: 0;
max-height: $icon-recommended-small-size;
.RecommendedBadge-large & {
max-height: $icon-recommended-large-size;
}
&,
&:link,
&:visited {
color: $orange-50;
font-weight: normal;
text-decoration: none;
}
a:active,
a:focus,
a:hover {
border-color: $recommended-hover-color;
color: $recommended-hover-color;
&:active,
&:focus,
&:hover {
border-color: $orange-60;
color: $orange-60;
.RecommendedBadge-icon {
background-color: $recommended-hover-color;
.IconRecommendedBadge-shellPath {
fill: $orange-60;
}
}
}
.RecommendedBadge-link {
@include padding-end(10px);
border: 1px solid $recommended-text-color;
border-radius: 20px;
height: 24px;
}
.RecommendedBadge-icon {
@include margin-end(6px);
@include padding-end(0);
@include padding-start(4px);
background-color: $recommended-text-color;
border-radius: 50%;
display: inline-block;
height: 22px;
padding-bottom: 4px;
padding-top: 2px;
width: 22px;
}
.RecommendedBadge-label {
@include margin-start(2px);
@include margin-end(8px);
.RecommendedBadge-large & {
@include margin-start(6px);
}
color: $orange-80;
}

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

@ -7,5 +7,6 @@ import './setup/styles.scss';
// Components
import './ui/Badge';
import './ui/Button';
import './ui/IconRecommendedBadge';
import './ui/Rating';
import './ui/RecommendedBadge';

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

@ -0,0 +1,26 @@
/* @flow */
import React from 'react';
import { storiesOf } from '@storybook/react';
import IconRecommendedBadge from 'ui/components/IconRecommendedBadge';
const render = ({ size = 'large' } = {}) => {
return <IconRecommendedBadge size={size} />;
};
storiesOf('IconRecommendedBadge', module).addWithChapters('all variants', {
chapters: [
{
sections: [
{
title: 'size="large"',
sectionFn: () => render({ size: 'large' }),
},
{
title: 'size="small"',
sectionFn: () => render({ size: 'small' }),
},
],
},
],
});

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

@ -3,8 +3,34 @@ import React from 'react';
import { storiesOf } from '@storybook/react';
import { fakeI18n } from 'tests/unit/helpers';
import RecommendedBadge from 'ui/components/RecommendedBadge';
import { RecommendedBadgeBase } from 'ui/components/RecommendedBadge';
storiesOf('RecommendedBadge', module).add('default', () => (
<RecommendedBadge i18n={fakeI18n({ includeJedSpy: false })} />
));
const render = (moreProps = {}) => {
const props = {
size: 'large',
...moreProps,
};
return (
<RecommendedBadgeBase
i18n={fakeI18n({ includeJedSpy: false })}
{...props}
/>
);
};
storiesOf('RecommendedBadge', module).addWithChapters('all variants', {
chapters: [
{
sections: [
{
title: 'size="large"',
sectionFn: () => render({ size: 'large' }),
},
{
title: 'size="small"',
sectionFn: () => render({ size: 'small' }),
},
],
},
],
});

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

@ -75,7 +75,6 @@ describe(__filename, () => {
};
const root = shallowComponent(props);
expect(root.find(Icon)).toHaveLength(2);
expect(root.find('.SearchSuggestion-icon-recommended')).toHaveLength(1);
});

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

@ -0,0 +1,38 @@
import { shallow } from 'enzyme';
import * as React from 'react';
import Icon from 'ui/components/Icon';
import IconRecommendedBadge from 'ui/components/IconRecommendedBadge';
describe(__filename, () => {
const render = (moreProps = {}) => {
const props = {
size: 'large',
...moreProps,
};
return shallow(<IconRecommendedBadge {...props} />);
};
it.each([
['IconRecommendedBadge-large', 'large'],
['IconRecommendedBadge-small', 'small'],
])('adds the class "%s" for size="%s"', (className, size) => {
const root = render({ size });
expect(root).toHaveClassName(className);
});
it('adds a custom class', () => {
const className = 'MyCoolBadge';
const root = render({ className });
expect(root).toHaveClassName(className);
});
it('adds an alt property', () => {
const alt = 'This is a badge';
const root = render({ alt });
expect(root.find(Icon)).toHaveProp('alt', alt);
});
});

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

@ -4,17 +4,26 @@ import { fakeI18n, shallowUntilTarget } from 'tests/unit/helpers';
import RecommendedBadge, {
RecommendedBadgeBase,
} from 'ui/components/RecommendedBadge';
import Icon from 'ui/components/Icon';
describe(__filename, () => {
it('renders a badge', () => {
const root = shallowUntilTarget(
<RecommendedBadge i18n={fakeI18n()} />,
const render = (moreProps = {}) => {
const props = {
i18n: fakeI18n(),
size: 'large',
...moreProps,
};
return shallowUntilTarget(
<RecommendedBadge {...props} />,
RecommendedBadgeBase,
);
const label = 'Recommended';
};
expect(root.find(Icon)).toHaveProp('alt', label);
expect(root.find('.RecommendedBadge-label')).toIncludeText(label);
it.each([
['RecommendedBadge-large', 'large'],
['RecommendedBadge-small', 'small'],
])('adds the class "%s" for size="%s"', (className, size) => {
const root = render({ size });
expect(root).toHaveClassName(className);
});
});