-
Notifications
You must be signed in to change notification settings - Fork 52
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(icon): Copy to /components folder
- Loading branch information
Showing
6 changed files
with
384 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,7 +12,8 @@ | |
{ | ||
"ignoreAtRules": [ | ||
"mixin", | ||
"include" | ||
"include", | ||
"each" | ||
] | ||
} | ||
] | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
import React from 'react' | ||
import PropTypes from 'prop-types' | ||
|
||
import { deprecate } from '../../warn' | ||
|
||
import styles from './Icon.modules.scss' | ||
|
||
const Icon = ({ glyph, variant, label, fixedWidth, size, className, children, ...rest }) => { | ||
if (className) { | ||
deprecate('Icon', 'Custom CSS classes are deprecated. This component will soon stop supporting custom styling.') | ||
} | ||
|
||
if (rest.style) { | ||
deprecate('Icon', 'Inline styles are deprecated. This component will soon stop supporting custom styling.') | ||
} | ||
|
||
if (variant === 'disabled') { | ||
deprecate('Icon', '\'disabled\' variant is deprecated.') | ||
} | ||
|
||
if (fixedWidth) { | ||
deprecate('Icon', '\'fixedWidth\' prop is deprecated.') | ||
} | ||
|
||
const classes = `${styles.icon} ${styles[`icon-core-${glyph}`]}` | ||
+ ` ${variant ? styles[`icon--${variant}`] : ''}` | ||
+ `${fixedWidth ? ` ${styles['icon--fw']}` : ''}` | ||
+ `${size ? ` ${styles[`icon--${size}`]}` : ''}` | ||
+ `${className ? ` ${className}` : ''}` | ||
|
||
return ( | ||
<i | ||
{...rest} | ||
className={classes} | ||
aria-label={label} | ||
aria-hidden={label ? undefined : 'true'} | ||
> | ||
{children} | ||
</i> | ||
) | ||
} | ||
|
||
Icon.propTypes = { | ||
/** | ||
* Name of the icon glyph. | ||
*/ | ||
glyph: PropTypes.oneOf([ | ||
'caret-down', | ||
'caret-up', | ||
'checkmark', | ||
'chevron', | ||
'left-chevron', | ||
'exclamation-point-circle', | ||
'expander', | ||
'hamburger', | ||
'incomplete', | ||
'location', | ||
'minus', | ||
'plus', | ||
'question-mark-circle', | ||
'spyglass', | ||
'times' | ||
]).isRequired, | ||
/** | ||
* The appearance of the Icon. | ||
*/ | ||
variant: PropTypes.oneOf([ | ||
'inherit', | ||
'primary', | ||
'secondary', | ||
'inverted', | ||
'disabled', | ||
'error' | ||
]), | ||
/** | ||
* Whether or not to give the icon a fixed width. | ||
* | ||
* @deprecated an alternative will be provided soon. | ||
*/ | ||
fixedWidth: PropTypes.bool, | ||
/** | ||
* | ||
*/ | ||
size: PropTypes.oneOf(['small', 'medium', 'large']), | ||
/** | ||
* One or more CSS class names separated by spaces to append onto the icon. | ||
* Don't advertise as we plan on removing this feature soon. | ||
* | ||
* @ignore | ||
*/ | ||
className: PropTypes.string, | ||
/** | ||
* Creates an `aria-label` attribute with the label you specify. | ||
* | ||
* If not provided, `aria-hidden` is set to true. | ||
*/ | ||
label: PropTypes.string, | ||
/** | ||
* @ignore | ||
*/ | ||
children: PropTypes.node | ||
} | ||
Icon.defaultProps = { | ||
variant: 'inherit', | ||
fixedWidth: false, | ||
size: 'medium', | ||
className: '', | ||
children: null | ||
} | ||
|
||
export default Icon |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
### Available Icons | ||
|
||
``` | ||
<div className="docs--horizontal-spacing"> | ||
<Icon glyph="caret-down" /> | ||
<Icon glyph="caret-up" /> | ||
<Icon glyph="checkmark" /> | ||
<Icon glyph="left-chevron" /> | ||
<Icon glyph="chevron" /> | ||
<Icon glyph="exclamation-point-circle" /> | ||
<Icon glyph="expander" /> | ||
<Icon glyph="hamburger" /> | ||
<Icon glyph="incomplete" /> | ||
<Icon glyph="location" /> | ||
<Icon glyph="minus" /> | ||
<Icon glyph="plus" /> | ||
<Icon glyph="question-mark-circle" /> | ||
<Icon glyph="spyglass" /> | ||
<Icon glyph="times" /> | ||
</div> | ||
``` | ||
|
||
### Modifying color | ||
|
||
Use the `variant` prop to alter the icon's color. Each variant has semantic meaning. | ||
|
||
``` | ||
<div className="docs--horizontal-spacing"> | ||
<Icon glyph="checkmark" variant="primary" /> | ||
<Icon glyph="incomplete" variant="secondary" /> | ||
<Icon glyph="exclamation-point-circle" variant="error" /> | ||
</div> | ||
``` | ||
|
||
#### Primary and secondary | ||
|
||
Indicates a primary or secondary action. | ||
|
||
``` | ||
<div> | ||
<div><Icon glyph="plus" variant="primary" /> Add a user</div> | ||
<div><Icon glyph="minus" variant="secondary" /> Remove a user</div> | ||
</div> | ||
``` | ||
|
||
#### Error | ||
|
||
Indicates a problem. | ||
|
||
``` | ||
<div> | ||
<Icon glyph="location" variant="error" /> Your location needs to be updated | ||
</div> | ||
``` | ||
|
||
### Accessibility considerations | ||
|
||
Icons can be either decorative or meaningful. | ||
|
||
**Decorative icons** do not perform a role beyond visual aesthetics and should be hidden from screen readers using the | ||
`aria-hidden` attribute. Usually, the information being communicated with the icon is also conveyed in another manner. | ||
|
||
This example shows a decorative icon that is hidden from screen readers. The Icon component sets `aria-hidden` to `true` by default; you can inspect the element and see. | ||
|
||
``` | ||
<Paragraph> | ||
<Icon glyph="location" /> You are located in British Columbia. | ||
</Paragraph> | ||
``` | ||
|
||
**Meaningful icons** have meaning within the context of the page, which should be communicated to screen readers with the | ||
`aria-label` attribute. Meaningful icons can also be interactive elements, which should be designated with | ||
the `role` prop. | ||
|
||
This example shows a meaningful icon that needs accessibility attributes. | ||
|
||
``` | ||
<Paragraph> | ||
<button style={{appearance: 'none', background: 'none', border: 0, cursor: 'pointer'}} type="submit"><Icon glyph="spyglass" label="search" /></button> | ||
</Paragraph> | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
@import '../../scss/settings/icons'; | ||
@import '../../scss/settings/colours'; | ||
@import '../../scss/utility/icons-utility'; | ||
|
||
@font-face { | ||
font-family: "TELUS Core Icons"; | ||
src: url('#{$icon-font-prefix}/core-icons.eot'); | ||
src: | ||
url('#{$icon-font-prefix}/core-icons.woff2') format('woff2'), | ||
url('#{$icon-font-prefix}/core-icons.woff') format('woff'), | ||
url('#{$icon-font-prefix}/core-icons.ttf') format('truetype'), | ||
url('#{$icon-font-prefix}/core-icons.eot?#iefix') format('eot'); | ||
font-weight: normal; | ||
font-style: normal; | ||
} | ||
|
||
.icon { | ||
@include core-icon; | ||
|
||
transition: color 0.1s linear; | ||
|
||
&--primary { | ||
color: $color-icon-primary; | ||
} | ||
|
||
&--secondary { | ||
color: $color-icon-secondary; | ||
} | ||
|
||
&--inverted { | ||
color: $color-white; | ||
} | ||
|
||
&--error { | ||
color: $color-cardinal; | ||
} | ||
|
||
&--disabled { | ||
color: $color-icon-disabled; | ||
} | ||
|
||
&--fw { | ||
width: 1.09rem; | ||
text-align: center; | ||
} | ||
|
||
&--small { | ||
font-size: 1 rem; | ||
} | ||
|
||
&--medium { | ||
font-size: 1.5rem; | ||
} | ||
|
||
&--large { | ||
font-size: 3rem; | ||
} | ||
} | ||
|
||
@each $name, $codepoint in $core-icon-codepoints { | ||
.icon-core-#{$name}::before { | ||
content: $codepoint; | ||
} | ||
} | ||
|
||
.icon-core-left-chevron { | ||
@include core-icon(chevron); | ||
|
||
&::before { | ||
display: inline-block; | ||
transform: rotate(-180deg) translateY(1.5px); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
import React from 'react' | ||
import { shallow } from 'enzyme' | ||
import toJson from 'enzyme-to-json' | ||
import { deprecate } from '../../../warn' | ||
|
||
import Icon from '../Icon' | ||
|
||
jest.mock('../../../warn', () => ( | ||
{ deprecate: jest.fn() } | ||
)) | ||
|
||
describe('<Icon />', () => { | ||
const defaultProps = { | ||
glyph: 'checkmark' | ||
} | ||
|
||
const doShallow = (overrides = {}) => shallow(<Icon {...defaultProps} {...overrides} />) | ||
|
||
it('renders', () => { | ||
const icon = doShallow() | ||
|
||
expect(toJson(icon)).toMatchSnapshot() | ||
}) | ||
|
||
it('needs a glyph', () => { | ||
const icon = doShallow({ glyph: 'spyglass' }) | ||
|
||
expect(icon).toHaveClassName('icon-core-spyglass') | ||
}) | ||
|
||
it('supports variants', () => { | ||
const icon = doShallow({ variant: 'secondary' }) | ||
|
||
expect(icon).toHaveClassName('icon--secondary') | ||
}) | ||
|
||
it('can be fixed width', () => { | ||
const icon = doShallow({ fixedWidth: true }) | ||
|
||
expect(icon).toHaveClassName('icon--fw') | ||
}) | ||
|
||
it('can be sized', () => { | ||
const icon = doShallow({ size: 'small' }) | ||
|
||
expect(icon).toHaveClassName('icon--small') | ||
}) | ||
|
||
it('supports custom CSS classes', () => { | ||
const icon = doShallow({ className: 'custom-class' }) | ||
|
||
expect(icon).toHaveClassName('custom-class') | ||
}) | ||
|
||
it('passes additional attributes to the icon element', () => { | ||
const icon = doShallow({ id: 'the-icon', role: 'button' }) | ||
|
||
expect(icon).toHaveProp('id', 'the-icon') | ||
expect(icon).toHaveProp('role', 'button') | ||
}) | ||
|
||
describe('deprecated props', () => { | ||
it('deprecates className', () => { | ||
jest.clearAllMocks() | ||
const icon = doShallow({ className: 'my-custom-class' }) | ||
|
||
expect(icon).toHaveProp('className') | ||
expect(deprecate).toHaveBeenCalled() | ||
}) | ||
|
||
it('deprecates style', () => { | ||
jest.clearAllMocks() | ||
const icon = doShallow({ style: 'color: hotpink' }) | ||
|
||
expect(icon).toHaveProp('style') | ||
expect(deprecate).toHaveBeenCalled() | ||
}) | ||
|
||
it('deprecates disabled variant', () => { | ||
jest.clearAllMocks() | ||
const icon = doShallow({ variant: 'disabled' }) | ||
|
||
expect(icon).toHaveClassName('icon--disabled') | ||
expect(deprecate).toHaveBeenCalled() | ||
}) | ||
|
||
it('deprecates fixedWidth prop', () => { | ||
jest.clearAllMocks() | ||
const icon = doShallow({ fixedWidth: true }) | ||
|
||
expect(icon).toHaveClassName('icon--fw') | ||
expect(deprecate).toHaveBeenCalled() | ||
}) | ||
}) | ||
|
||
it('provides a label to specific glyphs', () => { | ||
const icon = doShallow({ glyph: 'exclamation-point-circle', label: 'alert' }) | ||
|
||
expect(icon).toHaveProp('aria-label', 'alert') | ||
expect(icon).not.toHaveProp('aria-hidden', 'undefined') | ||
}) | ||
|
||
it('sets aria-hidden to true when label is not set', () => { | ||
const icon = doShallow({ glyph: 'checkmark' }) | ||
|
||
expect(icon).toHaveProp('aria-hidden', 'true') | ||
expect(icon).not.toHaveProp('aria-label', 'undefined') | ||
}) | ||
}) |
8 changes: 8 additions & 0 deletions
8
src/components/Icon/__tests__/__snapshots__/Icon.spec.jsx.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`<Icon /> renders 1`] = ` | ||
<i | ||
aria-hidden="true" | ||
className="icon icon-core-checkmark icon--inherit icon--medium" | ||
/> | ||
`; |