Skip to content
This repository has been archived by the owner on Dec 11, 2021. It is now read-only.

Commit

Permalink
Makes centered add buttons the default behaviour.
Browse files Browse the repository at this point in the history
  • Loading branch information
BertrandBordage committed Feb 27, 2019
1 parent b10d6c5 commit 5e90f50
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 64 deletions.
57 changes: 35 additions & 22 deletions example/index.story.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ storiesOf('React StreamField demo', module)
],
value: [{ type: 'title', value: 'Wagtail is awesome!' }]
};
return <StreamField {...props} id='stream-1' />;
return <StreamField {...props} id='stream' />;
})
.add('1 open block type', () => {
const props = {
Expand All @@ -41,7 +41,7 @@ storiesOf('React StreamField demo', module)
],
value: [{ type: 'title', value: 'Wagtail is awesome!' }]
};
return <StreamField {...props} id='stream-2' />;
return <StreamField {...props} id='stream' />;
})
.add('1 static block type', () => {
const props = {
Expand All @@ -55,7 +55,7 @@ storiesOf('React StreamField demo', module)
],
value: [{ type: 'static' }]
};
return <StreamField {...props} id='stream-3' />;
return <StreamField {...props} id='stream' />;
})
.add('1 block type, default value', () => {
const props = {
Expand All @@ -71,7 +71,7 @@ storiesOf('React StreamField demo', module)
],
value: [{ type: 'title', value: 'Wagtail is awesome!' }]
};
return <StreamField {...props} id='stream-4' />;
return <StreamField {...props} id='stream' />;
})
.add('1 block type, custom per-value HTML', () => {
const props = {
Expand All @@ -94,7 +94,7 @@ storiesOf('React StreamField demo', module)
{ type: 'title', value: 'This time, no custom HTML.' }
]
};
return <StreamField {...props} id='stream-5' />;
return <StreamField {...props} id='stream' />;
})
.add('2 block types', () => {
const props = {
Expand All @@ -118,7 +118,7 @@ storiesOf('React StreamField demo', module)
{ type: 'text', value: 'And it’s always getting better 😃' }
]
};
return <StreamField {...props} id='stream-6' />;
return <StreamField {...props} id='stream' />;
})
.add('List block, 1 child block type', () => {
const props = {
Expand All @@ -142,7 +142,7 @@ storiesOf('React StreamField demo', module)
]
};

return <StreamField {...props} id='stream-7' />;
return <StreamField {...props} id='stream' />;
})
.add('List block, 1 child block type, default value', () => {
const props = {
Expand All @@ -161,7 +161,7 @@ storiesOf('React StreamField demo', module)
],
value: []
};
return <StreamField {...props} id='stream-8' />;
return <StreamField {...props} id='stream' />;
})
.add('List block, 1 child block type, custom HTML', () => {
const props = {
Expand All @@ -181,7 +181,7 @@ storiesOf('React StreamField demo', module)
],
value: []
};
return <StreamField {...props} id='stream-9' />;
return <StreamField {...props} id='stream' />;
})
.add('List block, 2 children block types with groups', () => {
const props = {
Expand Down Expand Up @@ -228,7 +228,7 @@ storiesOf('React StreamField demo', module)
}
]
};
return <StreamField {...props} id='stream-10' />;
return <StreamField {...props} id='stream' />;
})
.add('Simple block layout', () => {
const props = {
Expand Down Expand Up @@ -261,7 +261,7 @@ storiesOf('React StreamField demo', module)
{ type: 'static' }
]
};
return <StreamField {...props} id='stream-11' />;
return <StreamField {...props} id='stream' />;
})
.add('Mixed block layouts', () => {
const props = {
Expand Down Expand Up @@ -293,7 +293,20 @@ storiesOf('React StreamField demo', module)
{ type: 'static' }
]
};
return <StreamField {...props} id='stream-12' />;
return <StreamField {...props} id='stream' />;
})
.add('Gutter of add buttons', () => {
const props = {
required: true,
gutteredAdd: true,
blockDefinitions: [
{
key: 'text',
}
],
value: []
};
return <StreamField {...props} id='stream' />
})
.add('Maximum number of blocks', () => {
const props = {
Expand All @@ -319,7 +332,7 @@ storiesOf('React StreamField demo', module)
}
]
};
return <StreamField {...props} id='stream-13' />;
return <StreamField {...props} id='stream' />;
})
.add('Error in one of the nested blocks', () => {
const props = {
Expand All @@ -345,7 +358,7 @@ storiesOf('React StreamField demo', module)
}
]
};
return <StreamField {...props} id='stream-14' />;
return <StreamField {...props} id='stream' />;
})
.add('Struct block', () => {
const props = {
Expand All @@ -366,7 +379,7 @@ storiesOf('React StreamField demo', module)
],
value: []
};
return <StreamField {...props} id='stream-15' />;
return <StreamField {...props} id='stream' />;
})
.add('Struct block with default value', () => {
const props = {
Expand All @@ -390,7 +403,7 @@ storiesOf('React StreamField demo', module)
value: []
};

return <StreamField {...props} id='stream-16' />;
return <StreamField {...props} id='stream' />;
})
.add('Struct block with custom HTML', () => {
const props = {
Expand All @@ -413,7 +426,7 @@ storiesOf('React StreamField demo', module)
],
value: []
};
return <StreamField {...props} id='stream-17' />;
return <StreamField {...props} id='stream' />;
})
.add('Struct block as a struct block field', () => {
const props = {
Expand Down Expand Up @@ -449,7 +462,7 @@ storiesOf('React StreamField demo', module)
}
]
};
return <StreamField {...props} id='stream-18' />;
return <StreamField {...props} id='stream' />;
})
.add('StructBlock as a list block child', () => {
const props = {
Expand Down Expand Up @@ -477,10 +490,10 @@ storiesOf('React StreamField demo', module)
],
value: []
};
return <StreamField {...props} id='stream-19' />;
return <StreamField {...props} id='stream' />;
})
.add('Complex nested StreamField', () => {
return <StreamField {...complexNestedStreamField} id='stream-20' />;
return <StreamField {...complexNestedStreamField} id='stream' />;
})
.add('Custom action icons', () => {
const props = {
Expand All @@ -504,7 +517,7 @@ storiesOf('React StreamField demo', module)
value: [{ type: 'title', value: 'Wagtail is awesome!' }]
};

return <StreamField {...props} id='stream-21' />;
return <StreamField {...props} id='stream' />;
})
.add('JavaScript widget', () => {
const props = {
Expand All @@ -520,5 +533,5 @@ storiesOf('React StreamField demo', module)
],
value: [],
};
return <StreamField {...props} id="stream-22" />;
return <StreamField {...props} id="stream" />;
});
12 changes: 5 additions & 7 deletions src/Block.js
Original file line number Diff line number Diff line change
Expand Up @@ -171,15 +171,13 @@ class Block extends React.Component {
);
}
return (
<>
<AnimateHeight className="draggable-container"
height={this.draggableHeight}
onAnimationEnd={this.onDraggableContainerAnimationEnd}>
{this.wrapSortable(blockContent)}
</AnimateHeight>
<AnimateHeight className="draggable-container"
height={this.draggableHeight}
onAnimationEnd={this.onDraggableContainerAnimationEnd}>
{this.wrapSortable(blockContent)}
<AddButton fieldId={fieldId} parentId={parentId} blockId={id}
visible={canAdd} />
</>
</AnimateHeight>
);
}
}
Expand Down
17 changes: 7 additions & 10 deletions src/BlocksContainer.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import {connect} from 'react-redux';
import {Droppable} from 'react-beautiful-dnd';
import Block from './Block';
Expand Down Expand Up @@ -31,6 +32,7 @@ import {getNestedBlockDefinition, isNA} from './processing/utils';
}
return {
minNum, maxNum,
gutteredAdd: fieldData.gutteredAdd,
blocksIds: blocksIds,
};
})
Expand All @@ -52,24 +54,19 @@ class BlocksContainer extends React.Component {
);
}

static getClassName(snapshot) {
let className = 'children-container';
if (snapshot.isDraggingOver) {
className += ' is-dragging';
}
return className;
}

render() {
const {fieldId, id, blocksIds, maxNum} = this.props;
const {fieldId, id, blocksIds, maxNum, gutteredAdd} = this.props;
const droppableId = `${fieldId}-${id}`;
const num = blocksIds.length;
const canAdd = num < maxNum;
return (
<Droppable droppableId={droppableId} type={droppableId}>
{(provided, snapshot) => (
<div ref={provided.innerRef}
className={BlocksContainer.getClassName(snapshot)}>
className={classNames(
'children-container',
snapshot.isDraggingOver && 'is-dragging',
gutteredAdd && 'guttered-add')}>
<AddButton fieldId={fieldId} parentId={id}
open={blocksIds.length === 0} visible={canAdd} />
{blocksIds.map(blockId => this.renderBlock(blockId, canAdd))}
Expand Down
9 changes: 5 additions & 4 deletions src/StreamField.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ class StreamField extends React.Component {
duplicate: PropTypes.string,
delete: PropTypes.string,
}),
gutteredAdd: PropTypes.bool,
blockDefinitions: PropTypes.arrayOf(BlockDefinitionType).isRequired,
value: PropTypes.arrayOf(BlockValueType).isRequired,
};
Expand Down Expand Up @@ -145,15 +146,15 @@ class StreamField extends React.Component {

componentDidMount() {
const {
initializeStreamField, required, minNum, maxNum, blockDefinitions, value,
initializeStreamField, required, minNum, maxNum, gutteredAdd,
blockDefinitions, value,
} = this.props;
const defaultProps = StreamFieldDefaultProps;
const icons = {...defaultProps.icons, ...this.props.icons};
const labels = {...defaultProps.labels, ...this.props.labels};
initializeStreamField({
required, minNum, maxNum, icons, labels, blockDefinitions,
isMobile: getIsMobile(),
value,
required, minNum, maxNum, icons, labels, gutteredAdd,
blockDefinitions, isMobile: getIsMobile(), value,
});
window.addEventListener('resize', this.onWindowResize);
}
Expand Down
34 changes: 16 additions & 18 deletions src/index.scss
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
$grid-gutter-width: 30px;
$header-padding: 8px;
$block-vertical-margin: 3px;
$block-full-margin: $block-vertical-margin 0;
$block-vertical-padding: 3px;
$block-full-padding: $block-vertical-padding 0;
$add-button-size: 34px;
$add-button-font-size: 28px;
$children-container-padding: $add-button-size / 2;
Expand All @@ -21,29 +21,33 @@ $error-border-color: #dbc7c8;
$error-border-color-focus: #cdb2b3;
$error-background-color: #fbefef;
$screen-xs-max: 799px;
$screen-sm-min: 800px;

.children-container {
position: relative;
padding: $children-container-padding 0
$children-container-padding $add-button-size;
$children-container-padding 0;
transition: padding $hover-transition-duration ease-in-out;
@media (max-width: $screen-xs-max) {
padding-left: 0;
padding-top: $children-container-padding + $add-button-size;
&.guttered-add {
@media (min-width: $screen-sm-min) {
padding-left: $add-button-size;
button.add {
position: absolute;
width: $add-button-size;
transform: translate(-100%, -50%);
}
}
}
&.is-dragging {
> button.add.visible {
button.add.visible {
opacity: 0;
pointer-events: none;
}
}
.block {
position: relative;
display: flex;
margin: $block-full-margin;
@media (max-width: $screen-xs-max) {
margin-bottom: $block-vertical-margin + $add-button-size;
}
padding: $block-full-padding;
&.has-error {
> .block-container {
border-color: $error-border-color;
Expand Down Expand Up @@ -209,15 +213,13 @@ $screen-xs-max: 799px;
}
}
button.add {
position: absolute;
width: $add-button-size;
width: 100%;
height: $add-button-size;
appearance: none;
border: none;
color: $teal;
font-weight: bold;
background: none;
transform: translate(-100%, -50%);
padding: 0;
cursor: pointer;
outline: none;
Expand All @@ -231,10 +233,6 @@ $screen-xs-max: 799px;
opacity: 1;
pointer-events: unset;
}
@media (max-width: $screen-xs-max) {
width: 100%;
transform: translate(0, -100%);
}
i {
display: block;
transition: transform $add-transition-duration $bounce-transition-timing;
Expand Down
7 changes: 4 additions & 3 deletions src/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,14 @@ export default (state=initialState, action) => {
case 'INITIALIZE_STREAM_FIELD': {
const data = deepCopy(action.data);
const {
required, minNum, maxNum, icons, labels, blockDefinitions, isMobile,
value,
required, minNum, maxNum, icons, labels, gutteredAdd,
blockDefinitions, isMobile, value,
} = data;
state = {
...state,
[action.id]: {
required, minNum, maxNum, icons, labels, blockDefinitions, isMobile,
required, minNum, maxNum, icons, labels, gutteredAdd,
blockDefinitions, isMobile,
},
};
return valueToState(state, action.id, value);
Expand Down

0 comments on commit 5e90f50

Please sign in to comment.