Skip to content

Commit

Permalink
Add support for custom icons in actions [ActionButton] (#66)
Browse files Browse the repository at this point in the history
* [ActionButton] Add support for custom icons in actions.

* Fix key prop

* Fix eslint errors.

* Moved action item key calculation to function.
  • Loading branch information
NewOldMax authored and xotahal committed Jan 28, 2017
1 parent c466c33 commit 094a90d
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 34 deletions.
10 changes: 8 additions & 2 deletions docs/ActionButton.md
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,19 @@ render() {
```js
const propTypes = {
/**
* Array of names of icons that will be shown after the main button is pressed
* Array of names of icons (or elements) that will be shown after the main button is pressed
* Remember, you should specify key for each element, if you use array of elements
*/
actions: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.string),
PropTypes.arrayOf(PropTypes.element),
PropTypes.arrayOf(PropTypes.shape({
icon: PropTypes.string,
icon: PropTypes.oneOfType([
PropTypes.string,
PropTypes.element,
]),
label: PropTypes.string,
name: PropTypes.string,
})),
]),
/**
Expand Down
152 changes: 120 additions & 32 deletions src/ActionButton/ActionButton.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,19 @@ import getPlatformElevation from '../styles/getPlatformElevation';

const propTypes = {
/**
* Array of names of icons that will be shown after the main button is pressed
* Array of names of icons (or elements) that will be shown after the main button is pressed
* Remember, you should specify key for each element, if you use array of elements
*/
actions: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.string),
PropTypes.arrayOf(PropTypes.element),
PropTypes.arrayOf(PropTypes.shape({
icon: PropTypes.string,
icon: PropTypes.oneOfType([
PropTypes.string,
PropTypes.element,
]),
label: PropTypes.string,
name: PropTypes.string,
})),
]),
/**
Expand Down Expand Up @@ -190,6 +196,15 @@ class ActionButton extends PureComponent {
onPress(action);
}
}
getActionItemKey = ({ icon, name }) => {
let key = icon;
if (name) {
key = name;
} else if (React.isValidElement(icon) && icon.key) {
key = icon.key;
}
return key;
}
toggleState = () => {
const { transition } = this.props;

Expand Down Expand Up @@ -225,16 +240,16 @@ class ActionButton extends PureComponent {
return (
<View style={styles.toolbarPositionContainer}>
<View key="main-button" style={styles.toolbarContainer}>
{actions.map(action => (
<View key={action} style={styles.toolbarActionContainer}>
<IconToggle
key={action}
name={action}
onPress={() => this.onPress(action)}
style={{ icon: styles.icon }}
/>
</View>
))}
{actions.map((action) => {
if (typeof action === 'string') {
return this.renderToolbarAction(styles, action);
}
if (React.isValidElement(action)) {
return this.renderToolbarElementAction(styles, action);
}
return this.renderToolbarLabelAction(
styles, action.icon, action.label, action.name);
})}
</View>
</View>
);
Expand All @@ -253,8 +268,12 @@ class ActionButton extends PureComponent {
return this.renderAction(styles, action);
}

if (React.isValidElement(action)) {
return this.renderElementAction(styles, action);
}

return this.renderLabelAction(
styles, action.icon, action.label);
styles, action.icon, action.label, action.name);
})}
</View>
{this.renderMainButton(styles)}
Expand Down Expand Up @@ -285,32 +304,101 @@ class ActionButton extends PureComponent {
</View>
);
}
renderAction = (styles, icon) => (
<View key={icon} style={styles.speedDialActionIconContainer}>
<View style={styles.speedDialActionIcon}>
renderToolbarAction = (styles, icon, name) => {
let content;
const key = this.getActionItemKey({ icon, name });

if (React.isValidElement(icon)) {
content = (
<RippleFeedback
color="#AAF"
onPress={() => this.onPress(icon)}
onPress={() => this.onPress(key)}
delayPressIn={20}
>
{this.renderIconButton(styles, icon)}
</RippleFeedback>
</RippleFeedback>);
} else {
content = (
<IconToggle
key={key}
name={key}
onPress={() => this.onPress(key)}
style={{ icon: styles.icon }}
/>);
}
return (
<View key={key} style={styles.toolbarActionContainer}>
{content}
</View>
</View>
)
renderLabelAction = (styles, icon, label) => (
<View key={icon} style={styles.speedDialActionContainer}>
<View style={styles.speedDialActionLabelContainer}>
<Text style={styles.speedDialActionLabel}>{label}</Text>
);
}
renderToolbarElementAction = (styles, icon) => {
const key = this.getActionItemKey({ icon });
return (
<View key={key} style={styles.toolbarActionContainer}>
{this.renderToolbarAction(styles, icon)}
</View>
);
}
/**
* TODO: implement labels for toolbar?
*/
renderToolbarLabelAction = (styles, icon, label, name) => {
const key = this.getActionItemKey({ icon, name });
return (
<View key={key} style={styles.toolbarActionContainer}>
{this.renderToolbarAction(styles, icon, name)}
</View>
{this.renderAction(styles, icon)}
</View>
)
renderIconButton = (styles, name) => (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Icon name={name} style={styles.icon} />
</View>
)
);
}
renderAction = (styles, icon, name) => {
const key = this.getActionItemKey({ icon, name });
return (
<View key={key} style={styles.speedDialActionIconContainer}>
<View style={styles.speedDialActionIcon}>
<RippleFeedback
color="#AAF"
onPress={() => this.onPress(key)}
delayPressIn={20}
>
{this.renderIconButton(styles, icon)}
</RippleFeedback>
</View>
</View>
);
}
renderElementAction = (styles, icon) => {
const key = this.getActionItemKey({ icon });
return (
<View key={key} style={styles.speedDialActionContainer}>
{this.renderAction(styles, icon)}
</View>
);
}
renderLabelAction = (styles, icon, label, name) => {
const key = this.getActionItemKey({ icon, name });
return (
<View key={key} style={styles.speedDialActionContainer}>
<View style={styles.speedDialActionLabelContainer}>
<Text style={styles.speedDialActionLabel}>{label}</Text>
</View>
{this.renderAction(styles, icon, name)}
</View>
);
}
renderIconButton = (styles, icon) => {
let result;
if (React.isValidElement(icon)) {
result = icon;
} else {
result = <Icon name={icon} style={styles.icon} />;
}
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
{result}
</View>
);
}
renderButton = styles => (
<Animated.View
style={[styles.positionContainer, {
Expand Down

0 comments on commit 094a90d

Please sign in to comment.