Skip to content

Commit

Permalink
Merge pull request #1514 from Automattic/fix/143-header-cake-back-ove…
Browse files Browse the repository at this point in the history
…rflow

Components: header cake cleanup
  • Loading branch information
adambbecker committed Jan 29, 2016
2 parents 3f9594e + 03c5e2c commit a3f6453
Show file tree
Hide file tree
Showing 10 changed files with 144 additions and 84 deletions.
8 changes: 5 additions & 3 deletions client/components/header-cake/README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
Back Button aka Header Cake
===========================

The "header cake" component should be used at the top of an item's detail page. It's purpose is to display a title and back link.

## Usage

```
```js
var HeaderCake = require( 'components/header-cake' );

<HeaderCake onClick={ callback }>Button Text</HeaderCake>
<HeaderCake onClick={ callback }>Item Details</HeaderCake>
```

## Props

* `onClick` - Function to trigger when the back text is clicked
* `onClick` - (**required**) Function to trigger when the back text is clicked
* `onTitleClick` - Function to trigger when the title is clicked
* `backText` - React Element or string to use in place of default "Back" text
* `isCompact` - Optional variant of a more visually compact header cake
61 changes: 61 additions & 0 deletions client/components/header-cake/back.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/**
* External dependencies
*/
import React, { PropTypes } from 'react';
import classNames from 'classnames';

/**
* Internal dependencies
*/
import ObserveWindowSizeMixin from 'lib/mixins/observe-window-resize';
import Gridicon from 'components/gridicon';

/**
* Module variables
*/
const HIDE_BACK_CRITERIA = {
windowWidth: 480,
characterLength: 8
};

export default React.createClass( {

displayName: 'HeaderCakeBack',

mixins: [ ObserveWindowSizeMixin ],

propTypes: {
onClick: PropTypes.func,
href: PropTypes.string,
text: PropTypes.string,
spacer: PropTypes.bool
},

getDefaultProps() {
return {
spacer: false
};
},

render() {
const { text = this.translate( 'Back' ), href, onClick, spacer } = this.props;
const windowWidth = window.innerWidth;
const hideText = windowWidth <= HIDE_BACK_CRITERIA.windowWidth && text.length >= HIDE_BACK_CRITERIA.characterLength || windowWidth <= 300;
const linkClasses = classNames( {
'header-cake__back': true,
'is-spacer': spacer
} );

return (
<a className={ linkClasses } href={ href } onClick={ onClick }>
<Gridicon icon="chevron-left" size={ 18 } />
{ ! hideText && <span className="header-cake__back-text">{ text }</span> }
</a>
);
},

onWindowResize() {
this.forceUpdate();
}

} );
41 changes: 18 additions & 23 deletions client/components/header-cake/index.jsx
Original file line number Diff line number Diff line change
@@ -1,35 +1,34 @@
/**
* External dependencies
*/
var React = require( 'react' ),
classNames = require( 'classnames' );
import React, { PropTypes } from 'react';
import classNames from 'classnames';

/**
* Internal dependencies
*/
var Card = require( 'components/card' ),
Gridicon = require( 'components/gridicon' );
import Card from 'components/card';
import HeaderCakeBack from './back';

export default React.createClass( {

module.exports = React.createClass( {
displayName: 'HeaderCake',

propTypes: {
onClick: React.PropTypes.func.isRequired,
onTitleClick: React.PropTypes.func,
backText: React.PropTypes.oneOfType( [
React.PropTypes.element,
React.PropTypes.string
] )
onClick: PropTypes.func.isRequired,
onTitleClick: PropTypes.func,
backText: PropTypes.string
},

getDefaultProps: function() {
getDefaultProps() {
return {
isCompact: false
};
},

render: function() {
var classes = classNames(
render() {
const { backText } = this.props;
const classes = classNames(
'header-cake',
this.props.className,
{
Expand All @@ -39,17 +38,13 @@ module.exports = React.createClass( {

return (
<Card className={ classes }>
<div className="header-cake__corner">
<a className="header-cake__back" onClick={ this.props.onClick }>
<Gridicon icon="chevron-left" size={ 16 } />
<span className="header-cake__back-text">{ this.props.backText || this.translate( 'Back' ) }</span>
</a>
</div>
<span className="header-cake__title" onClick={ this.props.onTitleClick }>
<HeaderCakeBack text={ backText } onClick={ this.props.onClick } />
<div className="header-cake__title" onClick={ this.props.onTitleClick }>
{ this.props.children }
</span>
<div className="header-cake__corner" />
</div>
<HeaderCakeBack text={ backText } spacer />
</Card>
);
}

} );
47 changes: 28 additions & 19 deletions client/components/header-cake/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -7,47 +7,56 @@

.header-cake.card {
display: flex;
align-items: stretch;
justify-content: center;
align-items: center;
font-size: 14px;
line-height: 18px;
padding: 16px;
padding: 0;

&::after {
display: none;
}

@include breakpoint( "<660px" ) {
margin-top: 10px;
}
}

.header-cake__title {
color: darken( $gray, 20% );
text-align: center;
word-break: break-word;
flex: 2 1;
}

.header-cake__corner {
display: flex;
flex: 1 0;
}

.header-cake__back {
flex: 1 0;
flex: none;
display: block;
margin: -16px;
margin-right: 0;
padding: 15px 16px 16px;
max-width: 33.333%;
padding: 16px;
color: darken( $gray, 20% );
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
cursor: pointer;

.gridicon {
display: inline-block;
vertical-align: middle;
opacity: 0.6;
}

&.is-spacer {
opacity: 0;
cursor: default;
}
}

.header-cake__back-text {
font-size: 11px;
font-weight: 600;
text-transform: uppercase;
}

.header-cake__title {
flex: 1 1 auto;
padding: 16px 0;
color: darken( $gray, 20% );
text-align: center;
word-break: break-word;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ const DomainManagementHeader = React.createClass( {
render() {
return (
<HeaderCake className="domain-management-header" onClick={ this.props.onClick }>
{ this.domainName() }
<span className="domain-management-header__children">
{ this.props.children }
</span>
<div className="domain-management-header__children">
{ this.domainName() }
<span className="domain-management-header__title">
{ this.props.children }
</span>
</div>
</HeaderCake>
);
},
Expand Down
9 changes: 8 additions & 1 deletion client/my-sites/upgrades/domain-management/style.scss
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
.domain-main-placeholder {
.header-cake__title {
.domain-management-header__children {
@include placeholder(23%);

@include breakpoint('>480px') {
max-width: 60%;
margin: 0 auto;
}
}
}

Expand Down Expand Up @@ -47,6 +52,8 @@

.domain-management-header__children {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}

.domain-management-list-item__link {
Expand Down
24 changes: 6 additions & 18 deletions client/post-editor/media-modal/detail/_style.scss
Original file line number Diff line number Diff line change
@@ -1,24 +1,16 @@
.editor-media-modal-detail .header-cake.card,
.editor-media-modal-detail .header-cake__corner {
display: block;

.editor-media-modal-detail .header-cake.card {
@include breakpoint( "<660px" ) {
margin-bottom: 0;
}
}

.editor-media-modal-detail .header-cake__back {
display: inline-block;
.editor-media-modal-detail .header-cake__title {
padding: 6px 0;
}

.editor-media-modal-detail__title .editor-media-modal-detail__title-input {
@extend .header-cake__title;
position: absolute;
top: 50%;
left: 50%;
transform: translate( -50%, -50% );
width: 200px;
width: calc( 100vw - 175px );
.editor-media-modal-detail .editor-media-modal-detail__title-input {
width: 100%;
color: inherit;
word-break: normal;
white-space: nowrap;
overflow: hidden;
Expand All @@ -27,10 +19,6 @@
outline: none;
text-align: center;

@include breakpoint( ">480px" ) {
width: 60%;
}

&[readonly]:hover,
&[readonly]:focus {
box-shadow: none;
Expand Down
22 changes: 10 additions & 12 deletions client/post-editor/media-modal/detail/detail-title.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,18 +81,16 @@ export default React.createClass( {

render() {
return (
<h2 className="editor-media-modal-detail__title">
<TrackInputChanges onNewValue={ this.bumpStat }>
<FormTextInput
onKeyUp={ this.onKeyUp }
onChange={ this.onChange }
onBlur={ this.saveTitle }
value={ this.getTitleValue() }
placeholder={ this.translate( 'Untitled' ) }
readOnly={ ! userCan( 'upload_files', this.props.site ) }
className="editor-media-modal-detail__title-input" />
</TrackInputChanges>
</h2>
<TrackInputChanges onNewValue={ this.bumpStat }>
<FormTextInput
onKeyUp={ this.onKeyUp }
onChange={ this.onChange }
onBlur={ this.saveTitle }
value={ this.getTitleValue() }
placeholder={ this.translate( 'Untitled' ) }
readOnly={ ! userCan( 'upload_files', this.props.site ) }
className="editor-media-modal-detail__title-input" />
</TrackInputChanges>
);
}
} );
3 changes: 1 addition & 2 deletions client/post-editor/media-modal/detail/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ var React = require( 'react' ),
var DetailItem = require( './detail-item' ),
MediaUtils = require( 'lib/media/utils' ),
HeaderCake = require( 'components/header-cake' ),
BackToLibrary = require( '../back-to-library' ),
EditorMediaModalDetailTitle = require( './detail-title' ),
preloadImage = require( '../preload-image' ),
ModalViews = require( '../constants' ).Views;
Expand Down Expand Up @@ -65,7 +64,7 @@ module.exports = React.createClass( {

return (
<div className="editor-media-modal-detail">
<HeaderCake onClick={ this.returnToList } backText={ <BackToLibrary /> }>
<HeaderCake onClick={ this.returnToList } backText={ this.translate( 'Media Library' ) }>
<EditorMediaModalDetailTitle
site={ this.props.site }
item={ items[ this.props.selectedIndex ] } />
Expand Down
3 changes: 1 addition & 2 deletions client/post-editor/media-modal/gallery/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import isEqual from 'lodash/lang/isEqual';
* Internal dependencies
*/
import HeaderCake from 'components/header-cake';
import BackToLibrary from '../back-to-library';
import MediaStore from 'lib/media/store';
import EditorMediaModalGalleryDropZone from './drop-zone';
import EditorMediaModalGalleryFields from './fields';
Expand Down Expand Up @@ -132,7 +131,7 @@ export default React.createClass( {
<EditorMediaModalGalleryDropZone
site={ site }
onInvalidItemAdded={ () => this.setState( { invalidItemDropped: true } ) } />
<HeaderCake onClick={ this.returnToList } backText={ <BackToLibrary /> } />
<HeaderCake onClick={ this.returnToList } backText={ this.translate( 'Media Library' ) } />
<div className="editor-media-modal-gallery__content editor-media-modal__content">
<EditorMediaModalGalleryPreview
site={ site }
Expand Down

0 comments on commit a3f6453

Please sign in to comment.