diff --git a/common/changes/@uifabric/experiments/chiclet_2018-05-16-00-12.json b/common/changes/@uifabric/experiments/chiclet_2018-05-16-00-12.json new file mode 100644 index 0000000000000..c86fde920bb8a --- /dev/null +++ b/common/changes/@uifabric/experiments/chiclet_2018-05-16-00-12.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "packageName": "@uifabric/experiments", + "comment": "Implementation of the Chiclet component", + "type": "minor" + } + ], + "packageName": "@uifabric/experiments", + "email": "naethell@microsoft.com" +} \ No newline at end of file diff --git a/common/changes/office-ui-fabric-react/chiclet_2018-05-18-19-25.json b/common/changes/office-ui-fabric-react/chiclet_2018-05-18-19-25.json new file mode 100644 index 0000000000000..f83fc44d7e964 --- /dev/null +++ b/common/changes/office-ui-fabric-react/chiclet_2018-05-18-19-25.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "packageName": "office-ui-fabric-react", + "comment": "Implementation of experimental chiclet component", + "type": "minor" + } + ], + "packageName": "office-ui-fabric-react", + "email": "naethell@microsoft.com" +} \ No newline at end of file diff --git a/packages/experiments/index.html b/packages/experiments/index.html index e393a626195dd..dda8acdd7c6a6 100644 --- a/packages/experiments/index.html +++ b/packages/experiments/index.html @@ -5,6 +5,11 @@ + + + + + Office UI Fabric React Examples diff --git a/packages/experiments/src/Chiclet.ts b/packages/experiments/src/Chiclet.ts new file mode 100644 index 0000000000000..bb147afc0b1b6 --- /dev/null +++ b/packages/experiments/src/Chiclet.ts @@ -0,0 +1 @@ +export * from './components/Chiclet/index'; \ No newline at end of file diff --git a/packages/experiments/src/common/TestImages.ts b/packages/experiments/src/common/TestImages.ts new file mode 100644 index 0000000000000..c7de1f611a9c8 --- /dev/null +++ b/packages/experiments/src/common/TestImages.ts @@ -0,0 +1,5 @@ +const baseProductionCdnUrl = 'https://az742526.vo.msecnd.net/files/odsp-next-release-odc_2018-04-13_20180418.001/odsp-media/images/apps/'; + +export const ChicletTestImages = { + iconWordDoc: baseProductionCdnUrl + 'word_16x1.svg', +}; \ No newline at end of file diff --git a/packages/experiments/src/components/Chiclet/Chiclet.base.tsx b/packages/experiments/src/components/Chiclet/Chiclet.base.tsx new file mode 100644 index 0000000000000..67474b1ace12a --- /dev/null +++ b/packages/experiments/src/components/Chiclet/Chiclet.base.tsx @@ -0,0 +1,51 @@ +import * as React from 'react'; +import { + BaseComponent, + customizable +} from '../../Utilities'; +import { ChicletCard } from './ChicletCard'; +import { getOpenGraphProperties } from './OpenGraph'; +import { IChicletProps, ChicletSize } from './Chiclet.types'; +import { IChicletCardProps } from './ChicletCard.types'; + +export interface IChicletState { + chicletCardProps?: IChicletCardProps; +} + +@customizable('ChicletBase', ['theme']) +export class ChicletBase extends BaseComponent { + + constructor(props: IChicletProps) { + super(props); + + const chicletCardProps = getOpenGraphProperties(this.props.url); + this.state = { chicletCardProps: chicletCardProps }; + } + + public render(): JSX.Element { + const { size, footer, description } = this.props; + const { chicletCardProps } = this.state; + + switch (size) { + case ChicletSize.medium: + return ( + + ); + // @todo: handle other types of chiclets + default: + return ( + + ); + } + } + + public componentWillReceiveProps(nextProps: IChicletProps): void { + if (this.props.url !== nextProps.url) { + this.setState({ chicletCardProps: getOpenGraphProperties(this.props.url) }); + } + } + + private _onClick(): void { // @todo: default click handler + } + +} diff --git a/packages/experiments/src/components/Chiclet/Chiclet.styles.ts b/packages/experiments/src/components/Chiclet/Chiclet.styles.ts new file mode 100644 index 0000000000000..140ebcead20c4 --- /dev/null +++ b/packages/experiments/src/components/Chiclet/Chiclet.styles.ts @@ -0,0 +1,9 @@ +import { IChicletStyleProps, IChicletStyles } from './Chiclet.types'; + +export const getStyles = ( + props: IChicletStyleProps +): IChicletStyles => { + return ({ + root: {} + }); +}; \ No newline at end of file diff --git a/packages/experiments/src/components/Chiclet/Chiclet.tsx b/packages/experiments/src/components/Chiclet/Chiclet.tsx new file mode 100644 index 0000000000000..e9910fc917c9c --- /dev/null +++ b/packages/experiments/src/components/Chiclet/Chiclet.tsx @@ -0,0 +1,13 @@ +import { styled } from '../../Utilities'; +import { + IChicletProps, + IChicletStyleProps, + IChicletStyles +} from './Chiclet.types'; +import { getStyles } from './Chiclet.styles'; +import { ChicletBase } from './Chiclet.base'; + +export const Chiclet = styled( + ChicletBase, + getStyles +); \ No newline at end of file diff --git a/packages/experiments/src/components/Chiclet/Chiclet.types.ts b/packages/experiments/src/components/Chiclet/Chiclet.types.ts new file mode 100644 index 0000000000000..910fa3c3d36a5 --- /dev/null +++ b/packages/experiments/src/components/Chiclet/Chiclet.types.ts @@ -0,0 +1,90 @@ +import * as React from 'react'; +import { ChicletBase } from './Chiclet.base'; +import { IStyleFunction } from '../../Utilities'; +import { + IStyle, + ITheme +} from '../../Styling'; + +export interface IChiclet { + +} + +export interface IChicletProps extends React.Props { + /** + * Optional callback to access the IChiclet interface. Use this instead of ref for accessing + * the public methods and properties of the component. + */ + componentRef?: (component: IChiclet | null) => void; + + /** + * Call to provide customized styling that will layer on top of the variant rules. + */ + getStyles?: IStyleFunction; + + /** + * Optional class for chiclet. + */ + className?: string; + + /** + * Sharing link + */ + url: string; + + /** + * Chiclet size to render + */ + size?: ChicletSize; + + /** + * Description to render for the component. + */ + description?: React.ReactElement; + + /** + * Footer to render for the component. + */ + footer?: React.ReactElement; + + /** + * Theme for the component. + */ + theme?: ITheme; +} + +export interface IChicletStyleProps { + /** + * Theme for the component. + */ + theme?: ITheme; +} + +export interface IChicletStyles { + /** + * Style for the root element when fixed. + */ + root?: IStyle; +} + +export enum ChicletSize { + /** + * X-Small Chiclet + */ + xSmall = 0, + + /** + * Small Chiclet + */ + small = 1, + + /** + * Medium Chiclet + */ + medium = 2, + + /** + * Large Chiclet + */ + large = 3 +} \ No newline at end of file diff --git a/packages/experiments/src/components/Chiclet/ChicletCard.base.tsx b/packages/experiments/src/components/Chiclet/ChicletCard.base.tsx new file mode 100644 index 0000000000000..fca9e9f5c37de --- /dev/null +++ b/packages/experiments/src/components/Chiclet/ChicletCard.base.tsx @@ -0,0 +1,162 @@ +import * as React from 'react'; +import { + BaseComponent, + css, + customizable, + classNamesFunction +} from '../../Utilities'; +import { IChicletCardStyles, IChicletCardStyleProps, IChicletCardProps } from './ChicletCard.types'; +import { mergeStyles } from '../../Styling'; +import { Image } from 'office-ui-fabric-react/lib/Image'; + +const getClassNames = classNamesFunction(); + +const ASSET_CDN_BASE_URL = 'https://static2.sharepointonline.com/files/fabric/assets'; + +const PREVIEW_IMAGE_WIDTH = '198px'; +const PREVIEW_IMAGE_HEIGHT = '122px'; + +@customizable('ChicletCardBase', ['theme']) +export class ChicletCardBase extends BaseComponent { + public static defaultProps: IChicletCardProps = { + imageWidth: PREVIEW_IMAGE_WIDTH, + imageHeight: PREVIEW_IMAGE_HEIGHT + }; + + private _classNames: { [key in keyof IChicletCardStyles]: string }; + + public render(): JSX.Element { + const { + title, + itemType, + description, + image, + imageWidth, + imageHeight, + imageAlt, + url, + onClick, + className, + footer, + theme, + getStyles + } = this.props; + const actionable = (onClick) ? true : false; + + this._classNames = getClassNames(getStyles, { theme: theme! }); + + // if this element is actionable it should have an aria role + const role = actionable ? (onClick ? 'button' : 'link') : undefined; + const tabIndex = actionable ? 0 : undefined; + + const preview = this._renderPreviewImage(image, imageHeight, imageWidth, itemType, imageAlt); + + return ( +
+
+ { preview } +
+
+
+ { title ? title : (null) } +
+
+ { description ? description : url } +
+ { footer } +
+
+ ); + } + + private _renderPreviewImage(imageUrl?: string, imageHeight?: string, imageWidth?: string, itemType?: string, imageAlt?: string) + : React.ReactElement> { + let image; + if (imageUrl) { + image = ( + { + ); + } else { + image = ( + { + ); + } + + let src; + if (itemType !== null) { + src = `${ASSET_CDN_BASE_URL}/brand-icons/product/svg/` + itemType + `_16x1_5.svg`; + } + let icon = ; + switch (itemType) { // for "hero" apps, we'll use the app icons + case 'word': + case 'docx': + icon = ( + + ); + break; + case 'powerpoint': + case 'pptx': + icon = ( + + ); + break; + case 'excel': + icon = ( + + ); + break; + } + + return ( +
+ { image } + { icon } +
+ ); + } + + private _onClick = (ev: React.MouseEvent): void => { + const { onClick } = this.props; + if (onClick) { + onClick(ev); + } + } + +} \ No newline at end of file diff --git a/packages/experiments/src/components/Chiclet/ChicletCard.styles.ts b/packages/experiments/src/components/Chiclet/ChicletCard.styles.ts new file mode 100644 index 0000000000000..003e39f941c81 --- /dev/null +++ b/packages/experiments/src/components/Chiclet/ChicletCard.styles.ts @@ -0,0 +1,96 @@ +import { + normalize +} from '../../Styling'; +import { IChicletCardStyleProps, IChicletCardStyles } from './ChicletCard.types'; + +export const getStyles = ( + props: IChicletCardStyleProps +): IChicletCardStyles => { + const { theme } = props; + const { palette } = theme; + + return ({ + root: [ + normalize, + { + WebkitFontSmoothing: 'antialiased', + backgroundColor: palette.white, + borderRadius: 2, + boxShadow: '0 1px 3px 0 rgba(0, 0, 0, 0.3)', + width: 600, + height: 126, + userSelect: 'none', + position: 'relative', + selectors: { + ':hover': { + cursor: 'pointer' + } + } + } + ], + icon: [ + { + height: 24, + left: 10, + bottom: 10, + position: 'absolute' + } + ], + preview: [ + { + float: 'left', + height: 122, + width: 198, + position: 'relative', + backgroundColor: palette.white, + display: 'block', + padding: '2px 0px 2px 2px', + } + ], + info: [ + { + position: 'relative', + display: 'block', + height: '100%', + overflow: 'hidden', + wordWrap: 'break-word', + width: 400 + } + ], + title: [ + { + padding: '9px 26px 5px 11px', + fontSize: 16, + fontWeight: 'normal', + fontStyle: 'normal', + fontStretch: 'normal', + color: palette.neutralPrimary, + letterSpacing: 'normal', + textAlign: 'left', + height: 41, // Two lines of text, making sure the third line is hidden + width: 363, + lineHeight: '1.25', + overflow: 'hidden', + wordWrap: 'break-word' + } + ], + description: [ + { + padding: '0px 16px 17px 11px', + fontSize: 12, + fontWeight: 'normal', + fontStyle: 'normal', + fontStretch: 'normal', + lineHeight: '1.33', + letterSpacing: 'normal', + textAlign: 'left', + color: '#797671', // @todo: get theme from designers + width: 248, + height: 16, + overflow: 'hidden', + whiteSpace: 'nowrap', + textOverflow: 'ellipsis' + } + ] + }); +}; \ No newline at end of file diff --git a/packages/experiments/src/components/Chiclet/ChicletCard.test.tsx b/packages/experiments/src/components/Chiclet/ChicletCard.test.tsx new file mode 100644 index 0000000000000..6c1f0f4e9e262 --- /dev/null +++ b/packages/experiments/src/components/Chiclet/ChicletCard.test.tsx @@ -0,0 +1,18 @@ +import * as React from 'react'; +import * as renderer from 'react-test-renderer'; + +import { ChicletCard } from './ChicletCard'; +import { IChicletCardProps } from './ChicletCard.types'; + +describe('Dialog', () => { + it('renders chiclet with title, icon, onClick, and url', () => { + const chicletCardProps: IChicletCardProps = { title: 'My Daily Notes', itemType: 'docx', onClick: () => alert('test') }; + const component = renderer.create( + + ); + + const tree = component.toJSON(); + + expect(tree).toMatchSnapshot(); + }); +}); \ No newline at end of file diff --git a/packages/experiments/src/components/Chiclet/ChicletCard.tsx b/packages/experiments/src/components/Chiclet/ChicletCard.tsx new file mode 100644 index 0000000000000..1537c02a8f079 --- /dev/null +++ b/packages/experiments/src/components/Chiclet/ChicletCard.tsx @@ -0,0 +1,13 @@ +import { styled } from '../../Utilities'; +import { + IChicletCardProps, + IChicletCardStyleProps, + IChicletCardStyles +} from './ChicletCard.types'; +import { getStyles } from './ChicletCard.styles'; +import { ChicletCardBase } from './ChicletCard.base'; + +export const ChicletCard = styled( + ChicletCardBase, + getStyles +); \ No newline at end of file diff --git a/packages/experiments/src/components/Chiclet/ChicletCard.types.ts b/packages/experiments/src/components/Chiclet/ChicletCard.types.ts new file mode 100644 index 0000000000000..cc1a38ab6a85d --- /dev/null +++ b/packages/experiments/src/components/Chiclet/ChicletCard.types.ts @@ -0,0 +1,114 @@ +import * as React from 'react'; +import { ChicletCardBase } from './ChicletCard.base'; +import { ITheme, IStyle } from '../../Styling'; +import { IStyleFunction } from '../../Utilities'; + +export interface IChicletCard { + +} + +export interface IChicletCardStyles { + /** + * Style for the root element. + */ + root?: IStyle; + + /** + * Style for the icon that overlays the file preview image. + */ + icon?: IStyle; + + /** + * Style for the file preview image. + */ + preview?: IStyle; + + /** + * Style for preview information about the file, such as title and link. + */ + info?: IStyle; + + /** + * Style for the title of the file. + */ + title?: IStyle; + + /** + * Style for the dile description, which could be a link, description, etc. + */ + description?: IStyle; +} + +export interface IChicletCardProps extends React.Props { + /** + * Optional callback to access the IChicletCard interface. Use this instead of ref for accessing + * the public methods and properties of the component. + */ + componentRef?: (component: IChicletCard | null) => void; + + /** + * Call to provide customized styling that will layer on top of the variant rules. + */ + getStyles?: IStyleFunction; + + /** + * Optional class for ChicletCard. + */ + className?: string; + + /** + * Function to call when the card is clicked. + */ + onClick?: (ev?: React.MouseEvent) => void; + + /** + * Description to render for the component. + */ + description?: React.ReactElement; + + /** + * Footer to render for the component. + */ + footer?: React.ReactElement; + + /** + * Theme for the component. + */ + theme?: ITheme; + + /** + * Item metadata. + */ + title?: string; + itemType?: string; + image?: string; + imageSecureUrl?: string; + + /** + * The width of the preview image. + * @default '198px' + */ + imageWidth?: string; + + /** + * The height of the preview image. + * @default '122px' + */ + imageHeight?: string; + + imageType?: string; + imageAlt?: string; + url?: string; +} + +export interface IChicletCardStyleProps { + /** + * Accept theme prop. + */ + theme: ITheme; + + /** + * Accept custom classNames + */ + className?: string; +} \ No newline at end of file diff --git a/packages/experiments/src/components/Chiclet/ChicletPage.tsx b/packages/experiments/src/components/Chiclet/ChicletPage.tsx new file mode 100644 index 0000000000000..ef1f8864343ba --- /dev/null +++ b/packages/experiments/src/components/Chiclet/ChicletPage.tsx @@ -0,0 +1,63 @@ +import * as React from 'react'; +import { + ExampleCard, + IComponentDemoPageProps, + ComponentPage, + PropertiesTableSet +} from '@uifabric/example-app-base'; + +import { ChicletBasicExample } from './examples/Chiclet.Basic.Example'; +const ChicletBasicExampleCode = + require('!raw-loader!@uifabric/experiments/src/components/Chiclet/examples/Chiclet.Basic.Example.tsx') as string; +import { ChicletBreadcrumbExample } from './examples/Chiclet.Breadcrumb.Example'; +const ChicletBreadcrumbExampleCode = + require('!raw-loader!@uifabric/experiments/src/components/Chiclet/examples/Chiclet.Breadcrumb.Example.tsx') as string; + +export class ChicletPage extends React.Component { + public render(): JSX.Element { + return ( + + + + + + + + + } + propertiesTables={ + ('!raw-loader!@uifabric/experiments/src/components/Chiclet/Chiclet.types.ts') + ] } + /> + } + overview={ +
+ } + bestPractices={ +
+ } + dos={ +
+
    +
  • Use them to represent an item in a card with relevant metadata.
  • +
+
+ } + donts={ // @todo: fill in description +
+
    +
  • +
+
+ } + isHeaderVisible={ this.props.isHeaderVisible } + /> + ); + } +} diff --git a/packages/experiments/src/components/Chiclet/OpenGraph.ts b/packages/experiments/src/components/Chiclet/OpenGraph.ts new file mode 100644 index 0000000000000..da5abe973ce07 --- /dev/null +++ b/packages/experiments/src/components/Chiclet/OpenGraph.ts @@ -0,0 +1,55 @@ +import { IChicletCardProps } from './ChicletCard.types'; + +export function getOpenGraphProperties(url: string): IChicletCardProps { + const attributes: IChicletCardProps = {}; + const metaElements = extractMetaTags(url); + + for (let i = 0; i < metaElements.length; i++) { + if (metaElements[i].attributes !== null && metaElements[i].attributes.length >= 2) { + switch (metaElements[i].attributes[0].nodeValue) { + case 'og:title': + attributes.title = metaElements[i].content; + break; + case 'og:type': + attributes.itemType = metaElements[i].content; + break; + case 'og:image': + case 'og:image:url': + attributes.image = metaElements[i].content; + break; + case 'og:image:secure_url': + attributes.imageSecureUrl = metaElements[i].content; + break; + case 'og:image:type': + attributes.imageType = metaElements[i].content; + break; + case 'og:image:width': + attributes.imageWidth = metaElements[i].content; + break; + case 'og:image:height': + attributes.imageHeight = metaElements[i].content; + break; + case 'og:image:alt': + attributes.imageAlt = metaElements[i].content; + break; + case 'og:url': + attributes.url = metaElements[i].content; + break; + } + } + } + return attributes; +} + +function extractMetaTags(url: string): NodeListOf { + const xmlHttp = new XMLHttpRequest(); + xmlHttp.open('GET', url, false); + xmlHttp.overrideMimeType('application/xml'); + xmlHttp.send(null); + + const parser = new DOMParser(); + const doc = parser.parseFromString(xmlHttp.responseText, 'text/html'); + + const metaElements = doc.getElementsByTagName('meta'); + return metaElements; +} diff --git a/packages/experiments/src/components/Chiclet/__snapshots__/ChicletCard.test.tsx.snap b/packages/experiments/src/components/Chiclet/__snapshots__/ChicletCard.test.tsx.snap new file mode 100644 index 0000000000000..e689c98f394ea --- /dev/null +++ b/packages/experiments/src/components/Chiclet/__snapshots__/ChicletCard.test.tsx.snap @@ -0,0 +1,158 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Dialog renders chiclet with title, icon, onClick, and url 1`] = ` +
+
+
+
+ {undefined} +
+ +
+
+
+
+ My Daily Notes +
+
+ https://onedrive.com +
+
+
+`; diff --git a/packages/experiments/src/components/Chiclet/examples/Chiclet.Basic.Example.scss b/packages/experiments/src/components/Chiclet/examples/Chiclet.Basic.Example.scss new file mode 100644 index 0000000000000..d04360275d4d3 --- /dev/null +++ b/packages/experiments/src/components/Chiclet/examples/Chiclet.Basic.Example.scss @@ -0,0 +1,59 @@ +.footer { + height: 36px; + padding-left: 11px; +} + +.activities { + width: 184px; + height: 16px; + font-size: 12px; + font-weight: normal; + font-style: normal; + font-stretch: normal; + line-height: 1.83; + letter-spacing: normal; + float: left; + padding-top: 8px; + padding-bottom: 12px; +} + +.actions { + padding-right: 6px; + position: relative; +} + +.action { + float: right; + cursor: pointer; + width: 32px; + height: 36px; + background-color: white; + color: #0078D7; +} + +.description { + font-size: 12px; + font-weight: normal; + font-style: normal; + font-stretch: normal; + line-height: 1.33; + letter-spacing: normal; + text-align: left; + color: #797671; + width: 248px; + height: 16px; + white-space: nowrap; + text-overflow: ellipsis; +} + +.chevron { + font-size: 8px; + padding-left: 3px; + padding-right: 3px; +} + +:global { + .ms-ChicletCard .ms-Breadcrumb { + margin-top: 0px; + } +} \ No newline at end of file diff --git a/packages/experiments/src/components/Chiclet/examples/Chiclet.Basic.Example.tsx b/packages/experiments/src/components/Chiclet/examples/Chiclet.Basic.Example.tsx new file mode 100644 index 0000000000000..9495dbfba237f --- /dev/null +++ b/packages/experiments/src/components/Chiclet/examples/Chiclet.Basic.Example.tsx @@ -0,0 +1,61 @@ +import * as React from 'react'; +import { + Chiclet +} from '../Chiclet'; +import { ChicletSize } from '../Chiclet.types'; +import { IButtonProps } from 'office-ui-fabric-react/lib/Button'; +import * as exampleStyles from './Chiclet.Basic.Example.scss'; +import { IconButton } from 'office-ui-fabric-react/lib/Button'; + +export class FooterComponent extends React.Component { + constructor(props: IFooterComponent) { + super(props); + } + + public render(): JSX.Element { + const { buttonProps, activities } = this.props; + + return _renderFooter(buttonProps, activities); + } +} + +export class ChicletBasicExample extends React.Component<{}, {}> { + constructor(props: {}) { + super(props); + } + + public render(): JSX.Element { + const footerButtonProps: IButtonProps[] = [ + { iconProps: { iconName: 'More' } }, { iconProps: { iconName: 'Save' } }, { iconProps: { iconName: 'Share' } } + ]; + const footer = ; + + return ( + + ); + } +} + +export interface IFooterComponent extends React.Props { + buttonProps: IButtonProps[]; + activities: string; +} + +function _renderFooter(buttonProps: IButtonProps[], activities: string): React.ReactElement { + return ( +
+
+ { activities ? activities : (null) } +
+
+ { buttonProps && buttonProps.map((buttonProp: IButtonProps, index: number) => { + return ( +
+ +
+ ); + }) } +
+
+ ); +} \ No newline at end of file diff --git a/packages/experiments/src/components/Chiclet/examples/Chiclet.Breadcrumb.Example.tsx b/packages/experiments/src/components/Chiclet/examples/Chiclet.Breadcrumb.Example.tsx new file mode 100644 index 0000000000000..832db919841de --- /dev/null +++ b/packages/experiments/src/components/Chiclet/examples/Chiclet.Breadcrumb.Example.tsx @@ -0,0 +1,98 @@ +import * as React from 'react'; +import { + Chiclet +} from '../Chiclet'; +import { ChicletSize } from '../Chiclet.types'; +import { IButtonProps } from 'office-ui-fabric-react/lib/Button'; +import * as exampleStyles from './Chiclet.Basic.Example.scss'; +import { IconButton } from 'office-ui-fabric-react/lib/Button'; +import { Icon } from 'office-ui-fabric-react/lib/Icon'; +import { TooltipHost, TooltipOverflowMode } from 'office-ui-fabric-react/lib/Tooltip'; +import { Breadcrumb, IBreadcrumbItem } from 'office-ui-fabric-react/lib/Breadcrumb'; +import { getRTL } from '../../../Utilities'; + +export class FooterComponent extends React.Component { + constructor(props: IFooterComponent) { + super(props); + } + + public render(): JSX.Element { + const { buttonProps, activities } = this.props; + + return _renderFooter(buttonProps, activities); + } +} + +export class ChicletBreadcrumbExample extends React.Component<{}, {}> { + constructor(props: {}) { + super(props); + } + + public render(): JSX.Element { + const footerButtonProps: IButtonProps[] = [ + { iconProps: { iconName: 'More' } }, { iconProps: { iconName: 'Save' } }, { iconProps: { iconName: 'Share' } } + ]; + const footer = + ; + + const divider = () => ; + const breadcrumb = ( + + ); + + return ( + + ); + } + + private _onRenderItem(item: IBreadcrumbItem): JSX.Element { + return ( + + { item.text } + + ); + } +} + +export interface IFooterComponent extends React.Props { + buttonProps: IButtonProps[]; + activities: string; +} + +function _renderFooter(buttonProps: IButtonProps[], activities: string): React.ReactElement { + return ( +
+
+ { activities ? activities : (null) } +
+
+ { buttonProps && buttonProps.map((buttonProp: IButtonProps, index: number) => { + return ( +
+ +
+ ); + }) } +
+
+ ); +} diff --git a/packages/experiments/src/components/Chiclet/index.ts b/packages/experiments/src/components/Chiclet/index.ts new file mode 100644 index 0000000000000..da098a2bbe68a --- /dev/null +++ b/packages/experiments/src/components/Chiclet/index.ts @@ -0,0 +1,5 @@ +export * from './Chiclet.base'; +export * from './Chiclet'; +export * from './ChicletCard.base'; +export * from './ChicletCard'; +export * from './OpenGraph'; \ No newline at end of file diff --git a/packages/experiments/src/demo/AppDefinition.tsx b/packages/experiments/src/demo/AppDefinition.tsx index f93c450e5416c..1ae21dfd5c25f 100644 --- a/packages/experiments/src/demo/AppDefinition.tsx +++ b/packages/experiments/src/demo/AppDefinition.tsx @@ -16,6 +16,12 @@ export const AppDefinition: IAppDefinition = { name: 'CommandBar', url: '#/examples/commandbar' }, + { + component: require('../components/Chiclet/ChicletPage').ChicletPage, + key: 'Chiclet', + name: 'Chiclet', + url: '#/examples/chiclet' + }, { component: require('../components/FolderCover/FolderCoverPage').FolderCoverPage, key: 'FolderCover', diff --git a/packages/experiments/src/index.ts b/packages/experiments/src/index.ts index 35f51abf258f0..3cbf22e1a37ea 100644 --- a/packages/experiments/src/index.ts +++ b/packages/experiments/src/index.ts @@ -4,4 +4,5 @@ export { FolderCover } from './FolderCover'; export { Tile } from './Tile'; export { TilesList } from './TilesList'; export { CommandBar as ExperimentCommandBar } from './CommandBar'; -export { Shimmer } from './Shimmer'; \ No newline at end of file +export { Shimmer } from './Shimmer'; +export { Chiclet } from './Chiclet'; \ No newline at end of file diff --git a/packages/office-ui-fabric-react/src/components/FloatingPicker/Suggestions/SuggestionsCore.tsx b/packages/office-ui-fabric-react/src/components/FloatingPicker/Suggestions/SuggestionsCore.tsx index bad779a59f7ac..ae2508f5ed330 100644 --- a/packages/office-ui-fabric-react/src/components/FloatingPicker/Suggestions/SuggestionsCore.tsx +++ b/packages/office-ui-fabric-react/src/components/FloatingPicker/Suggestions/SuggestionsCore.tsx @@ -18,7 +18,7 @@ export class SuggestionsCore extends BaseComponent, public currentSuggestion: ISuggestionModel | undefined; protected _selectedElement: HTMLDivElement; private SuggestionsItemOfProperType: new (props: ISuggestionItemProps) => SuggestionsItem = - SuggestionsItem as new (props: ISuggestionItemProps) => SuggestionsItem; + SuggestionsItem as new (props: ISuggestionItemProps) => SuggestionsItem; constructor(suggestionsProps: ISuggestionsCoreProps) { super(suggestionsProps);