Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"changes": [
{
"packageName": "office-ui-fabric-react",
"comment": "Icon: undoing breaking change with regards to making `IIconStyles.root` required, adding tests to ensure backwards compatibility.",
"type": "minor"
}
],
"packageName": "office-ui-fabric-react",
"email": "[email protected]"
}
61 changes: 33 additions & 28 deletions packages/office-ui-fabric-react/src/components/Icon/Icon.base.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,43 +33,48 @@ export class IconBase extends BaseComponent<IIconProps, IIconState> {
getStyles,
iconName,
imageErrorAs,
styles,
} = this.props;
const isPlaceholder = typeof iconName === 'string' && iconName.length === 0;
const isImage = this.props.iconType === IconType.image || this.props.iconType === IconType.Image;
const { iconClassName, children } = this._getIconContent(iconName);

const classNames = getClassNames(getStyles, { className, isPlaceholder, isImage, iconClassName });
const classNames = getClassNames(getStyles, {
className,
iconClassName,
isImage,
isPlaceholder,
styles
});

const containerProps = ariaLabel ? { 'aria-label': ariaLabel, 'data-icon-name': iconName, } : {
role: 'presentation',
'aria-hidden': true,
'data-icon-name': iconName,
};
const containerProps = ariaLabel ?
{
'aria-label': ariaLabel,
} : {
role: 'presentation',
'aria-hidden': true,
};

if (this.props.iconType === IconType.image || this.props.iconType === IconType.Image) {
const RootType = isImage ? 'div' : 'i';
const nativeProps = getNativeProps(this.props, htmlElementProperties);
const { imageLoadError } = this.state;
const imageProps = { ...this.props.imageProps, onLoadingStateChange: this.onImageLoadingStateChange };
const ImageType = imageLoadError && imageErrorAs || Image;

const { imageLoadError } = this.state;
const imageProps = { ...this.props.imageProps, onLoadingStateChange: this.onImageLoadingStateChange };
const ImageType = imageLoadError && imageErrorAs || Image;
return (
<div
{ ...containerProps }
className={ classNames.root }
>
return (
<RootType
data-icon-name={ iconName }
{ ...nativeProps }
{ ...containerProps }
className={ classNames.root }
>
{ isImage ? (
<ImageType { ...imageProps } />
</div>
);
} else {
return (
<i
{ ...containerProps }
{ ...getNativeProps(this.props, htmlElementProperties, ['name', 'iconName']) }
className={ classNames.root }
>
{ children }
</i>
);
}
) : (
children
) }
</RootType>
);
}

private onImageLoadingStateChange = (state: ImageLoadState): void => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { IIconStyleProps, IIconStyles } from './Icon.types';

export const getStyles = (props: IIconStyleProps): IIconStyles => {
const { className, iconClassName, isPlaceholder, isImage } = props;
const { className, iconClassName, isPlaceholder, isImage, styles } = props;

return {
root: [
Expand All @@ -17,7 +17,9 @@ export const getStyles = (props: IIconStyleProps): IIconStyles => {
overflow: 'hidden'
},
iconClassName,
className
className,
styles && styles.root,
styles && styles.imageContainer
],
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Icon } from './index';

describe('Icon', () => {
it('renders Icon correctly', () => {
const component = renderer.create(<Icon iconName='CompassNW' />);
const component = renderer.create(<Icon iconName='CompassNW' ariaLabel='asdf' />);
const tree = component.toJSON();
expect(tree).toMatchSnapshot();
});
Expand All @@ -16,4 +16,26 @@ describe('Icon', () => {
expect(tree).toMatchSnapshot();
});

it('renders Icon with custom styles', () => {
const component = renderer.create(
<Icon
iconName='Upload'
styles={ { root: 'root', imageContainer: 'imageContainer' } }
/>
);
expect(component.toJSON()).toMatchSnapshot();
});

it('renders Icon with getStyles', () => {
const customStyles = (props: {}) => ({ root: 'root', imageContainer: 'imageContainer' });

const component = renderer.create(
<Icon
className='className'
iconName='Upload'
getStyles={ customStyles }
/>
);
expect(component.toJSON()).toMatchSnapshot();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,6 @@ export interface IIconProps extends IBaseProps, React.HTMLAttributes<HTMLElement
*/
iconName?: string;

/**
* Optional styling for the elements within the Icon.
*/
styles?: IIconStyles;

/**
* The aria label of the button for the benefit of screen readers.
*/
Expand Down Expand Up @@ -70,16 +65,27 @@ export interface IIconProps extends IBaseProps, React.HTMLAttributes<HTMLElement
* Gets the styles for an Icon.
*/
getStyles?: IStyleFunction<IIconStyleProps, IIconStyles>;

/**
* Deprecated: use getStyles.
* @deprecated
*/
styles?: IIconStyles;
}

export interface IIconStyleProps {
className?: string;
iconClassName?: string;
isPlaceholder: boolean;
isImage: boolean;
styles?: Partial<IIconStyles>;
}

export interface IIconStyles {
root: IStyle;
root?: IStyle;

/**
* Deprecated. Use 'root'.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing @deprecated. Hm would it be helpful to continue tracking the major version these vars were deprecated, to help in deprecated cleanup later?

*/
imageContainer?: IStyle;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

exports[`Icon renders Icon correctly 1`] = `
<i
aria-hidden={true}
aria-label="asdf"
className=

{
Expand All @@ -15,7 +15,6 @@ exports[`Icon renders Icon correctly 1`] = `
speak: none;
}
data-icon-name="CompassNW"
role="presentation"
>
</i>
Expand All @@ -41,3 +40,47 @@ exports[`Icon renders Icon correctly using iconName 1`] = `
</i>
`;

exports[`Icon renders Icon with custom styles 1`] = `
<i
aria-hidden={true}
className=
root
imageContainer
{
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
display: inline-block;
font-family: "FabricMDL2Icons";
font-style: normal;
font-weight: normal;
speak: none;
}
data-icon-name="Upload"
role="presentation"
>
</i>
`;

exports[`Icon renders Icon with getStyles 1`] = `
<i
aria-hidden={true}
className=
className
root
{
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
display: inline-block;
font-family: "FabricMDL2Icons";
font-style: normal;
font-weight: normal;
speak: none;
}
data-icon-name="Upload"
role="presentation"
>
</i>
`;