From 6d0decd33bc648ebfe5ea4f4d2e02b47db18af15 Mon Sep 17 00:00:00 2001 From: Vitalie Braga Date: Tue, 8 May 2018 22:55:22 -0700 Subject: [PATCH 01/32] Adds new prop: className. Removes some styling from shimmer container. --- .../src/components/Shimmer/Shimmer.base.tsx | 5 +++-- .../src/components/Shimmer/Shimmer.styles.ts | 15 +++++---------- .../src/components/Shimmer/Shimmer.types.ts | 6 ++++++ .../Shimmer/examples/Shimmer.Basic.Example.tsx | 9 +++++---- .../Shimmer/examples/Shimmer.Example.scss | 14 +++++++++----- 5 files changed, 28 insertions(+), 21 deletions(-) diff --git a/packages/experiments/src/components/Shimmer/Shimmer.base.tsx b/packages/experiments/src/components/Shimmer/Shimmer.base.tsx index 589b7e7bc72df5..8846f1a7ec90bf 100644 --- a/packages/experiments/src/components/Shimmer/Shimmer.base.tsx +++ b/packages/experiments/src/components/Shimmer/Shimmer.base.tsx @@ -40,13 +40,14 @@ export class ShimmerBase extends BaseComponent { isDataLoaded, isBaseStyle, widthInPercentage, - widthInPixel + widthInPixel, + className } = this.props; const rowHeight: number | undefined = lineElements ? findMaxElementHeight(lineElements) : undefined; this._classNames = getClassNames(getStyles!, { - width, rowHeight, isDataLoaded, isBaseStyle, widthInPercentage, widthInPixel + width, rowHeight, isDataLoaded, isBaseStyle, widthInPercentage, widthInPixel, className }); const renderedElements: React.ReactNode = getRenderedElements(lineElements, rowHeight); diff --git a/packages/experiments/src/components/Shimmer/Shimmer.styles.ts b/packages/experiments/src/components/Shimmer/Shimmer.styles.ts index 730d0c737b1b7e..6586f88437cf7c 100644 --- a/packages/experiments/src/components/Shimmer/Shimmer.styles.ts +++ b/packages/experiments/src/components/Shimmer/Shimmer.styles.ts @@ -8,7 +8,8 @@ export function getStyles(props: IShimmerStyleProps): IShimmerStyles { isDataLoaded, isBaseStyle, widthInPercentage, - widthInPixel + widthInPixel, + className } = props; const BACKGROUND_OFF_SCREEN_POSITION = '1000%'; @@ -33,17 +34,12 @@ export function getStyles(props: IShimmerStyleProps): IShimmerStyles { 'ms-Shimmer-container', { position: 'relative', - margin: '10px', - width: 'auto', - boxSizing: 'content-box', minHeight: rowHeight ? `${rowHeight}px` : '16px' }, isBaseStyle && { - margin: '0', - minHeight: 'inherit', - display: 'flex', - alignItems: 'center' - } + minHeight: 'inherit' + }, + className ], shimmerWrapper: [ 'ms-Shimmer-shimmerWrapper', @@ -57,7 +53,6 @@ export function getStyles(props: IShimmerStyleProps): IShimmerStyles { alignItems: 'center', alignContent: 'space-between', width: ACTUAL_WIDTH, - height: 'auto', boxSizing: 'border-box', background: `${DefaultPalette.neutralLighter} linear-gradient( diff --git a/packages/experiments/src/components/Shimmer/Shimmer.types.ts b/packages/experiments/src/components/Shimmer/Shimmer.types.ts index 8e1f437aaa4298..4cd6f76139c7bc 100644 --- a/packages/experiments/src/components/Shimmer/Shimmer.types.ts +++ b/packages/experiments/src/components/Shimmer/Shimmer.types.ts @@ -57,6 +57,11 @@ export interface IShimmerProps extends React.AllHTMLAttributes { * Call to provide customized styling that will layer on top of the variant rules. */ getStyles?: IStyleFunction; + + /** + * Additional CSS class(es) to apply to the Shimmer container. + */ + className?: string; } export interface IShimmerElement { @@ -145,6 +150,7 @@ export interface IShimmerStyleProps { widthInPixel?: number; isDataLoaded?: boolean; isBaseStyle?: boolean; + className?: string; } export interface IShimmerStyles { diff --git a/packages/experiments/src/components/Shimmer/examples/Shimmer.Basic.Example.tsx b/packages/experiments/src/components/Shimmer/examples/Shimmer.Basic.Example.tsx index 3016cb7e965995..63ac07d772d987 100644 --- a/packages/experiments/src/components/Shimmer/examples/Shimmer.Basic.Example.tsx +++ b/packages/experiments/src/components/Shimmer/examples/Shimmer.Basic.Example.tsx @@ -1,10 +1,12 @@ import * as React from 'react'; + import { Shimmer, getRenderedElements, ShimmerElementType as ElemType, ShimmerElementVerticalAlign as ElemVerticalAlign } from '@uifabric/experiments/lib/Shimmer'; + import './Shimmer.Example.scss'; export class ShimmerBasicExample extends React.Component<{}, {}> { @@ -16,8 +18,7 @@ export class ShimmerBasicExample extends React.Component<{}, {}> { public render(): JSX.Element { return ( - // tslint:disable-next-line:jsx-ban-props -
+
Generic Shimmer with no elements provided. { ] } /> Split line examples. -
+
{
-
+
Date: Wed, 9 May 2018 14:11:44 -0700 Subject: [PATCH 02/32] Removes unnecessary styles. Setup of elements wrapper. --- .../src/components/Shimmer/Shimmer.base.tsx | 5 ++-- .../src/components/Shimmer/Shimmer.styles.ts | 3 -- .../Shimmer/ShimmerElementsGroup.tsx | 28 +++++++++++++++++++ 3 files changed, 30 insertions(+), 6 deletions(-) create mode 100644 packages/experiments/src/components/Shimmer/ShimmerElementsGroup.tsx diff --git a/packages/experiments/src/components/Shimmer/Shimmer.base.tsx b/packages/experiments/src/components/Shimmer/Shimmer.base.tsx index 8846f1a7ec90bf..06c35240db8793 100644 --- a/packages/experiments/src/components/Shimmer/Shimmer.base.tsx +++ b/packages/experiments/src/components/Shimmer/Shimmer.base.tsx @@ -55,10 +55,9 @@ export class ShimmerBase extends BaseComponent { return (
- { !!isBaseStyle ? children : renderedElements } + { isBaseStyle ? children : renderedElements }
- - { !!isDataLoaded && + { isDataLoaded &&
{ !!children ? children : null }
diff --git a/packages/experiments/src/components/Shimmer/Shimmer.styles.ts b/packages/experiments/src/components/Shimmer/Shimmer.styles.ts index 6586f88437cf7c..7ec1bb2e2370c3 100644 --- a/packages/experiments/src/components/Shimmer/Shimmer.styles.ts +++ b/packages/experiments/src/components/Shimmer/Shimmer.styles.ts @@ -36,9 +36,6 @@ export function getStyles(props: IShimmerStyleProps): IShimmerStyles { position: 'relative', minHeight: rowHeight ? `${rowHeight}px` : '16px' }, - isBaseStyle && { - minHeight: 'inherit' - }, className ], shimmerWrapper: [ diff --git a/packages/experiments/src/components/Shimmer/ShimmerElementsGroup.tsx b/packages/experiments/src/components/Shimmer/ShimmerElementsGroup.tsx new file mode 100644 index 00000000000000..ca92a5b9a853eb --- /dev/null +++ b/packages/experiments/src/components/Shimmer/ShimmerElementsGroup.tsx @@ -0,0 +1,28 @@ +import * as React from 'react'; + +import { + IShimmerProps, + IShimmerStyleProps, + IShimmerStyles, + ShimmerElementType, + ICircle, + ILine, + IGap, + ShimmerElementVerticalAlign +} from './Shimmer.types'; + +export interface IShimmerElementsGroup { + /** + * Elements to be rendered on top of the Shimmering background. + */ + lineElements?: Array; +} + +export function ShimmerElementsGroup(props: IShimmerElementsGroup): JSX.Element { + + return ( +
+ TODO +
+ ); +} From 0db37edc9bbc620c1478002eeb13bcc81f509381 Mon Sep 17 00:00:00 2001 From: Vitalie Braga Date: Wed, 9 May 2018 22:24:25 -0700 Subject: [PATCH 03/32] Refactoring some styles. Extracts some logic to a new module. --- .../src/components/Shimmer/Shimmer.base.tsx | 127 ++++------------ .../src/components/Shimmer/Shimmer.styles.ts | 7 +- .../src/components/Shimmer/Shimmer.types.ts | 6 + .../Shimmer/ShimmerElementsGroup.tsx | 96 ++++++++++-- .../Shimmer/ShimmerTile/ShimmerTile.base.tsx | 142 ++++++++---------- .../examples/Shimmer.Basic.Example.tsx | 5 +- .../examples/TilesList.Document.Example.tsx | 18 +-- 7 files changed, 196 insertions(+), 205 deletions(-) diff --git a/packages/experiments/src/components/Shimmer/Shimmer.base.tsx b/packages/experiments/src/components/Shimmer/Shimmer.base.tsx index 06c35240db8793..ba63757c04bb23 100644 --- a/packages/experiments/src/components/Shimmer/Shimmer.base.tsx +++ b/packages/experiments/src/components/Shimmer/Shimmer.base.tsx @@ -1,6 +1,5 @@ import * as React from 'react'; import { BaseComponent, classNamesFunction } from '../../Utilities'; -import { DefaultPalette, IStyleSet } from '../../Styling'; import { IShimmerProps, IShimmerStyleProps, @@ -9,15 +8,9 @@ import { ICircle, ILine, IGap, - ShimmerElementVerticalAlign, + ShimmerElementsDefaultHeights, } from './Shimmer.types'; -import { ShimmerLine } from './ShimmerLine/ShimmerLine'; -import { ShimmerGap } from './ShimmerGap/ShimmerGap'; -import { ShimmerCircle } from './ShimmerCircle/ShimmerCircle'; - -const LINE_DEFAULT_HEIGHT = 16; -const GAP_DEFAULT_HEIGHT = 16; -const CIRCLE_DEFAULT_HEIGHT = 24; +import { ShimmerElementsGroup } from './ShimmerElementsGroup'; const getClassNames = classNamesFunction(); @@ -44,18 +37,21 @@ export class ShimmerBase extends BaseComponent { className } = this.props; - const rowHeight: number | undefined = lineElements ? findMaxElementHeight(lineElements) : undefined; + const rowHeight: number | undefined = lineElements ? this._findMaxElementHeight(lineElements) : undefined; this._classNames = getClassNames(getStyles!, { width, rowHeight, isDataLoaded, isBaseStyle, widthInPercentage, widthInPixel, className }); - const renderedElements: React.ReactNode = getRenderedElements(lineElements, rowHeight); - return (
- { isBaseStyle ? children : renderedElements } + { isBaseStyle ? children : + + }
{ isDataLoaded &&
@@ -65,97 +61,32 @@ export class ShimmerBase extends BaseComponent {
); } -} -export function getRenderedElements(lineElements?: Array, rowHeight?: number): React.ReactNode { - const renderedElements: React.ReactNode = lineElements ? - lineElements.map((elem: ICircle | ILine | IGap, index: number): JSX.Element => { + private _findMaxElementHeight(elements: Array): number { + const itemsDefaulted: Array = elements.map((elem: ICircle | IGap | ILine): ICircle | IGap | ILine => { switch (elem.type) { case ShimmerElementType.circle: - return ( - - ); - case ShimmerElementType.gap: - return ( - - ); + if (!elem.height) { + elem.height = ShimmerElementsDefaultHeights.circle; + } case ShimmerElementType.line: - return ( - - ); + if (!elem.height) { + elem.height = ShimmerElementsDefaultHeights.line; + } + case ShimmerElementType.gap: + if (!elem.height) { + elem.height = ShimmerElementsDefaultHeights.gap; + } } - }) : ( - - ); - - return renderedElements; -} - -export function getBorderStyles(elem: ICircle | IGap | ILine, rowHeight?: number): IStyleSet | undefined { - const elemHeight: number | undefined = elem.height; - - const dif: number = rowHeight && elemHeight ? rowHeight - elemHeight : 0; + return elem; + }); - let borderStyle: IStyleSet | undefined; + const rowHeight = itemsDefaulted.reduce((acc: number, next: ICircle | IGap | ILine): number => { + return next.height ? + next.height > acc ? next.height : acc + : acc; + }, 0); - if (!elem.verticalAlign || elem.verticalAlign === ShimmerElementVerticalAlign.center) { - borderStyle = { - borderBottom: `${dif ? Math.floor(dif / 2) : 0}px solid ${DefaultPalette.white}`, - borderTop: `${dif ? Math.ceil(dif / 2) : 0}px solid ${DefaultPalette.white}` - }; - } else if (elem.verticalAlign && elem.verticalAlign === ShimmerElementVerticalAlign.top) { - borderStyle = { - borderBottom: `${dif ? dif : 0}px solid ${DefaultPalette.white}`, - borderTop: `0px solid ${DefaultPalette.white}` - }; - } else if (elem.verticalAlign && elem.verticalAlign === ShimmerElementVerticalAlign.bottom) { - borderStyle = { - borderBottom: `0px solid ${DefaultPalette.white}`, - borderTop: `${dif ? dif : 0}px solid ${DefaultPalette.white}` - }; + return rowHeight; } - - return borderStyle; -} - -export function findMaxElementHeight(elements: Array): number { - const itemsDefaulted: Array = elements.map((elem: ICircle | IGap | ILine): ICircle | IGap | ILine => { - switch (elem.type) { - case ShimmerElementType.circle: - if (!elem.height) { - elem.height = CIRCLE_DEFAULT_HEIGHT; - } - case ShimmerElementType.line: - if (!elem.height) { - elem.height = LINE_DEFAULT_HEIGHT; - } - case ShimmerElementType.gap: - if (!elem.height) { - elem.height = GAP_DEFAULT_HEIGHT; - } - } - return elem; - }); - - const rowHeight = itemsDefaulted.reduce((acc: number, next: ICircle | IGap | ILine): number => { - return next.height ? - next.height > acc ? next.height : acc - : acc; - }, 0); - - return rowHeight; } \ No newline at end of file diff --git a/packages/experiments/src/components/Shimmer/Shimmer.styles.ts b/packages/experiments/src/components/Shimmer/Shimmer.styles.ts index 7ec1bb2e2370c3..50e4e5aca27ee1 100644 --- a/packages/experiments/src/components/Shimmer/Shimmer.styles.ts +++ b/packages/experiments/src/components/Shimmer/Shimmer.styles.ts @@ -41,16 +41,12 @@ export function getStyles(props: IShimmerStyleProps): IShimmerStyles { shimmerWrapper: [ 'ms-Shimmer-shimmerWrapper', { - display: 'flex', position: 'absolute', top: '0', bottom: '0', left: '0', right: '0', - alignItems: 'center', - alignContent: 'space-between', width: ACTUAL_WIDTH, - boxSizing: 'border-box', background: `${DefaultPalette.neutralLighter} linear-gradient( to right, @@ -58,8 +54,7 @@ export function getStyles(props: IShimmerStyleProps): IShimmerStyles { ${DefaultPalette.neutralLight} 50%, ${DefaultPalette.neutralLighter} 100%) 0 0 / 90% 100% - no-repeat - content-box`, + no-repeat`, animationDuration: '2s', animationTimingFunction: 'ease-in-out', animationDirection: 'normal', diff --git a/packages/experiments/src/components/Shimmer/Shimmer.types.ts b/packages/experiments/src/components/Shimmer/Shimmer.types.ts index 4cd6f76139c7bc..084ce754c5d1bc 100644 --- a/packages/experiments/src/components/Shimmer/Shimmer.types.ts +++ b/packages/experiments/src/components/Shimmer/Shimmer.types.ts @@ -183,4 +183,10 @@ export const enum ShimmerElementVerticalAlign { center = 'center', bottom = 'bottom', top = 'top' +} + +export const enum ShimmerElementsDefaultHeights { + line = 16, + gap = 16, + circle = 24 } \ No newline at end of file diff --git a/packages/experiments/src/components/Shimmer/ShimmerElementsGroup.tsx b/packages/experiments/src/components/Shimmer/ShimmerElementsGroup.tsx index ca92a5b9a853eb..6e52de5fb9998c 100644 --- a/packages/experiments/src/components/Shimmer/ShimmerElementsGroup.tsx +++ b/packages/experiments/src/components/Shimmer/ShimmerElementsGroup.tsx @@ -1,28 +1,102 @@ import * as React from 'react'; +import { DefaultPalette, IStyleSet } from '../../Styling'; import { - IShimmerProps, - IShimmerStyleProps, - IShimmerStyles, ShimmerElementType, ICircle, ILine, IGap, - ShimmerElementVerticalAlign + ShimmerElementVerticalAlign, + ShimmerElementsDefaultHeights } from './Shimmer.types'; +import { ShimmerLine } from './ShimmerLine/ShimmerLine'; +import { ShimmerGap } from './ShimmerGap/ShimmerGap'; +import { ShimmerCircle } from './ShimmerCircle/ShimmerCircle'; -export interface IShimmerElementsGroup { - /** - * Elements to be rendered on top of the Shimmering background. - */ +export interface IShimmerElementsGroupProps { lineElements?: Array; + rowHeight?: number; } -export function ShimmerElementsGroup(props: IShimmerElementsGroup): JSX.Element { +export function ShimmerElementsGroup(props: IShimmerElementsGroupProps): JSX.Element { + const { lineElements, rowHeight } = props; return ( -
- TODO +
+ { getRenderedElements(lineElements, rowHeight) }
); } + +function getRenderedElements(lineElements?: Array, rowHeight?: number): React.ReactNode { + const renderedElements: React.ReactNode = lineElements ? + lineElements.map((elem: ICircle | ILine | IGap, index: number): JSX.Element => { + switch (elem.type) { + case ShimmerElementType.circle: + return ( + + ); + case ShimmerElementType.gap: + return ( + + ); + case ShimmerElementType.line: + return ( + + ); + } + }) : ( + + ); + + return renderedElements; +} + +function getBorderStyles(elem: ICircle | IGap | ILine, rowHeight?: number): IStyleSet | undefined { + const elemHeight: number | undefined = elem.height; + + const dif: number = rowHeight && elemHeight ? rowHeight - elemHeight : 0; + + let borderStyle: IStyleSet | undefined; + + if (!elem.verticalAlign || elem.verticalAlign === ShimmerElementVerticalAlign.center) { + borderStyle = { + borderBottom: `${dif ? Math.floor(dif / 2) : 0}px solid ${DefaultPalette.white}`, + borderTop: `${dif ? Math.ceil(dif / 2) : 0}px solid ${DefaultPalette.white}` + }; + } else if (elem.verticalAlign && elem.verticalAlign === ShimmerElementVerticalAlign.top) { + borderStyle = { + borderBottom: `${dif ? dif : 0}px solid ${DefaultPalette.white}`, + borderTop: `0px solid ${DefaultPalette.white}` + }; + } else if (elem.verticalAlign && elem.verticalAlign === ShimmerElementVerticalAlign.bottom) { + borderStyle = { + borderBottom: `0px solid ${DefaultPalette.white}`, + borderTop: `${dif ? dif : 0}px solid ${DefaultPalette.white}` + }; + } + + return borderStyle; +} \ No newline at end of file diff --git a/packages/experiments/src/components/Shimmer/ShimmerTile/ShimmerTile.base.tsx b/packages/experiments/src/components/Shimmer/ShimmerTile/ShimmerTile.base.tsx index 76ec1eb52a549a..3eecd1eb51e937 100644 --- a/packages/experiments/src/components/Shimmer/ShimmerTile/ShimmerTile.base.tsx +++ b/packages/experiments/src/components/Shimmer/ShimmerTile/ShimmerTile.base.tsx @@ -10,7 +10,7 @@ import { } from './ShimmerTile.types'; import { TileLayoutSizes, TileSize } from '../../../Tile'; import { ShimmerGap } from '../ShimmerGap/ShimmerGap'; -import { getRenderedElements } from '../Shimmer.base'; +import { ShimmerElementsGroup } from '../ShimmerElementsGroup'; import { ShimmerElementType as ElemType } from '../Shimmer.types'; const enum ShimmerTileLayoutValues { @@ -113,38 +113,34 @@ export class ShimmerTileBase extends BaseComponent { widthInPixel={ contentSize.width } height={ contentSize.height - squareHeight - nameplateHeight } /> -
- { - getRenderedElements( - [ + + rowHeight={ squareHeight } + /> { itemActivity || itemName ?
@@ -154,61 +150,53 @@ export class ShimmerTileBase extends BaseComponent { /> { itemName ? -
- { - getRenderedElements( - [ - { - type: ElemType.gap, - widthInPixel: (contentSize.width - nameWidth) / 2, - height: nameplateNameHeight - }, - { - type: ElemType.line, - widthInPixel: nameWidth, - height: nameHeight - }, - { - type: ElemType.gap, - widthInPixel: (contentSize.width - nameWidth) / 2, - height: nameplateNameHeight - } - ], - nameplateNameHeight - ) + : null + rowHeight={ nameplateNameHeight } + /> : null } { itemActivity ? -
- { - getRenderedElements( - [ - { - type: ElemType.gap, - widthInPixel: (contentSize.width - activityWidth) / 2, - height: nameplateActivityHeight - }, - { - type: ElemType.line, - widthInPixel: activityWidth, - height: activityHeight - }, - { - type: ElemType.gap, - widthInPixel: (contentSize.width - activityWidth) / 2, - height: nameplateActivityHeight - } - ], - nameplateActivityHeight - ) + : null + rowHeight={ nameplateActivityHeight } + /> : null } { ] } /> Split line examples. -
+ {/*
{ ], 20) }
-
+
*/}
); } diff --git a/packages/experiments/src/components/TilesList/examples/TilesList.Document.Example.tsx b/packages/experiments/src/components/TilesList/examples/TilesList.Document.Example.tsx index 9b730404d77920..bbde03247a80cd 100644 --- a/packages/experiments/src/components/TilesList/examples/TilesList.Document.Example.tsx +++ b/packages/experiments/src/components/TilesList/examples/TilesList.Document.Example.tsx @@ -24,8 +24,8 @@ import { ISize } from '@uifabric/experiments/lib/Utilities'; import { ShimmerTile, ShimmerElementType as ElemType, - getRenderedElements } from '@uifabric/experiments/lib/Shimmer'; +import { ShimmerElementsGroup } from '../../Shimmer/ShimmerElementsGroup'; const HEADER_VERTICAL_PADDING = 13; const HEADER_FONT_SIZE = 18; @@ -263,16 +263,14 @@ export class TilesListDocumentExample extends React.Component { return ( -
- { - getRenderedElements( - [ - { type: ElemType.line, height: HEADER_FONT_SIZE, widthInPercentage: 100 }, - ], - HEADER_VERTICAL_PADDING * 2 + HEADER_FONT_SIZE - ) + + rowHeight={ HEADER_VERTICAL_PADDING * 2 + HEADER_FONT_SIZE } + /> ); } } From 762e3c5d5caf58ebe442f3f644b3242f574be264 Mon Sep 17 00:00:00 2001 From: Vitalie Braga Date: Fri, 11 May 2018 20:23:22 -0700 Subject: [PATCH 04/32] A lot of refactor. Still a lot to do. --- .../src/components/Shimmer/Shimmer.base.tsx | 48 ++++++++++++------- .../src/components/Shimmer/Shimmer.styles.ts | 21 ++++---- .../src/components/Shimmer/Shimmer.types.ts | 26 ++++++++-- .../Shimmer/ShimmerElementsGroup.tsx | 29 ++++++----- .../Shimmer/ShimmerTile/ShimmerTile.base.tsx | 6 +-- .../examples/Shimmer.Application.Example.tsx | 44 ----------------- .../examples/Shimmer.Basic.Example.tsx | 8 ++-- .../Shimmer/examples/Shimmer.Example.scss | 16 ------- .../examples/TilesList.Document.Example.tsx | 2 +- 9 files changed, 83 insertions(+), 117 deletions(-) diff --git a/packages/experiments/src/components/Shimmer/Shimmer.base.tsx b/packages/experiments/src/components/Shimmer/Shimmer.base.tsx index ba63757c04bb23..70502746b26215 100644 --- a/packages/experiments/src/components/Shimmer/Shimmer.base.tsx +++ b/packages/experiments/src/components/Shimmer/Shimmer.base.tsx @@ -5,10 +5,8 @@ import { IShimmerStyleProps, IShimmerStyles, ShimmerElementType, - ICircle, - ILine, - IGap, ShimmerElementsDefaultHeights, + IShimmerElement, } from './Shimmer.types'; import { ShimmerElementsGroup } from './ShimmerElementsGroup'; @@ -22,6 +20,18 @@ export class ShimmerBase extends BaseComponent { private _classNames: { [key in keyof IShimmerStyles]: string }; constructor(props: IShimmerProps) { super(props); + + this._warnDeprecations({ + 'isBaseStyle': 'onRenderCustomElement', + 'width': 'widthInPercentage or widthInPixel', + 'lineElements': 'shimmerElements' + }); + + this._warnMutuallyExclusive({ + 'widthInPixel': 'widthInPercentage', + 'lineElements': 'shimmerElements', + 'onRenderCustomElements': 'lineElements' + }); } public render(): JSX.Element { @@ -29,41 +39,47 @@ export class ShimmerBase extends BaseComponent { getStyles, width, lineElements, + shimmerElements, children, isDataLoaded, isBaseStyle, widthInPercentage, widthInPixel, - className + className, + onRenderCustomElements } = this.props; - const rowHeight: number | undefined = lineElements ? this._findMaxElementHeight(lineElements) : undefined; + // lineElements is a deprecated prop so need to check which one was used. + const elements: IShimmerElement[] | undefined = shimmerElements || lineElements; + const rowHeight: number | undefined = elements ? this._findMaxElementHeight(elements) : undefined; this._classNames = getClassNames(getStyles!, { - width, rowHeight, isDataLoaded, isBaseStyle, widthInPercentage, widthInPixel, className + width, rowHeight, isDataLoaded, widthInPercentage, widthInPixel, className }); return (
- { isBaseStyle ? children : - + { isBaseStyle ? children : // isBaseStyle prop is deprecated and this check needs to be removed in the future + onRenderCustomElements ? onRenderCustomElements() : + }
- { isDataLoaded && + { !isBaseStyle && // same in here... this check needs to be removed in the future
- { !!children ? children : null } + { children ? children : null }
}
); } - private _findMaxElementHeight(elements: Array): number { - const itemsDefaulted: Array = elements.map((elem: ICircle | IGap | ILine): ICircle | IGap | ILine => { + // User should not worry to provide which of the elements is the highest, we do the calculation for him. + private _findMaxElementHeight(elements: IShimmerElement[]): number { + const itemsDefaulted: IShimmerElement[] = elements.map((elem: IShimmerElement): IShimmerElement => { switch (elem.type) { case ShimmerElementType.circle: if (!elem.height) { @@ -81,7 +97,7 @@ export class ShimmerBase extends BaseComponent { return elem; }); - const rowHeight = itemsDefaulted.reduce((acc: number, next: ICircle | IGap | ILine): number => { + const rowHeight = itemsDefaulted.reduce((acc: number, next: IShimmerElement): number => { return next.height ? next.height > acc ? next.height : acc : acc; diff --git a/packages/experiments/src/components/Shimmer/Shimmer.styles.ts b/packages/experiments/src/components/Shimmer/Shimmer.styles.ts index 50e4e5aca27ee1..6d4caa221b8043 100644 --- a/packages/experiments/src/components/Shimmer/Shimmer.styles.ts +++ b/packages/experiments/src/components/Shimmer/Shimmer.styles.ts @@ -6,7 +6,6 @@ export function getStyles(props: IShimmerStyleProps): IShimmerStyles { width, rowHeight, isDataLoaded, - isBaseStyle, widthInPercentage, widthInPixel, className @@ -41,11 +40,6 @@ export function getStyles(props: IShimmerStyleProps): IShimmerStyles { shimmerWrapper: [ 'ms-Shimmer-shimmerWrapper', { - position: 'absolute', - top: '0', - bottom: '0', - left: '0', - right: '0', width: ACTUAL_WIDTH, background: `${DefaultPalette.neutralLighter} linear-gradient( @@ -60,25 +54,26 @@ export function getStyles(props: IShimmerStyleProps): IShimmerStyles { animationDirection: 'normal', animationIterationCount: 'infinite', animationName: shimmerAnimation, - transition: 'opacity 200ms, visibility 200ms' + transition: 'opacity 2000ms' }, isDataLoaded && { - opacity: '0', - visibility: 'hidden' - }, - isBaseStyle && { - position: 'static' + opacity: '0' } ], dataWrapper: [ 'ms-Shimmer-dataWrapper', { + position: 'absolute', + top: '0', + bottom: '0', + left: '0', + right: '0', opacity: '0', lineHeight: '1', background: 'none', backgroundColor: 'transparent', border: 'none', - transition: 'opacity 200ms' + transition: 'opacity 2000ms' }, isDataLoaded && { opacity: '1' diff --git a/packages/experiments/src/components/Shimmer/Shimmer.types.ts b/packages/experiments/src/components/Shimmer/Shimmer.types.ts index 084ce754c5d1bc..022b4259dc2175 100644 --- a/packages/experiments/src/components/Shimmer/Shimmer.types.ts +++ b/packages/experiments/src/components/Shimmer/Shimmer.types.ts @@ -18,9 +18,9 @@ export interface IShimmerProps extends React.AllHTMLAttributes { /** * Sets the width of the shimmer wave wrapper in percentages. - * Deprecated, use a more specific width like widthInPixel or widthInPercentage. + * Deprecated, use a more specific width like 'widthInPixel' or 'widthInPercentage'. * @default 100% - * @deprecated + * @deprecated Use a more specific width like 'widthInPixel' or 'widthInPercentage'. */ width?: number; @@ -43,15 +43,29 @@ export interface IShimmerProps extends React.AllHTMLAttributes { isDataLoaded?: boolean; /** - * Provide when Shimmer is intended to be used when using 'onRenderMissingItem' optional callback of the DetailsList Fabric Component. + * Use when providing custom skeleton as children wrapped by shimmer. + * Deprecated in favor of 'onRenderCustomElements' * @default false + * @deprecated Use 'onRenderCustomElements' instead. */ isBaseStyle?: boolean; /** * Elements to render in one line of the Shimmer. + * Deprecated, use 'shimmerElements' for better semantic meaning. + * @deprecated Use 'shimmerElements' instead. */ - lineElements?: Array; + lineElements?: IShimmerElement[]; + + /** + * Elements to render in one line of the Shimmer. + */ + shimmerElements?: IShimmerElement[]; + + /** + * Optional custom renderer when need to build complex placeholder skeletons. + */ + onRenderCustomElements?: () => React.ReactNode; /** * Call to provide customized styling that will layer on top of the variant rules. @@ -64,6 +78,9 @@ export interface IShimmerProps extends React.AllHTMLAttributes { className?: string; } +/** + * Shimmer Elements Interface + */ export interface IShimmerElement { /** * Required for every element you intend to use. @@ -149,7 +166,6 @@ export interface IShimmerStyleProps { widthInPercentage?: number; widthInPixel?: number; isDataLoaded?: boolean; - isBaseStyle?: boolean; className?: string; } diff --git a/packages/experiments/src/components/Shimmer/ShimmerElementsGroup.tsx b/packages/experiments/src/components/Shimmer/ShimmerElementsGroup.tsx index 6e52de5fb9998c..3a392af1e70249 100644 --- a/packages/experiments/src/components/Shimmer/ShimmerElementsGroup.tsx +++ b/packages/experiments/src/components/Shimmer/ShimmerElementsGroup.tsx @@ -3,42 +3,41 @@ import * as React from 'react'; import { DefaultPalette, IStyleSet } from '../../Styling'; import { ShimmerElementType, - ICircle, - ILine, - IGap, ShimmerElementVerticalAlign, - ShimmerElementsDefaultHeights + ShimmerElementsDefaultHeights, + IShimmerElement } from './Shimmer.types'; import { ShimmerLine } from './ShimmerLine/ShimmerLine'; import { ShimmerGap } from './ShimmerGap/ShimmerGap'; import { ShimmerCircle } from './ShimmerCircle/ShimmerCircle'; export interface IShimmerElementsGroupProps { - lineElements?: Array; + shimmerElements?: IShimmerElement[]; rowHeight?: number; } -export function ShimmerElementsGroup(props: IShimmerElementsGroupProps): JSX.Element { - const { lineElements, rowHeight } = props; +export type ShimmerElementsGroup = React.StatelessComponent; + +export const ShimmerElementsGroup: ShimmerElementsGroup = (props: IShimmerElementsGroupProps): JSX.Element => { + const { shimmerElements, rowHeight } = props; return (
- { getRenderedElements(lineElements, rowHeight) } + { getRenderedElements(shimmerElements, rowHeight) }
); -} +}; -function getRenderedElements(lineElements?: Array, rowHeight?: number): React.ReactNode { - const renderedElements: React.ReactNode = lineElements ? - lineElements.map((elem: ICircle | ILine | IGap, index: number): JSX.Element => { +function getRenderedElements(shimmerElements?: IShimmerElement[], rowHeight?: number): React.ReactNode { + const renderedElements: React.ReactNode = shimmerElements ? + shimmerElements.map((elem: IShimmerElement, index: number): JSX.Element => { switch (elem.type) { case ShimmerElementType.circle: return ( @@ -74,7 +73,7 @@ function getRenderedElements(lineElements?: Array, rowHe return renderedElements; } -function getBorderStyles(elem: ICircle | IGap | ILine, rowHeight?: number): IStyleSet | undefined { +function getBorderStyles(elem: IShimmerElement, rowHeight?: number): IStyleSet | undefined { const elemHeight: number | undefined = elem.height; const dif: number = rowHeight && elemHeight ? rowHeight - elemHeight : 0; diff --git a/packages/experiments/src/components/Shimmer/ShimmerTile/ShimmerTile.base.tsx b/packages/experiments/src/components/Shimmer/ShimmerTile/ShimmerTile.base.tsx index 3eecd1eb51e937..2bc676cd60d0b8 100644 --- a/packages/experiments/src/components/Shimmer/ShimmerTile/ShimmerTile.base.tsx +++ b/packages/experiments/src/components/Shimmer/ShimmerTile/ShimmerTile.base.tsx @@ -114,7 +114,7 @@ export class ShimmerTileBase extends BaseComponent { height={ contentSize.height - squareHeight - nameplateHeight } /> { { itemName ? { { itemActivity ? { - const expandingCardProps: IExpandingCardProps = { - onRenderCompactCard: this._onRenderCompactCard, - onRenderExpandedCard: this._onRenderExpandedCard, - renderData: item - }; - - if (column.key === 'key') { - return ( - -
- { item.key } -
-
- ); - } - if (column.key === 'thumbnail') { return ( { - return ( - - ); - } - - private _onRenderExpandedCard = (item: IItem): JSX.Element => { - const { items, columns } = this.state; - return ( -
- { item.description } - -
- ); - } - private _randomFileIcon(): { docType: string; url: string; } { const docType: string = fileIcons[Math.floor(Math.random() * fileIcons.length) + 0].name; return { diff --git a/packages/experiments/src/components/Shimmer/examples/Shimmer.Basic.Example.tsx b/packages/experiments/src/components/Shimmer/examples/Shimmer.Basic.Example.tsx index 6229c99402cb42..cdcdfc42ce55ae 100644 --- a/packages/experiments/src/components/Shimmer/examples/Shimmer.Basic.Example.tsx +++ b/packages/experiments/src/components/Shimmer/examples/Shimmer.Basic.Example.tsx @@ -28,7 +28,7 @@ export class ShimmerBasicExample extends React.Component<{}, {}> { /> Custom Shimmer with elements provided. { /> Notice how the same elements change relative to the shimmer width provided. { /> { /> Variations of vertical alignment for Circles and Lines. { return ( Date: Tue, 15 May 2018 11:26:20 -0700 Subject: [PATCH 05/32] Change new prop name for better semantics. --- .../experiments/src/components/Shimmer/Shimmer.base.tsx | 8 ++++---- .../experiments/src/components/Shimmer/Shimmer.types.ts | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/experiments/src/components/Shimmer/Shimmer.base.tsx b/packages/experiments/src/components/Shimmer/Shimmer.base.tsx index 70502746b26215..e4a1e13db68b31 100644 --- a/packages/experiments/src/components/Shimmer/Shimmer.base.tsx +++ b/packages/experiments/src/components/Shimmer/Shimmer.base.tsx @@ -22,7 +22,7 @@ export class ShimmerBase extends BaseComponent { super(props); this._warnDeprecations({ - 'isBaseStyle': 'onRenderCustomElement', + 'isBaseStyle': 'customElement', 'width': 'widthInPercentage or widthInPixel', 'lineElements': 'shimmerElements' }); @@ -30,7 +30,7 @@ export class ShimmerBase extends BaseComponent { this._warnMutuallyExclusive({ 'widthInPixel': 'widthInPercentage', 'lineElements': 'shimmerElements', - 'onRenderCustomElements': 'lineElements' + 'customElementsGroup': 'lineElements' }); } @@ -46,7 +46,7 @@ export class ShimmerBase extends BaseComponent { widthInPercentage, widthInPixel, className, - onRenderCustomElements + customElementsGroup } = this.props; // lineElements is a deprecated prop so need to check which one was used. @@ -61,7 +61,7 @@ export class ShimmerBase extends BaseComponent {
{ isBaseStyle ? children : // isBaseStyle prop is deprecated and this check needs to be removed in the future - onRenderCustomElements ? onRenderCustomElements() : + customElementsGroup ? customElementsGroup : { /** * Use when providing custom skeleton as children wrapped by shimmer. - * Deprecated in favor of 'onRenderCustomElements' + * Deprecated in favor of 'customElementsGroup' * @default false - * @deprecated Use 'onRenderCustomElements' instead. + * @deprecated Use 'customElementsGroup' instead. */ isBaseStyle?: boolean; @@ -63,9 +63,9 @@ export interface IShimmerProps extends React.AllHTMLAttributes { shimmerElements?: IShimmerElement[]; /** - * Optional custom renderer when need to build complex placeholder skeletons. + * Custom elements when necessary to build complex placeholder skeletons. */ - onRenderCustomElements?: () => React.ReactNode; + customElementsGroup?: React.ReactNode; /** * Call to provide customized styling that will layer on top of the variant rules. From f2d84d57fedaaba30d7d6aeb951ce1171387370d Mon Sep 17 00:00:00 2001 From: Vitalie Braga Date: Tue, 15 May 2018 11:37:05 -0700 Subject: [PATCH 06/32] Apply new prop to application in detailsList example. --- .../src/components/Shimmer/Shimmer.base.tsx | 2 +- .../Shimmer/examples/Shimmer.Application.Example.tsx | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/experiments/src/components/Shimmer/Shimmer.base.tsx b/packages/experiments/src/components/Shimmer/Shimmer.base.tsx index e4a1e13db68b31..3f466c9eec94f6 100644 --- a/packages/experiments/src/components/Shimmer/Shimmer.base.tsx +++ b/packages/experiments/src/components/Shimmer/Shimmer.base.tsx @@ -22,7 +22,7 @@ export class ShimmerBase extends BaseComponent { super(props); this._warnDeprecations({ - 'isBaseStyle': 'customElement', + 'isBaseStyle': 'customElementsGroup', 'width': 'widthInPercentage or widthInPixel', 'lineElements': 'shimmerElements' }); diff --git a/packages/experiments/src/components/Shimmer/examples/Shimmer.Application.Example.tsx b/packages/experiments/src/components/Shimmer/examples/Shimmer.Application.Example.tsx index 93db78059ca293..0b722053061eaf 100644 --- a/packages/experiments/src/components/Shimmer/examples/Shimmer.Application.Example.tsx +++ b/packages/experiments/src/components/Shimmer/examples/Shimmer.Application.Example.tsx @@ -142,12 +142,14 @@ export class ShimmerApplicationExample extends BaseComponent<{}, IShimmerApplica const { isDataLoaded } = this.state; isDataLoaded && this._onDataMiss(index as number); + const shimmerRow: JSX.Element = ( + + ); + return ( - - + customElementsGroup={ shimmerRow } + /> ); } From 053648bf147507690c9c2bba2f65d80839f6b26d Mon Sep 17 00:00:00 2001 From: Vitalie Braga Date: Tue, 15 May 2018 11:40:34 -0700 Subject: [PATCH 07/32] Use the new prop in TilesList. --- packages/experiments/src/components/TilesList/TilesList.tsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/experiments/src/components/TilesList/TilesList.tsx b/packages/experiments/src/components/TilesList/TilesList.tsx index 3f85151a29ecb4..9b6417b455381a 100644 --- a/packages/experiments/src/components/TilesList/TilesList.tsx +++ b/packages/experiments/src/components/TilesList/TilesList.tsx @@ -329,11 +329,9 @@ export class TilesList extends React.Component, IT ( - { finalGrid } - + /> ) : finalGrid ); From 567983c44bc5fa53453844eb3562374ba6635f30 Mon Sep 17 00:00:00 2001 From: Vitalie Braga Date: Tue, 15 May 2018 13:27:20 -0700 Subject: [PATCH 08/32] More REFACTOR. --- .../src/components/Shimmer/Shimmer.base.tsx | 35 +------- .../src/components/Shimmer/Shimmer.styles.ts | 9 +-- .../src/components/Shimmer/Shimmer.types.ts | 3 +- .../Shimmer/ShimmerElementsGroup.tsx | 42 +++++++++- .../src/components/Shimmer/ShimmerPage.tsx | 11 +++ .../Shimmer/ShimmerTile/ShimmerTile.base.tsx | 3 - .../Shimmer/ShimmerTile/ShimmerTile.styles.ts | 6 -- .../Shimmer/ShimmerTile/ShimmerTile.types.ts | 1 - .../examples/Shimmer.Basic.Example.tsx | 55 ------------- .../Shimmer.CustomElements.Example.tsx | 79 +++++++++++++++++++ .../src/components/Shimmer/index.ts | 3 +- .../examples/TilesList.Document.Example.tsx | 4 +- 12 files changed, 139 insertions(+), 112 deletions(-) create mode 100644 packages/experiments/src/components/Shimmer/examples/Shimmer.CustomElements.Example.tsx diff --git a/packages/experiments/src/components/Shimmer/Shimmer.base.tsx b/packages/experiments/src/components/Shimmer/Shimmer.base.tsx index 3f466c9eec94f6..28a4c52abef1b3 100644 --- a/packages/experiments/src/components/Shimmer/Shimmer.base.tsx +++ b/packages/experiments/src/components/Shimmer/Shimmer.base.tsx @@ -4,8 +4,6 @@ import { IShimmerProps, IShimmerStyleProps, IShimmerStyles, - ShimmerElementType, - ShimmerElementsDefaultHeights, IShimmerElement, } from './Shimmer.types'; import { ShimmerElementsGroup } from './ShimmerElementsGroup'; @@ -51,10 +49,9 @@ export class ShimmerBase extends BaseComponent { // lineElements is a deprecated prop so need to check which one was used. const elements: IShimmerElement[] | undefined = shimmerElements || lineElements; - const rowHeight: number | undefined = elements ? this._findMaxElementHeight(elements) : undefined; this._classNames = getClassNames(getStyles!, { - width, rowHeight, isDataLoaded, widthInPercentage, widthInPixel, className + width, isDataLoaded, widthInPercentage, widthInPixel, className }); return ( @@ -64,7 +61,6 @@ export class ShimmerBase extends BaseComponent { customElementsGroup ? customElementsGroup : }
@@ -76,33 +72,4 @@ export class ShimmerBase extends BaseComponent {
); } - - // User should not worry to provide which of the elements is the highest, we do the calculation for him. - private _findMaxElementHeight(elements: IShimmerElement[]): number { - const itemsDefaulted: IShimmerElement[] = elements.map((elem: IShimmerElement): IShimmerElement => { - switch (elem.type) { - case ShimmerElementType.circle: - if (!elem.height) { - elem.height = ShimmerElementsDefaultHeights.circle; - } - case ShimmerElementType.line: - if (!elem.height) { - elem.height = ShimmerElementsDefaultHeights.line; - } - case ShimmerElementType.gap: - if (!elem.height) { - elem.height = ShimmerElementsDefaultHeights.gap; - } - } - return elem; - }); - - const rowHeight = itemsDefaulted.reduce((acc: number, next: IShimmerElement): number => { - return next.height ? - next.height > acc ? next.height : acc - : acc; - }, 0); - - return rowHeight; - } } \ No newline at end of file diff --git a/packages/experiments/src/components/Shimmer/Shimmer.styles.ts b/packages/experiments/src/components/Shimmer/Shimmer.styles.ts index 6d4caa221b8043..ce244dc005a1c1 100644 --- a/packages/experiments/src/components/Shimmer/Shimmer.styles.ts +++ b/packages/experiments/src/components/Shimmer/Shimmer.styles.ts @@ -4,7 +4,6 @@ import { keyframes, DefaultPalette } from '../../Styling'; export function getStyles(props: IShimmerStyleProps): IShimmerStyles { const { width, - rowHeight, isDataLoaded, widthInPercentage, widthInPixel, @@ -33,7 +32,6 @@ export function getStyles(props: IShimmerStyleProps): IShimmerStyles { 'ms-Shimmer-container', { position: 'relative', - minHeight: rowHeight ? `${rowHeight}px` : '16px' }, className ], @@ -54,10 +52,11 @@ export function getStyles(props: IShimmerStyleProps): IShimmerStyles { animationDirection: 'normal', animationIterationCount: 'infinite', animationName: shimmerAnimation, - transition: 'opacity 2000ms' + transition: 'opacity 200ms, background 200ms' }, isDataLoaded && { - opacity: '0' + opacity: '0', + background: 'none' } ], dataWrapper: [ @@ -73,7 +72,7 @@ export function getStyles(props: IShimmerStyleProps): IShimmerStyles { background: 'none', backgroundColor: 'transparent', border: 'none', - transition: 'opacity 2000ms' + transition: 'opacity 200ms' }, isDataLoaded && { opacity: '1' diff --git a/packages/experiments/src/components/Shimmer/Shimmer.types.ts b/packages/experiments/src/components/Shimmer/Shimmer.types.ts index ecae34186698bc..b994273279f448 100644 --- a/packages/experiments/src/components/Shimmer/Shimmer.types.ts +++ b/packages/experiments/src/components/Shimmer/Shimmer.types.ts @@ -88,7 +88,7 @@ export interface IShimmerElement { type: ShimmerElementType; /** - * The height of the element (ICircle, ILine) in pixels. + * The height of the element (ICircle, ILine, IGap) in pixels. * Read more details for each specific element. */ height?: number; @@ -162,7 +162,6 @@ export interface IGap extends IShimmerElement { export interface IShimmerStyleProps { width?: number; - rowHeight?: number; widthInPercentage?: number; widthInPixel?: number; isDataLoaded?: boolean; diff --git a/packages/experiments/src/components/Shimmer/ShimmerElementsGroup.tsx b/packages/experiments/src/components/Shimmer/ShimmerElementsGroup.tsx index 3a392af1e70249..5d1b25e0f5fa66 100644 --- a/packages/experiments/src/components/Shimmer/ShimmerElementsGroup.tsx +++ b/packages/experiments/src/components/Shimmer/ShimmerElementsGroup.tsx @@ -14,23 +14,30 @@ import { ShimmerCircle } from './ShimmerCircle/ShimmerCircle'; export interface IShimmerElementsGroupProps { shimmerElements?: IShimmerElement[]; rowHeight?: number; + flexWrap?: boolean; } export type ShimmerElementsGroup = React.StatelessComponent; export const ShimmerElementsGroup: ShimmerElementsGroup = (props: IShimmerElementsGroupProps): JSX.Element => { - const { shimmerElements, rowHeight } = props; + const { + shimmerElements, + rowHeight, + flexWrap = false + } = props; + const height = rowHeight ? rowHeight : findMaxElementHeight(shimmerElements ? shimmerElements : []); return (
- { getRenderedElements(shimmerElements, rowHeight) } + { getRenderedElements(shimmerElements, height) }
); }; @@ -98,4 +105,33 @@ function getBorderStyles(elem: IShimmerElement, rowHeight?: number): IStyleSet | } return borderStyle; +} + +// User should not worry to provide which of the elements is the highest, we do the calculation for him. +export function findMaxElementHeight(elements: IShimmerElement[]): number { + const itemsDefaulted: IShimmerElement[] = elements.map((elem: IShimmerElement): IShimmerElement => { + switch (elem.type) { + case ShimmerElementType.circle: + if (!elem.height) { + elem.height = ShimmerElementsDefaultHeights.circle; + } + case ShimmerElementType.line: + if (!elem.height) { + elem.height = ShimmerElementsDefaultHeights.line; + } + case ShimmerElementType.gap: + if (!elem.height) { + elem.height = ShimmerElementsDefaultHeights.gap; + } + } + return elem; + }); + + const rowHeight = itemsDefaulted.reduce((acc: number, next: IShimmerElement): number => { + return next.height ? + next.height > acc ? next.height : acc + : acc; + }, 0); + + return rowHeight; } \ No newline at end of file diff --git a/packages/experiments/src/components/Shimmer/ShimmerPage.tsx b/packages/experiments/src/components/Shimmer/ShimmerPage.tsx index c6856225b25180..b081bd150e16c2 100644 --- a/packages/experiments/src/components/Shimmer/ShimmerPage.tsx +++ b/packages/experiments/src/components/Shimmer/ShimmerPage.tsx @@ -6,6 +6,7 @@ import { PropertiesTableSet } from '@uifabric/example-app-base'; import { ShimmerBasicExample } from './examples/Shimmer.Basic.Example'; +import { ShimmerCustomElementsExample } from './examples/Shimmer.CustomElements.Example'; import { ShimmerLoadDataExample } from './examples/Shimmer.LoadData.Example'; import { ShimmerApplicationExample } from './examples/Shimmer.Application.Example'; @@ -13,6 +14,10 @@ const ShimmerBasicExampleCode = require( '!raw-loader!@uifabric/experiments/src/components/Shimmer/examples/Shimmer.Basic.Example.tsx' ) as string; +const ShimmerCustomExampleCode = require( + '!raw-loader!@uifabric/experiments/src/components/Shimmer/examples/Shimmer.CustomElements.Example.tsx' +) as string; + const ShimmerLoadDataExampleCode = require( '!raw-loader!@uifabric/experiments/src/components/Shimmer/examples/Shimmer.LoadData.Example.tsx' ) as string; @@ -35,6 +40,12 @@ export class ShimmerPage extends React.Component { > + + + { } ] } - rowHeight={ squareHeight } /> { itemActivity || itemName ? @@ -170,7 +169,6 @@ export class ShimmerTileBase extends BaseComponent { } ] } - rowHeight={ nameplateNameHeight } /> : null } { @@ -195,7 +193,6 @@ export class ShimmerTileBase extends BaseComponent { } ] } - rowHeight={ nameplateActivityHeight } /> : null } { { type: ElemType.line, height: 10, verticalAlign: ElemVerticalAlign.bottom } ] } /> - Split line examples. - {/*
- - { getRenderedElements([ - { type: ElemType.line, widthInPixel: 40, height: 40 }, - { type: ElemType.gap, widthInPixel: 10, height: 40 } - ], 40) } -
- { getRenderedElements([ - { type: ElemType.line, widthInPixel: 300, height: 10 }, - { type: ElemType.line, widthInPixel: 200, height: 10 }, - { type: ElemType.gap, widthInPixel: 100, height: 20 } - ], 20) } -
-
-
-
- - { getRenderedElements([ - { type: ElemType.circle, height: 40 }, - { type: ElemType.gap, widthInPixel: 10, height: 40 } - ], 40) } -
- { getRenderedElements([ - { type: ElemType.line, widthInPixel: 400, height: 10 }, - { type: ElemType.gap, widthInPixel: 100, height: 20 }, - { type: ElemType.line, widthInPixel: 500, height: 10 } - ], 20) } -
-
-
*/}
); } diff --git a/packages/experiments/src/components/Shimmer/examples/Shimmer.CustomElements.Example.tsx b/packages/experiments/src/components/Shimmer/examples/Shimmer.CustomElements.Example.tsx new file mode 100644 index 00000000000000..2b9f320022c3b9 --- /dev/null +++ b/packages/experiments/src/components/Shimmer/examples/Shimmer.CustomElements.Example.tsx @@ -0,0 +1,79 @@ +import * as React from 'react'; + +import { + Shimmer, + ShimmerElementsGroup, + ShimmerElementType as ElemType, +} from '@uifabric/experiments/lib/Shimmer'; + +import './Shimmer.Example.scss'; + +export class ShimmerCustomElementsExample extends React.Component<{}, {}> { + + constructor(props: {}) { + super(props); + } + + public render(): JSX.Element { + + return ( +
+ Split line examples. + + +
+ ); + } + + private _getCustomElementsExampleOne = (): JSX.Element => { + return ( +
+ + +
+ ); + } + + private _getCustomElementsExampleTwo = (): JSX.Element => { + return ( +
+ + +
+ ); + } +} \ No newline at end of file diff --git a/packages/experiments/src/components/Shimmer/index.ts b/packages/experiments/src/components/Shimmer/index.ts index 616724aa5a7268..5e5551bb064c57 100644 --- a/packages/experiments/src/components/Shimmer/index.ts +++ b/packages/experiments/src/components/Shimmer/index.ts @@ -8,4 +8,5 @@ export * from './ShimmerLine/ShimmerLine.types'; export * from './ShimmerCircle/ShimmerCircle'; export * from './ShimmerCircle/ShimmerCircle.types'; export * from './ShimmerGap/ShimmerGap'; -export * from './ShimmerGap/ShimmerGap.types'; \ No newline at end of file +export * from './ShimmerGap/ShimmerGap.types'; +export * from './ShimmerElementsGroup'; \ No newline at end of file diff --git a/packages/experiments/src/components/TilesList/examples/TilesList.Document.Example.tsx b/packages/experiments/src/components/TilesList/examples/TilesList.Document.Example.tsx index f6c2d4f21dec76..c18fd58244aa0f 100644 --- a/packages/experiments/src/components/TilesList/examples/TilesList.Document.Example.tsx +++ b/packages/experiments/src/components/TilesList/examples/TilesList.Document.Example.tsx @@ -266,10 +266,10 @@ export class TilesListDocumentExample extends React.Component ); } From 8c375a6fff82a8cc53e612a63efed7b91a581adc Mon Sep 17 00:00:00 2001 From: Vitalie Braga Date: Tue, 15 May 2018 19:22:37 -0700 Subject: [PATCH 09/32] More examples... --- .../Shimmer/ShimmerElementsGroup.tsx | 7 +- .../src/components/Shimmer/ShimmerPage.tsx | 8 +- .../Shimmer/examples/ExampleHelper.tsx | 8 ++ .../examples/Shimmer.Basic.Example.tsx | 5 +- .../Shimmer.CustomElements.Example.tsx | 53 ++++++++- .../examples/Shimmer.LoadData.Example.tsx | 111 +++++++++++++++--- 6 files changed, 166 insertions(+), 26 deletions(-) create mode 100644 packages/experiments/src/components/Shimmer/examples/ExampleHelper.tsx diff --git a/packages/experiments/src/components/Shimmer/ShimmerElementsGroup.tsx b/packages/experiments/src/components/Shimmer/ShimmerElementsGroup.tsx index 5d1b25e0f5fa66..f34b764b721c0e 100644 --- a/packages/experiments/src/components/Shimmer/ShimmerElementsGroup.tsx +++ b/packages/experiments/src/components/Shimmer/ShimmerElementsGroup.tsx @@ -15,6 +15,7 @@ export interface IShimmerElementsGroupProps { shimmerElements?: IShimmerElement[]; rowHeight?: number; flexWrap?: boolean; + width?: string; } export type ShimmerElementsGroup = React.StatelessComponent; @@ -23,7 +24,8 @@ export const ShimmerElementsGroup: ShimmerElementsGroup = (props: IShimmerElemen const { shimmerElements, rowHeight, - flexWrap = false + flexWrap = false, + width } = props; const height = rowHeight ? rowHeight : findMaxElementHeight(shimmerElements ? shimmerElements : []); @@ -33,7 +35,8 @@ export const ShimmerElementsGroup: ShimmerElementsGroup = (props: IShimmerElemen { display: 'flex', alignItems: 'center', - flexWrap: flexWrap ? 'wrap' : 'nowrap' + flexWrap: flexWrap ? 'wrap' : 'nowrap', + width: width ? width : 'auto' } } > diff --git a/packages/experiments/src/components/Shimmer/ShimmerPage.tsx b/packages/experiments/src/components/Shimmer/ShimmerPage.tsx index b081bd150e16c2..9092d58dcd1822 100644 --- a/packages/experiments/src/components/Shimmer/ShimmerPage.tsx +++ b/packages/experiments/src/components/Shimmer/ShimmerPage.tsx @@ -35,25 +35,25 @@ export class ShimmerPage extends React.Component { exampleCards={
diff --git a/packages/experiments/src/components/Shimmer/examples/ExampleHelper.tsx b/packages/experiments/src/components/Shimmer/examples/ExampleHelper.tsx new file mode 100644 index 00000000000000..a60df5732fe1c8 --- /dev/null +++ b/packages/experiments/src/components/Shimmer/examples/ExampleHelper.tsx @@ -0,0 +1,8 @@ +const baseProductionCdnUrl = 'https://static2.sharepointonline.com/files/fabric/office-ui-fabric-react-assets/'; + +export const PersonaDetails = { + imageUrl: baseProductionCdnUrl + 'persona-female.png', + imageInitials: 'AL', + primaryText: 'Annie Lindqvist', + secondaryText: 'Software Engineer', +}; \ No newline at end of file diff --git a/packages/experiments/src/components/Shimmer/examples/Shimmer.Basic.Example.tsx b/packages/experiments/src/components/Shimmer/examples/Shimmer.Basic.Example.tsx index 40628606376672..339fe4234158b4 100644 --- a/packages/experiments/src/components/Shimmer/examples/Shimmer.Basic.Example.tsx +++ b/packages/experiments/src/components/Shimmer/examples/Shimmer.Basic.Example.tsx @@ -18,7 +18,7 @@ export class ShimmerBasicExample extends React.Component<{}, {}> { return (
- Generic Shimmer with no elements provided. + Basic Shimmer with no elements provided. It defaults to a line of 16px height. { - Custom Shimmer with elements provided. + Basic Shimmer with elements provided. { { type: ElemType.line }, ] } /> - Notice how the same elements change relative to the shimmer width provided. { return (
- Split line examples. + Using ShimmerElementsGroup component to build complex structures of the placeholder you need. { customElementsGroup={ this._getCustomElementsExampleTwo() } widthInPixel={ 550 } /> +
); } @@ -76,4 +81,50 @@ export class ShimmerCustomElementsExample extends React.Component<{}, {}> {
); } + + private _getCustomElementsExampleThree = (): JSX.Element => { + return ( +
+ +
+ + + +
+
+ ); + } } \ No newline at end of file diff --git a/packages/experiments/src/components/Shimmer/examples/Shimmer.LoadData.Example.tsx b/packages/experiments/src/components/Shimmer/examples/Shimmer.LoadData.Example.tsx index 7864e1ed4805e2..7ab773322ec5e7 100644 --- a/packages/experiments/src/components/Shimmer/examples/Shimmer.LoadData.Example.tsx +++ b/packages/experiments/src/components/Shimmer/examples/Shimmer.LoadData.Example.tsx @@ -1,40 +1,119 @@ import * as React from 'react'; -import { Shimmer } from '@uifabric/experiments/lib/Shimmer'; +import { + Shimmer, + ShimmerElementsGroup, + ShimmerElementType as ElemType, + ShimmerElementVerticalAlign as ElemVerticalAlign +} from '@uifabric/experiments/lib/Shimmer'; +import { + Persona, + PersonaSize, + PersonaPresence, + IPersonaProps +} from 'office-ui-fabric-react/lib/Persona'; import { Toggle } from 'office-ui-fabric-react/lib/Toggle'; +import { PersonaDetails } from './ExampleHelper'; -export interface IShimmerLoadDataExample { - isDataLoaded?: boolean; +export interface IShimmerLoadDataExampleState { + isDataLoadedOne?: boolean; + isDataLoadedTwo?: boolean; + contentOne?: string; + examplePersona?: IPersonaProps; } -export class ShimmerLoadDataExample extends React.Component<{}, IShimmerLoadDataExample> { +export class ShimmerLoadDataExample extends React.Component<{}, IShimmerLoadDataExampleState> { constructor(props: {}) { super(props); this.state = { - isDataLoaded: false + isDataLoadedOne: false, + isDataLoadedTwo: false, + contentOne: '', + examplePersona: {} }; } public render(): JSX.Element { const { - isDataLoaded: dataLoaded, + isDataLoadedOne, + isDataLoadedTwo, + contentOne, + examplePersona } = this.state; return ( - // tslint:disable-next-line:jsx-ban-props -
+
+ -
Data Loaded Data Loaded Data Loaded Data Loaded Data Loaded Data Loaded Data Loaded
+
+ { contentOne } + { contentOne } + { contentOne } +
this.setState({ isDataLoaded }) } - onText='Loaded' - offText='Loading...' + checked={ isDataLoadedTwo } + onChanged={ this._getContentTwo } + onText='Toggle to show shimmer' + offText='Toggle to load content' + /> + + + +
+ ); + } + + private _getContentOne = (checked: boolean): void => { + const { isDataLoadedOne } = this.state; + this.setState({ + isDataLoadedOne: checked, + contentOne: !isDataLoadedOne ? 'Congratulations!!! You have successfully loaded the content. ' : '' + }); + } + + private _getContentTwo = (checked: boolean): void => { + const { isDataLoadedTwo } = this.state; + this.setState({ + isDataLoadedTwo: checked, + examplePersona: !isDataLoadedTwo ? { ...PersonaDetails } : {} + }); + } + + private _getCustomElements = (): JSX.Element => { + return ( +
+ +
); From 3b2d55439302a8cb533e94e5256bf3ddcbfc2bcd Mon Sep 17 00:00:00 2001 From: Vitalie Braga Date: Tue, 15 May 2018 20:08:38 -0700 Subject: [PATCH 10/32] Enums refactor and documentation. --- .../src/components/Shimmer/Shimmer.types.ts | 95 ++++++++++++++----- .../Shimmer/ShimmerElementsGroup.tsx | 7 +- 2 files changed, 76 insertions(+), 26 deletions(-) diff --git a/packages/experiments/src/components/Shimmer/Shimmer.types.ts b/packages/experiments/src/components/Shimmer/Shimmer.types.ts index b994273279f448..e95e00d9485d79 100644 --- a/packages/experiments/src/components/Shimmer/Shimmer.types.ts +++ b/packages/experiments/src/components/Shimmer/Shimmer.types.ts @@ -174,34 +174,83 @@ export interface IShimmerStyles { dataWrapper?: IStyle; } -/** - * The CAPS lock values will be deprecated soon. - * @deprecated - */ -export const enum ShimmerElementType { - LINE = 'line', - CIRCLE = 'circle', - GAP = 'gap', - line = 'line', - circle = 'circle', - gap = 'gap' +export enum ShimmerElementType { + /** + * Line element type + */ + line = 1, + + /** + * Circle element type + */ + circle = 2, + + /** + * Gap element type + */ + gap = 3, + + /** + * @deprecated Use 'line' instead + */ + LINE = 1, + + /** + * @deprecated Use 'circle' instead + */ + CIRCLE = 2, + + /** + * @deprecated Use 'gap' instead + */ + GAP = 3 } -/** - * The CAPS lock values will be deprecated soon. - * @deprecated - */ -export const enum ShimmerElementVerticalAlign { - CENTER = 'center', - BOTTOM = 'bottom', - TOP = 'top', - center = 'center', - bottom = 'bottom', - top = 'top' +export enum ShimmerElementVerticalAlign { + /** + * @deprecated Use 'center' instead + */ + CENTER = 1, + + /** + * @deprecated Use 'bottom' instead + */ + BOTTOM = 2, + + /** + * @deprecated Use 'top' instead + */ + TOP = 3, + + /** + * Positions the element vertically in center + */ + center = 1, + + /** + * Positions the element vertically at the bottom + */ + bottom = 2, + + /** + * Positions the element vertically at the top + */ + top = 3 } -export const enum ShimmerElementsDefaultHeights { +export enum ShimmerElementsDefaultHeights { + /** + * Default height of the line element when not provided by user: 16px + */ line = 16, + + /** + * Default height of the gap element when not provided by user: 16px + */ gap = 16, + + /** + * Default height of the circle element when not provided by user: 24px + */ circle = 24 } \ No newline at end of file diff --git a/packages/experiments/src/components/Shimmer/ShimmerElementsGroup.tsx b/packages/experiments/src/components/Shimmer/ShimmerElementsGroup.tsx index f34b764b721c0e..151e40def611c6 100644 --- a/packages/experiments/src/components/Shimmer/ShimmerElementsGroup.tsx +++ b/packages/experiments/src/components/Shimmer/ShimmerElementsGroup.tsx @@ -48,12 +48,13 @@ export const ShimmerElementsGroup: ShimmerElementsGroup = (props: IShimmerElemen function getRenderedElements(shimmerElements?: IShimmerElement[], rowHeight?: number): React.ReactNode { const renderedElements: React.ReactNode = shimmerElements ? shimmerElements.map((elem: IShimmerElement, index: number): JSX.Element => { + const { type, ...filteredElem } = elem; switch (elem.type) { case ShimmerElementType.circle: return ( ); @@ -61,7 +62,7 @@ function getRenderedElements(shimmerElements?: IShimmerElement[], rowHeight?: nu return ( ); @@ -69,7 +70,7 @@ function getRenderedElements(shimmerElements?: IShimmerElement[], rowHeight?: nu return ( ); From ce8d11639b96901accda25537b4ec712de1dc5f8 Mon Sep 17 00:00:00 2001 From: Vitalie Braga Date: Wed, 16 May 2018 10:10:37 -0700 Subject: [PATCH 11/32] Overflow text fix in LoadData example. --- .../Shimmer/examples/Shimmer.LoadData.Example.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/experiments/src/components/Shimmer/examples/Shimmer.LoadData.Example.tsx b/packages/experiments/src/components/Shimmer/examples/Shimmer.LoadData.Example.tsx index 7ab773322ec5e7..267735800625c7 100644 --- a/packages/experiments/src/components/Shimmer/examples/Shimmer.LoadData.Example.tsx +++ b/packages/experiments/src/components/Shimmer/examples/Shimmer.LoadData.Example.tsx @@ -52,7 +52,13 @@ export class ShimmerLoadDataExample extends React.Component<{}, IShimmerLoadData -
+
{ contentOne } { contentOne } { contentOne } From 8689193f652ebe0203744bda1dc68311623d4225 Mon Sep 17 00:00:00 2001 From: Vitalie Braga Date: Wed, 16 May 2018 11:04:55 -0700 Subject: [PATCH 12/32] Moves deprecated props down. --- .../src/components/Shimmer/Shimmer.types.ts | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/packages/experiments/src/components/Shimmer/Shimmer.types.ts b/packages/experiments/src/components/Shimmer/Shimmer.types.ts index e95e00d9485d79..657b6698c3b278 100644 --- a/packages/experiments/src/components/Shimmer/Shimmer.types.ts +++ b/packages/experiments/src/components/Shimmer/Shimmer.types.ts @@ -16,14 +16,6 @@ export interface IShimmerProps extends React.AllHTMLAttributes { */ componentRef?: (component: IShimmer | null) => void; - /** - * Sets the width of the shimmer wave wrapper in percentages. - * Deprecated, use a more specific width like 'widthInPixel' or 'widthInPercentage'. - * @default 100% - * @deprecated Use a more specific width like 'widthInPixel' or 'widthInPercentage'. - */ - width?: number; - /** * Sets the width of the shimmer wave wrapper in percentages relative to the containig parent element. * @default 100% @@ -42,21 +34,6 @@ export interface IShimmerProps extends React.AllHTMLAttributes { */ isDataLoaded?: boolean; - /** - * Use when providing custom skeleton as children wrapped by shimmer. - * Deprecated in favor of 'customElementsGroup' - * @default false - * @deprecated Use 'customElementsGroup' instead. - */ - isBaseStyle?: boolean; - - /** - * Elements to render in one line of the Shimmer. - * Deprecated, use 'shimmerElements' for better semantic meaning. - * @deprecated Use 'shimmerElements' instead. - */ - lineElements?: IShimmerElement[]; - /** * Elements to render in one line of the Shimmer. */ @@ -76,6 +53,29 @@ export interface IShimmerProps extends React.AllHTMLAttributes { * Additional CSS class(es) to apply to the Shimmer container. */ className?: string; + + /** + * Elements to render in one line of the Shimmer. + * Deprecated, use 'shimmerElements' for better semantic meaning. + * @deprecated Use 'shimmerElements' instead. + */ + lineElements?: IShimmerElement[]; + + /** + * Sets the width of the shimmer wave wrapper in percentages. + * Deprecated, use a more specific width like 'widthInPixel' or 'widthInPercentage'. + * @default 100% + * @deprecated Use a more specific width like 'widthInPixel' or 'widthInPercentage'. + */ + width?: number; + + /** + * Use when providing custom skeleton as children wrapped by shimmer. + * Deprecated in favor of 'customElementsGroup' + * @default false + * @deprecated Use 'customElementsGroup' instead. + */ + isBaseStyle?: boolean; } /** From df48bbbec2a98cc07ae24b5091d7300be6cf9208 Mon Sep 17 00:00:00 2001 From: Vitalie Braga Date: Wed, 16 May 2018 13:18:09 -0700 Subject: [PATCH 13/32] Brings logic for RTL animation. --- .../src/components/Shimmer/Shimmer.styles.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/packages/experiments/src/components/Shimmer/Shimmer.styles.ts b/packages/experiments/src/components/Shimmer/Shimmer.styles.ts index ce244dc005a1c1..b20ff1654fd09a 100644 --- a/packages/experiments/src/components/Shimmer/Shimmer.styles.ts +++ b/packages/experiments/src/components/Shimmer/Shimmer.styles.ts @@ -1,5 +1,6 @@ import { IShimmerStyleProps, IShimmerStyles } from './Shimmer.types'; import { keyframes, DefaultPalette } from '../../Styling'; +import { getRTL } from '../../Utilities'; export function getStyles(props: IShimmerStyleProps): IShimmerStyles { const { @@ -10,6 +11,8 @@ export function getStyles(props: IShimmerStyleProps): IShimmerStyles { className } = props; + const isRTL = getRTL(); + const BACKGROUND_OFF_SCREEN_POSITION = '1000%'; // TODO reduce the logic after the deprecated value will be removed. @@ -27,6 +30,15 @@ export function getStyles(props: IShimmerStyleProps): IShimmerStyles { } }); + const shimmerAnimationRTL: string = keyframes({ + '100%': { + backgroundPosition: `-${BACKGROUND_OFF_SCREEN_POSITION}` + }, + '0%': { + backgroundPosition: BACKGROUND_OFF_SCREEN_POSITION + } + }); + return { root: [ 'ms-Shimmer-container', @@ -51,7 +63,7 @@ export function getStyles(props: IShimmerStyleProps): IShimmerStyles { animationTimingFunction: 'ease-in-out', animationDirection: 'normal', animationIterationCount: 'infinite', - animationName: shimmerAnimation, + animationName: isRTL ? shimmerAnimationRTL : shimmerAnimation, transition: 'opacity 200ms, background 200ms' }, isDataLoaded && { From a536e6cb5617f38557bdb3391345a8d16aa47cb6 Mon Sep 17 00:00:00 2001 From: Vitalie Braga Date: Wed, 16 May 2018 13:59:47 -0700 Subject: [PATCH 14/32] Introduces @customizable decorator to enable custom theming of the colors. --- .../src/components/Shimmer/Shimmer.base.tsx | 13 +++- .../src/components/Shimmer/Shimmer.styles.ts | 68 +++++++++++-------- .../src/components/Shimmer/Shimmer.types.ts | 8 ++- 3 files changed, 56 insertions(+), 33 deletions(-) diff --git a/packages/experiments/src/components/Shimmer/Shimmer.base.tsx b/packages/experiments/src/components/Shimmer/Shimmer.base.tsx index 28a4c52abef1b3..2b215cf0a45101 100644 --- a/packages/experiments/src/components/Shimmer/Shimmer.base.tsx +++ b/packages/experiments/src/components/Shimmer/Shimmer.base.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { BaseComponent, classNamesFunction } from '../../Utilities'; +import { BaseComponent, classNamesFunction, customizable } from '../../Utilities'; import { IShimmerProps, IShimmerStyleProps, @@ -10,6 +10,7 @@ import { ShimmerElementsGroup } from './ShimmerElementsGroup'; const getClassNames = classNamesFunction(); +@customizable('Shimmer', ['theme']) export class ShimmerBase extends BaseComponent { public static defaultProps: IShimmerProps = { isDataLoaded: false, @@ -44,14 +45,20 @@ export class ShimmerBase extends BaseComponent { widthInPercentage, widthInPixel, className, - customElementsGroup + customElementsGroup, + theme } = this.props; // lineElements is a deprecated prop so need to check which one was used. const elements: IShimmerElement[] | undefined = shimmerElements || lineElements; this._classNames = getClassNames(getStyles!, { - width, isDataLoaded, widthInPercentage, widthInPixel, className + theme: theme!, + width, + isDataLoaded, + widthInPercentage, + widthInPixel, + className }); return ( diff --git a/packages/experiments/src/components/Shimmer/Shimmer.styles.ts b/packages/experiments/src/components/Shimmer/Shimmer.styles.ts index b20ff1654fd09a..42041f00f708d4 100644 --- a/packages/experiments/src/components/Shimmer/Shimmer.styles.ts +++ b/packages/experiments/src/components/Shimmer/Shimmer.styles.ts @@ -1,19 +1,47 @@ import { IShimmerStyleProps, IShimmerStyles } from './Shimmer.types'; -import { keyframes, DefaultPalette } from '../../Styling'; +import { keyframes, getGlobalClassNames } from '../../Styling'; import { getRTL } from '../../Utilities'; +const GlobalClassNames = { + root: 'ms-Shimmer-container', + shimmerWrapper: 'ms-Shimmer-shimmerWrapper', + dataWrapper: 'ms-Shimmer-dataWrapper' +}; + +const BACKGROUND_OFF_SCREEN_POSITION = '1000%'; + +const shimmerAnimation: string = keyframes({ + '0%': { + backgroundPosition: `-${BACKGROUND_OFF_SCREEN_POSITION}` + }, + '100%': { + backgroundPosition: BACKGROUND_OFF_SCREEN_POSITION + } +}); + +const shimmerAnimationRTL: string = keyframes({ + '100%': { + backgroundPosition: `-${BACKGROUND_OFF_SCREEN_POSITION}` + }, + '0%': { + backgroundPosition: BACKGROUND_OFF_SCREEN_POSITION + } +}); + export function getStyles(props: IShimmerStyleProps): IShimmerStyles { const { width, isDataLoaded, widthInPercentage, widthInPixel, - className + className, + theme } = props; - const isRTL = getRTL(); + const { palette } = theme; + const classNames = getGlobalClassNames(GlobalClassNames, theme); - const BACKGROUND_OFF_SCREEN_POSITION = '1000%'; + const isRTL = getRTL(); // TODO reduce the logic after the deprecated value will be removed. const ACTUAL_WIDTH = @@ -21,42 +49,24 @@ export function getStyles(props: IShimmerStyleProps): IShimmerStyles { widthInPercentage ? widthInPercentage + '%' : widthInPixel ? widthInPixel + 'px' : '100%'; - const shimmerAnimation: string = keyframes({ - '0%': { - backgroundPosition: `-${BACKGROUND_OFF_SCREEN_POSITION}` - }, - '100%': { - backgroundPosition: BACKGROUND_OFF_SCREEN_POSITION - } - }); - - const shimmerAnimationRTL: string = keyframes({ - '100%': { - backgroundPosition: `-${BACKGROUND_OFF_SCREEN_POSITION}` - }, - '0%': { - backgroundPosition: BACKGROUND_OFF_SCREEN_POSITION - } - }); - return { root: [ - 'ms-Shimmer-container', + classNames.root, { position: 'relative', }, className ], shimmerWrapper: [ - 'ms-Shimmer-shimmerWrapper', + classNames.shimmerWrapper, { width: ACTUAL_WIDTH, - background: `${DefaultPalette.neutralLighter} + background: `${palette.neutralLighter} linear-gradient( to right, - ${DefaultPalette.neutralLighter} 0%, - ${DefaultPalette.neutralLight} 50%, - ${DefaultPalette.neutralLighter} 100%) + ${palette.neutralLighter} 0%, + ${palette.neutralLight} 50%, + ${palette.neutralLighter} 100%) 0 0 / 90% 100% no-repeat`, animationDuration: '2s', @@ -72,7 +82,7 @@ export function getStyles(props: IShimmerStyleProps): IShimmerStyles { } ], dataWrapper: [ - 'ms-Shimmer-dataWrapper', + classNames.dataWrapper, { position: 'absolute', top: '0', diff --git a/packages/experiments/src/components/Shimmer/Shimmer.types.ts b/packages/experiments/src/components/Shimmer/Shimmer.types.ts index 657b6698c3b278..b447401941e9e8 100644 --- a/packages/experiments/src/components/Shimmer/Shimmer.types.ts +++ b/packages/experiments/src/components/Shimmer/Shimmer.types.ts @@ -1,5 +1,5 @@ import * as React from 'react'; -import { IStyle } from '../../Styling'; +import { IStyle, ITheme } from '../../Styling'; import { IStyleFunction } from '../../Utilities'; export interface IShimmer { @@ -54,6 +54,11 @@ export interface IShimmerProps extends React.AllHTMLAttributes { */ className?: string; + /** + * Theme provided by High-Order Component. + */ + theme?: ITheme; + /** * Elements to render in one line of the Shimmer. * Deprecated, use 'shimmerElements' for better semantic meaning. @@ -166,6 +171,7 @@ export interface IShimmerStyleProps { widthInPixel?: number; isDataLoaded?: boolean; className?: string; + theme: ITheme; } export interface IShimmerStyles { From 22a23e05a29df4d5fe2a68ae9e01d452637a4134 Mon Sep 17 00:00:00 2001 From: Vitalie Braga Date: Wed, 16 May 2018 15:36:58 -0700 Subject: [PATCH 15/32] Sets an example for getStyles prop. --- .../src/components/Shimmer/ShimmerPage.tsx | 11 ++++ .../examples/Shimmer.Styling.Example.tsx | 51 +++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 packages/experiments/src/components/Shimmer/examples/Shimmer.Styling.Example.tsx diff --git a/packages/experiments/src/components/Shimmer/ShimmerPage.tsx b/packages/experiments/src/components/Shimmer/ShimmerPage.tsx index 9092d58dcd1822..a13a6c8326bfd6 100644 --- a/packages/experiments/src/components/Shimmer/ShimmerPage.tsx +++ b/packages/experiments/src/components/Shimmer/ShimmerPage.tsx @@ -9,6 +9,7 @@ import { ShimmerBasicExample } from './examples/Shimmer.Basic.Example'; import { ShimmerCustomElementsExample } from './examples/Shimmer.CustomElements.Example'; import { ShimmerLoadDataExample } from './examples/Shimmer.LoadData.Example'; import { ShimmerApplicationExample } from './examples/Shimmer.Application.Example'; +import { ShimmerStylingExample } from './examples/Shimmer.Styling.Example'; const ShimmerBasicExampleCode = require( '!raw-loader!@uifabric/experiments/src/components/Shimmer/examples/Shimmer.Basic.Example.tsx' @@ -18,6 +19,10 @@ const ShimmerCustomExampleCode = require( '!raw-loader!@uifabric/experiments/src/components/Shimmer/examples/Shimmer.CustomElements.Example.tsx' ) as string; +const ShimmerStylingExampleCode = require( + '!raw-loader!@uifabric/experiments/src/components/Shimmer/examples/Shimmer.Styling.Example.tsx' +) as string; + const ShimmerLoadDataExampleCode = require( '!raw-loader!@uifabric/experiments/src/components/Shimmer/examples/Shimmer.LoadData.Example.tsx' ) as string; @@ -58,6 +63,12 @@ export class ShimmerPage extends React.Component { > + + +
} propertiesTables={ diff --git a/packages/experiments/src/components/Shimmer/examples/Shimmer.Styling.Example.tsx b/packages/experiments/src/components/Shimmer/examples/Shimmer.Styling.Example.tsx new file mode 100644 index 00000000000000..3fee862b813098 --- /dev/null +++ b/packages/experiments/src/components/Shimmer/examples/Shimmer.Styling.Example.tsx @@ -0,0 +1,51 @@ +import * as React from 'react'; + +import { + Shimmer, IShimmerStyleProps, IShimmerStyles +} from '@uifabric/experiments/lib/Shimmer'; + +import './Shimmer.Example.scss'; + +export class ShimmerStylingExample extends React.Component<{}, {}> { + + constructor(props: {}) { + super(props); + } + + public render(): JSX.Element { + + return ( +
+ + + + + +
+ ); + } + + private _getShimmerStyles = (props: IShimmerStyleProps): IShimmerStyles => { + return { + shimmerWrapper: [{ + backgroundColor: '#deecf9', + backgroundImage: 'linear-gradient(to right, transparent 0%, #c7e0f4 50%, transparent 100%)' + }] + }; + } +} \ No newline at end of file From c2af0ab1f6cd4ac096e07dd5bac26f3d85c89695 Mon Sep 17 00:00:00 2001 From: Vitalie Braga Date: Wed, 16 May 2018 17:08:46 -0700 Subject: [PATCH 16/32] Adds more documentation to Shimmer Page. --- .../src/components/Shimmer/ShimmerPage.tsx | 52 ++++++++++++++++--- .../examples/Shimmer.Application.Example.tsx | 15 +++--- 2 files changed, 53 insertions(+), 14 deletions(-) diff --git a/packages/experiments/src/components/Shimmer/ShimmerPage.tsx b/packages/experiments/src/components/Shimmer/ShimmerPage.tsx index a13a6c8326bfd6..c2c38564a61e94 100644 --- a/packages/experiments/src/components/Shimmer/ShimmerPage.tsx +++ b/packages/experiments/src/components/Shimmer/ShimmerPage.tsx @@ -5,6 +5,7 @@ import { IComponentDemoPageProps, PropertiesTableSet } from '@uifabric/example-app-base'; +import { Link } from 'office-ui-fabric-react/lib/Link'; import { ShimmerBasicExample } from './examples/Shimmer.Basic.Example'; import { ShimmerCustomElementsExample } from './examples/Shimmer.CustomElements.Example'; import { ShimmerLoadDataExample } from './examples/Shimmer.LoadData.Example'; @@ -81,7 +82,22 @@ export class ShimmerPage extends React.Component { overview={

- Shimmer is a temporary animation placeholder for the upcoming data from an API call + Shimmer is a temporary animation placeholder for when data from the service call takes time to get back and we don't want + to block rendering the rest of the UI. +

+

+ When Shimmer is not wrapping the actual component to be rendered when data is + fetched, shimmerElements or customElementsGroup props should be used, and later just replace the + Shimmer UI with the intended content. Otherwise, if smooth transition from Shimmer UI to content is wanted, wrap the content + nodewith Shimmer tags and use isDataLoaded prop to trigger the transition. For reference use the examples + provided below. +

+

+ For cases when your application supports theming, Shimmer component is equiped with everything you need to just load the + custom theme to the application, and as long as the color palette you provide has an overried for the + two Fabric colors, + everything should be ok. If no theming is supported, then follow the example showing the use of + the getStyles prop.

} @@ -92,12 +108,26 @@ export class ShimmerPage extends React.Component {
  • - When construncting a shimmer line using different elements like Circle, Line or Gap, best if providing widths for each - of them to experience a better layout looking as close as possible to real data it is replacing. + Use shimmer to help ease a UI transition when we know the service will potentially take a longer amount of time to retrieve + the data. +
  • +
  • + Provide widths for each of the shimmer elements you used to build a skeleton layout looking as close as possible to real + content it is replacing. +
  • +
  • + Use isDataLoaded prop to trigger the transition once we have the data from the service. + The Shimmer UI should Fade out while the real UI Fades In. +
  • +
  • + Use shimmer if you know the UI loading time is longer than 1 second. +
  • +
  • + Provide an ETA as quickly as possible to help the user understand that the system isn’t broken if you use shimmer and the + delay is longer than 10 seconds you must.
  • - Try avoiding multiple shimmer lines of different widths. Each shimmer line is it's own animation and it is dependent on the - width you provide. So for a better visual animation keep the widths consistent. + Provide shimmer designs for the breakpoints that your experience is supported in.
@@ -106,7 +136,17 @@ export class ShimmerPage extends React.Component {
  • - Do not try using on the same element both types of widths. It will always default to just one of them. + Use on the same element both types of widths. It will always default to just one of them. See documentation below. +
  • +
  • + Build Shimmer UI should with a lot of details. Circles and rectangles are really as detailed as you want to get. Adding more + detail will result in confusion once the UI loads. +
  • +
  • + Use shimmer if you are confident that the UI will take less than a second to load. +
  • +
  • + Use shimmer as a way to not make improvements in your code to improve performance.
diff --git a/packages/experiments/src/components/Shimmer/examples/Shimmer.Application.Example.tsx b/packages/experiments/src/components/Shimmer/examples/Shimmer.Application.Example.tsx index 0b722053061eaf..41e56b4b206cda 100644 --- a/packages/experiments/src/components/Shimmer/examples/Shimmer.Application.Example.tsx +++ b/packages/experiments/src/components/Shimmer/examples/Shimmer.Application.Example.tsx @@ -111,15 +111,14 @@ export class ShimmerApplicationExample extends BaseComponent<{}, IShimmerApplica onText='Compact' offText='Normal' /> +
- Toggle the Load data switch to start async simulation. -
Date: Mon, 21 May 2018 11:15:57 -0700 Subject: [PATCH 17/32] Sets up a flag to remove the shimmerWrapper from the flow as soon as the transition animation is done. --- .../src/components/Shimmer/Shimmer.base.tsx | 47 +++++++++++++++++-- .../src/components/Shimmer/Shimmer.styles.ts | 17 +++++-- .../src/components/Shimmer/Shimmer.types.ts | 4 ++ 3 files changed, 61 insertions(+), 7 deletions(-) diff --git a/packages/experiments/src/components/Shimmer/Shimmer.base.tsx b/packages/experiments/src/components/Shimmer/Shimmer.base.tsx index 2b215cf0a45101..96f175761fea1e 100644 --- a/packages/experiments/src/components/Shimmer/Shimmer.base.tsx +++ b/packages/experiments/src/components/Shimmer/Shimmer.base.tsx @@ -1,5 +1,9 @@ import * as React from 'react'; -import { BaseComponent, classNamesFunction, customizable } from '../../Utilities'; +import { + BaseComponent, + classNamesFunction, + customizable +} from '../../Utilities'; import { IShimmerProps, IShimmerStyleProps, @@ -8,18 +12,31 @@ import { } from './Shimmer.types'; import { ShimmerElementsGroup } from './ShimmerElementsGroup'; +export interface IShimmerState { + contentLoaded?: boolean; +} + +const ANIMATION_INTERVAL = 200; /* ms */ + const getClassNames = classNamesFunction(); @customizable('Shimmer', ['theme']) -export class ShimmerBase extends BaseComponent { +export class ShimmerBase extends BaseComponent { public static defaultProps: IShimmerProps = { isDataLoaded: false, isBaseStyle: false }; + private _classNames: { [key in keyof IShimmerStyles]: string }; + private _lastTimeoutId: number | undefined; + constructor(props: IShimmerProps) { super(props); + this.state = { + contentLoaded: props.isDataLoaded + }; + this._warnDeprecations({ 'isBaseStyle': 'customElementsGroup', 'width': 'widthInPercentage or widthInPixel', @@ -33,6 +50,27 @@ export class ShimmerBase extends BaseComponent { }); } + public componentWillReceiveProps(nextProps: IShimmerProps): void { + const { isDataLoaded } = nextProps; + + if (this._lastTimeoutId !== undefined) { + this._async.clearTimeout(this._lastTimeoutId); + this._lastTimeoutId = undefined; + } + if (isDataLoaded) { + this._lastTimeoutId = this._async.setTimeout(() => { + this.setState({ + contentLoaded: isDataLoaded + }); + this._lastTimeoutId = undefined; + }, ANIMATION_INTERVAL); + } else { + this.setState({ + contentLoaded: isDataLoaded + }); + } + } + public render(): JSX.Element { const { getStyles, @@ -49,6 +87,8 @@ export class ShimmerBase extends BaseComponent { theme } = this.props; + const { contentLoaded } = this.state; + // lineElements is a deprecated prop so need to check which one was used. const elements: IShimmerElement[] | undefined = shimmerElements || lineElements; @@ -58,7 +98,8 @@ export class ShimmerBase extends BaseComponent { isDataLoaded, widthInPercentage, widthInPixel, - className + className, + contentLoaded }); return ( diff --git a/packages/experiments/src/components/Shimmer/Shimmer.styles.ts b/packages/experiments/src/components/Shimmer/Shimmer.styles.ts index 42041f00f708d4..a7446962ab5494 100644 --- a/packages/experiments/src/components/Shimmer/Shimmer.styles.ts +++ b/packages/experiments/src/components/Shimmer/Shimmer.styles.ts @@ -35,7 +35,8 @@ export function getStyles(props: IShimmerStyleProps): IShimmerStyles { widthInPercentage, widthInPixel, className, - theme + theme, + contentLoaded } = props; const { palette } = theme; @@ -54,6 +55,7 @@ export function getStyles(props: IShimmerStyleProps): IShimmerStyles { classNames.root, { position: 'relative', + height: 'auto' }, className ], @@ -78,7 +80,14 @@ export function getStyles(props: IShimmerStyleProps): IShimmerStyles { }, isDataLoaded && { opacity: '0', - background: 'none' + position: 'absolute', + top: '0', + bottom: '0', + left: '0', + right: '0', + }, + contentLoaded && { + display: 'none' } ], dataWrapper: [ @@ -90,14 +99,14 @@ export function getStyles(props: IShimmerStyleProps): IShimmerStyles { left: '0', right: '0', opacity: '0', - lineHeight: '1', background: 'none', backgroundColor: 'transparent', border: 'none', transition: 'opacity 200ms' }, isDataLoaded && { - opacity: '1' + opacity: '1', + position: 'static' } ] }; diff --git a/packages/experiments/src/components/Shimmer/Shimmer.types.ts b/packages/experiments/src/components/Shimmer/Shimmer.types.ts index b447401941e9e8..8820d261f3cbb4 100644 --- a/packages/experiments/src/components/Shimmer/Shimmer.types.ts +++ b/packages/experiments/src/components/Shimmer/Shimmer.types.ts @@ -172,6 +172,10 @@ export interface IShimmerStyleProps { isDataLoaded?: boolean; className?: string; theme: ITheme; + /** + * Flag to check when to remove the shimmerWrapper from the flow. + */ + contentLoaded?: boolean; } export interface IShimmerStyles { From 9607b8f9ffc196015b5d623d2531334f341a185f Mon Sep 17 00:00:00 2001 From: Vitalie Braga Date: Mon, 21 May 2018 11:32:25 -0700 Subject: [PATCH 18/32] Adds rounded corners to shimmer lines. --- .../Shimmer/ShimmerLine/ShimmerLine.base.tsx | 17 +++++++- .../Shimmer/ShimmerLine/ShimmerLine.styles.ts | 39 ++++++++++++++++++- .../Shimmer/ShimmerLine/ShimmerLine.types.ts | 4 ++ 3 files changed, 58 insertions(+), 2 deletions(-) diff --git a/packages/experiments/src/components/Shimmer/ShimmerLine/ShimmerLine.base.tsx b/packages/experiments/src/components/Shimmer/ShimmerLine/ShimmerLine.base.tsx index 6fe9ad6c3bfcbe..474410bb88f296 100644 --- a/packages/experiments/src/components/Shimmer/ShimmerLine/ShimmerLine.base.tsx +++ b/packages/experiments/src/components/Shimmer/ShimmerLine/ShimmerLine.base.tsx @@ -24,7 +24,22 @@ export class ShimmerLineBase extends BaseComponent { this._classNames = getClassNames(getStyles!, { height, widthInPixel, widthInPercentage, borderStyle }); return ( -
+
+ + + + + + + + + + + + +
); } } \ No newline at end of file diff --git a/packages/experiments/src/components/Shimmer/ShimmerLine/ShimmerLine.styles.ts b/packages/experiments/src/components/Shimmer/ShimmerLine/ShimmerLine.styles.ts index 3025743b7437bd..ffae2a8011d0f2 100644 --- a/packages/experiments/src/components/Shimmer/ShimmerLine/ShimmerLine.styles.ts +++ b/packages/experiments/src/components/Shimmer/ShimmerLine/ShimmerLine.styles.ts @@ -2,7 +2,7 @@ import { IShimmerLineStyleProps, IShimmerLineStyles } from './ShimmerLine.types'; -import { IStyleSet } from '../../../Styling'; +import { IStyleSet, DefaultPalette } from '../../../Styling'; export function getStyles(props: IShimmerLineStyleProps): IShimmerLineStyles { const { @@ -22,8 +22,45 @@ export function getStyles(props: IShimmerLineStyleProps): IShimmerLineStyles { width: ACTUAL_WIDTH, height: `${height}px`, boxSizing: 'content-box', + position: 'relative' }, styles + ], + topLeftCorner: [ + 'ms-ShimmerLine-topLeftCorner', + { + position: 'absolute', + top: '0', + left: '0', + fill: `${DefaultPalette.white}` + } + ], + topRightCorner: [ + 'ms-ShimmerLine-topRightCorner', + { + position: 'absolute', + top: '0', + right: '0', + fill: `${DefaultPalette.white}` + } + ], + bottomRightCorner: [ + 'ms-ShimmerLine-bottomRightCorner', + { + position: 'absolute', + bottom: '0', + right: '0', + fill: `${DefaultPalette.white}` + } + ], + bottomLeftCorner: [ + 'ms-ShimmerLine-bottomLeftCorner', + { + position: 'absolute', + bottom: '0', + left: '0', + fill: `${DefaultPalette.white}` + } ] }; } diff --git a/packages/experiments/src/components/Shimmer/ShimmerLine/ShimmerLine.types.ts b/packages/experiments/src/components/Shimmer/ShimmerLine/ShimmerLine.types.ts index c37742f5269f53..fca95a42ea98f3 100644 --- a/packages/experiments/src/components/Shimmer/ShimmerLine/ShimmerLine.types.ts +++ b/packages/experiments/src/components/Shimmer/ShimmerLine/ShimmerLine.types.ts @@ -54,4 +54,8 @@ export interface IShimmerLineStyleProps { export interface IShimmerLineStyles { root?: IStyle; + topLeftCorner?: IStyle; + topRightCorner?: IStyle; + bottomRightCorner?: IStyle; + bottomLeftCorner?: IStyle; } \ No newline at end of file From 61356d3f3d97ff43aed404c160cee3bc10dd1f94 Mon Sep 17 00:00:00 2001 From: Vitalie Braga Date: Mon, 21 May 2018 14:45:30 -0700 Subject: [PATCH 19/32] More refactor :) --- .../src/components/Shimmer/Shimmer.base.tsx | 32 +++++++++++-------- .../src/components/Shimmer/Shimmer.styles.ts | 9 ++---- .../src/components/Shimmer/Shimmer.types.ts | 5 +-- .../src/components/Shimmer/ShimmerPage.tsx | 10 +++--- .../examples/Shimmer.LoadData.Example.tsx | 4 ++- 5 files changed, 30 insertions(+), 30 deletions(-) diff --git a/packages/experiments/src/components/Shimmer/Shimmer.base.tsx b/packages/experiments/src/components/Shimmer/Shimmer.base.tsx index 96f175761fea1e..a8b7724ad69ec0 100644 --- a/packages/experiments/src/components/Shimmer/Shimmer.base.tsx +++ b/packages/experiments/src/components/Shimmer/Shimmer.base.tsx @@ -13,10 +13,13 @@ import { import { ShimmerElementsGroup } from './ShimmerElementsGroup'; export interface IShimmerState { + /** + * Flag for knowing when to remove the shimmerWrapper from the DOM. + */ contentLoaded?: boolean; } -const ANIMATION_INTERVAL = 200; /* ms */ +const TRANSITION_ANIMATION_INTERVAL = 200; /* ms */ const getClassNames = classNamesFunction(); @@ -44,7 +47,6 @@ export class ShimmerBase extends BaseComponent { }); this._warnMutuallyExclusive({ - 'widthInPixel': 'widthInPercentage', 'lineElements': 'shimmerElements', 'customElementsGroup': 'lineElements' }); @@ -63,7 +65,7 @@ export class ShimmerBase extends BaseComponent { contentLoaded: isDataLoaded }); this._lastTimeoutId = undefined; - }, ANIMATION_INTERVAL); + }, TRANSITION_ANIMATION_INTERVAL); } else { this.setState({ contentLoaded: isDataLoaded @@ -99,22 +101,24 @@ export class ShimmerBase extends BaseComponent { widthInPercentage, widthInPixel, className, - contentLoaded + transitionAnimationInterval: TRANSITION_ANIMATION_INTERVAL }); return (
-
- { isBaseStyle ? children : // isBaseStyle prop is deprecated and this check needs to be removed in the future - customElementsGroup ? customElementsGroup : - - } -
- { !isBaseStyle && // same in here... this check needs to be removed in the future + { !contentLoaded && +
+ { isBaseStyle ? children : // isBaseStyle prop is deprecated and this check needs to be removed in the future + customElementsGroup ? customElementsGroup : + + } +
+ } + { !isBaseStyle && children && // isBaseStyle prop is deprecated and needs to be removed in the future
- { children ? children : null } + { children }
}
diff --git a/packages/experiments/src/components/Shimmer/Shimmer.styles.ts b/packages/experiments/src/components/Shimmer/Shimmer.styles.ts index a7446962ab5494..b63b8d5a6018a8 100644 --- a/packages/experiments/src/components/Shimmer/Shimmer.styles.ts +++ b/packages/experiments/src/components/Shimmer/Shimmer.styles.ts @@ -36,7 +36,7 @@ export function getStyles(props: IShimmerStyleProps): IShimmerStyles { widthInPixel, className, theme, - contentLoaded + transitionAnimationInterval } = props; const { palette } = theme; @@ -76,7 +76,7 @@ export function getStyles(props: IShimmerStyleProps): IShimmerStyles { animationDirection: 'normal', animationIterationCount: 'infinite', animationName: isRTL ? shimmerAnimationRTL : shimmerAnimation, - transition: 'opacity 200ms, background 200ms' + transition: `opacity ${transitionAnimationInterval}ms` }, isDataLoaded && { opacity: '0', @@ -85,9 +85,6 @@ export function getStyles(props: IShimmerStyleProps): IShimmerStyles { bottom: '0', left: '0', right: '0', - }, - contentLoaded && { - display: 'none' } ], dataWrapper: [ @@ -102,7 +99,7 @@ export function getStyles(props: IShimmerStyleProps): IShimmerStyles { background: 'none', backgroundColor: 'transparent', border: 'none', - transition: 'opacity 200ms' + transition: `opacity ${transitionAnimationInterval}ms` }, isDataLoaded && { opacity: '1', diff --git a/packages/experiments/src/components/Shimmer/Shimmer.types.ts b/packages/experiments/src/components/Shimmer/Shimmer.types.ts index 8820d261f3cbb4..7710118eecabe6 100644 --- a/packages/experiments/src/components/Shimmer/Shimmer.types.ts +++ b/packages/experiments/src/components/Shimmer/Shimmer.types.ts @@ -172,10 +172,7 @@ export interface IShimmerStyleProps { isDataLoaded?: boolean; className?: string; theme: ITheme; - /** - * Flag to check when to remove the shimmerWrapper from the flow. - */ - contentLoaded?: boolean; + transitionAnimationInterval?: number; } export interface IShimmerStyles { diff --git a/packages/experiments/src/components/Shimmer/ShimmerPage.tsx b/packages/experiments/src/components/Shimmer/ShimmerPage.tsx index c2c38564a61e94..162fd2f2099316 100644 --- a/packages/experiments/src/components/Shimmer/ShimmerPage.tsx +++ b/packages/experiments/src/components/Shimmer/ShimmerPage.tsx @@ -86,17 +86,17 @@ export class ShimmerPage extends React.Component { to block rendering the rest of the UI.

- When Shimmer is not wrapping the actual component to be rendered when data is - fetched, shimmerElements or customElementsGroup props should be used, and later just replace the + When Shimmer is not wrapping the actual component to be rendered while data is + fetching, shimmerElements or customElementsGroup props should be used, and later just replace the Shimmer UI with the intended content. Otherwise, if smooth transition from Shimmer UI to content is wanted, wrap the content - nodewith Shimmer tags and use isDataLoaded prop to trigger the transition. For reference use the examples + node with Shimmer tags and use isDataLoaded prop to trigger the transition. For reference use the examples provided below.

For cases when your application supports theming, Shimmer component is equiped with everything you need to just load the custom theme to the application, and as long as the color palette you provide has an overried for the - two Fabric colors, - everything should be ok. If no theming is supported, then follow the example showing the use of + two Fabric colors used in + Shimmer, everything should be ok. If no theming is supported, then follow the example showing the use of the getStyles prop.

diff --git a/packages/experiments/src/components/Shimmer/examples/Shimmer.LoadData.Example.tsx b/packages/experiments/src/components/Shimmer/examples/Shimmer.LoadData.Example.tsx index 267735800625c7..c3b7d93d2632fc 100644 --- a/packages/experiments/src/components/Shimmer/examples/Shimmer.LoadData.Example.tsx +++ b/packages/experiments/src/components/Shimmer/examples/Shimmer.LoadData.Example.tsx @@ -56,7 +56,9 @@ export class ShimmerLoadDataExample extends React.Component<{}, IShimmerLoadData style={ { overflow: 'hidden', textOverflow: 'ellipsis', - whiteSpace: 'nowrap' + whiteSpace: 'nowrap', + lineHeight: '1', + minHeight: '16px' // Default height of Shimmer when no elements being provided. } } > { contentOne } From a063dd2b4a2f31bf4ecca1a902aa4fb124780032 Mon Sep 17 00:00:00 2001 From: Vitalie Braga Date: Mon, 21 May 2018 15:03:33 -0700 Subject: [PATCH 20/32] Clears a timeout for application example. --- .../Shimmer/examples/Shimmer.Application.Example.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/experiments/src/components/Shimmer/examples/Shimmer.Application.Example.tsx b/packages/experiments/src/components/Shimmer/examples/Shimmer.Application.Example.tsx index 41e56b4b206cda..517e8fe881af22 100644 --- a/packages/experiments/src/components/Shimmer/examples/Shimmer.Application.Example.tsx +++ b/packages/experiments/src/components/Shimmer/examples/Shimmer.Application.Example.tsx @@ -71,6 +71,7 @@ export interface IShimmerApplicationExampleState { export class ShimmerApplicationExample extends BaseComponent<{}, IShimmerApplicationExampleState> { private _isFetchingItems: boolean; + private _lastTimeoutId: number; constructor(props: {}) { super(props); @@ -157,7 +158,7 @@ export class ShimmerApplicationExample extends BaseComponent<{}, IShimmerApplica index = Math.floor(index / ITEMS_BATCH_SIZE) * ITEMS_BATCH_SIZE; if (!this._isFetchingItems) { this._isFetchingItems = true; - setTimeout(() => { + this._lastTimeoutId = this._async.setTimeout(() => { this._isFetchingItems = false; // tslint:disable-next-line:no-any const itemsCopy = ([] as any[]).concat(this.state.items); @@ -183,6 +184,7 @@ export class ShimmerApplicationExample extends BaseComponent<{}, IShimmerApplica items = _items.slice(0, ITEMS_BATCH_SIZE).concat(new Array(ITEMS_COUNT - ITEMS_BATCH_SIZE)); } else { items = new Array(); + this._async.clearTimeout(this._lastTimeoutId); } this.setState({ isDataLoaded: checked, From 4a261d1a673b446965c9b0e293b2d1d7020d30a3 Mon Sep 17 00:00:00 2001 From: Vitalie Braga Date: Mon, 21 May 2018 16:45:23 -0700 Subject: [PATCH 21/32] Adds accessibility capabilities for screenreaders. --- .../src/components/Shimmer/Shimmer.base.tsx | 13 +++++++++++-- .../src/components/Shimmer/Shimmer.styles.ts | 5 +++-- .../src/components/Shimmer/Shimmer.types.ts | 6 ++++++ .../Shimmer/examples/Shimmer.LoadData.Example.tsx | 1 + 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/packages/experiments/src/components/Shimmer/Shimmer.base.tsx b/packages/experiments/src/components/Shimmer/Shimmer.base.tsx index a8b7724ad69ec0..c391c8cd2003ca 100644 --- a/packages/experiments/src/components/Shimmer/Shimmer.base.tsx +++ b/packages/experiments/src/components/Shimmer/Shimmer.base.tsx @@ -2,7 +2,8 @@ import * as React from 'react'; import { BaseComponent, classNamesFunction, - customizable + customizable, + DelayedRender } from '../../Utilities'; import { IShimmerProps, @@ -86,7 +87,8 @@ export class ShimmerBase extends BaseComponent { widthInPixel, className, customElementsGroup, - theme + theme, + ariaLabel } = this.props; const { contentLoaded } = this.state; @@ -121,6 +123,13 @@ export class ShimmerBase extends BaseComponent { { children }
} + { ariaLabel && !isDataLoaded && +
+ +
{ ariaLabel }
+
+
+ }
); } diff --git a/packages/experiments/src/components/Shimmer/Shimmer.styles.ts b/packages/experiments/src/components/Shimmer/Shimmer.styles.ts index b63b8d5a6018a8..aaf5b499523a3e 100644 --- a/packages/experiments/src/components/Shimmer/Shimmer.styles.ts +++ b/packages/experiments/src/components/Shimmer/Shimmer.styles.ts @@ -1,5 +1,5 @@ import { IShimmerStyleProps, IShimmerStyles } from './Shimmer.types'; -import { keyframes, getGlobalClassNames } from '../../Styling'; +import { keyframes, getGlobalClassNames, hiddenContentStyle } from '../../Styling'; import { getRTL } from '../../Utilities'; const GlobalClassNames = { @@ -105,6 +105,7 @@ export function getStyles(props: IShimmerStyleProps): IShimmerStyles { opacity: '1', position: 'static' } - ] + ], + screenReaderText: hiddenContentStyle }; } diff --git a/packages/experiments/src/components/Shimmer/Shimmer.types.ts b/packages/experiments/src/components/Shimmer/Shimmer.types.ts index 7710118eecabe6..c1d5211784c44d 100644 --- a/packages/experiments/src/components/Shimmer/Shimmer.types.ts +++ b/packages/experiments/src/components/Shimmer/Shimmer.types.ts @@ -44,6 +44,11 @@ export interface IShimmerProps extends React.AllHTMLAttributes { */ customElementsGroup?: React.ReactNode; + /** + * Localized string of the status label for screen reader + */ + ariaLabel?: string; + /** * Call to provide customized styling that will layer on top of the variant rules. */ @@ -179,6 +184,7 @@ export interface IShimmerStyles { root?: IStyle; shimmerWrapper?: IStyle; dataWrapper?: IStyle; + screenReaderText?: IStyle; } export enum ShimmerElementType { diff --git a/packages/experiments/src/components/Shimmer/examples/Shimmer.LoadData.Example.tsx b/packages/experiments/src/components/Shimmer/examples/Shimmer.LoadData.Example.tsx index c3b7d93d2632fc..86fcbdea4ee408 100644 --- a/packages/experiments/src/components/Shimmer/examples/Shimmer.LoadData.Example.tsx +++ b/packages/experiments/src/components/Shimmer/examples/Shimmer.LoadData.Example.tsx @@ -51,6 +51,7 @@ export class ShimmerLoadDataExample extends React.Component<{}, IShimmerLoadData />
Date: Mon, 21 May 2018 18:07:05 -0700 Subject: [PATCH 22/32] Refactors some highContrast styling. Refactors common styles in ShimmerLine.styles --- .../src/components/Shimmer/Shimmer.styles.ts | 16 +++++++-- .../Shimmer/ShimmerLine/ShimmerLine.styles.ts | 33 ++++++++++--------- 2 files changed, 30 insertions(+), 19 deletions(-) diff --git a/packages/experiments/src/components/Shimmer/Shimmer.styles.ts b/packages/experiments/src/components/Shimmer/Shimmer.styles.ts index aaf5b499523a3e..99f475549e469e 100644 --- a/packages/experiments/src/components/Shimmer/Shimmer.styles.ts +++ b/packages/experiments/src/components/Shimmer/Shimmer.styles.ts @@ -1,5 +1,10 @@ import { IShimmerStyleProps, IShimmerStyles } from './Shimmer.types'; -import { keyframes, getGlobalClassNames, hiddenContentStyle } from '../../Styling'; +import { + keyframes, + getGlobalClassNames, + hiddenContentStyle, + HighContrastSelector +} from '../../Styling'; import { getRTL } from '../../Utilities'; const GlobalClassNames = { @@ -39,7 +44,7 @@ export function getStyles(props: IShimmerStyleProps): IShimmerStyles { transitionAnimationInterval } = props; - const { palette } = theme; + const { palette, semanticColors } = theme; const classNames = getGlobalClassNames(GlobalClassNames, theme); const isRTL = getRTL(); @@ -76,7 +81,12 @@ export function getStyles(props: IShimmerStyleProps): IShimmerStyles { animationDirection: 'normal', animationIterationCount: 'infinite', animationName: isRTL ? shimmerAnimationRTL : shimmerAnimation, - transition: `opacity ${transitionAnimationInterval}ms` + transition: `opacity ${transitionAnimationInterval}ms`, + selectors: { + [HighContrastSelector]: { + backgroundColor: semanticColors.bodyText + } + } }, isDataLoaded && { opacity: '0', diff --git a/packages/experiments/src/components/Shimmer/ShimmerLine/ShimmerLine.styles.ts b/packages/experiments/src/components/Shimmer/ShimmerLine/ShimmerLine.styles.ts index ffae2a8011d0f2..2672ba427cae57 100644 --- a/packages/experiments/src/components/Shimmer/ShimmerLine/ShimmerLine.styles.ts +++ b/packages/experiments/src/components/Shimmer/ShimmerLine/ShimmerLine.styles.ts @@ -15,6 +15,11 @@ export function getStyles(props: IShimmerLineStyleProps): IShimmerLineStyles { const styles: IStyleSet = !!borderStyle ? borderStyle : {}; const ACTUAL_WIDTH = widthInPercentage ? widthInPercentage + '%' : widthInPixel ? widthInPixel + 'px' : '100%'; + const sharedCornerStyles: IStyleSet = { + position: 'absolute', + fill: DefaultPalette.white + }; + return { root: [ 'ms-ShimmerLine-root', @@ -29,38 +34,34 @@ export function getStyles(props: IShimmerLineStyleProps): IShimmerLineStyles { topLeftCorner: [ 'ms-ShimmerLine-topLeftCorner', { - position: 'absolute', top: '0', - left: '0', - fill: `${DefaultPalette.white}` - } + left: '0' + }, + sharedCornerStyles ], topRightCorner: [ 'ms-ShimmerLine-topRightCorner', { - position: 'absolute', top: '0', - right: '0', - fill: `${DefaultPalette.white}` - } + right: '0' + }, + sharedCornerStyles ], bottomRightCorner: [ 'ms-ShimmerLine-bottomRightCorner', { - position: 'absolute', bottom: '0', - right: '0', - fill: `${DefaultPalette.white}` - } + right: '0' + }, + sharedCornerStyles ], bottomLeftCorner: [ 'ms-ShimmerLine-bottomLeftCorner', { - position: 'absolute', bottom: '0', - left: '0', - fill: `${DefaultPalette.white}` - } + left: '0' + }, + sharedCornerStyles ] }; } From 074a924a28c027cf9ca4fe6c2e2cc7926cda8a42 Mon Sep 17 00:00:00 2001 From: Vitalie Braga Date: Mon, 21 May 2018 18:54:13 -0700 Subject: [PATCH 23/32] Modularize ShimmerElementsGroup --- .../src/components/Shimmer/Shimmer.base.tsx | 2 +- .../Shimmer/ShimmerElementsGroup.tsx | 141 ----------------- .../ShimmerElementsGroup.base.tsx | 142 ++++++++++++++++++ .../ShimmerElementsGroup.styles.ts | 23 +++ .../ShimmerElementsGroup.tsx | 13 ++ .../ShimmerElementsGroup.types.ts | 53 +++++++ .../Shimmer/ShimmerTile/ShimmerTile.base.tsx | 2 +- .../src/components/Shimmer/index.ts | 2 +- .../examples/TilesList.Document.Example.tsx | 2 +- 9 files changed, 235 insertions(+), 145 deletions(-) delete mode 100644 packages/experiments/src/components/Shimmer/ShimmerElementsGroup.tsx create mode 100644 packages/experiments/src/components/Shimmer/ShimmerElementsGroup/ShimmerElementsGroup.base.tsx create mode 100644 packages/experiments/src/components/Shimmer/ShimmerElementsGroup/ShimmerElementsGroup.styles.ts create mode 100644 packages/experiments/src/components/Shimmer/ShimmerElementsGroup/ShimmerElementsGroup.tsx create mode 100644 packages/experiments/src/components/Shimmer/ShimmerElementsGroup/ShimmerElementsGroup.types.ts diff --git a/packages/experiments/src/components/Shimmer/Shimmer.base.tsx b/packages/experiments/src/components/Shimmer/Shimmer.base.tsx index c391c8cd2003ca..f6bd841131d5a6 100644 --- a/packages/experiments/src/components/Shimmer/Shimmer.base.tsx +++ b/packages/experiments/src/components/Shimmer/Shimmer.base.tsx @@ -11,7 +11,7 @@ import { IShimmerStyles, IShimmerElement, } from './Shimmer.types'; -import { ShimmerElementsGroup } from './ShimmerElementsGroup'; +import { ShimmerElementsGroup } from './ShimmerElementsGroup/ShimmerElementsGroup'; export interface IShimmerState { /** diff --git a/packages/experiments/src/components/Shimmer/ShimmerElementsGroup.tsx b/packages/experiments/src/components/Shimmer/ShimmerElementsGroup.tsx deleted file mode 100644 index 151e40def611c6..00000000000000 --- a/packages/experiments/src/components/Shimmer/ShimmerElementsGroup.tsx +++ /dev/null @@ -1,141 +0,0 @@ -import * as React from 'react'; - -import { DefaultPalette, IStyleSet } from '../../Styling'; -import { - ShimmerElementType, - ShimmerElementVerticalAlign, - ShimmerElementsDefaultHeights, - IShimmerElement -} from './Shimmer.types'; -import { ShimmerLine } from './ShimmerLine/ShimmerLine'; -import { ShimmerGap } from './ShimmerGap/ShimmerGap'; -import { ShimmerCircle } from './ShimmerCircle/ShimmerCircle'; - -export interface IShimmerElementsGroupProps { - shimmerElements?: IShimmerElement[]; - rowHeight?: number; - flexWrap?: boolean; - width?: string; -} - -export type ShimmerElementsGroup = React.StatelessComponent; - -export const ShimmerElementsGroup: ShimmerElementsGroup = (props: IShimmerElementsGroupProps): JSX.Element => { - const { - shimmerElements, - rowHeight, - flexWrap = false, - width - } = props; - const height = rowHeight ? rowHeight : findMaxElementHeight(shimmerElements ? shimmerElements : []); - - return ( -
- { getRenderedElements(shimmerElements, height) } -
- ); -}; - -function getRenderedElements(shimmerElements?: IShimmerElement[], rowHeight?: number): React.ReactNode { - const renderedElements: React.ReactNode = shimmerElements ? - shimmerElements.map((elem: IShimmerElement, index: number): JSX.Element => { - const { type, ...filteredElem } = elem; - switch (elem.type) { - case ShimmerElementType.circle: - return ( - - ); - case ShimmerElementType.gap: - return ( - - ); - case ShimmerElementType.line: - return ( - - ); - } - }) : ( - - ); - - return renderedElements; -} - -function getBorderStyles(elem: IShimmerElement, rowHeight?: number): IStyleSet | undefined { - const elemHeight: number | undefined = elem.height; - - const dif: number = rowHeight && elemHeight ? rowHeight - elemHeight : 0; - - let borderStyle: IStyleSet | undefined; - - if (!elem.verticalAlign || elem.verticalAlign === ShimmerElementVerticalAlign.center) { - borderStyle = { - borderBottom: `${dif ? Math.floor(dif / 2) : 0}px solid ${DefaultPalette.white}`, - borderTop: `${dif ? Math.ceil(dif / 2) : 0}px solid ${DefaultPalette.white}` - }; - } else if (elem.verticalAlign && elem.verticalAlign === ShimmerElementVerticalAlign.top) { - borderStyle = { - borderBottom: `${dif ? dif : 0}px solid ${DefaultPalette.white}`, - borderTop: `0px solid ${DefaultPalette.white}` - }; - } else if (elem.verticalAlign && elem.verticalAlign === ShimmerElementVerticalAlign.bottom) { - borderStyle = { - borderBottom: `0px solid ${DefaultPalette.white}`, - borderTop: `${dif ? dif : 0}px solid ${DefaultPalette.white}` - }; - } - - return borderStyle; -} - -// User should not worry to provide which of the elements is the highest, we do the calculation for him. -export function findMaxElementHeight(elements: IShimmerElement[]): number { - const itemsDefaulted: IShimmerElement[] = elements.map((elem: IShimmerElement): IShimmerElement => { - switch (elem.type) { - case ShimmerElementType.circle: - if (!elem.height) { - elem.height = ShimmerElementsDefaultHeights.circle; - } - case ShimmerElementType.line: - if (!elem.height) { - elem.height = ShimmerElementsDefaultHeights.line; - } - case ShimmerElementType.gap: - if (!elem.height) { - elem.height = ShimmerElementsDefaultHeights.gap; - } - } - return elem; - }); - - const rowHeight = itemsDefaulted.reduce((acc: number, next: IShimmerElement): number => { - return next.height ? - next.height > acc ? next.height : acc - : acc; - }, 0); - - return rowHeight; -} \ No newline at end of file diff --git a/packages/experiments/src/components/Shimmer/ShimmerElementsGroup/ShimmerElementsGroup.base.tsx b/packages/experiments/src/components/Shimmer/ShimmerElementsGroup/ShimmerElementsGroup.base.tsx new file mode 100644 index 00000000000000..19a66472a8e87d --- /dev/null +++ b/packages/experiments/src/components/Shimmer/ShimmerElementsGroup/ShimmerElementsGroup.base.tsx @@ -0,0 +1,142 @@ +import * as React from 'react'; + +import { + BaseComponent, + classNamesFunction, +} from '../../../Utilities'; +import { + IShimmerElementsGroupProps, + IShimmerElementsGroupStyleProps, + IShimmerElementsGroupStyles +} from './ShimmerElementsGroup.types'; +import { DefaultPalette, IStyleSet } from '../../../Styling'; +import { + ShimmerElementType, + ShimmerElementVerticalAlign, + ShimmerElementsDefaultHeights, + IShimmerElement +} from '../Shimmer.types'; +import { ShimmerLine } from '../ShimmerLine/ShimmerLine'; +import { ShimmerGap } from '../ShimmerGap/ShimmerGap'; +import { ShimmerCircle } from '../ShimmerCircle/ShimmerCircle'; + +const getClassNames = classNamesFunction(); + +export class ShimmerElementsGroupBase extends BaseComponent { + private _classNames: { [key in keyof IShimmerElementsGroupStyles]: string }; + + constructor(props: IShimmerElementsGroupProps) { + super(props); + } + + // User should not worry to provide which of the elements is the highest, we do the calculation for him. + public findMaxElementHeight = (elements: IShimmerElement[]): number => { + const itemsDefaulted: IShimmerElement[] = elements.map((elem: IShimmerElement): IShimmerElement => { + switch (elem.type) { + case ShimmerElementType.circle: + if (!elem.height) { + elem.height = ShimmerElementsDefaultHeights.circle; + } + case ShimmerElementType.line: + if (!elem.height) { + elem.height = ShimmerElementsDefaultHeights.line; + } + case ShimmerElementType.gap: + if (!elem.height) { + elem.height = ShimmerElementsDefaultHeights.gap; + } + } + return elem; + }); + + const rowHeight = itemsDefaulted.reduce((acc: number, next: IShimmerElement): number => { + return next.height ? + next.height > acc ? next.height : acc + : acc; + }, 0); + + return rowHeight; + } + + public render(): JSX.Element { + const { getStyles, width, shimmerElements, rowHeight, flexWrap } = this.props; + + this._classNames = getClassNames(getStyles!, { flexWrap, width }); + + const height = rowHeight ? rowHeight : this.findMaxElementHeight(shimmerElements ? shimmerElements : []); + + return ( +
+ { this._getRenderedElements(shimmerElements, height) } +
+ ); + } + + private _getRenderedElements = (shimmerElements?: IShimmerElement[], rowHeight?: number): React.ReactNode => { + const renderedElements: React.ReactNode = shimmerElements ? + shimmerElements.map((elem: IShimmerElement, index: number): JSX.Element => { + const { type, ...filteredElem } = elem; + switch (elem.type) { + case ShimmerElementType.circle: + return ( + + ); + case ShimmerElementType.gap: + return ( + + ); + case ShimmerElementType.line: + return ( + + ); + } + }) : ( + + ); + + return renderedElements; + } + + private _getBorderStyles = (elem: IShimmerElement, rowHeight?: number): IStyleSet | undefined => { + const elemHeight: number | undefined = elem.height; + + const dif: number = rowHeight && elemHeight ? rowHeight - elemHeight : 0; + + let borderStyle: IStyleSet | undefined; + + if (!elem.verticalAlign || elem.verticalAlign === ShimmerElementVerticalAlign.center) { + borderStyle = { + borderBottom: `${dif ? Math.floor(dif / 2) : 0}px solid ${DefaultPalette.white}`, + borderTop: `${dif ? Math.ceil(dif / 2) : 0}px solid ${DefaultPalette.white}` + }; + } else if (elem.verticalAlign && elem.verticalAlign === ShimmerElementVerticalAlign.top) { + borderStyle = { + borderBottom: `${dif ? dif : 0}px solid ${DefaultPalette.white}`, + borderTop: `0px solid ${DefaultPalette.white}` + }; + } else if (elem.verticalAlign && elem.verticalAlign === ShimmerElementVerticalAlign.bottom) { + borderStyle = { + borderBottom: `0px solid ${DefaultPalette.white}`, + borderTop: `${dif ? dif : 0}px solid ${DefaultPalette.white}` + }; + } + + return borderStyle; + } +} \ No newline at end of file diff --git a/packages/experiments/src/components/Shimmer/ShimmerElementsGroup/ShimmerElementsGroup.styles.ts b/packages/experiments/src/components/Shimmer/ShimmerElementsGroup/ShimmerElementsGroup.styles.ts new file mode 100644 index 00000000000000..93ba4a820606c6 --- /dev/null +++ b/packages/experiments/src/components/Shimmer/ShimmerElementsGroup/ShimmerElementsGroup.styles.ts @@ -0,0 +1,23 @@ +import { + IShimmerElementsGroupStyleProps, + IShimmerElementsGroupStyles +} from './ShimmerElementsGroup.types'; + +export function getStyles(props: IShimmerElementsGroupStyleProps): IShimmerElementsGroupStyles { + const { + width, + flexWrap + } = props; + + return { + root: [ + 'ms-ShimmerElementsGroup-root', + { + display: 'flex', + alignItems: 'center', + flexWrap: flexWrap ? 'wrap' : 'nowrap', + width: width ? width : 'auto' + } + ] + }; +} diff --git a/packages/experiments/src/components/Shimmer/ShimmerElementsGroup/ShimmerElementsGroup.tsx b/packages/experiments/src/components/Shimmer/ShimmerElementsGroup/ShimmerElementsGroup.tsx new file mode 100644 index 00000000000000..ddc92b292c22b9 --- /dev/null +++ b/packages/experiments/src/components/Shimmer/ShimmerElementsGroup/ShimmerElementsGroup.tsx @@ -0,0 +1,13 @@ +import { styled } from '../../../Utilities'; +import { + IShimmerElementsGroupProps, + IShimmerElementsGroupStyleProps, + IShimmerElementsGroupStyles +} from './ShimmerElementsGroup.types'; +import { ShimmerElementsGroupBase } from './ShimmerElementsGroup.base'; +import { getStyles } from './ShimmerElementsGroup.styles'; + +export const ShimmerElementsGroup = styled( + ShimmerElementsGroupBase, + getStyles +); diff --git a/packages/experiments/src/components/Shimmer/ShimmerElementsGroup/ShimmerElementsGroup.types.ts b/packages/experiments/src/components/Shimmer/ShimmerElementsGroup/ShimmerElementsGroup.types.ts new file mode 100644 index 00000000000000..bca3da9b74a32e --- /dev/null +++ b/packages/experiments/src/components/Shimmer/ShimmerElementsGroup/ShimmerElementsGroup.types.ts @@ -0,0 +1,53 @@ +import * as React from 'react'; +import { IStyle } from '../../../Styling'; +import { IStyleFunction } from '../../../Utilities'; +import { IShimmerElement } from '../Shimmer.types'; + +export interface IShimmerElementsGroup { +} + +/** + * ShimmerElementsGroup component props. + */ +export interface IShimmerElementsGroupProps extends React.AllHTMLAttributes { + /** + * Optional callback to access the IShimmerElementsGroup interface. Use this instead of ref for accessing + * the public methods and properties of the component. + */ + componentRef?: (component: IShimmerElementsGroup | null) => void; + + /** + * Optional maximum row height of the shimmerElements container. + */ + rowHeight?: number; + + /** + * Elements to render in one group of the Shimmer. + */ + shimmerElements?: IShimmerElement[]; + + /** + * Optional boolean for enabling flexWrap of the container containing the shimmerElements. + * @default false + */ + flexWrap?: boolean; + + /** + * Optional width for ShimmerElements container. + */ + width?: string; + + /** + * Call to provide customized styling that will layer on top of the variant rules. + */ + getStyles?: IStyleFunction; +} + +export interface IShimmerElementsGroupStyleProps { + flexWrap?: boolean; + width?: string; +} + +export interface IShimmerElementsGroupStyles { + root?: IStyle; +} \ No newline at end of file diff --git a/packages/experiments/src/components/Shimmer/ShimmerTile/ShimmerTile.base.tsx b/packages/experiments/src/components/Shimmer/ShimmerTile/ShimmerTile.base.tsx index aed7236da73533..13b08d12539a98 100644 --- a/packages/experiments/src/components/Shimmer/ShimmerTile/ShimmerTile.base.tsx +++ b/packages/experiments/src/components/Shimmer/ShimmerTile/ShimmerTile.base.tsx @@ -10,7 +10,7 @@ import { } from './ShimmerTile.types'; import { TileLayoutSizes, TileSize } from '../../../Tile'; import { ShimmerGap } from '../ShimmerGap/ShimmerGap'; -import { ShimmerElementsGroup } from '../ShimmerElementsGroup'; +import { ShimmerElementsGroup } from '../ShimmerElementsGroup/ShimmerElementsGroup'; import { ShimmerElementType as ElemType } from '../Shimmer.types'; const enum ShimmerTileLayoutValues { diff --git a/packages/experiments/src/components/Shimmer/index.ts b/packages/experiments/src/components/Shimmer/index.ts index 5e5551bb064c57..88daed3258c1cb 100644 --- a/packages/experiments/src/components/Shimmer/index.ts +++ b/packages/experiments/src/components/Shimmer/index.ts @@ -9,4 +9,4 @@ export * from './ShimmerCircle/ShimmerCircle'; export * from './ShimmerCircle/ShimmerCircle.types'; export * from './ShimmerGap/ShimmerGap'; export * from './ShimmerGap/ShimmerGap.types'; -export * from './ShimmerElementsGroup'; \ No newline at end of file +export * from './ShimmerElementsGroup/ShimmerElementsGroup'; \ No newline at end of file diff --git a/packages/experiments/src/components/TilesList/examples/TilesList.Document.Example.tsx b/packages/experiments/src/components/TilesList/examples/TilesList.Document.Example.tsx index c18fd58244aa0f..1ee4ebd57ab4ba 100644 --- a/packages/experiments/src/components/TilesList/examples/TilesList.Document.Example.tsx +++ b/packages/experiments/src/components/TilesList/examples/TilesList.Document.Example.tsx @@ -24,8 +24,8 @@ import { ISize } from '@uifabric/experiments/lib/Utilities'; import { ShimmerTile, ShimmerElementType as ElemType, + ShimmerElementsGroup } from '@uifabric/experiments/lib/Shimmer'; -import { ShimmerElementsGroup } from '../../Shimmer/ShimmerElementsGroup'; const HEADER_VERTICAL_PADDING = 13; const HEADER_FONT_SIZE = 18; From 6fcd497d8515695e8bdbd97b1a12a2557a231029 Mon Sep 17 00:00:00 2001 From: Vitalie Braga Date: Tue, 22 May 2018 10:51:01 -0700 Subject: [PATCH 24/32] Customize ShimmerElementsGroup. --- .../ShimmerElementsGroup/ShimmerElementsGroup.base.tsx | 2 ++ .../ShimmerElementsGroup/ShimmerElementsGroup.types.ts | 7 ++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/experiments/src/components/Shimmer/ShimmerElementsGroup/ShimmerElementsGroup.base.tsx b/packages/experiments/src/components/Shimmer/ShimmerElementsGroup/ShimmerElementsGroup.base.tsx index 19a66472a8e87d..5a08f166688661 100644 --- a/packages/experiments/src/components/Shimmer/ShimmerElementsGroup/ShimmerElementsGroup.base.tsx +++ b/packages/experiments/src/components/Shimmer/ShimmerElementsGroup/ShimmerElementsGroup.base.tsx @@ -3,6 +3,7 @@ import * as React from 'react'; import { BaseComponent, classNamesFunction, + customizable, } from '../../../Utilities'; import { IShimmerElementsGroupProps, @@ -22,6 +23,7 @@ import { ShimmerCircle } from '../ShimmerCircle/ShimmerCircle'; const getClassNames = classNamesFunction(); +@customizable('ShimmerElementsGroup', ['theme']) export class ShimmerElementsGroupBase extends BaseComponent { private _classNames: { [key in keyof IShimmerElementsGroupStyles]: string }; diff --git a/packages/experiments/src/components/Shimmer/ShimmerElementsGroup/ShimmerElementsGroup.types.ts b/packages/experiments/src/components/Shimmer/ShimmerElementsGroup/ShimmerElementsGroup.types.ts index bca3da9b74a32e..d37a6a38d7bc32 100644 --- a/packages/experiments/src/components/Shimmer/ShimmerElementsGroup/ShimmerElementsGroup.types.ts +++ b/packages/experiments/src/components/Shimmer/ShimmerElementsGroup/ShimmerElementsGroup.types.ts @@ -1,5 +1,5 @@ import * as React from 'react'; -import { IStyle } from '../../../Styling'; +import { IStyle, ITheme } from '../../../Styling'; import { IStyleFunction } from '../../../Utilities'; import { IShimmerElement } from '../Shimmer.types'; @@ -37,6 +37,11 @@ export interface IShimmerElementsGroupProps extends React.AllHTMLAttributes Date: Tue, 22 May 2018 11:18:38 -0700 Subject: [PATCH 25/32] Refactor mergeStyles pattern in ShimmerElementsGroup --- .../ShimmerElementsGroup.base.tsx | 78 +++++++++++-------- .../ShimmerElementsGroup.styles.ts | 12 ++- .../ShimmerElementsGroup.types.ts | 1 + 3 files changed, 55 insertions(+), 36 deletions(-) diff --git a/packages/experiments/src/components/Shimmer/ShimmerElementsGroup/ShimmerElementsGroup.base.tsx b/packages/experiments/src/components/Shimmer/ShimmerElementsGroup/ShimmerElementsGroup.base.tsx index 5a08f166688661..42117c5f2ca277 100644 --- a/packages/experiments/src/components/Shimmer/ShimmerElementsGroup/ShimmerElementsGroup.base.tsx +++ b/packages/experiments/src/components/Shimmer/ShimmerElementsGroup/ShimmerElementsGroup.base.tsx @@ -1,5 +1,4 @@ import * as React from 'react'; - import { BaseComponent, classNamesFunction, @@ -31,41 +30,23 @@ export class ShimmerElementsGroupBase extends BaseComponent { - const itemsDefaulted: IShimmerElement[] = elements.map((elem: IShimmerElement): IShimmerElement => { - switch (elem.type) { - case ShimmerElementType.circle: - if (!elem.height) { - elem.height = ShimmerElementsDefaultHeights.circle; - } - case ShimmerElementType.line: - if (!elem.height) { - elem.height = ShimmerElementsDefaultHeights.line; - } - case ShimmerElementType.gap: - if (!elem.height) { - elem.height = ShimmerElementsDefaultHeights.gap; - } - } - return elem; - }); - - const rowHeight = itemsDefaulted.reduce((acc: number, next: IShimmerElement): number => { - return next.height ? - next.height > acc ? next.height : acc - : acc; - }, 0); - - return rowHeight; - } - public render(): JSX.Element { - const { getStyles, width, shimmerElements, rowHeight, flexWrap } = this.props; - - this._classNames = getClassNames(getStyles!, { flexWrap, width }); + const { + getStyles, + width, + shimmerElements, + rowHeight, + flexWrap, + theme + } = this.props; + + this._classNames = getClassNames(getStyles!, { + theme: theme!, + flexWrap, + width + }); - const height = rowHeight ? rowHeight : this.findMaxElementHeight(shimmerElements ? shimmerElements : []); + const height = rowHeight ? rowHeight : this._findMaxElementHeight(shimmerElements ? shimmerElements : []); return (
{ + const itemsDefaulted: IShimmerElement[] = elements.map((elem: IShimmerElement): IShimmerElement => { + switch (elem.type) { + case ShimmerElementType.circle: + if (!elem.height) { + elem.height = ShimmerElementsDefaultHeights.circle; + } + case ShimmerElementType.line: + if (!elem.height) { + elem.height = ShimmerElementsDefaultHeights.line; + } + case ShimmerElementType.gap: + if (!elem.height) { + elem.height = ShimmerElementsDefaultHeights.gap; + } + } + return elem; + }); + + const rowHeight = itemsDefaulted.reduce((acc: number, next: IShimmerElement): number => { + return next.height ? + next.height > acc ? next.height : acc + : acc; + }, 0); + + return rowHeight; + } } \ No newline at end of file diff --git a/packages/experiments/src/components/Shimmer/ShimmerElementsGroup/ShimmerElementsGroup.styles.ts b/packages/experiments/src/components/Shimmer/ShimmerElementsGroup/ShimmerElementsGroup.styles.ts index 93ba4a820606c6..ff5fdff5dfde66 100644 --- a/packages/experiments/src/components/Shimmer/ShimmerElementsGroup/ShimmerElementsGroup.styles.ts +++ b/packages/experiments/src/components/Shimmer/ShimmerElementsGroup/ShimmerElementsGroup.styles.ts @@ -2,16 +2,24 @@ import { IShimmerElementsGroupStyleProps, IShimmerElementsGroupStyles } from './ShimmerElementsGroup.types'; +import { getGlobalClassNames } from '../../../Styling'; + +const GlobalClassNames = { + root: 'ms-ShimmerElementsGroup-root' +}; export function getStyles(props: IShimmerElementsGroupStyleProps): IShimmerElementsGroupStyles { const { width, - flexWrap + flexWrap, + theme } = props; + const classNames = getGlobalClassNames(GlobalClassNames, theme); + return { root: [ - 'ms-ShimmerElementsGroup-root', + classNames.root, { display: 'flex', alignItems: 'center', diff --git a/packages/experiments/src/components/Shimmer/ShimmerElementsGroup/ShimmerElementsGroup.types.ts b/packages/experiments/src/components/Shimmer/ShimmerElementsGroup/ShimmerElementsGroup.types.ts index d37a6a38d7bc32..bf93025075367c 100644 --- a/packages/experiments/src/components/Shimmer/ShimmerElementsGroup/ShimmerElementsGroup.types.ts +++ b/packages/experiments/src/components/Shimmer/ShimmerElementsGroup/ShimmerElementsGroup.types.ts @@ -51,6 +51,7 @@ export interface IShimmerElementsGroupProps extends React.AllHTMLAttributes Date: Tue, 22 May 2018 12:55:44 -0700 Subject: [PATCH 26/32] Convert subelements to the new pattern of mergeStyles. --- .../ShimmerCircle/ShimmerCircle.base.tsx | 17 +++++-- .../ShimmerCircle/ShimmerCircle.styles.ts | 40 +++++++++++++--- .../ShimmerCircle/ShimmerCircle.types.ts | 8 +++- .../ShimmerElementsGroup.base.tsx | 6 ++- .../Shimmer/ShimmerGap/ShimmerGap.base.tsx | 21 +++++++-- .../Shimmer/ShimmerGap/ShimmerGap.styles.ts | 33 ++++++++++--- .../Shimmer/ShimmerGap/ShimmerGap.types.ts | 8 +++- .../Shimmer/ShimmerLine/ShimmerLine.base.tsx | 19 +++++++- .../Shimmer/ShimmerLine/ShimmerLine.styles.ts | 46 ++++++++++++++----- .../Shimmer/ShimmerLine/ShimmerLine.types.ts | 8 +++- 10 files changed, 169 insertions(+), 37 deletions(-) diff --git a/packages/experiments/src/components/Shimmer/ShimmerCircle/ShimmerCircle.base.tsx b/packages/experiments/src/components/Shimmer/ShimmerCircle/ShimmerCircle.base.tsx index 273d5d606f440d..bd3d71fdadd8f7 100644 --- a/packages/experiments/src/components/Shimmer/ShimmerCircle/ShimmerCircle.base.tsx +++ b/packages/experiments/src/components/Shimmer/ShimmerCircle/ShimmerCircle.base.tsx @@ -2,6 +2,7 @@ import * as React from 'react'; import { BaseComponent, classNamesFunction, + customizable } from '../../../Utilities'; import { IShimmerCircleProps, @@ -11,16 +12,26 @@ import { const getClassNames = classNamesFunction(); +@customizable('ShimmerCircle', ['theme']) export class ShimmerCircleBase extends BaseComponent { - private _classNames: {[key in keyof IShimmerCircleStyles]: string}; + private _classNames: { [key in keyof IShimmerCircleStyles]: string }; constructor(props: IShimmerCircleProps) { super(props); } public render(): JSX.Element { - const { height, getStyles, borderStyle } = this.props; - this._classNames = getClassNames(getStyles!, { height, borderStyle }); + const { + height, + getStyles, + borderStyle, + theme + } = this.props; + this._classNames = getClassNames(getStyles!, { + theme: theme!, + height, + borderStyle + }); return (
diff --git a/packages/experiments/src/components/Shimmer/ShimmerCircle/ShimmerCircle.styles.ts b/packages/experiments/src/components/Shimmer/ShimmerCircle/ShimmerCircle.styles.ts index 6ca7cf7207b03a..82196af6504f95 100644 --- a/packages/experiments/src/components/Shimmer/ShimmerCircle/ShimmerCircle.styles.ts +++ b/packages/experiments/src/components/Shimmer/ShimmerCircle/ShimmerCircle.styles.ts @@ -2,29 +2,55 @@ import { IShimmerCircleStyleProps, IShimmerCircleStyles } from './ShimmerCircle.types'; -import { IStyleSet, DefaultPalette } from '../../../Styling'; +import { + IStyleSet, + getGlobalClassNames, + HighContrastSelector +} from '../../../Styling'; + +const GlobalClassNames = { + root: 'ms-ShimmerCircle-root', + svg: 'ms-ShimmerCircle-svg' +}; export function getStyles(props: IShimmerCircleStyleProps): IShimmerCircleStyles { const { height, - borderStyle + borderStyle, + theme } = props; + const { palette, semanticColors } = theme; + const classNames = getGlobalClassNames(GlobalClassNames, theme); + const styles: IStyleSet = !!borderStyle ? borderStyle : {}; return { root: [ - 'ms-ShimmerCircle-root', + classNames.root, + styles, { width: `${height}px`, height: `${height}px`, - }, - styles + borderTopStyle: 'solid', + borderBottomStyle: 'solid', + borderColor: palette.white, + selectors: { + [HighContrastSelector]: { + borderColor: semanticColors.bodyBackground + } + } + } ], svg: [ - 'ms-ShimmerCircle-svg', + classNames.svg, { - fill: `${DefaultPalette.white}` + fill: palette.white, + selectors: { + [HighContrastSelector]: { + fill: semanticColors.bodyBackground + } + } } ] }; diff --git a/packages/experiments/src/components/Shimmer/ShimmerCircle/ShimmerCircle.types.ts b/packages/experiments/src/components/Shimmer/ShimmerCircle/ShimmerCircle.types.ts index 9c606d96728a1b..8f7d06d5f5aa01 100644 --- a/packages/experiments/src/components/Shimmer/ShimmerCircle/ShimmerCircle.types.ts +++ b/packages/experiments/src/components/Shimmer/ShimmerCircle/ShimmerCircle.types.ts @@ -1,5 +1,5 @@ import * as React from 'react'; -import { IStyle, IStyleSet } from '../../../Styling'; +import { IStyle, IStyleSet, ITheme } from '../../../Styling'; import { IStyleFunction } from '../../../Utilities'; export interface IShimmerCircle { @@ -27,6 +27,11 @@ export interface IShimmerCircleProps extends React.AllHTMLAttributes { const elemHeight: number | undefined = elem.height; - const dif: number = rowHeight && elemHeight ? rowHeight - elemHeight : 0; let borderStyle: IStyleSet | undefined; @@ -123,7 +122,10 @@ export class ShimmerElementsGroupBase extends BaseComponent { const itemsDefaulted: IShimmerElement[] = elements.map((elem: IShimmerElement): IShimmerElement => { switch (elem.type) { diff --git a/packages/experiments/src/components/Shimmer/ShimmerGap/ShimmerGap.base.tsx b/packages/experiments/src/components/Shimmer/ShimmerGap/ShimmerGap.base.tsx index cbee8e6b743cf9..201225e5897586 100644 --- a/packages/experiments/src/components/Shimmer/ShimmerGap/ShimmerGap.base.tsx +++ b/packages/experiments/src/components/Shimmer/ShimmerGap/ShimmerGap.base.tsx @@ -2,6 +2,7 @@ import * as React from 'react'; import { BaseComponent, classNamesFunction, + customizable } from '../../../Utilities'; import { IShimmerGapProps, @@ -11,17 +12,31 @@ import { const getClassNames = classNamesFunction(); +@customizable('ShimmerGap', ['theme']) export class ShimmerGapBase extends BaseComponent { - private _classNames: {[key in keyof IShimmerGapStyles]: string}; + private _classNames: { [key in keyof IShimmerGapStyles]: string }; constructor(props: IShimmerGapProps) { super(props); } public render(): JSX.Element { - const { height, getStyles, widthInPercentage, widthInPixel, borderStyle } = this.props; + const { + height, + getStyles, + widthInPercentage, + widthInPixel, + borderStyle, + theme + } = this.props; - this._classNames = getClassNames(getStyles!, { height, widthInPixel, widthInPercentage, borderStyle }); + this._classNames = getClassNames(getStyles!, { + theme: theme!, + height, + widthInPixel, + widthInPercentage, + borderStyle + }); return (
diff --git a/packages/experiments/src/components/Shimmer/ShimmerGap/ShimmerGap.styles.ts b/packages/experiments/src/components/Shimmer/ShimmerGap/ShimmerGap.styles.ts index cf5bbfb0842e76..2a3d24b8f0d2ba 100644 --- a/packages/experiments/src/components/Shimmer/ShimmerGap/ShimmerGap.styles.ts +++ b/packages/experiments/src/components/Shimmer/ShimmerGap/ShimmerGap.styles.ts @@ -2,29 +2,50 @@ import { IShimmerGapStyleProps, IShimmerGapStyles } from './ShimmerGap.types'; -import { IStyleSet, DefaultPalette } from '../../../Styling'; +import { + IStyleSet, + getGlobalClassNames, + HighContrastSelector +} from '../../../Styling'; + +const GlobalClassNames = { + root: 'ms-ShimmerGap-root' +}; export function getStyles(props: IShimmerGapStyleProps): IShimmerGapStyles { const { height, widthInPercentage, widthInPixel, - borderStyle + borderStyle, + theme } = props; + const { palette, semanticColors } = theme; + const classNames = getGlobalClassNames(GlobalClassNames, theme); + const styles: IStyleSet = !!borderStyle ? borderStyle : {}; const ACTUAL_WIDTH = widthInPercentage ? widthInPercentage + '%' : widthInPixel ? widthInPixel + 'px' : '10px'; return { root: [ - 'ms-ShimmerGap-root', + classNames.root, + styles, { - backgroundColor: `${DefaultPalette.white}`, + backgroundColor: palette.white, width: ACTUAL_WIDTH, height: `${height}px`, boxSizing: 'content-box', - }, - styles + borderTopStyle: 'solid', + borderBottomStyle: 'solid', + borderColor: palette.white, + selectors: { + [HighContrastSelector]: { + backgroundColor: semanticColors.bodyBackground, + borderColor: semanticColors.bodyBackground + } + } + } ] }; } diff --git a/packages/experiments/src/components/Shimmer/ShimmerGap/ShimmerGap.types.ts b/packages/experiments/src/components/Shimmer/ShimmerGap/ShimmerGap.types.ts index 2c7e0525782a49..543cdcc4ac4425 100644 --- a/packages/experiments/src/components/Shimmer/ShimmerGap/ShimmerGap.types.ts +++ b/packages/experiments/src/components/Shimmer/ShimmerGap/ShimmerGap.types.ts @@ -1,5 +1,5 @@ import * as React from 'react'; -import { IStyle, IStyleSet } from '../../../Styling'; +import { IStyle, IStyleSet, ITheme } from '../../../Styling'; import { IStyleFunction } from '../../../Utilities'; export interface IShimmerGap { @@ -39,6 +39,11 @@ export interface IShimmerGapProps extends React.AllHTMLAttributes { */ borderStyle?: IStyleSet; + /** + * Theme provided by High-Order Component. + */ + theme?: ITheme; + /** * Call to provide customized styling that will layer on top of the variant rules. */ @@ -50,6 +55,7 @@ export interface IShimmerGapStyleProps { widthInPercentage?: number; widthInPixel?: number; borderStyle?: IStyleSet; + theme: ITheme; } export interface IShimmerGapStyles { diff --git a/packages/experiments/src/components/Shimmer/ShimmerLine/ShimmerLine.base.tsx b/packages/experiments/src/components/Shimmer/ShimmerLine/ShimmerLine.base.tsx index 474410bb88f296..169f829f9b836b 100644 --- a/packages/experiments/src/components/Shimmer/ShimmerLine/ShimmerLine.base.tsx +++ b/packages/experiments/src/components/Shimmer/ShimmerLine/ShimmerLine.base.tsx @@ -2,6 +2,7 @@ import * as React from 'react'; import { BaseComponent, classNamesFunction, + customizable } from '../../../Utilities'; import { IShimmerLineProps, @@ -11,6 +12,7 @@ import { const getClassNames = classNamesFunction(); +@customizable('ShimmerLine', ['theme']) export class ShimmerLineBase extends BaseComponent { private _classNames: { [key in keyof IShimmerLineStyles]: string }; @@ -19,9 +21,22 @@ export class ShimmerLineBase extends BaseComponent { } public render(): JSX.Element { - const { height, getStyles, widthInPercentage, widthInPixel, borderStyle } = this.props; + const { + height, + getStyles, + widthInPercentage, + widthInPixel, + borderStyle, + theme + } = this.props; - this._classNames = getClassNames(getStyles!, { height, widthInPixel, widthInPercentage, borderStyle }); + this._classNames = getClassNames(getStyles!, { + theme: theme!, + height, + widthInPixel, + widthInPercentage, + borderStyle + }); return (
*/ borderStyle?: IStyleSet; + /** + * Theme provided by High-Order Component. + */ + theme?: ITheme; + /** * Call to provide customized styling that will layer on top of the variant rules. */ @@ -50,6 +55,7 @@ export interface IShimmerLineStyleProps { widthInPercentage?: number; widthInPixel?: number; borderStyle?: IStyleSet; + theme: ITheme; } export interface IShimmerLineStyles { From 535bd6962c0fc7dcd9b495904d90ffef160fbb1e Mon Sep 17 00:00:00 2001 From: Vitalie Braga Date: Tue, 22 May 2018 14:57:30 -0700 Subject: [PATCH 27/32] Removes some styles. --- .../src/components/Shimmer/Shimmer.styles.ts | 2 +- .../ShimmerElementsGroup.base.tsx | 14 +++++++------- .../Shimmer/ShimmerLine/ShimmerLine.styles.ts | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/experiments/src/components/Shimmer/Shimmer.styles.ts b/packages/experiments/src/components/Shimmer/Shimmer.styles.ts index 99f475549e469e..e83949d770ef49 100644 --- a/packages/experiments/src/components/Shimmer/Shimmer.styles.ts +++ b/packages/experiments/src/components/Shimmer/Shimmer.styles.ts @@ -84,7 +84,7 @@ export function getStyles(props: IShimmerStyleProps): IShimmerStyles { transition: `opacity ${transitionAnimationInterval}ms`, selectors: { [HighContrastSelector]: { - backgroundColor: semanticColors.bodyText + backgroundColor: 'WindowText' } } }, diff --git a/packages/experiments/src/components/Shimmer/ShimmerElementsGroup/ShimmerElementsGroup.base.tsx b/packages/experiments/src/components/Shimmer/ShimmerElementsGroup/ShimmerElementsGroup.base.tsx index 7094bbe8de7617..443c85ae0cbf9f 100644 --- a/packages/experiments/src/components/Shimmer/ShimmerElementsGroup/ShimmerElementsGroup.base.tsx +++ b/packages/experiments/src/components/Shimmer/ShimmerElementsGroup/ShimmerElementsGroup.base.tsx @@ -9,7 +9,7 @@ import { IShimmerElementsGroupStyleProps, IShimmerElementsGroupStyles } from './ShimmerElementsGroup.types'; -import { DefaultPalette, IStyleSet } from '../../../Styling'; +import { IStyleSet } from '../../../Styling'; import { ShimmerElementType, ShimmerElementVerticalAlign, @@ -104,18 +104,18 @@ export class ShimmerElementsGroupBase extends BaseComponent Date: Tue, 22 May 2018 18:12:33 -0700 Subject: [PATCH 28/32] Fixes support for various browsers. High Contrast capability. --- .../src/components/Shimmer/Shimmer.styles.ts | 11 +++++++++-- .../Shimmer/ShimmerCircle/ShimmerCircle.styles.ts | 7 ++++--- .../Shimmer/ShimmerGap/ShimmerGap.styles.ts | 7 ++++--- .../Shimmer/ShimmerLine/ShimmerLine.styles.ts | 5 +++-- .../Shimmer/examples/Shimmer.Styling.Example.tsx | 2 +- 5 files changed, 21 insertions(+), 11 deletions(-) diff --git a/packages/experiments/src/components/Shimmer/Shimmer.styles.ts b/packages/experiments/src/components/Shimmer/Shimmer.styles.ts index e83949d770ef49..66493a4e99cfc5 100644 --- a/packages/experiments/src/components/Shimmer/Shimmer.styles.ts +++ b/packages/experiments/src/components/Shimmer/Shimmer.styles.ts @@ -44,7 +44,7 @@ export function getStyles(props: IShimmerStyleProps): IShimmerStyles { transitionAnimationInterval } = props; - const { palette, semanticColors } = theme; + const { palette } = theme; const classNames = getGlobalClassNames(GlobalClassNames, theme); const isRTL = getRTL(); @@ -84,7 +84,14 @@ export function getStyles(props: IShimmerStyleProps): IShimmerStyles { transition: `opacity ${transitionAnimationInterval}ms`, selectors: { [HighContrastSelector]: { - backgroundColor: 'WindowText' + background: `WindowText + linear-gradient( + to right, + transparent 0%, + Window 50%, + transparent 100%) + 0 0 / 90% 100% + no-repeat` } } }, diff --git a/packages/experiments/src/components/Shimmer/ShimmerCircle/ShimmerCircle.styles.ts b/packages/experiments/src/components/Shimmer/ShimmerCircle/ShimmerCircle.styles.ts index 82196af6504f95..c47f2a7205702f 100644 --- a/packages/experiments/src/components/Shimmer/ShimmerCircle/ShimmerCircle.styles.ts +++ b/packages/experiments/src/components/Shimmer/ShimmerCircle/ShimmerCircle.styles.ts @@ -20,7 +20,7 @@ export function getStyles(props: IShimmerCircleStyleProps): IShimmerCircleStyles theme } = props; - const { palette, semanticColors } = theme; + const { palette } = theme; const classNames = getGlobalClassNames(GlobalClassNames, theme); const styles: IStyleSet = !!borderStyle ? borderStyle : {}; @@ -32,12 +32,13 @@ export function getStyles(props: IShimmerCircleStyleProps): IShimmerCircleStyles { width: `${height}px`, height: `${height}px`, + minWidth: `${height}px`, // Fix for IE11 flex items borderTopStyle: 'solid', borderBottomStyle: 'solid', borderColor: palette.white, selectors: { [HighContrastSelector]: { - borderColor: semanticColors.bodyBackground + borderColor: 'Window' } } } @@ -48,7 +49,7 @@ export function getStyles(props: IShimmerCircleStyleProps): IShimmerCircleStyles fill: palette.white, selectors: { [HighContrastSelector]: { - fill: semanticColors.bodyBackground + fill: 'Window' } } } diff --git a/packages/experiments/src/components/Shimmer/ShimmerGap/ShimmerGap.styles.ts b/packages/experiments/src/components/Shimmer/ShimmerGap/ShimmerGap.styles.ts index 2a3d24b8f0d2ba..c71bb783a9009e 100644 --- a/packages/experiments/src/components/Shimmer/ShimmerGap/ShimmerGap.styles.ts +++ b/packages/experiments/src/components/Shimmer/ShimmerGap/ShimmerGap.styles.ts @@ -21,7 +21,7 @@ export function getStyles(props: IShimmerGapStyleProps): IShimmerGapStyles { theme } = props; - const { palette, semanticColors } = theme; + const { palette } = theme; const classNames = getGlobalClassNames(GlobalClassNames, theme); const styles: IStyleSet = !!borderStyle ? borderStyle : {}; @@ -34,6 +34,7 @@ export function getStyles(props: IShimmerGapStyleProps): IShimmerGapStyles { { backgroundColor: palette.white, width: ACTUAL_WIDTH, + minWidth: widthInPixel ? ACTUAL_WIDTH : 'auto', // Fix for IE11 flex items height: `${height}px`, boxSizing: 'content-box', borderTopStyle: 'solid', @@ -41,8 +42,8 @@ export function getStyles(props: IShimmerGapStyleProps): IShimmerGapStyles { borderColor: palette.white, selectors: { [HighContrastSelector]: { - backgroundColor: semanticColors.bodyBackground, - borderColor: semanticColors.bodyBackground + backgroundColor: 'Window', + borderColor: 'Window' } } } diff --git a/packages/experiments/src/components/Shimmer/ShimmerLine/ShimmerLine.styles.ts b/packages/experiments/src/components/Shimmer/ShimmerLine/ShimmerLine.styles.ts index 5baf2b4edf5f15..b865fa724287e8 100644 --- a/packages/experiments/src/components/Shimmer/ShimmerLine/ShimmerLine.styles.ts +++ b/packages/experiments/src/components/Shimmer/ShimmerLine/ShimmerLine.styles.ts @@ -25,7 +25,7 @@ export function getStyles(props: IShimmerLineStyleProps): IShimmerLineStyles { theme } = props; - const { palette, semanticColors } = theme; + const { palette } = theme; const classNames = getGlobalClassNames(GlobalClassNames, theme); const styles: IStyleSet = !!borderStyle ? borderStyle : { borderWidth: '0px' }; @@ -42,6 +42,7 @@ export function getStyles(props: IShimmerLineStyleProps): IShimmerLineStyles { styles, { width: ACTUAL_WIDTH, + minWidth: widthInPixel ? ACTUAL_WIDTH : 'auto', // Fix for IE11 flex items height: `${height}px`, boxSizing: 'content-box', position: 'relative', @@ -50,7 +51,7 @@ export function getStyles(props: IShimmerLineStyleProps): IShimmerLineStyles { borderColor: palette.white, selectors: { [HighContrastSelector]: { - borderColor: semanticColors.bodyBackground + borderColor: 'Window' } } } diff --git a/packages/experiments/src/components/Shimmer/examples/Shimmer.Styling.Example.tsx b/packages/experiments/src/components/Shimmer/examples/Shimmer.Styling.Example.tsx index 3fee862b813098..4fcd355dc2a975 100644 --- a/packages/experiments/src/components/Shimmer/examples/Shimmer.Styling.Example.tsx +++ b/packages/experiments/src/components/Shimmer/examples/Shimmer.Styling.Example.tsx @@ -44,7 +44,7 @@ export class ShimmerStylingExample extends React.Component<{}, {}> { return { shimmerWrapper: [{ backgroundColor: '#deecf9', - backgroundImage: 'linear-gradient(to right, transparent 0%, #c7e0f4 50%, transparent 100%)' + backgroundImage: 'linear-gradient(to right, rgba(255, 255, 255, 0) 0%, #c7e0f4 50%, rgba(255, 255, 255, 0) 100%)' }] }; } From 8ab9d7555ca7d0b1150b239d9b44062b16ec5775 Mon Sep 17 00:00:00 2001 From: Vitalie Braga Date: Tue, 22 May 2018 18:35:51 -0700 Subject: [PATCH 29/32] Fill color for line corners in high contrast mode. --- .../components/Shimmer/ShimmerLine/ShimmerLine.styles.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/experiments/src/components/Shimmer/ShimmerLine/ShimmerLine.styles.ts b/packages/experiments/src/components/Shimmer/ShimmerLine/ShimmerLine.styles.ts index b865fa724287e8..ceb6b79905ad57 100644 --- a/packages/experiments/src/components/Shimmer/ShimmerLine/ShimmerLine.styles.ts +++ b/packages/experiments/src/components/Shimmer/ShimmerLine/ShimmerLine.styles.ts @@ -51,7 +51,12 @@ export function getStyles(props: IShimmerLineStyleProps): IShimmerLineStyles { borderColor: palette.white, selectors: { [HighContrastSelector]: { - borderColor: 'Window' + borderColor: 'Window', + selectors: { + '> *': { + fill: 'Window' + } + } } } } From d8ae65b4d2d5b19f223631052f15414c5b9a3752 Mon Sep 17 00:00:00 2001 From: Vitalie Braga Date: Tue, 22 May 2018 18:58:21 -0700 Subject: [PATCH 30/32] Rush change log. --- .../v-vibr-RefactorShimmer_2018-05-23-01-57.json | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 common/changes/@uifabric/experiments/v-vibr-RefactorShimmer_2018-05-23-01-57.json diff --git a/common/changes/@uifabric/experiments/v-vibr-RefactorShimmer_2018-05-23-01-57.json b/common/changes/@uifabric/experiments/v-vibr-RefactorShimmer_2018-05-23-01-57.json new file mode 100644 index 00000000000000..065cf10890a6c5 --- /dev/null +++ b/common/changes/@uifabric/experiments/v-vibr-RefactorShimmer_2018-05-23-01-57.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "packageName": "@uifabric/experiments", + "comment": "Shimmer: Refactors and enhances Shimmer with more features.", + "type": "minor" + } + ], + "packageName": "@uifabric/experiments", + "email": "v-vibr@microsoft.com" +} \ No newline at end of file From f2a6c76b9f1929a2d5af7f5f80c8ba17d4e8fdf7 Mon Sep 17 00:00:00 2001 From: Vitalie Braga Date: Wed, 23 May 2018 07:50:53 -0700 Subject: [PATCH 31/32] Fix tslint warnings. --- .../Shimmer/examples/Shimmer.CustomElements.Example.tsx | 4 ++++ .../components/Shimmer/examples/Shimmer.LoadData.Example.tsx | 2 ++ 2 files changed, 6 insertions(+) diff --git a/packages/experiments/src/components/Shimmer/examples/Shimmer.CustomElements.Example.tsx b/packages/experiments/src/components/Shimmer/examples/Shimmer.CustomElements.Example.tsx index 19d92087cb74ba..d5ad5f8c5c3a47 100644 --- a/packages/experiments/src/components/Shimmer/examples/Shimmer.CustomElements.Example.tsx +++ b/packages/experiments/src/components/Shimmer/examples/Shimmer.CustomElements.Example.tsx @@ -39,6 +39,7 @@ export class ShimmerCustomElementsExample extends React.Component<{}, {}> { private _getCustomElementsExampleOne = (): JSX.Element => { return (
{ private _getCustomElementsExampleTwo = (): JSX.Element => { return (
{ private _getCustomElementsExampleThree = (): JSX.Element => { return (
{ ] } />
{ return (
Date: Thu, 24 May 2018 15:01:32 -0700 Subject: [PATCH 32/32] Adds a default prop in ShimmerElementsGroup --- .../ShimmerElementsGroup/ShimmerElementsGroup.base.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/experiments/src/components/Shimmer/ShimmerElementsGroup/ShimmerElementsGroup.base.tsx b/packages/experiments/src/components/Shimmer/ShimmerElementsGroup/ShimmerElementsGroup.base.tsx index 443c85ae0cbf9f..75ae8bf4958eb6 100644 --- a/packages/experiments/src/components/Shimmer/ShimmerElementsGroup/ShimmerElementsGroup.base.tsx +++ b/packages/experiments/src/components/Shimmer/ShimmerElementsGroup/ShimmerElementsGroup.base.tsx @@ -24,6 +24,10 @@ const getClassNames = classNamesFunction { + public static defaultProps: IShimmerElementsGroupProps = { + flexWrap: false + }; + private _classNames: { [key in keyof IShimmerElementsGroupStyles]: string }; constructor(props: IShimmerElementsGroupProps) {