Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
7df53a3
Adds basic skeleton of Shimmer Component to office-ui-fabric-react.
Feb 27, 2018
fe588ad
Register the Shimmer component in the library.
Feb 27, 2018
8eec1df
Adds basic skeleton of Shimmer Component to office-ui-fabric-react.
Feb 27, 2018
2fafb18
Register the Shimmer component in the library.
Feb 27, 2018
d4de449
Merge branch 'v-vibr/ShimmerComponent' of https://github.com/Vitalius…
Feb 27, 2018
6c6c90c
Starting to implement mergeStyles to create examples of component.
Feb 28, 2018
8a01736
Introduces the svg plus styles a little.
Feb 28, 2018
0df88f9
Adds css background-size to mergeStyles.api and adds basic shimmer an…
Feb 28, 2018
9dc20e5
Splits Shimmer into the main host and shapes inside.
Mar 1, 2018
575740f
Adds rectangle shape to shimmer.
Mar 1, 2018
d1200a9
Changes the logic to exposure of the shapes of shimmer only internaly.
Mar 2, 2018
1679fc3
Adds ability to to add different elements to the shimmer line.
Mar 3, 2018
7e017e2
Refactors the naming of some interfaces and forces a more strict type…
Mar 4, 2018
7d9493e
Moves the function bo get the borderAlignStyles to Shimmer.base.tsx
Mar 4, 2018
67550f6
Adds wrapper around the shimmer to position it absolute for fadeOut a…
Mar 4, 2018
be34e94
Creates two basic examples for shimmer page.
Mar 5, 2018
115c4fa
Sets a list with hovercards to demonstrate Shimmer Application.
Mar 5, 2018
76e6b37
Small changes in the logic of calculating the borders.
Mar 6, 2018
b280fd7
Merge branch 'master' into v-vibr/ShimmerComponent
Mar 6, 2018
67bca2f
Change log plus remove mergeStyleAPI change for a different PR
Mar 6, 2018
b26e1fb
Cleans TSLint errors.
Mar 6, 2018
15594af
Cleans unused import.
Mar 6, 2018
65c81ae
Moves the shimmer component to experiments folder.
Mar 6, 2018
e214e35
Adjusts all imports to make it run in experiments.
Mar 6, 2018
6c0533d
Adds Change log plus cleans the code a little.
Mar 6, 2018
769dc87
Corrects all typescript linting errors.
Mar 6, 2018
b63ecbc
Fixes another tslint error
Mar 6, 2018
349cfc9
Removes unnecessary circle state.
Mar 6, 2018
f793c63
Small fix for importing.
Mar 7, 2018
edc319d
Sets up a scrolling list simulating data loading when scrolling using…
Mar 7, 2018
ab3ce8d
Introduces more props to Shimmer.
Mar 8, 2018
2b9f0e8
Enables back simulation of asynchronus loading of data for example page.
Mar 8, 2018
5ec6b2e
Adds shimmer to DetailsList advanced example.
Mar 9, 2018
8c29055
Merge branch 'master' into v-vibr/ShimmerIntegration
Mar 9, 2018
828d9cd
Fixes some names and styles.
Mar 9, 2018
630a6cf
Merge branch 'master' into v-vibr/ShimmerComponent
Mar 10, 2018
2203780
Adds props and logic to prepare the shimmer to work with DetailsList …
Mar 10, 2018
9edc399
Moved ShimmerRectangle Interfaces in a different folder.
Mar 10, 2018
9cdccdc
Moves ShimmerCircle Interfaces to a different file.
Mar 10, 2018
f256225
Reevaluates some of the language for the documentation.
Mar 10, 2018
384373a
Changes the ShimmerRectangle name to ShimmerLine for better semantics…
Mar 10, 2018
e514fa7
Extracts a value to a constant.
Mar 12, 2018
5e553b3
Merging master with new changes.
Mar 12, 2018
c200526
Changes the logic of calculating the maxHeight and extracting height …
Mar 12, 2018
941dfd7
Changes the name for isDetailsList prop.
Mar 12, 2018
e2313a4
Merge branch 'master' into v-vibr/Shimmer
Mar 12, 2018
e3580ec
Renames Shimmer prop from isListMissingItem to isBaseStyle to give it…
Mar 13, 2018
e23a1ef
Cleans up the code a little.
Mar 13, 2018
7b07f62
Styles left margin only for the Shimmer Application Example.
Mar 13, 2018
f881b09
Merge branch 'master' into v-vibr/Shimmer
Mar 13, 2018
bae314d
Change log commit.
Mar 13, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"changes": [
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@Vitalius1 are you working with someone on this? It would be great to have pair ownership to ensure we have someone who can more deeply provide feedback and shared fixing.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes I am. Mainly I get feedback from @atneik .

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@atneik can you review please?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@atneik can you review please?

{
"packageName": "@uifabric/experiments",
"comment": "Adds a new Shimmer Component to experiments package.",
"type": "minor"
}
],
"packageName": "@uifabric/experiments",
"email": "v-vibr@microsoft.com"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"changes": [
{
"packageName": "@uifabric/experiments",
"comment": "Changes in the props and naming.",
"type": "minor"
}
],
"packageName": "@uifabric/experiments",
"email": "v-vibr@microsoft.com"
}
80 changes: 51 additions & 29 deletions packages/experiments/src/components/Shimmer/Shimmer.base.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,30 +17,37 @@ import {
DefaultPalette,
IStyleSet
} from '../../Styling';
import { ShimmerRectangle } from './ShimmerRectangle/ShimmerRectangle';
import { ShimmerLine } from './ShimmerLine/ShimmerLine';
import { ShimmerCircle } from './ShimmerCircle/ShimmerCircle';

const LINE_DEFAULT_HEIGHT = 16;
const CIRCLE_DEFAULT_HEIGHT = 24;

const getClassNames = classNamesFunction<IShimmerStyleProps, IShimmerStyles>();

export class ShimmerBase extends BaseComponent<IShimmerProps, {}> {
public static defaultProps: IShimmerProps = {
width: 100,
isDataLoaded: false
isDataLoaded: false,
isBaseStyle: false
};
private _classNames: {[key in keyof IShimmerStyles]: string};
constructor(props: IShimmerProps) {
super(props);
}

public render(): JSX.Element {
const { getStyles, width, lineElements, children, isDataLoaded } = this.props;
const { getStyles, width, lineElements, children, isDataLoaded, isBaseStyle } = this.props;
const maxHeight: number | undefined = lineElements ? this._findMaxHeight(lineElements) : undefined;
this._classNames = getClassNames(getStyles!, { width, maxHeight, isDataLoaded });
this._classNames = getClassNames(getStyles!, { width, maxHeight, isDataLoaded, isBaseStyle });

const elements: JSX.Element[] | JSX.Element = lineElements ?
lineElements.map((elem: ICircle | ILine | IGap, index: number): JSX.Element => {
switch (elem.type) {
case ShimmerElementType.CIRCLE:
if (!elem.height) {
elem.height = CIRCLE_DEFAULT_HEIGHT;
}
return (
<ShimmerCircle
key={ index }
Expand All @@ -49,7 +56,9 @@ export class ShimmerBase extends BaseComponent<IShimmerProps, {}> {
/>
);
case ShimmerElementType.GAP:
const gapWidth = elem.width ? elem.width + '%' : '1%';
const gapWidth = elem.widthInPercentage || elem.widthInPixel ?
elem.widthInPercentage ? elem.widthInPercentage + '%' : elem.widthInPixel + 'px'
: '5px';
return (
<div
key={ index }
Expand All @@ -61,34 +70,55 @@ export class ShimmerBase extends BaseComponent<IShimmerProps, {}> {
} }
/>
);
case ShimmerElementType.RECTANGLE:
case ShimmerElementType.LINE:
if (!elem.height) {
elem.height = LINE_DEFAULT_HEIGHT;
}
return (
<ShimmerRectangle
<ShimmerLine
key={ index }
{ ...elem }
borderAlignStyle={ this._getBorderAlignStyles(maxHeight, elem) }
/>
);
}
}) :
<ShimmerRectangle />;
}) : (
<ShimmerLine
height={ LINE_DEFAULT_HEIGHT }
/>
);

return (
<div className={ this._classNames.root }>
<div className={ this._classNames.shimmerWrapper }>
{ elements }
</div>
<div className={ this._classNames.dataWrapper }>
{ !!isDataLoaded ?
!!children ? children : null
: null }
{ !!isBaseStyle ? children : elements }
</div>

{ !!isDataLoaded &&
<div className={ this._classNames.dataWrapper }>
{ !!children ? children : null }
</div>
}
</div>
);
}

private _findMaxHeight(items: Array<ICircle | IGap | ILine>): number {
const maxHeight = items.reduce((acc: number, next: ICircle | IGap | ILine): number => {
const itemsDefaulted: Array<ICircle | IGap | ILine> = items.map((item: ICircle | IGap | ILine): ICircle | IGap | ILine => {
switch (item.type) {
case ShimmerElementType.CIRCLE:
if (!item.height) {
item.height = CIRCLE_DEFAULT_HEIGHT;
}
case ShimmerElementType.LINE:
if (!item.height) {
item.height = LINE_DEFAULT_HEIGHT;
}
}
return item;
});

const maxHeight = itemsDefaulted.reduce((acc: number, next: ICircle | IGap | ILine): number => {
return next.height ?
next.height > acc ? next.height : acc
: acc;
Expand All @@ -97,19 +127,11 @@ export class ShimmerBase extends BaseComponent<IShimmerProps, {}> {
}

private _getBorderAlignStyles(maxHeight: number | undefined, elem: ICircle | IGap | ILine): IStyleSet | undefined {
let height: number | undefined;
switch (elem.type) {
case ShimmerElementType.RECTANGLE:
height = !!elem.height ? elem.height : 16;
break;
case ShimmerElementType.CIRCLE:
height = !!elem.height ? elem.height : 24;
break;
}
console.log(height);
const dif: number | undefined = maxHeight && height ?
maxHeight - height > 0 ?
maxHeight - height : undefined
const elemHeight: number | undefined = elem.height;

const dif: number | undefined = maxHeight && elemHeight ?
maxHeight - elemHeight > 0 ?
maxHeight - elemHeight : undefined
: undefined;

let borderStyle: IStyleSet | undefined;
Expand Down
20 changes: 17 additions & 3 deletions packages/experiments/src/components/Shimmer/Shimmer.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,18 @@ export function getStyles(props: IShimmerStyleProps): IShimmerStyles {
const {
width,
maxHeight,
isDataLoaded
isDataLoaded,
isBaseStyle
} = props;

const BACKGROUND_OFF_SCREEN_POSITION = '1000%';

const shimmerAnimation: string = keyframes({
'0%': {
backgroundPosition: '-900%'
backgroundPosition: `-${BACKGROUND_OFF_SCREEN_POSITION}`
},
'100%': {
backgroundPosition: '1000%'
backgroundPosition: BACKGROUND_OFF_SCREEN_POSITION
}
});

Expand All @@ -26,8 +29,15 @@ export function getStyles(props: IShimmerStyleProps): IShimmerStyles {
{
position: 'relative',
margin: '10px',
width: 'auto',
boxSizing: 'content-box',
minHeight: maxHeight ? `${maxHeight}px` : '16px'
},
isBaseStyle && {
margin: '0',
minHeight: 'inherit',
display: 'flex',
alignItems: 'center'
}
],
shimmerWrapper: [
Expand Down Expand Up @@ -60,6 +70,10 @@ export function getStyles(props: IShimmerStyleProps): IShimmerStyles {
isDataLoaded && {
opacity: '0',
visibility: 'hidden'
},
isBaseStyle && {
position: 'static',
width: 'auto'
}
],
dataWrapper: [
Expand Down
63 changes: 36 additions & 27 deletions packages/experiments/src/components/Shimmer/Shimmer.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export interface IShimmerProps extends React.AllHTMLAttributes<HTMLElement> {
componentRef?: (component: IShimmer) => void;

/**
* Sets the width of the shimmer wave container in percentages.
* Sets the width of the shimmer wave wrapper in percentages.
* @default 100%
*/
width?: number;
Expand All @@ -30,6 +30,12 @@ export interface IShimmerProps extends React.AllHTMLAttributes<HTMLElement> {
*/
isDataLoaded?: boolean;

/**
* Provide when Shimmer is intended to be used when using 'onRenderMissingItem' optional callback of the DetailsList Fabric Component.
* @default false
*/
isBaseStyle?: boolean;

/**
* Elements to render in one line of the Shimmer.
*/
Expand All @@ -48,72 +54,75 @@ export interface IShimmerElement {
type: ShimmerElementType;

/**
* The hight of the element (ICircle, ILine, IGap).
* The hight of the element in pixels (ICircle, ILine).
* Read more details for each specific element.
*/
height?: number;

/**
* The width of the element (ICircle, ILine, IGap).
* The width of the element in pixels (ILine, IGap).
* Read more details for each specific element.
*/
width?: number;
widthInPixel?: number;

/**
* The vertical alignemt of the element (ICircle, ILine, IGap).
* The width of the element in pixels (ILine, IGap).
* Read more details for each specific element.
*/
widthInPercentage?: number;

/**
* The vertical alignemt of the element (ICircle, ILine).
* @default center
*/
verticalAlign?: ShimmerElementVerticalAlign;
}

export interface ILine extends IShimmerElement {
/**
* Sets the height of the rectangle.
* The value will represent the height in pixels.
* @default 16
* Sets the height of the shimmer line in pixels.
* @default 16px
*/
height?: number;

/**
* If not provided the line will the take the remaining space to fill the shimmer container.
* The value provided will represent the width as '%' relative to the shimmer container.
* The value provided will represent the width as '%' relative to the shimmer wrapper.
*/
width?: number;
}
widthInPercentage?: number;

export interface ICircle extends IShimmerElement {
/**
* Sets the height of the circle.
* The value will represent the height in pixels.
* @default 24
* Sets the width of the Line to an exact value in pixels.
* @default 50px
*/
height?: number;
widthInPixel?: number;
}

export interface ICircle extends IShimmerElement {
/**
* Width of the circle element if provided will be ignored.
* The value will be set equal to the height of the circle for scale ratio reasons.
* Sets the height of the shimmer circle in pixels.
* @default 24px
*/
width?: number;
height?: number;
}

export interface IGap extends IShimmerElement {
/**
* Height for gap element will be ignored and set equal to the heighest element on the line.
* The value will be calculated as '%' relative the to shimmer wrapper.
*/
height?: number;
widthInPercentage?: number;

/**
* Sets the width relative to the shimmer container width for responsiveness reasons.
* The value will be calculated as '%' relative the to shimmer container.
* @default 1%
* Sets the width of the Gap to an exact value in pixels.
* @default 5px
*/
width?: number;
widthInPixel?: number;
}

export interface IShimmerStyleProps {
width?: number;
maxHeight?: number;
isDataLoaded?: boolean;
isBaseStyle?: boolean;
}

export interface IShimmerStyles {
Expand All @@ -123,7 +132,7 @@ export interface IShimmerStyles {
}

export const enum ShimmerElementType {
RECTANGLE = 'line',
LINE = 'line',
Copy link
Copy Markdown
Member

@dzearing dzearing Mar 20, 2018

Choose a reason for hiding this comment

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

These enum values should just be camelCased.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Got it. Will definitely change them in my next PR. Thanks!

CIRCLE = 'circle',
GAP = 'gap'
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,13 @@ import {
IShimmerCircleProps,
IShimmerCircleStyleProps,
IShimmerCircleStyles
} from './ShimmerCircle.styles';
} from './ShimmerCircle.types';

const getClassNames = classNamesFunction<IShimmerCircleStyleProps, IShimmerCircleStyles>();

export class ShimmerCircleBase extends BaseComponent<IShimmerCircleProps, {}> {
public static defaultProps: IShimmerCircleProps = {
height: 24
};
private _classNames: {[key in keyof IShimmerCircleStyles]: string};

constructor(props: IShimmerCircleProps) {
super(props);
}
Expand Down
Loading