-
Notifications
You must be signed in to change notification settings - Fork 311
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(media): create media object component (#1383)
* feat(media): create media object component * feat(media): add menu elements * chore(media): rename media.img to media.figure * docs(media): add layout examples * docs(media): add form elements to media object example * docs(media): add titles to examples * feat(media): add aria-label prop to media.menu * style(media): change to arrow fns from function keyword * style(media): use defaultProps for everything * fix(media): adjust composition of body + figure content * refactor(media): remove menu wrapper div, pass props to button * fix(media): remove unneeded css attr * refactor(media): scss shorthand declaration * fix(media): ie11 proofing * refactor(media): use flex shorthand * fix(media): revert change to dropdownmenu, add dropdownProps instead
- Loading branch information
1 parent
099a09e
commit 5140c13
Showing
15 changed files
with
524 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
// @flow | ||
import * as React from 'react'; | ||
import classnames from 'classnames'; | ||
import MediaFigure from './MediaFigure'; | ||
import MediaBody from './MediaBody'; | ||
import MediaMenu from './MediaMenu'; | ||
import './Media.scss'; | ||
|
||
type Props = { | ||
/** Component to use as outermost element, e.g., 'li' */ | ||
as: React.ElementType, | ||
/** Child elements */ | ||
children: React.ChildrenArray<React.Element<typeof MediaFigure | typeof MediaBody | typeof MediaMenu>>, | ||
/** Additional class names */ | ||
className?: string, | ||
}; | ||
|
||
const Media = ({ as: Wrapper, children, className, ...rest }: Props) => ( | ||
<Wrapper className={classnames('bdl-Media', className)} {...rest}> | ||
{children} | ||
</Wrapper> | ||
); | ||
|
||
// Use this instead of default value because of param destructuring bug in Flow | ||
// that affects union types | ||
// https://github.com/facebook/flow/issues/5461 | ||
Media.defaultProps = { | ||
as: 'div', | ||
}; | ||
|
||
Media.Body = MediaBody; | ||
Media.Menu = MediaMenu; | ||
Media.Figure = MediaFigure; | ||
|
||
export default Media; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
> **Note** | ||
> | ||
> `Media` is a compound component, the inner elements are not meant to be used outside of the Media container | ||
Implements the "media object" element | ||
|
||
```plaintext | ||
import Media from 'box-ui-elements/es/components/media' | ||
``` | ||
|
||
```js | ||
const { MenuItem } = require('../menu'); | ||
|
||
<Media style={{ width: 300 }}> | ||
<Media.Figure> | ||
<Avatar size="large" /> | ||
</Media.Figure> | ||
|
||
<Media.Body> | ||
<Media.Menu label="Options"> | ||
<MenuItem>Edit</MenuItem> | ||
<MenuItem>Delete</MenuItem> | ||
</Media.Menu> | ||
<div> | ||
<b>Yo Yo Ma</b> commented on this file | ||
</div> | ||
<div> | ||
Please review the notes | ||
<br />a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 | ||
9 0 1 2 3 4 5 6 7 8 9 | ||
</div> | ||
</Media.Body> | ||
</Media>; | ||
``` | ||
|
||
```js | ||
const { MenuItem } = require('../menu'); | ||
|
||
<> | ||
<code> | ||
<span style={{ color: 'green' }}>Media</span>{' '} | ||
<span style={{ color: 'purple' }}>Media.Figure</span>{' '} | ||
<span style={{ color: 'orange' }}>Media.Body</span>{' '} | ||
<span style={{ color: 'red' }}>Media.Menu</span> | ||
</code> | ||
<br /> | ||
<br /> | ||
<Media style={{ width: 300, boxShadow: '0 0 2px 3px green', padding: 5 }}> | ||
<Media.Figure style={{ boxShadow: '0 0 2px 3px purple' }}> | ||
<Avatar size="large" /> | ||
</Media.Figure> | ||
|
||
<Media.Body style={{ boxShadow: '0 0 2px 3px orange', padding: 3 }}> | ||
<Media.Menu | ||
style={{ boxShadow: '0 0 2px 3px red', margin: 3, padding: 3 }} | ||
> | ||
<MenuItem>Edit</MenuItem> | ||
<MenuItem>Delete</MenuItem> | ||
</Media.Menu> | ||
<div> | ||
<b>Yo Yo Ma</b> commented on this file | ||
</div> | ||
<div> | ||
Please review the notes | ||
<br />a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 | ||
8 9 0 1 2 3 4 5 6 7 8 9 | ||
</div> | ||
</Media.Body> | ||
</Media> | ||
</>; | ||
``` | ||
|
||
## Nesting Media Components | ||
|
||
```js | ||
const { MenuItem } = require('../menu'); | ||
|
||
<Media style={{ width: 300 }}> | ||
<Media.Figure> | ||
<Avatar /> | ||
</Media.Figure> | ||
|
||
<Media.Body> | ||
<Media.Menu> | ||
<MenuItem>Edit</MenuItem> | ||
<MenuItem>Delete</MenuItem> | ||
</Media.Menu> | ||
<div> | ||
<b>Yo Yo Ma</b> commented on this file | ||
</div> | ||
<div>This is a nested media object</div> | ||
<ul style={{ margin: 0, padding: 0 }}> | ||
<Media as="li" style={{ marginTop: 10 }}> | ||
<Media.Figure> | ||
<Avatar /> | ||
</Media.Figure> | ||
|
||
<Media.Body> | ||
<div> | ||
<b>Bjork</b> replied | ||
</div> | ||
<div>I must agree!</div> | ||
<Media as="li" style={{ marginTop: 10 }}> | ||
<Media.Figure> | ||
<Avatar /> | ||
</Media.Figure> | ||
|
||
<Media.Body> | ||
<div> | ||
<b>Bono</b> replied | ||
</div> | ||
<div>Me too!</div> | ||
</Media.Body> | ||
</Media> | ||
</Media.Body> | ||
</Media> | ||
</ul> | ||
</Media.Body> | ||
</Media>; | ||
``` | ||
|
||
## With Form Elements | ||
|
||
```js | ||
const { MenuItem } = require('../menu'); | ||
|
||
<Media style={{ width: 300 }}> | ||
<Media.Figure> | ||
<Avatar size="large" /> | ||
</Media.Figure> | ||
|
||
<Media.Body> | ||
<Media.Menu> | ||
<MenuItem>Edit</MenuItem> | ||
<MenuItem>Delete</MenuItem> | ||
</Media.Menu> | ||
<div> | ||
<b>W.A. Mozart</b> commented on this file | ||
</div> | ||
<div>Everyone get ready to perform the symphony tonight!</div> | ||
<div> | ||
<Button>Reply</Button> | ||
<Button>Cancel</Button> | ||
<TextArea label="Response" /> | ||
</div> | ||
</Media.Body> | ||
</Media>; | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
@import '../../styles/variables'; | ||
|
||
// the outermost element | ||
.bdl-Media { | ||
align-items: flex-start; | ||
display: flex; | ||
} | ||
|
||
// the media content, ie, an avatar | ||
.bdl-Media-figure { | ||
align-self: flex-start; | ||
flex: 0 0 auto; | ||
justify-self: flex-start; | ||
margin: 0; | ||
padding: 0; | ||
} | ||
|
||
// the main content, e.g. title and message | ||
.bdl-Media-body { | ||
flex: 1 1 100%; | ||
margin-left: 10px; | ||
// handle wrapping long words in text content without breaking | ||
// float position of menu | ||
overflow-wrap: break-word; | ||
word-break: break-word; // CJK scripts | ||
word-wrap: break-word; // old IE | ||
} | ||
|
||
// the "..." menu button, meant to be used inside Media-body | ||
.bdl-Media-menu { | ||
// float is used to reflow content instead of pushing it to the left | ||
float: right; | ||
|
||
// overrides for .btn-plain's margin resets on focus states | ||
&, | ||
&:active, | ||
&:hover, | ||
&:focus { | ||
margin-bottom: 5px; | ||
margin-left: 10px; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
// @flow | ||
import * as React from 'react'; | ||
import classnames from 'classnames'; | ||
import './Media.scss'; | ||
|
||
type Props = { | ||
/** Child elements */ | ||
children: React.Node, | ||
/** Additional class names */ | ||
className?: string, | ||
}; | ||
|
||
const MediaBody = ({ className, children, ...rest }: Props) => ( | ||
<div className={classnames('bdl-Media-body', className)} {...rest}> | ||
{children} | ||
</div> | ||
); | ||
|
||
export default MediaBody; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
> **Note** | ||
> | ||
> `Media` is a compound component, the inner elements are not meant to be used outside of the Media container | ||
```js | ||
const { MenuItem } = require('../menu'); | ||
|
||
<Media style={{ width: 300 }}> | ||
<Media.Figure> | ||
<Avatar size="large" /> | ||
</Media.Figure> | ||
|
||
<Media.Body style={{ boxShadow: '0 0 2px 3px red' }}> | ||
<Media.Menu> | ||
<MenuItem>Edit</MenuItem> | ||
<MenuItem>Delete</MenuItem> | ||
</Media.Menu> | ||
<div> | ||
<b>Yo Yo Ma</b> commented on this file | ||
</div> | ||
<div> | ||
Long strings without spaces wrap: | ||
<br /> | ||
Thistextdoesnothaveanyspacesanditshouldbewrappedinsidethecontaineralignedwiththerightedge | ||
<br />a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 | ||
9 0 1 2 3 4 5 6 7 8 9 | ||
</div> | ||
</Media.Body> | ||
</Media>; | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
// @flow | ||
import * as React from 'react'; | ||
import classnames from 'classnames'; | ||
import './Media.scss'; | ||
|
||
type Props = { | ||
/** Component to use as outermost element, e.g., 'div' */ | ||
as: React.ElementType, | ||
/** Child elements */ | ||
children: React.Node, | ||
/** Additional class names */ | ||
className?: string, | ||
}; | ||
|
||
const MediaFigure = ({ as: Wrapper, className, children, ...rest }: Props) => ( | ||
<Wrapper className={classnames('bdl-Media-figure', className)} {...rest}> | ||
{children} | ||
</Wrapper> | ||
); | ||
|
||
// Use this instead of default value because of param destructuring bug in Flow | ||
// that affects union types | ||
// https://github.com/facebook/flow/issues/5461 | ||
MediaFigure.defaultProps = { | ||
as: 'figure', | ||
}; | ||
|
||
export default MediaFigure; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
> **Note** | ||
> | ||
> `Media` is a compound component, the inner elements are not meant to be used outside of the Media container | ||
```js | ||
const { MenuItem } = require('../menu'); | ||
|
||
<Media style={{ width: 300 }}> | ||
<Media.Figure style={{ boxShadow: '0 0 2px 3px red' }}> | ||
<Avatar size="large" /> | ||
</Media.Figure> | ||
|
||
<Media.Body> | ||
<Media.Menu> | ||
<MenuItem>Edit</MenuItem> | ||
<MenuItem>Delete</MenuItem> | ||
</Media.Menu> | ||
<div> | ||
<b>Yo Yo Ma</b> commented on this file | ||
</div> | ||
<div> | ||
Please review the notes | ||
<br />a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 | ||
9 0 1 2 3 4 5 6 7 8 9 | ||
</div> | ||
</Media.Body> | ||
</Media>; | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
// @flow | ||
import * as React from 'react'; | ||
import classnames from 'classnames'; | ||
import IconEllipsis from '../../icons/general/IconEllipsis'; | ||
import PlainButton from '../plain-button'; | ||
import DropdownMenu from '../dropdown-menu'; | ||
import { Menu } from '../menu'; | ||
import { bdlGray62 } from '../../styles/variables'; | ||
import './Media.scss'; | ||
|
||
type Props = { | ||
/** Child elements */ | ||
children: React.Node, | ||
/** Additional class names for the menu button */ | ||
className?: string, | ||
/** Additional props for the DropdownMenu */ | ||
dropdownProps?: {}, | ||
/** is the dropdown menu button disabled */ | ||
isDisabled: boolean, | ||
}; | ||
|
||
const MediaMenu = ({ className, children, isDisabled, dropdownProps, ...rest }: Props) => ( | ||
<DropdownMenu constrainToScrollParent isRightAligned {...dropdownProps}> | ||
<PlainButton | ||
isDisabled={isDisabled} | ||
className={classnames('bdl-Media-menu', className)} | ||
type="button" | ||
{...rest} | ||
> | ||
<IconEllipsis color={bdlGray62} height={16} width={16} /> | ||
</PlainButton> | ||
<Menu>{children}</Menu> | ||
</DropdownMenu> | ||
); | ||
|
||
MediaMenu.defaultProps = { | ||
dropdownProps: {}, | ||
isDisabled: false, | ||
}; | ||
|
||
export default MediaMenu; |
Oops, something went wrong.