-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Overflow set #1537
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Overflow set #1537
Changes from 16 commits
a8e4cc3
7345c8c
c3ff083
62a5469
eb237c8
9de2ec2
d54c5c6
228ddd1
cd011db
1085601
850c74a
8155ef5
e296f1a
e8e30c0
458ad1f
c81f76e
ac1cb5e
b526d40
7e74eef
fe718e3
6d9fd0f
a887b22
82a4188
2eab455
fd424b4
8f35a16
8d7bc00
e7b86db
82c5b6d
988e0c7
c0884d9
198e3ae
2520d1d
d9ba936
d57593a
ac26ad3
e8eff9c
473c484
78275f9
35f9325
bb54cbd
e8c2960
6d424e3
038b3f7
edb0ec5
a72004f
30c1a74
501956d
8f64dec
2e4df29
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| { | ||
| "changes": [ | ||
| { | ||
| "packageName": "office-ui-fabric-react", | ||
| "comment": "OverflowSet: New Overflow Set componet to create sets of elements with overflow showing in callout", | ||
| "type": "patch" | ||
| } | ||
| ], | ||
| "email": "micahgodbolt@gmail.com" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export * from './components/OverflowSet/index'; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| import * as React from 'react'; | ||
| import { OverflowSet } from './OverflowSet'; | ||
| import { IContextualMenuItem } from '../../ContextualMenu'; | ||
| import { IIconProps } from '../../Icon'; | ||
| import { IRenderFunction } from '../../Utilities'; | ||
|
|
||
| export interface IOverflowSetProps extends React.Props<OverflowSet> { | ||
|
|
||
| /** | ||
| * An array of items to be rendered by your onRenderItem function in the primary content area | ||
| */ | ||
| items?: any[]; | ||
|
|
||
| /** | ||
| * An array of items to be passed to overflow contextual menu | ||
| */ | ||
| overflowItems?: IContextualMenuItem[]; | ||
|
|
||
| /** | ||
| * Icon props used to override overflow icon. | ||
| */ | ||
| iconProps?: IIconProps; | ||
|
|
||
| /** | ||
| * Method to call when trying to render an item. | ||
| * If item contains an onRender, that function will be used instead. | ||
| */ | ||
| onRenderItem?: IRenderFunction<any>; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| @import '../../common/common'; | ||
|
|
||
| .root { | ||
| position: relative; | ||
| display: flex; | ||
| flex-wrap: nowrap; | ||
| } | ||
|
|
||
|
|
||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit blank |
||
| .item { | ||
| flex-shrink: 0; | ||
| } | ||
|
|
||
| .overflowIcon { | ||
| align-self: stretch; | ||
| height: auto; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| import * as React from 'react'; | ||
| import { | ||
| css, | ||
| autobind, | ||
| BaseComponent | ||
| } from '../../Utilities'; | ||
| import { IOverflowSetProps } from './OverflowSet.Props'; | ||
| import { IconButton } from '../../Button'; | ||
| import { FocusZone, FocusZoneDirection } from '../../FocusZone'; | ||
|
|
||
| const styles: any = require('./OverflowSet.scss'); | ||
|
|
||
| export class OverflowSet extends BaseComponent<IOverflowSetProps, null> { | ||
|
|
||
| public render() { | ||
| let { items, overflowItems } = this.props; | ||
| return ( | ||
| <FocusZone className={ css('ms-OverflowSet', styles.root) } direction={ FocusZoneDirection.horizontal } role='menubar' > | ||
| { items && this._onRenderItems(items) } | ||
| { overflowItems.length && this._onRenderOverflowButton(overflowItems) } | ||
| </FocusZone> | ||
| ); | ||
| } | ||
|
|
||
| @autobind | ||
| private _onRenderOverflowButton(items) { | ||
| let { iconProps = {} } = this.props; | ||
| iconProps.iconName = iconProps.iconName ? iconProps.iconName : 'More'; | ||
| return ( | ||
| <IconButton | ||
| className={ css(styles.overflowIcon) } | ||
| iconProps={ iconProps } | ||
| menuIconProps={ { iconName: null } } | ||
| menuProps={ { | ||
| items: items | ||
| } } | ||
| /> | ||
| ); | ||
| } | ||
|
|
||
| @autobind | ||
| private _onRenderItems(items) { | ||
| return items.map((item, i) => { | ||
| let key = item.key ? item.key : i; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The props definition should say that items can take a key. It might even be worth explicitly stating this in the type definition instead of just putting any (though not sure how to best do that, maybe an intersection type?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can do this in the prop
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure if this really solves it though. Basically it's either anything, or just a key. Unless I don't understand intersection properly.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You actually probably don't need an intersection, you can just say items?: {key?: string} []. You can assign anything to that.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| let onRender = item.onRender ? item.onRender : this.props.onRenderItem; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This won't work; onRender has a signature (item) => JSX.Element Youre passing item and index, which satisfies neither. |
||
| return ( | ||
| <div | ||
| className={ css('ms-OverflowSet-item', styles.item) } | ||
| key={ key } > | ||
| { onRender ? onRender(item, i) : item } | ||
| </div> | ||
| ); | ||
| }); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| import * as React from 'react'; | ||
| import { Link } from 'office-ui-fabric-react/lib/Link'; | ||
| import { LayerHost } from 'office-ui-fabric-react/lib/Layer'; | ||
| import { | ||
| ExampleCard, | ||
| ComponentPage, | ||
| PropertiesTableSet | ||
| } from '@uifabric/example-app-base'; | ||
| import { OverflowSetBasicExample } from './examples/OverflowSet.Basic.Example'; | ||
|
|
||
| const OverflowSetBasicExampleCode = require('!raw-loader!office-ui-fabric-react/src/components/OverflowSet/examples/OverflowSet.Basic.Example.tsx') as string; | ||
|
|
||
| export class OverflowSetPage extends React.Component<any, any> { | ||
| public render() { | ||
| return ( | ||
| <ComponentPage | ||
| title='OverflowSet' | ||
| componentName='OverflowSetExample' | ||
| overview={ | ||
| <div> | ||
| <p> | ||
| The Overflow Set component is a flexible container component that is usefull for displaying a primary set of content with additional content in an overflow callout. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. spelling
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OverflowSet ? |
||
| </p> | ||
| </div> | ||
| } | ||
| exampleCards={ | ||
| <LayerHost> | ||
| <ExampleCard title='OverflowSet' code={ OverflowSetBasicExampleCode }> | ||
| <OverflowSetBasicExample /> | ||
| </ExampleCard> | ||
| </LayerHost> | ||
| } | ||
| propertiesTables={ | ||
| <PropertiesTableSet | ||
| sources={ [ | ||
| require<string>('!raw-loader!office-ui-fabric-react/src/components/OverflowSet/OverflowSet.Props.ts') | ||
| ] } | ||
| /> | ||
| } | ||
| /> | ||
| ); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,123 @@ | ||
| /* tslint:disable:no-unused-variable */ | ||
| import * as React from 'react'; | ||
| /* tslint:enable:no-unused-variable */ | ||
| import { BaseComponent } from 'office-ui-fabric-react/lib/Utilities'; | ||
| import { PrimaryButton } from 'office-ui-fabric-react/lib/Button'; | ||
| import { DefaultButton } from 'office-ui-fabric-react/lib/Button'; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you can collapse these two |
||
| import { | ||
| OverflowSet | ||
| } from '../index'; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. examples should have imports that the user would do... |
||
|
|
||
| export class OverflowSetBasicExample extends BaseComponent<any, any> { | ||
|
|
||
| public render() { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe you should keep the basic example basic and have a "customized" example to customized. Reading the docs this is basically a for loop on items to render them as a given thing, with a menuProps.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sounds good.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is done |
||
| return ( | ||
| <OverflowSet | ||
| items={ [ | ||
| { | ||
| key: 'search', | ||
| 'onRender': () => { | ||
| return ( | ||
| <PrimaryButton | ||
| iconProps={ { iconName: 'Add' } } | ||
| text='Add' | ||
| /> | ||
| ); | ||
| } | ||
| }, | ||
| { | ||
| key: 'newItem', | ||
| name: 'New', | ||
| icon: 'Add', | ||
| ariaLabel: 'New. Use left and right arrow keys to navigate', | ||
| onClick: () => { return; }, | ||
| subMenuProps: { | ||
| items: [ | ||
| { | ||
| key: 'emailMessage', | ||
| name: 'Email message', | ||
| icon: 'Mail', | ||
| }, | ||
| { | ||
| key: 'calendarEvent', | ||
| name: 'Calendar event', | ||
| icon: 'Calendar' | ||
| } | ||
| ], | ||
| }, | ||
| }, | ||
| { | ||
| key: 'upload', | ||
| name: 'Upload', | ||
| icon: 'Upload', | ||
| onClick: () => { return; }, | ||
| }, | ||
| { | ||
| key: 'share', | ||
| name: 'Share', | ||
| icon: 'Share', | ||
| onClick: () => { return; } | ||
| } | ||
| ] } | ||
| overflowItems={ [ | ||
| { | ||
| key: 'newItem', | ||
| name: 'Add', | ||
| icon: 'Add', | ||
| ariaLabel: 'New. Use left and right arrow keys to navigate', | ||
| onClick: () => { return; }, | ||
| subMenuProps: { | ||
| items: [ | ||
| { | ||
| key: 'emailMessage', | ||
| name: 'Email message', | ||
| icon: 'Mail', | ||
| }, | ||
| { | ||
| key: 'calendarEvent', | ||
| name: 'Calendar event', | ||
| icon: 'Calendar' | ||
| } | ||
| ], | ||
| }, | ||
| }, | ||
| { | ||
| key: 'move', | ||
| name: 'Move to...', | ||
| icon: 'MoveToFolder', | ||
| onClick: () => { return; } | ||
| }, | ||
| { | ||
| key: 'copy', | ||
| name: 'Copy to...', | ||
| icon: 'Copy', | ||
| onClick: () => { return; } | ||
| }, | ||
| { | ||
| key: 'rename', | ||
| name: 'Rename...', | ||
| icon: 'Edit', | ||
| onClick: () => { return; } | ||
| }, | ||
| { | ||
| key: 'disabled', | ||
| name: 'Disabled...', | ||
| icon: 'Cancel', | ||
| disabled: true, | ||
| onClick: () => { return; } | ||
| } | ||
| ] | ||
| } | ||
| onRenderItem={ (item) => { | ||
| return ( | ||
| <DefaultButton | ||
| iconProps={ { iconName: item.icon } } | ||
| menuProps={ item.subMenuProps } | ||
| text={ item.name } | ||
| > </DefaultButton> | ||
| ); | ||
| } } | ||
| /> | ||
| ); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| export * from './OverflowSet'; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. don't add this here until we're using it and happy with it. |
||
| export * from './OverflowSet.Props'; | ||

There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are the types different items vs overflow items?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OverflowItems are meant to be rendered in a contextual menu. Of course there isn't anything stopping someone from rendering them in something else....If any[] is prefered I have no problems either way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think contextualmenuitem already has a mechanism to render anything else inside them, so I think it is ok.