Skip to content

Commit

Permalink
Update padding logic for sm/xs button
Browse files Browse the repository at this point in the history
  • Loading branch information
nathanbrud committed May 22, 2023
1 parent 8b55ff8 commit 559b567
Show file tree
Hide file tree
Showing 3 changed files with 204 additions and 7 deletions.
34 changes: 28 additions & 6 deletions src/components/Button/Button.style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ export const ButtonStyled = styled.button<any>`

const sizePads = {
xxs: 0.125,
xs: 0.25,
sm: 0.5,
xs: 0.3125,
sm: 0.625,
md: 0.75,
lg: 1,
xl: 1.25,
Expand Down Expand Up @@ -134,24 +134,46 @@ function buttonMotion({ theme }) {

function buttonPadding({ icon, iconOnly, iconPosition, size }) {
return (
!iconOnly && iconButtonPadding(icon, iconPosition, sizePads[size])
!iconOnly &&
iconButtonPadding(icon, iconPosition, sizePads[size], size)
);
}

function iconButtonPadding(icon, iconPosition, pad) {
function iconButtonPadding(icon, iconPosition, pad, size) {
const minHeight = rem(3);
const minWidth = `${pad * 4 + 2}rem`;

// Some button sizes are "off" the padding formula based on design decions
const sizeAdjustments = {
xxs: { left: 0, right: 0 },
xs: { left: 0.065, right: 0.19125 },
sm: { left: -0.125, right: -0.125 },
md: { left: 0, right: 0 },
lg: { left: 0, right: 0 },
xl: { left: 0, right: 0 },
xxl: { left: 0, right: 0 },
};

switch (icon && iconPosition) {
case 'left':
return {
padding: '0 ' + pad + 'rem',
padding:
'0 ' +
(pad + sizeAdjustments[size].right) +
'rem 0 ' +
(pad + sizeAdjustments[size].left) +
'rem',
minHeight,
minWidth,
};
case 'right':
return {
padding: '0 ' + pad + 'rem',
padding:
'0 ' +
(pad + sizeAdjustments[size].right) +
'rem 0 ' +
(pad + sizeAdjustments[size].left) +
'rem',
minHeight,
minWidth,
};
Expand Down
175 changes: 175 additions & 0 deletions src/components/Button/Button.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
import '@testing-library/jest-dom';
import {
fireEvent,
render,
RenderOptions,
screen,
} from '@testing-library/react';
import React, { ReactElement } from 'react';

import { ThemeProvider } from 'styled-components';
import { Pencil } from '../../icons';
import { themes } from '../../themes';
import { Button } from './Button';

const Provider = ({ children }) => {
return (
<ThemeProvider theme={themes['light']}>{children}</ThemeProvider>
);
};

const renderWithThemeProvider = (
ui: ReactElement,
options?: Omit<RenderOptions, 'wrapper'>
) => render(ui, { wrapper: Provider, ...options });

describe('Button', () => {
it('Renders button', () => {
renderWithThemeProvider(<Button />);
const button = screen.getByRole('button');
expect(button).toBeInTheDocument();
});

it('Calls onClick handler when clicked', () => {
const handleClick = jest.fn();
const { getByText } = renderWithThemeProvider(
<Button onClick={handleClick}>Click me</Button>
);
const buttonElement = getByText('Click me');
fireEvent.click(buttonElement);
expect(handleClick).toHaveBeenCalledTimes(1);
});

it('Renders button with text child', () => {
const text = 'Click me';

const { getByText } = renderWithThemeProvider(
<Button>{text}</Button>
);

const buttonElement = getByText(text);
expect(buttonElement).toBeInTheDocument();
});

it('Renders button with icon', () => {
renderWithThemeProvider(<Button icon={<Pencil />} />);
const button = screen.getByRole('button');
expect(button.innerHTML).toContain('svg');
});

it('Renders button with icon on the right', () => {
renderWithThemeProvider(
<Button icon={<Pencil />} iconPosition="right">
Hello
</Button>
);

const button = screen.getByRole('button');
expect(button.children[0].tagName.toLocaleLowerCase()).toBe(
'span'
);
});

it('Renders loader', () => {
renderWithThemeProvider(<Button loading />);
const button = screen.getByRole('button');
expect(button.innerHTML).toContain('Loader');
});

it('Sets color of a button', () => {
const color = '#CCCCCC';
renderWithThemeProvider(<Button color={color} />);
const button = screen.getByRole('button');
expect(button).toHaveStyle({ background: color });
});

it('Changes size of a button', () => {
const { rerender } = renderWithThemeProvider(
<Button size="sm" />
);
const button = screen.getByRole('button');
expect(button).toHaveStyle({ fontSize: '0.875rem' });

rerender(<Button size="md" />);
expect(button).toHaveStyle({ fontSize: '0.875rem' });

rerender(<Button size="xs" />);
expect(button).toHaveStyle({ fontSize: '0.75rem' });

rerender(<Button size="lg" />);
expect(button).toHaveStyle({ fontSize: '1rem' });

rerender(<Button size="xl" />);
expect(button).toHaveStyle({ fontSize: '1.125rem' });
});

it('Changes status of a button', () => {
const { rerender } = renderWithThemeProvider(
<Button status="positive" />
);
const button = screen.getByRole('button');
expect(button).toHaveStyle({
background: '#28A878',
});

rerender(<Button status="negative" />);
expect(button).toHaveStyle({ background: '#E22B12' });
});

it('Changes format of a button', () => {
const { rerender } = renderWithThemeProvider(
<Button format="secondary" />
);
const button = screen.getByRole('button');
expect(button).toHaveStyle({
background: '#efefef',
});

rerender(<Button format="soft" />);
expect(button).toHaveStyle({ background: '#23313b' });
});

it('Changes variant of a button', () => {
const { rerender } = renderWithThemeProvider(
<Button variant="dashed" />
);
const button = screen.getByRole('button');
expect(button).toHaveStyle({
borderStyle: 'dashed',
});

rerender(<Button variant="hyperminimal" />);
expect(button).toHaveStyle({ borderColor: 'transparent' });
});

it('Changes element of a button', () => {
const { rerender, container } = renderWithThemeProvider(
<Button element="a" />
);
const buttonAnchor = container.querySelector('a');
expect(buttonAnchor).toBeInTheDocument();

rerender(<Button element="span" />);
const buttonSpan = container.querySelector('span');
expect(buttonSpan).toBeInTheDocument();

const button = container.querySelector('button');
expect(button).not.toBeInTheDocument();
});

it('Renders pill button', () => {
renderWithThemeProvider(<Button pill>Hello</Button>);
const button = screen.getByRole('button');

expect(button).toHaveStyle({
borderRadius: '2rem',
});
});

it('Renders disabled button', () => {
renderWithThemeProvider(<Button disabled>Hello</Button>);
const button = screen.getByRole('button');

expect(button).toHaveAttribute('disabled');
});
});
2 changes: 1 addition & 1 deletion src/components/Button/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ function ButtonComponent({
/>
)}

<Focus parent={ButtonStyled} radius={radius} />
<Focus parent={ButtonStyled} radius={radius} isKeyboardOnly />
</ButtonStyled>
);
}

0 comments on commit 559b567

Please sign in to comment.