Skip to content

Instantly share code, notes, and snippets.

@artyorsh
Created March 30, 2020 16:17
Show Gist options
  • Save artyorsh/f4521fb53ade5dad5a6c880f7785e971 to your computer and use it in GitHub Desktop.
Save artyorsh/f4521fb53ade5dad5a6c880f7785e971 to your computer and use it in GitHub Desktop.
import React from 'react';
import { StyleSheet, View, ViewProps, ViewStyle } from 'react-native';
import { ButtonElement } from '@ui-kitten/components';
interface ButtonSwitchProps extends ViewProps {
fullWidth?: boolean;
children: ButtonElement[];
selectedIndex: number;
onSelect: (index: number) => void;
}
export type ButtonSwitchElement = React.ReactElement<ButtonSwitchProps>;
const STATUS_DEFAULT: string = 'basic';
const STATUS_SELECTED: string = 'primary';
export class ButtonSwitch extends React.Component<ButtonSwitchProps> {
private get childCount(): number {
return React.Children.count(this.props.children);
}
private getBorderStyleForPosition = (index: number): ViewStyle => {
switch (index) {
case 0: return styles.firstButton;
case this.childCount - 1: return styles.lastButton;
default: return styles.middleButton;
}
};
private renderComponentChildren = (children: ButtonElement[]): ButtonElement[] => {
return React.Children.map(children, (element: ButtonElement, index: number): ButtonElement => {
const borderStyle: ViewStyle = this.getBorderStyleForPosition(index);
return React.cloneElement(element, {
style: [element.props.style, borderStyle, this.props.fullWidth && styles.buttonFullWidth],
status: index === this.props.selectedIndex ? STATUS_SELECTED : STATUS_DEFAULT,
onPress: () => this.props.onSelect(index),
});
});
};
public render(): React.ReactElement<ViewProps> {
const { style, children, ...viewProps } = this.props;
return (
<View
{...viewProps}
style={[styles.container, style]}>
{this.renderComponentChildren(children)}
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
alignItems: 'center',
},
firstButton: {
borderTopEndRadius: 0,
borderBottomEndRadius: 0,
},
middleButton: {
borderRadius: 0,
},
lastButton: {
borderTopStartRadius: 0,
borderBottomStartRadius: 0,
},
buttonFullWidth: {
flex: 1,
},
});
@TMcLoone
Copy link

Hey do you have an example of how to use this?

@SaltedBlowfish
Copy link

Usage is pretty straightforward, but I'll leave this here for anyone else looking for a quick copy / paste:

export default ({}: Props) => {
  const [selectedIndex, setSelectedIndex] = React.useState(0);

  return (
    <ButtonSwitch
      onSelect={(index) => setSelectedIndex(index)}
      selectedIndex={selectedIndex}
      fullWidth>
      <Button>OPTION 0</Button>
      <Button>OPTION 1</Button>
      <Button>OPTION 2</Button>
    </ButtonSwitch>
  );
};

This yields the following:

image
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment