Unverified Commit 86594b9a authored by Marcos Iglesias's avatar Marcos Iglesias Committed by GitHub

feat: Adds InformationIcon and LeftIcon (#715)

* Adds Left Icon
Signed-off-by: 's avatarMarcos Iglesias <miglesiasvalle@lyft.com>

* Adds Information Icon and uses it within the InfoButton; refactors client components
Signed-off-by: 's avatarMarcos Iglesias <miglesiasvalle@lyft.com>

* Constant for default placement
Signed-off-by: 's avatarMarcos Iglesias <miglesiasvalle@lyft.com>
parent 284c91f3
......@@ -3,8 +3,8 @@
import * as React from 'react';
import { IconSizes } from 'interfaces';
import { AlertIcon } from '../SVGIcons';
import { IconSizes } from '../SVGIcons/types';
import './styles.scss';
......
......@@ -32,7 +32,6 @@ describe('EntityCardSection', () => {
expect(subject.find(InfoButton).props()).toMatchObject({
infoText: props.infoText,
placement: 'top',
size: 'small',
});
});
......
......@@ -4,7 +4,7 @@
import * as React from 'react';
import InfoButton from 'components/common/InfoButton';
// TODO: Use css-modules instead of 'import'
import { IconSizes } from 'interfaces';
import './styles.scss';
export interface EntityCardSectionProps {
......@@ -54,7 +54,7 @@ class EntityCardSection extends React.Component<
<InfoButton
infoText={this.props.infoText}
placement="top"
size="small"
size={IconSizes.SMALL}
/>
)}
{this.props.isEditable && (
......
......@@ -3,10 +3,9 @@
import * as React from 'react';
import SanitizedHTML from 'react-sanitized-html';
import { shallow } from 'enzyme';
import { OverlayTrigger, Popover } from 'react-bootstrap';
import InfoButton, { InfoButtonProps } from '.';
describe('InfoButton', () => {
......@@ -18,7 +17,6 @@ describe('InfoButton', () => {
infoText: 'Some info text to share',
title: 'Popover Title',
placement: 'left',
size: 'size',
};
subject = shallow(<InfoButton {...props} />);
});
......@@ -40,11 +38,5 @@ describe('InfoButton', () => {
expectedPopover
);
});
it('renders OverlayTrigger w/ correct placement', () => {
expect(
subject.find(OverlayTrigger).find('button').props().className
).toEqual(`btn icon info-button ${props.size}`);
});
});
});
......@@ -3,27 +3,28 @@
import * as React from 'react';
import { OverlayTrigger, Popover } from 'react-bootstrap';
// TODO - Consider an alternative to react-sanitized-html (large filesize)
import SanitizedHTML from 'react-sanitized-html';
// TODO: Use css-modules instead of 'import'
import { IconSizes } from 'interfaces';
import { InformationIcon } from '../SVGIcons';
import './styles.scss';
const INFO_BUTTON_TEXT = 'More info';
const DEFAULT_PLACEMENT = 'right';
export interface InfoButtonProps {
infoText?: string;
title?: string;
placement?: string;
size?: string;
size?: IconSizes;
}
const InfoButton: React.FC<InfoButtonProps> = ({
title,
infoText,
placement,
size,
placement = DEFAULT_PLACEMENT,
size = IconSizes.REGULAR,
}: InfoButtonProps) => {
const popoverHoverFocus = (
<Popover id="popover-trigger-hover-focus" title={title}>
......@@ -37,18 +38,15 @@ const InfoButton: React.FC<InfoButtonProps> = ({
placement={placement}
overlay={popoverHoverFocus}
>
<button className={'btn icon info-button ' + size} type="button">
<button
className={`btn info-button ${size === IconSizes.SMALL ? 'small' : ''}`}
type="button"
>
<InformationIcon size={size} />
<span className="sr-only">{INFO_BUTTON_TEXT}</span>
</button>
</OverlayTrigger>
);
};
InfoButton.defaultProps = {
infoText: '',
title: '',
placement: 'right',
size: '',
};
export default InfoButton;
......@@ -2,33 +2,47 @@
// SPDX-License-Identifier: Apache-2.0
import React from 'react';
import { storiesOf } from '@storybook/react';
import { withKnobs, object } from '@storybook/addon-knobs';
import { IconSizes } from 'interfaces';
import StorySection from '../StorySection';
import InfoButton from '.';
const stories = storiesOf('Components/Buttons', module);
stories.add('Info Button', () => (
export const InfoButtonStory = () => (
<>
<StorySection title="Info Button">
<InfoButton infoText="Some info text to share" title="Popover Title" />
<InfoButton
infoText={object('InfoButton infoText', 'Some info text to share')}
title={object('InfoButton title', 'Popover Title')}
/>
</StorySection>
<StorySection title="Info Button to left">
<InfoButton
infoText="Some info text to share"
title="Popover Title"
placement="left"
size="size"
infoText={object(
'InfoButton infoText to left title',
'Some info text to share'
)}
title={object('InfoButton to left title', 'Popover Title')}
placement={object('InfoButton placement to left', 'left')}
/>
</StorySection>
<StorySection title="Info Button small size">
<InfoButton
infoText="Some info text to share"
title="Popover Title"
placement="left"
size="small"
infoText={object(
'InfoButton infoText small size title',
'Some info text to share'
)}
title={object('InfoButton small size title', 'Popover Title')}
placement={object('InfoButton small size placement', 'left')}
size={IconSizes.SMALL}
/>
</StorySection>
</>
));
);
InfoButtonStory.storyName = 'Info Button';
export default {
title: 'Components/Buttons',
component: InfoButton,
decorators: [withKnobs],
};
......@@ -3,29 +3,24 @@
@import 'variables';
button.info-button {
background-color: $stroke;
$info-button-regular-size: 24px;
$info-button-small-size: 18px;
.btn.info-button {
background-color: transparent;
border: none;
height: 24px;
margin: 0 0 0 8px;
-webkit-mask-image: url('../../../../images/icons/Info.svg');
mask-image: url('../../../../images/icons/Info.svg');
-webkit-mask-position: center;
mask-position: center;
-webkit-mask-size: contain;
-webkit-mask-size: 110%;
mask-size: contain;
mask-size: 110%;
height: $info-button-regular-size;
margin: 0 0 0 $spacer-1;
padding: 0;
width: 24px;
}
width: $info-button-regular-size;
button.info-button.small {
height: 18px;
margin: -4px 0 0 4px;
width: 18px;
}
&.small {
height: $info-button-small-size;
margin: -4px 0 0 4px;
width: $info-button-small-size;
}
button.info-button:hover {
background-color: $brand-color-4;
&:hover path {
fill: $brand-color-4;
}
}
......@@ -3,7 +3,8 @@
import * as React from 'react';
import { IconSizes, IconProps } from './types';
import { IconSizes } from 'interfaces';
import { IconProps } from './types';
const DEFAULT_STROKE_COLOR = 'currentColor';
......
......@@ -2,31 +2,32 @@
// SPDX-License-Identifier: Apache-2.0
import * as React from 'react';
import { v4 as uuidv4 } from 'uuid';
import { IconSizes, IconProps } from './types';
const DEFAULT_STROKE_COLOR = '';
const DEFAULT_FILL_COLOR = '#9191A8'; // gray40
import { IconSizes } from 'interfaces';
import { IconProps } from './types';
import { DEFAULT_FILL_COLOR } from './constants';
export const DownIcon: React.FC<IconProps> = ({
stroke = DEFAULT_STROKE_COLOR,
size = IconSizes.REGULAR,
fill = DEFAULT_FILL_COLOR,
}: IconProps) => {
const id = `down_icon_${uuidv4()}`;
return (
<svg width={size} height={size} viewBox="0 0 24 24">
<title>Down</title>
<defs>
<path
d="M11.987 13.73l4.051-3.918a1.017 1.017 0 011.426.012.983.983 0 01-.012 1.403l-4.733 4.578a1.013 1.013 0 01-.63.283 1.024 1.024 0 01-.814-.277l-4.833-4.59a.975.975 0 01-.018-1.397 1.026 1.026 0 011.432-.018l4.131 3.924z"
id="prefix__a"
id={id}
/>
</defs>
<g fill="none" fillRule="evenodd">
<mask id="prefix__b" fill="#fff">
<use xlinkHref="#prefix__a" />
<use xlinkHref={`#${id}`} />
</mask>
<use fill={fill} xlinkHref="#prefix__a" stroke={stroke} />
<use fill={fill} xlinkHref={`#${id}`} />
</g>
</svg>
);
......
// Copyright Contributors to the Amundsen project.
// SPDX-License-Identifier: Apache-2.0
import * as React from 'react';
import { v4 as uuidv4 } from 'uuid';
import { IconSizes } from 'interfaces';
import { IconProps } from './types';
const DEFAULT_FILL_COLOR = '#9191A8'; // gray40
export const InformationIcon: React.FC<IconProps> = ({
size = IconSizes.REGULAR,
fill = DEFAULT_FILL_COLOR,
}: IconProps) => {
const id = `info_icon_${uuidv4()}`;
return (
<svg width={size} height={size} viewBox="0 0 24 24">
<title>Info</title>
<defs>
<path
d="M12 21a9 9 0 110-18 9 9 0 010 18zm0-2a7 7 0 100-14 7 7 0 000 14zm1-3.833c0 .46-.448.833-1 .833s-1-.373-1-.833v-3.334c0-.46.448-.833 1-.833s1 .373 1 .833v3.334zM12 10a1 1 0 110-2 1 1 0 010 2z"
id={id}
/>
</defs>
<g fill="none" fillRule="evenodd">
<mask id="prefix__b" fill="#fff">
<use xlinkHref={`#${id}`} />
</mask>
<use fill={fill} fillRule="nonzero" xlinkHref={`#${id}`} />
</g>
</svg>
);
};
// Copyright Contributors to the Amundsen project.
// SPDX-License-Identifier: Apache-2.0
import * as React from 'react';
import { v4 as uuidv4 } from 'uuid';
import { IconSizes } from 'interfaces';
import { IconProps } from './types';
import { DEFAULT_FILL_COLOR } from './constants';
export const LeftIcon: React.FC<IconProps> = ({
size = IconSizes.REGULAR,
fill = DEFAULT_FILL_COLOR,
}: IconProps) => {
const id = `left_icon_${uuidv4()}`;
return (
<svg width={size} height={size} viewBox="0 0 24 24">
<title>Left</title>
<defs>
<path
d="M11.694 13l4.136-3.987c.4-.385 1.034-.38 1.427.013a.982.982 0 01-.013 1.401l-4.843 4.67a1.017 1.017 0 01-.857.273 1.005 1.005 0 01-.577-.28l-4.743-4.656a.99.99 0 01-.007-1.408 1.01 1.01 0 011.42-.006L11.695 13z"
id={id}
/>
</defs>
<g fill="none" fillRule="evenodd">
<mask id="prefix__b" fill="#fff">
<use xlinkHref={`#${id}`} />
</mask>
<use
fill={fill}
transform="rotate(90 11.736 12.055)"
xlinkHref={`#${id}`}
/>
</g>
</svg>
);
};
......@@ -2,34 +2,34 @@
// SPDX-License-Identifier: Apache-2.0
import * as React from 'react';
import { v4 as uuidv4 } from 'uuid';
import { IconSizes, IconProps } from './types';
const DEFAULT_STROKE_COLOR = '';
const DEFAULT_FILL_COLOR = '#9191A8'; // gray40
import { IconSizes } from 'interfaces';
import { IconProps } from './types';
import { DEFAULT_FILL_COLOR } from './constants';
export const RightIcon: React.FC<IconProps> = ({
stroke = DEFAULT_STROKE_COLOR,
size = IconSizes.REGULAR,
fill = DEFAULT_FILL_COLOR,
}: IconProps) => {
const id = `right_icon_${uuidv4()}`;
return (
<svg width={size} height={size} viewBox="0 0 24 24">
<title>Right</title>
<defs>
<path
d="M11.836 12.968l4.05-3.897a1.02 1.02 0 011.427.014.981.981 0 01-.014 1.4l-4.73 4.553c-.18.174-.409.268-.641.283a1.026 1.026 0 01-.806-.276l-4.83-4.566a.972.972 0 01-.019-1.394 1.028 1.028 0 011.434-.02l4.129 3.903z"
id="prefix__a"
id={id}
/>
</defs>
<g fill="none" fillRule="evenodd">
<mask id="prefix__b" fill="#fff">
<use xlinkHref="#prefix__a" />
<use xlinkHref={`#${id}`} />
</mask>
<use
fill={fill}
xlinkHref="#prefix__a"
stroke={stroke}
xlinkHref={`#${id}`}
transform="rotate(-90 11.794 12.055)"
/>
</g>
......
......@@ -2,35 +2,35 @@
// SPDX-License-Identifier: Apache-2.0
import * as React from 'react';
import { v4 as uuidv4 } from 'uuid';
import { IconSizes, IconProps } from './types';
const DEFAULT_STROKE_COLOR = '';
const DEFAULT_FILL_COLOR = '#9191A8'; // gray40
import { IconSizes } from 'interfaces';
import { IconProps } from './types';
import { DEFAULT_FILL_COLOR } from './constants';
export const UpIcon: React.FC<IconProps> = ({
stroke = DEFAULT_STROKE_COLOR,
size = IconSizes.REGULAR,
fill = DEFAULT_FILL_COLOR,
}: IconProps) => {
const id = `up_icon_${uuidv4()}`;
return (
<svg width={size} height={size} viewBox="0 0 24 24">
<title>Up</title>
<defs>
<path
d="M12.097 12.12l4.049-3.898a1.02 1.02 0 011.427.014.981.981 0 01-.013 1.4l-4.73 4.553c-.18.174-.41.268-.642.283a1.026 1.026 0 01-.805-.276L6.553 9.63a.972.972 0 01-.02-1.394 1.028 1.028 0 011.434-.02l4.13 3.904z"
id="prefix__a"
id={id}
/>
</defs>
<g fill="none" fillRule="evenodd">
<mask id="prefix__b" fill="#fff">
<use xlinkHref="#prefix__a" />
<use xlinkHref={`#${id}`} />
</mask>
<use
fill={fill}
stroke={stroke}
transform="rotate(-180 12.055 11.206)"
xlinkHref="#prefix__a"
xlinkHref={`#${id}`}
/>
</g>
</svg>
......
export const DEFAULT_FILL_COLOR = '#9191A8'; // gray40
// Copyright Contributors to the Amundsen project.
// SPDX-License-Identifier: Apache-2.0
export * from './types';
export * from './AlertIcon';
export * from './DownIcon';
export * from './UpIcon';
export * from './RightIcon';
export * from './LeftIcon';
export * from './InformationIcon';
......@@ -5,7 +5,14 @@ import React from 'react';
import { withKnobs, object } from '@storybook/addon-knobs';
import StorySection from '../StorySection';
import { AlertIcon, DownIcon, UpIcon, RightIcon } from '.';
import {
AlertIcon,
DownIcon,
UpIcon,
RightIcon,
LeftIcon,
InformationIcon,
} from '.';
export const SVGIcons = () => (
<>
......@@ -13,22 +20,19 @@ export const SVGIcons = () => (
<AlertIcon stroke={object('Alert stroke', 'currentColor')} />
</StorySection>
<StorySection title="Down">
<DownIcon
stroke={object('DownIcon stroke', 'currentColor')}
fill={object('DownIcon fill', '#9191A8')}
/>
<DownIcon fill={object('DownIcon fill', '#9191A8')} />
</StorySection>
<StorySection title="Up">
<UpIcon
stroke={object('UpIcon stroke', 'currentColor')}
fill={object('UpIcon fill', '#9191A8')}
/>
<UpIcon fill={object('UpIcon fill', '#9191A8')} />
</StorySection>
<StorySection title="Right">
<RightIcon
stroke={object('RightIcon stroke', 'currentColor')}
fill={object('RightIcon fill', '#9191A8')}
/>
<RightIcon fill={object('RightIcon fill', '#9191A8')} />
</StorySection>
<StorySection title="Left">
<LeftIcon fill={object('LeftIcon fill', '#9191A8')} />
</StorySection>
<StorySection title="Information">
<InformationIcon fill={object('InformationIcon fill', '#9191A8')} />
</StorySection>
</>
);
......
// Copyright Contributors to the Amundsen project.
// SPDX-License-Identifier: Apache-2.0
export enum IconSizes {
REGULAR = 24,
SMALL = 16,
}
export interface IconProps {
stroke?: string;
size?: number;
......
......@@ -62,3 +62,9 @@ export enum IconType {
REDSHIFT = 'icon-redshift',
SNOWFLAKE = 'icon-snowflake',
}
// Icon sizes
export enum IconSizes {
REGULAR = 24,
SMALL = 16,
}
......@@ -11,7 +11,7 @@ import {
} from 'ducks/search/filters/reducer';
import { GlobalState } from 'ducks/rootReducer';
import { FilterType } from 'interfaces';
import { FilterType, IconSizes } from 'interfaces';
import InfoButton from 'components/common/InfoButton';
import { CLEAR_BTN_TEXT } from '../constants';
......@@ -68,7 +68,11 @@ export class FilterSection extends React.Component<FilterSectionProps> {
{title}
</label>
{helpText && (
<InfoButton infoText={helpText} placement="top" size="small" />
<InfoButton
infoText={helpText}
placement="top"
size={IconSizes.SMALL}
/>
)}
</div>
{hasValue && (
......
......@@ -11776,6 +11776,14 @@
"log-symbols": "^2.1.0",
"loglevelnext": "^1.0.1",
"uuid": "^3.1.0"
},
"dependencies": {
"uuid": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
"dev": true
}
}
}
}
......@@ -11976,8 +11984,30 @@
"integrity": "sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA==",
"requires": {
"define-properties": "^1.1.3",
"es-abstract": "^1.18.0-next.0",
"has-symbols": "^1.0.1",
"object-keys": "^1.1.1"
},
"dependencies": {
"es-abstract": {
"version": "1.18.0-next.1",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz",
"integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==",
"requires": {
"es-to-primitive": "^1.2.1",
"function-bind": "^1.1.1",
"has": "^1.0.3",
"has-symbols": "^1.0.1",
"is-callable": "^1.2.2",
"is-negative-zero": "^2.0.0",
"is-regex": "^1.1.1",
"object-inspect": "^1.8.0",
"object-keys": "^1.1.1",
"object.assign": "^4.1.1",
"string.prototype.trimend": "^1.0.1",
"string.prototype.trimstart": "^1.0.1"
}
}
}
}
}
......@@ -24997,6 +25027,12 @@
"psl": "^1.1.28",
"punycode": "^2.1.1"
}
},
"uuid": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
"dev": true
}
}
},
......@@ -31360,6 +31396,14 @@
"tough-cookie": "~2.4.3",
"tunnel-agent": "^0.6.0",
"uuid": "^3.3.2"
},
"dependencies": {
"uuid": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
"dev": true
}
}
},
"request-promise-core": {
......@@ -36143,10 +36187,9 @@
"dev": true
},
"uuid": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
"integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==",
"dev": true
"version": "8.3.1",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.1.tgz",
"integrity": "sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg=="
},
"v8-compile-cache": {
"version": "2.0.3",
......@@ -37043,6 +37086,14 @@
"requires": {
"ansi-colors": "^3.0.0",
"uuid": "^3.3.2"
},
"dependencies": {
"uuid": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
"dev": true
}
}
},
"webpack-merge": {
......@@ -152,7 +152,8 @@
"sanitize-html": "^1.23.0",
"simple-query-string": "^1.3.2",
"throttle-debounce": "^2.3.0",
"urijs": "^1.19.2"
"urijs": "^1.19.2",
"uuid": "^8.3.1"
},
"optionalDependencies": {
"fsevents": "*"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment