Skip to content

Commit

Permalink
Merge pull request #266 from lifeomic/feature/positive-negative-btns
Browse files Browse the repository at this point in the history
feat: Add positive and  negative `color` values to `<Button`
  • Loading branch information
dexterca authored May 20, 2022
2 parents 68c9423 + dda70ed commit 45fa56c
Show file tree
Hide file tree
Showing 8 changed files with 262 additions and 6 deletions.
1 change: 1 addition & 0 deletions src/colors/green.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const green: SimplePaletteColorOptions & Color = {
...shades,
main: shades[800],
light: shades[500],
dark: shades[900],
contrastText: text.contrast,
};

Expand Down
1 change: 1 addition & 0 deletions src/colors/red.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const red: SimplePaletteColorOptions & Color = {
...shades,
main: shades[800],
light: shades[600],
dark: shades[900],
contrastText: text.contrast,
};

Expand Down
82 changes: 82 additions & 0 deletions src/components/Button/Button.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,89 @@ test('it renders with `variant="text" color="inverse"`', async () => {
const button = await findByTestId(testId);
expect(button).toHaveClass('ChromaButton-textInverse');
});
// #endregion

// #region negative tests
test('it renders with `variant="contained" color="negative"`', async () => {
const props = getBaseProps();
const { findByTestId } = renderWithTheme(
<Button
{...props}
data-testid={testId}
variant="contained"
color="negative"
>
Button
</Button>
);
const button = await findByTestId(testId);
expect(button).toHaveClass('ChromaButton-containedNegative');
});

test('it renders with `variant="outlined" color="negative"`', async () => {
const props = getBaseProps();
const { findByTestId } = renderWithTheme(
<Button {...props} data-testid={testId} variant="outlined" color="negative">
Button
</Button>
);
const button = await findByTestId(testId);
expect(button).toHaveClass('ChromaButton-outlinedNegative');
});

test('it renders with `variant="text" color="negative"`', async () => {
const props = getBaseProps();
const { findByTestId } = renderWithTheme(
<Button {...props} data-testid={testId} variant="text" color="negative">
Button
</Button>
);
const button = await findByTestId(testId);
expect(button).toHaveClass('ChromaButton-textNegative');
});
// #endregion

// #region positive tests
test('it renders with `variant="contained" color="positive"`', async () => {
const props = getBaseProps();
const { findByTestId } = renderWithTheme(
<Button
{...props}
data-testid={testId}
variant="contained"
color="positive"
>
Button
</Button>
);
const button = await findByTestId(testId);
expect(button).toHaveClass('ChromaButton-containedPositive');
});

test('it renders with `variant="outlined" color="positive"`', async () => {
const props = getBaseProps();
const { findByTestId } = renderWithTheme(
<Button {...props} data-testid={testId} variant="outlined" color="positive">
Button
</Button>
);
const button = await findByTestId(testId);
expect(button).toHaveClass('ChromaButton-outlinedPositive');
});

test('it renders with `variant="text" color="positive"`', async () => {
const props = getBaseProps();
const { findByTestId } = renderWithTheme(
<Button {...props} data-testid={testId} variant="text" color="positive">
Button
</Button>
);
const button = await findByTestId(testId);
expect(button).toHaveClass('ChromaButton-textPositive');
});
// #endregion

// #region trailing icon tests
test('it renders a trailing icon', async () => {
const props = getBaseProps();
const { findByTestId } = renderWithTheme(
Expand Down
78 changes: 76 additions & 2 deletions src/components/Button/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export const useStyles = makeStyles(
(theme) => ({
root: {
background: theme.palette.primary.main,
border: `1px solid transparent`,
border: `${theme.pxToRem(1)} solid transparent`,
borderRadius: theme.pxToRem(4),
color: theme.palette.common.white,
cursor: 'pointer',
Expand Down Expand Up @@ -141,6 +141,70 @@ export const useStyles = makeStyles(
opacity: 0.44,
},
},
containedNegative: {
backgroundColor: theme.palette.negative.main,
color: theme.palette.common.white,
'&:hover': {
backgroundColor: theme.palette.negative.dark,
},
'&:disabled, &[disabled]': {
backgroundColor: theme.palette.negative.main,
color: theme.palette.common.white,
},
},
containedPositive: {
backgroundColor: theme.palette.positive.main,
color: theme.palette.common.white,
'&:hover': {
backgroundColor: theme.palette.positive.dark,
},
'&:disabled, &[disabled]': {
backgroundColor: theme.palette.positive.main,
color: theme.palette.common.white,
},
},
outlinedNegative: {
borderColor: theme.palette.negative.main,
color: theme.palette.negative.main,
'&:hover': {
borderColor: theme.palette.negative.dark,
color: theme.palette.negative.dark,
},
'&:disabled, &[disabled]': {
borderColor: theme.palette.negative.main,
color: theme.palette.negative.main,
},
},
outlinedPositive: {
borderColor: theme.palette.positive.main,
color: theme.palette.positive.main,
'&:hover': {
borderColor: theme.palette.positive.dark,
color: theme.palette.positive.dark,
},
'&:disabled, &[disabled]': {
borderColor: theme.palette.positive.main,
color: theme.palette.positive.main,
},
},
textNegative: {
color: theme.palette.negative.main,
'&:hover': {
color: theme.palette.negative.dark,
},
'&:disabled': {
color: theme.palette.negative.main,
},
},
textPositive: {
color: theme.palette.positive.main,
'&:hover': {
color: theme.palette.positive.dark,
},
'&:disabled': {
color: theme.palette.positive.main,
},
},
fullWidth: {
width: '100%',
},
Expand All @@ -164,7 +228,7 @@ export type ButtonClasses = GetClasses<typeof useStyles>;

export interface ButtonProps extends React.ComponentPropsWithoutRef<'button'> {
children?: React.ReactNode;
color?: 'default' | 'inverse';
color?: 'default' | 'inverse' | 'negative' | 'positive';
disabled?: boolean;
fullWidth?: boolean;
icon?: React.ComponentType<React.SVGProps<SVGSVGElement>>;
Expand Down Expand Up @@ -203,6 +267,16 @@ export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
[classes.outlinedInverse]:
variant === 'outlined' && color === 'inverse',
[classes.textInverse]: variant === 'text' && color === 'inverse',
[classes.containedNegative]:
variant === 'contained' && color === 'negative',
[classes.outlinedNegative]:
variant === 'outlined' && color === 'negative',
[classes.textNegative]: variant === 'text' && color === 'negative',
[classes.containedPositive]:
variant === 'contained' && color === 'positive',
[classes.outlinedPositive]:
variant === 'outlined' && color === 'positive',
[classes.textPositive]: variant === 'text' && color === 'positive',
},
fullWidth && classes.fullWidth,
className
Expand Down
14 changes: 12 additions & 2 deletions src/styles/__snapshots__/createTheme.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ Object {
"800": "#c31533",
"900": "#b40027",
"contrastText": "#f8f8f8",
"dark": "#d01e3a",
"dark": "#b40027",
"light": "#e22941",
"main": "#c31533",
},
Expand Down Expand Up @@ -312,6 +312,7 @@ Object {
"800": "#429218",
"900": "#0f7000",
"contrastText": "#f8f8f8",
"dark": "#0f7000",
"light": "#7dcb35",
"main": "#429218",
},
Expand Down Expand Up @@ -354,6 +355,10 @@ Object {
"light": "#6a7887",
"main": "#455769",
},
"negative": Object {
"dark": "#b40027",
"main": "#c31533",
},
"orange": Object {
"100": "#fce4cc",
"200": "#fbd7b3",
Expand All @@ -369,6 +374,10 @@ Object {
"light": "#f5a24d",
"main": "#f27a00",
},
"positive": Object {
"dark": "#0f7000",
"main": "#429218",
},
"primary": Object {
"100": "#aae3f8",
"200": "#6dd1f4",
Expand Down Expand Up @@ -412,6 +421,7 @@ Object {
"800": "#c31533",
"900": "#b40027",
"contrastText": "#f8f8f8",
"dark": "#b40027",
"light": "#e22941",
"main": "#c31533",
},
Expand All @@ -427,7 +437,7 @@ Object {
"800": "#429218",
"900": "#0f7000",
"contrastText": "#f8f8f8",
"dark": "rgb(46, 102, 16)",
"dark": "#0f7000",
"light": "#7dcb35",
"main": "#429218",
},
Expand Down
8 changes: 8 additions & 0 deletions src/styles/createPalette.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ const baseMuiPalette = {
paper: grey[50],
default: '#f5f8fa',
},
negative: {
main: red.main,
dark: red.dark,
},
positive: {
main: green.main,
dark: green.dark,
},
};

const basePalette = {
Expand Down
76 changes: 76 additions & 0 deletions stories/components/Button/Button.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -146,10 +146,80 @@ const InversedButtonStory: React.FunctionComponent = () => (
Contained Button
</Button>
</Container>
<Container>
<Button
variant="contained"
color="inverse"
icon={Grid}
{...getPropOptions()}
>
Button w/ Icon
</Button>
</Container>
</div>
</React.Fragment>
);

const NegativeButtonStory: React.FunctionComponent = () => (
<React.Fragment>
<Container containerStyles={{ display: 'flex' }}>
<Button variant="text" color="negative" {...getPropOptions()}>
Text Button
</Button>
</Container>
<Container containerStyles={{ display: 'flex' }}>
<Button variant="outlined" color="negative" {...getPropOptions()}>
Outlined Button
</Button>
</Container>
<Container>
<Button variant="contained" color="negative" {...getPropOptions()}>
Contained Button
</Button>
</Container>
<Container>
<Button
variant="contained"
color="negative"
icon={Grid}
{...getPropOptions()}
>
Button w/ Icon
</Button>
</Container>
</React.Fragment>
);

const PositiveButtonStory: React.FunctionComponent = () => (
<React.Fragment>
<Container containerStyles={{ display: 'flex' }}>
<Button variant="text" color="positive" {...getPropOptions()}>
Text Button
</Button>
</Container>
<Container containerStyles={{ display: 'flex' }}>
<Button variant="outlined" color="positive" {...getPropOptions()}>
Outlined Button
</Button>
</Container>
<Container>
<Button variant="contained" color="positive" {...getPropOptions()}>
Contained Button
</Button>
</Container>
<Container>
<Button
variant="contained"
color="positive"
icon={Grid}
{...getPropOptions()}
>
Button w/ Icon
</Button>
</Container>
</React.Fragment>
);

storiesOf('Components/Button', module)
.add('Default', () => <AllButtonsStory />, {
readme: { content: defaultMd },
Expand All @@ -165,4 +235,10 @@ storiesOf('Components/Button', module)
})
.add('Inverse Color', () => <InversedButtonStory />, {
readme: { content: defaultMd },
})
.add('Negative Color', () => <NegativeButtonStory />, {
readme: { content: defaultMd },
})
.add('Positive Color', () => <PositiveButtonStory />, {
readme: { content: defaultMd },
});
8 changes: 6 additions & 2 deletions stories/components/Button/default.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,15 @@ rendered after the text. It's recommended to use the Chromicons icon set.

### Color

When a button needs to be rendered, but on a dark-colored background, the
`color` prop can be utilized.
The button component takes multiple different colors, for different styled
buttons. Typically, the `inverse` color is used when a button needs to be
on a dark-colored background. When the action of the button will have a
negative or positive impact, `negative` or `positive` color are used.

```jsx
<Button color="inverse">Button</Button>
<Button color="negative">Button</Button>
<Button color="positive">Button</Button>
```

### Full Width
Expand Down

0 comments on commit 45fa56c

Please sign in to comment.