diff --git a/common/changes/office-ui-fabric-react/Spinner_2018-03-19-21-45.json b/common/changes/office-ui-fabric-react/Spinner_2018-03-19-21-45.json new file mode 100644 index 00000000000000..9a2b005c1a7fa6 --- /dev/null +++ b/common/changes/office-ui-fabric-react/Spinner_2018-03-19-21-45.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "packageName": "office-ui-fabric-react", + "comment": "Javascript styling for Spinner", + "type": "minor" + } + ], + "packageName": "office-ui-fabric-react", + "email": "adrum@microsoft.com" +} \ No newline at end of file diff --git a/packages/office-ui-fabric-react/src/components/Spinner/Spinner.base.tsx b/packages/office-ui-fabric-react/src/components/Spinner/Spinner.base.tsx new file mode 100644 index 00000000000000..3e32f6e5dfa8c7 --- /dev/null +++ b/packages/office-ui-fabric-react/src/components/Spinner/Spinner.base.tsx @@ -0,0 +1,67 @@ +import * as React from 'react'; +import { ISpinnerProps, ISpinnerStyleProps, ISpinnerStyles, SpinnerType, SpinnerSize } from './Spinner.types'; +import { + BaseComponent, + customizable, + classNamesFunction, + DelayedRender, + getNativeProps, + divProperties +} from '../../Utilities'; + +const getClassNames = classNamesFunction(); + +@customizable('Spinner', ['theme']) +export class SpinnerBase extends BaseComponent { + + public static defaultProps: ISpinnerProps = { + size: SpinnerSize.medium, + ariaLive: 'polite' + }; + + public render() { + const { + type, + size, + ariaLabel, + ariaLive, + getStyles, + label, + theme, + className + } = this.props; + const statusMessage = ariaLabel || label; + const nativeProps = getNativeProps(this.props, divProperties, ['size']); + + // SpinnerType is deprecated. If someone is still using this property, rather than putting the SpinnerType into the ISpinnerStyleProps, + // we'll map SpinnerType to its equivalent SpinnerSize and pass that in. Once SpinnerType finally goes away we should delete this. + let styleSize = size; + if (styleSize === undefined && type !== undefined) { + styleSize = type === SpinnerType.large ? SpinnerSize.large : SpinnerSize.medium; + } + + const classNames = getClassNames(getStyles!, { + theme: theme!, + size: styleSize, + className + }); + + return ( +
+
+ { + label &&
{ label }
+ } + { + statusMessage && +
+ +
{ statusMessage }
+
+
+ } +
+ ); + } + +} \ No newline at end of file diff --git a/packages/office-ui-fabric-react/src/components/Spinner/Spinner.scss b/packages/office-ui-fabric-react/src/components/Spinner/Spinner.scss deleted file mode 100644 index e5a2b7581fd87c..00000000000000 --- a/packages/office-ui-fabric-react/src/components/Spinner/Spinner.scss +++ /dev/null @@ -1,68 +0,0 @@ -@import '../../common/common'; - -// Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE in the project root for license information. - -// -// Office UI Fabric -// -------------------------------------------------- -// Spinner styles - -$spin-duration: 1.3s; -$borderSize: 1.5px; - -@keyframes spinAnimation { - 0% { - transform: rotateZ(0deg); - } - 100% { - transform: rotateZ(360deg); - } -} - -.root { - > .circle { - margin: auto; - box-sizing: border-box; - border-radius: 50%; - width: 100%; - height: 100%; - border: $borderSize solid $ms-color-themeLight; - border-top-color: $ms-color-themePrimary; - animation: spinAnimation $spin-duration infinite cubic-bezier(.53,.21,.29,.67); - &.circleIsXSmall { - width: 12px; - height: 12px; - } - &.circleIsSmall { - width: 16px; - height: 16px; - } - &.circleIsTypeMedium, - &.circleIsMedium { - width: 20px; - height: 20px; - } - &.circleIsTypeLarge, - &.circleIsLarge { - width: 28px; - height: 28px; - } - } - .label { - color: $ms-color-themePrimary; - margin-top: 10px; - text-align: center; - } - - .screenReaderOnly { - @include ms-screenReaderOnly; - } -} - -@include high-contrast { - .root { - > .circle { - border-top-color: Highlight; - } - } -} diff --git a/packages/office-ui-fabric-react/src/components/Spinner/Spinner.styles.tsx b/packages/office-ui-fabric-react/src/components/Spinner/Spinner.styles.tsx new file mode 100644 index 00000000000000..7a3474e498d411 --- /dev/null +++ b/packages/office-ui-fabric-react/src/components/Spinner/Spinner.styles.tsx @@ -0,0 +1,81 @@ +import { ISpinnerStyleProps, ISpinnerStyles, SpinnerSize, SpinnerType } from './Spinner.types'; +import { IRawStyle, hiddenContentStyle, keyframes, HighContrastSelector } from '../../Styling'; + +const spinAnimation: string = keyframes({ + '0%': { + transform: 'rotateZ(0deg)' + }, + '100%': { + transform: 'rotateZ(360deg)' + } +}); + +export const getStyles = (props: ISpinnerStyleProps): ISpinnerStyles => { + const { theme, size, className } = props; + const { palette } = theme; + + return { + root: [ + 'ms-Spinner', + className + ], + circle: [ + 'ms-Spinner-circle', + { + margin: 'auto', + boxSizing: 'border-box', + borderRadius: '50%', + width: '100%', + height: '100%', + border: '1.5px solid ' + palette.themeLight, + borderTopColor: palette.themePrimary, + animationName: spinAnimation, + animationDuration: '1.3s', + animationIterationCount: 'infinite', + animationTimingFunction: 'cubic-bezier(.53,.21,.29,.67)', + selectors: { + [HighContrastSelector]: { + borderTopColor: 'Highlight' + } + }, + }, + size === SpinnerSize.xSmall && [ + 'ms-Spinner--xSmall', + { + width: 12, + height: 12 + } + ], + size === SpinnerSize.small && [ + 'ms-Spinner--small', + { + width: 16, + height: 16 + } + ], + size === SpinnerSize.medium && [ + 'ms-Spinner--medium', + { + width: 20, + height: 20 + } + ], + size === SpinnerSize.large && [ + 'ms-Spinner--large', + { + width: 28, + height: 28 + } + ] + ], + label: [ + 'ms-Spinner-label', + { + color: palette.themePrimary, + marginTop: 10, + textAlign: 'center' + } + ], + screenReaderText: hiddenContentStyle + }; +}; \ No newline at end of file diff --git a/packages/office-ui-fabric-react/src/components/Spinner/Spinner.tsx b/packages/office-ui-fabric-react/src/components/Spinner/Spinner.tsx index 292534cd0efb53..8061900cebccc2 100644 --- a/packages/office-ui-fabric-react/src/components/Spinner/Spinner.tsx +++ b/packages/office-ui-fabric-react/src/components/Spinner/Spinner.tsx @@ -1,45 +1,9 @@ -import * as React from 'react'; -import { BaseComponent, css, DelayedRender } from '../../Utilities'; -import { ISpinnerProps, SpinnerType, SpinnerSize } from './Spinner.types'; -import * as stylesImport from './Spinner.scss'; -const styles: any = stylesImport; +import { styled } from '../../Utilities'; +import { SpinnerBase } from './Spinner.base'; +import { ISpinnerProps } from './Spinner.types'; +import { getStyles } from './Spinner.styles'; -export class Spinner extends BaseComponent { - public static defaultProps: ISpinnerProps = { - size: SpinnerSize.medium, - ariaLive: 'polite' - }; - - public render() { - const { type, size, label, className, ariaLive, ariaLabel } = this.props; // TODO remove deprecated type property at >= 2.0.0 - const statusMessage = ariaLabel || label; - - return ( -
-
= 2.0.0 - ['ms-Spinner--large ' + styles.circleIsTypeLarge]: type === SpinnerType.large // TODO remove deprecated value at >= 2.0.0 - }) - } - /> - { - label &&
{ label }
- } - { - statusMessage && -
- -
{ statusMessage }
-
-
- } -
- ); - } -} \ No newline at end of file +export const Spinner = styled( + SpinnerBase, + getStyles +); \ No newline at end of file diff --git a/packages/office-ui-fabric-react/src/components/Spinner/Spinner.types.ts b/packages/office-ui-fabric-react/src/components/Spinner/Spinner.types.ts index 998e7a387f2478..a0ed502efd8919 100644 --- a/packages/office-ui-fabric-react/src/components/Spinner/Spinner.types.ts +++ b/packages/office-ui-fabric-react/src/components/Spinner/Spinner.types.ts @@ -1,11 +1,13 @@ import * as React from 'react'; import { Spinner } from './Spinner'; +import { ITheme, IStyle, IRawStyle } from '../../Styling'; +import { IStyleFunction } from '../../Utilities'; export interface ISpinner { } -export interface ISpinnerProps extends React.Props { +export interface ISpinnerProps extends React.HTMLAttributes { /** * Optional callback to access the ISpinner interface. Use this instead of ref for accessing * the public methods and properties of the component. @@ -45,6 +47,16 @@ export interface ISpinnerProps extends React.Props { * Alternative status label for screen reader */ ariaLabel?: string; + + /** + * Theme (provided through customization.) + */ + theme?: ITheme; + + /** + * Call to provide customized styling that will layer on top of the variant rules. + */ + getStyles?: IStyleFunction; } export enum SpinnerSize { @@ -84,3 +96,16 @@ export enum SpinnerType { */ large = 1 } + +export interface ISpinnerStyleProps { + theme: ITheme; + size?: SpinnerSize; + className?: string; +} + +export interface ISpinnerStyles { + root?: IStyle; + circle?: IStyle; + label?: IStyle; + screenReaderText?: IStyle; +} \ No newline at end of file diff --git a/packages/office-ui-fabric-react/src/components/Spinner/examples/Spinner.Basic.Example.scss b/packages/office-ui-fabric-react/src/components/Spinner/examples/Spinner.Basic.Example.scss index fe6296704b7f14..46ec5fc996a2c6 100644 --- a/packages/office-ui-fabric-react/src/components/Spinner/examples/Spinner.Basic.Example.scss +++ b/packages/office-ui-fabric-react/src/components/Spinner/examples/Spinner.Basic.Example.scss @@ -1,6 +1,6 @@ :global { - .ms-BasicSpinnersExample .ms-Spinner { - display: inline-block; + .ms-BasicSpinnersExample { margin: 10px 0; + width: 300px; } }