Skip to content

Commit

Permalink
Component/4518 button tertiary (#4525)
Browse files Browse the repository at this point in the history
* [WIP] Push up icon changes

* Introduce assets

* Create script to generate Icon types based on icons in assets directory

* Change Icon component to use SVGs. Create script to auto generate SVG types. Use an svg transformer to allow for importing SVGs as components

* Update ignores on Icon.assets

* Update generate-assets script to add ignores

* Remove icon test - SVG mock issue. Update Icon docs with color prop

* Fix useStyles for other components

* Create BaseButton component

* Update Icon README

* Clean up BaseButton

* Create ButtomPrimary

* Add more stories to BaseButton

* Finalize ButtonPrimary

* Simplify ButtonPrimary types

* Clean up BaseButton

* Create secondary button

* Update test

* Update ButtonPrimary

* Create snapshot

* Create tertiary button

* Add variant

* Add vvariant

* Add variants

* Update test

* Update BaseButton type to extend TouchableOpacity

* Add pressed color

* Add pressed state

* Clean up types

* Update test

* Add pressed state
  • Loading branch information
Cal-L authored Jun 28, 2022
1 parent d86d23a commit ca3a1fe
Show file tree
Hide file tree
Showing 9 changed files with 270 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/* eslint-disable no-console */
import React from 'react';
import { storiesOf } from '@storybook/react-native';
import { select, text } from '@storybook/addon-knobs';
import { IconName } from '../Icon';
import { BaseButtonSize } from '../BaseButton';
import ButtonTertiary from './ButtonTertiary';
import { ButtonTertiaryVariant } from './ButtonTertiary.types';

storiesOf('Component Library / ButtonTertiary', module)
.addDecorator((getStory) => getStory())
.add('Default', () => {
const groupId = 'Props';
const sizeSelector = select(
'size',
BaseButtonSize,
BaseButtonSize.Md,
groupId,
);
const iconSelector = select(
'icon',
IconName,
IconName.AddSquareFilled,
groupId,
);
const labelSelector = text('label', 'Click Me!', groupId);

return (
<ButtonTertiary
icon={iconSelector}
size={sizeSelector}
label={labelSelector}
onPress={() => console.log("I'm clicked!")}
variant={ButtonTertiaryVariant.Normal}
/>
);
})
.add('Without icon', () => (
<ButtonTertiary
size={BaseButtonSize.Md}
label={'Click Me!'}
onPress={() => console.log("I'm clicked!")}
variant={ButtonTertiaryVariant.Normal}
/>
))
.add('Danger variant', () => (
<ButtonTertiary
size={BaseButtonSize.Md}
label={'Click Me!'}
onPress={() => console.log("I'm clicked!")}
variant={ButtonTertiaryVariant.Danger}
/>
));
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { StyleSheet, ViewStyle } from 'react-native';
import {
ButtonTertiaryStyleSheet,
ButtonTertiaryStyleSheetVars,
} from './ButtonTertiary.types';

/**
* Style sheet function for ButtonPrimary component.
*
* @param params Style sheet params.
* @param params.vars Inputs that the style sheet depends on.
* @returns StyleSheet object.
*/
const styleSheet = (params: {
vars: ButtonTertiaryStyleSheetVars;
}): ButtonTertiaryStyleSheet => {
const { vars } = params;
const { style } = vars;

return StyleSheet.create({
base: Object.assign(
{
backgroundColor: 'transparent',
} as ViewStyle,
style,
) as ViewStyle,
});
};

export default styleSheet;
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from 'react';
import { shallow } from 'enzyme';
import { IconName } from '../Icon';
import { BaseButtonSize } from '../BaseButton';
import ButtonTertiary from './ButtonTertiary';
import { ButtonTertiaryVariant } from './ButtonTertiary.types';

describe('ButtonTertiary', () => {
it('should render correctly', () => {
const wrapper = shallow(
<ButtonTertiary
icon={IconName.BankFilled}
size={BaseButtonSize.Md}
label={'Click me!'}
onPress={() => null}
variant={ButtonTertiaryVariant.Normal}
/>,
);
expect(wrapper).toMatchSnapshot();
});
});
65 changes: 65 additions & 0 deletions app/component-library/components/ButtonTertiary/ButtonTertiary.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/* eslint-disable react/prop-types */
import React, { useCallback, useMemo, useState } from 'react';
import { GestureResponderEvent } from 'react-native';
import { useStyles } from '../../hooks';
import BaseButton from '../BaseButton';
import styleSheet from './ButtonTertiary.styles';
import {
ButtonTertiaryProps,
ButtonTertiaryVariant,
} from './ButtonTertiary.types';

const ButtonTertiary = ({
style,
onPressIn,
onPressOut,
variant,
...props
}: ButtonTertiaryProps): JSX.Element => {
const [pressed, setPressed] = useState(false);
const { styles, theme } = useStyles(styleSheet, { style, variant });
const labelColor = useMemo(() => {
let color: string;
switch (variant) {
case ButtonTertiaryVariant.Normal:
color = pressed
? theme.colors.primary.alternative
: theme.colors.primary.default;
break;
case ButtonTertiaryVariant.Danger:
color = pressed
? theme.colors.error.alternative
: theme.colors.error.default;
break;
}
return color;
}, [theme, variant, pressed]);

const triggerOnPressedIn = useCallback(
(e: GestureResponderEvent) => {
setPressed(true);
onPressIn?.(e);
},
[setPressed, onPressIn],
);

const triggerOnPressedOut = useCallback(
(e: GestureResponderEvent) => {
setPressed(false);
onPressOut?.(e);
},
[setPressed, onPressOut],
);

return (
<BaseButton
style={styles.base}
labelColor={labelColor}
onPressIn={triggerOnPressedIn}
onPressOut={triggerOnPressedOut}
{...props}
/>
);
};

export default ButtonTertiary;
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { ViewStyle } from 'react-native';
import { BaseButtonProps } from '../BaseButton';

/**
* Enum used to select between variants.
*/
export enum ButtonTertiaryVariant {
Normal = 'Normal',
Danger = 'Danger',
}

/**
* ButtonTertiary component props.
*/
export interface ButtonTertiaryProps
extends Omit<BaseButtonProps, 'labelColor'> {
variant: ButtonTertiaryVariant;
}

/**
* ButtonTertiary component style sheet.
*/
export interface ButtonTertiaryStyleSheet {
base: ViewStyle;
}

/**
* Style sheet input parameters.
*/
export type ButtonTertiaryStyleSheetVars = Pick<
ButtonTertiaryProps,
'style' | 'variant'
>;
47 changes: 47 additions & 0 deletions app/component-library/components/ButtonTertiary/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# ButtonTertiary

ButtonTertiary is used for secondary call to actions.

## Props

This component extends `ViewProps` from React Native's [View Component](https://reactnative.dev/docs/view).

### `label`

Button text.

| <span style="color:gray;font-size:14px">TYPE</span> | <span style="color:gray;font-size:14px">REQUIRED</span> |
| :-------------------------------------------------- | :------------------------------------------------------ |
| string | Yes |

### `size`

Enum to select between size variants.

| <span style="color:gray;font-size:14px">TYPE</span> | <span style="color:gray;font-size:14px">REQUIRED</span> |
| :----------------------------------------------------- | :------------------------------------------------------ |
| [BaseButtonSize](../BaseButton/BaseButton.types.ts#L4) | Yes |

### `onPress`

Function to trigger when pressing the button.

| <span style="color:gray;font-size:14px">TYPE</span> | <span style="color:gray;font-size:14px">REQUIRED</span> |
| :-------------------------------------------------- | :------------------------------------------------------ |
| Function | Yes |

### `iconName`

Icon to use.

| <span style="color:gray;font-size:14px">TYPE</span> | <span style="color:gray;font-size:14px">REQUIRED</span> |
| :-------------------------------------------------- | :------------------------------------------------------ |
| [IconName](../Icon/Icon.types.ts#53) | False |

### `variant`

Enum used to select between variants.

| <span style="color:gray;font-size:14px">TYPE</span> | <span style="color:gray;font-size:14px">REQUIRED</span> |
| :---------------------------------------------------- | :------------------------------------------------------ |
| [ButtonTertiaryVariant](./ButtonTertiary.types.ts#L7) | Yes |
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`ButtonTertiary should render correctly 1`] = `
<BaseButton
icon="BankFilled"
label="Click me!"
labelColor="#037DD6"
onPress={[Function]}
onPressIn={[Function]}
onPressOut={[Function]}
size="40"
style={
Object {
"backgroundColor": "transparent",
}
}
/>
`;
1 change: 1 addition & 0 deletions app/component-library/components/ButtonTertiary/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './ButtonTertiary';
2 changes: 2 additions & 0 deletions storybook/storyLoader.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ function loadStories() {
require('../app/component-library/components/BaseButton/BaseButton.stories');
require('../app/component-library/components/ButtonPrimary/ButtonPrimary.stories');
require('../app/component-library/components/ButtonSecondary/ButtonSecondary.stories');
require('../app/component-library/components/ButtonTertiary/ButtonTertiary.stories');
require('../app/component-library/components/BaseText/BaseText.stories');
require('../app/component-library/components/Icon/Icon.stories');
require('../app/component-library/components/Link/Link.stories');
Expand All @@ -36,6 +37,7 @@ const stories = [
'../app/component-library/components/BaseButton/BaseButton.stories',
'../app/component-library/components/ButtonPrimary/ButtonPrimary.stories',
'../app/component-library/components/ButtonSecondary/ButtonSecondary.stories',
'../app/component-library/components/ButtonTertiary/ButtonTertiary.stories',
'../app/component-library/components/BaseText/BaseText.stories',
'../app/component-library/components/Icon/Icon.stories',
'../app/component-library/components/Link/Link.stories',
Expand Down

0 comments on commit ca3a1fe

Please sign in to comment.