Skip to content

Commit

Permalink
feat(AbstractButton): Add getButtonTypeStyles function
Browse files Browse the repository at this point in the history
  • Loading branch information
maxime-gendron committed Jan 21, 2021
1 parent 7296e32 commit d784a81
Show file tree
Hide file tree
Showing 6 changed files with 140 additions and 219 deletions.
104 changes: 89 additions & 15 deletions packages/react/src/components/buttons/abstract-button.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,7 @@
import { AriaAttributes, ButtonHTMLAttributes, DetailedHTMLProps, ReactNode } from 'react';
import styled from 'styled-components';
import styled, { css, FlattenInterpolation, ThemeProps, DefaultTheme } from 'styled-components';
import { Theme } from '../../themes/theme';
import { focus } from '../../utils/css-state';

type PartialButtonProps =
Pick<DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, 'type'>
& AriaAttributes;

export interface AbstractButtonProps extends PartialButtonProps {
label?: string;
children?: ReactNode;
className?: string;
disabled?: boolean;

onClick?(): void;
}

export const AbstractButton = styled.button<{ isMobile: boolean }>`
align-items: center;
appearance: none;
Expand Down Expand Up @@ -47,3 +34,90 @@ export const AbstractButton = styled.button<{ isMobile: boolean }>`
color: inherit;
}
`;

type ButtonType = 'primary' | 'secondary' | 'tertiary' | 'destructive';

interface ButtonTypeStyles {
buttonType: ButtonType;
inversed?: boolean;
theme: Theme;
}

export const getButtonTypeStyles: (props: ButtonTypeStyles) => FlattenInterpolation<ThemeProps<DefaultTheme>> = (props: ButtonTypeStyles) => css`
${focus(props, true)};
${() => {
const { buttonType, theme, inversed } = props;
switch (buttonType) {
case 'primary':
return `
background-color: ${theme.main['primary-1.1']};
border-color: ${theme.main['primary-1.1']};
color: ${theme.greys.white};
&:hover {
background-color: ${theme.main['primary-1.3']};
border-color: ${theme.main['primary-1.3']};
}
&:disabled {
background-color: ${theme.main['primary-1.2']};
border-color: ${theme.main['primary-1.2']};
}
`;
case 'secondary':
return `
background-color: transparent;
border-color: ${theme.main['primary-1.1']};
color: ${theme.main['primary-1.1']};
&:hover {
border-color: ${theme.main['primary-1.3']};
color: ${theme.main['primary-1.3']};
}
&:disabled {
border-color: ${theme.main['primary-1.2']};
color: ${theme.main['primary-1.2']};
}
`;
case 'tertiary':
return `
background-color: transparent;
border-color: transparent;
color: ${theme.greys['dark-grey']};
&:hover {
background-color: ${theme.greys.grey};
color: ${theme.greys.black};
}
&:disabled {
background-color: transparent;
color: ${theme.greys['mid-grey']};
}
`;
case 'destructive':
// TODO change colors when updating thematization
return `
background-color: ${inversed ? theme.greys.white : theme.notifications['error-2.1']};
border-color: ${inversed ? theme.greys.white : theme.notifications['error-2.1']};
color: ${inversed ? theme.notifications['error-2.1'] : theme.greys.white};
&:hover {
background-color: ${inversed ? theme.greys.white : '#62071b'};
color: ${inversed ? '#62071b' : theme.greys.white};
}
&:disabled {
&,
&:focus,
&:hover {
background-color: ${inversed ? theme.greys.white : '#ea8da3'};
border-color: ${inversed ? theme.greys.white : '#ea8da3'};
color: ${inversed ? '#ea8da3' : theme.greys.white};
}
}
`;
}
}}
`;
27 changes: 15 additions & 12 deletions packages/react/src/components/buttons/add-button.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,38 @@
import React, { ButtonHTMLAttributes, DetailedHTMLProps, ReactElement } from 'react';
import React, { ReactElement } from 'react';
import styled from 'styled-components';
import { useDeviceContext } from '../device-context-provider/device-context-provider';
import { Icon } from '../icon/icon';
import { AbstractButtonProps } from './abstract-button';
import { Button } from './button';

type ButtonType = 'primary' | 'secondary' | 'tertiary';

type Type = DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>['type'];

const PlusIcon = styled(Icon)`
margin-right: var(--spacing-1x);
`;

interface ButtonProps extends Omit<AbstractButtonProps, 'children'> {
type ButtonType = 'primary' | 'secondary' | 'tertiary' | 'destructive';

type Type = 'submit' | 'button' | 'reset';

interface ButtonProps {
/**
* Visual style
* @default primary
* */
buttonType: ButtonType;
/**
* Sets button type
* @default submit
*/
buttonType: ButtonType;
className?: string;
disabled?: boolean;
inversed?: boolean;
label?: string;
type?: Type;

onClick?(): void;
}

export function AddButton({
className,
type = 'submit',
buttonType,
disabled,
inversed,
label,
onClick,
}: ButtonProps): ReactElement {
Expand All @@ -43,6 +45,7 @@ export function AddButton({
buttonType={buttonType}
onClick={onClick}
disabled={disabled}
inversed={inversed}
label={label}
>
<PlusIcon name="plusSign" size={isMobile ? '24' : '16'} />
Expand Down
98 changes: 13 additions & 85 deletions packages/react/src/components/buttons/button.tsx
Original file line number Diff line number Diff line change
@@ -1,108 +1,35 @@
import React, { ReactElement } from 'react';
import React, { ReactElement, ReactNode } from 'react';
import styled from 'styled-components';
import { Theme } from '../../themes';
import { focus } from '../../utils/css-state';
import { useDeviceContext } from '../device-context-provider/device-context-provider';
import { AbstractButton, AbstractButtonProps } from './abstract-button';
import { AbstractButton, getButtonTypeStyles } from './abstract-button';

type ButtonType = 'primary' | 'secondary' | 'tertiary' | 'destructive';

type Type = 'submit' | 'button' | 'reset';

interface ButtonProps extends AbstractButtonProps {
interface ButtonProps {
/**
* Visual style
* @default primary
*/
buttonType: ButtonType;
/**
* Sets button type
* @default submit
*/
type?: Type;
children?: ReactNode;
className?: string;
disabled?: boolean;
inversed?: boolean;
label?: string;
type?: Type;

onClick?(): void;
}

const StyledButton = styled(AbstractButton)<{ theme: Theme } & ButtonProps>`
${(props) => focus(props, true)};
${({ theme, buttonType, inversed }) => {
switch (buttonType) {
case 'primary':
return `
background-color: ${theme.main['primary-1.1']};
border-color: ${theme.main['primary-1.1']};
color: ${theme.greys.white};
&:hover {
background-color: ${theme.main['primary-1.3']};
border-color: ${theme.main['primary-1.3']};
}
&:disabled {
background-color: ${theme.main['primary-1.2']};
border-color: ${theme.main['primary-1.2']};
}
`;
case 'secondary':
return `
background-color: transparent;
border-color: ${theme.main['primary-1.1']};
color: ${theme.main['primary-1.1']};
&:hover {
border-color: ${theme.main['primary-1.3']};
color: ${theme.main['primary-1.3']};
}
&:disabled {
border-color: ${theme.main['primary-1.2']};
color: ${theme.main['primary-1.2']};
}
`;
case 'tertiary':
return `
background-color: transparent;
border-color: transparent;
color: ${theme.greys['dark-grey']};
&:hover {
background-color: ${theme.greys.grey};
color: ${theme.greys.black};
}
&:disabled {
background-color: transparent;
color: ${theme.greys['mid-grey']};
}
`;
case 'destructive':
// TODO change colors when updating thematization
return `
background-color: ${inversed ? theme.greys.white : theme.notifications['error-2.1']};
border-color: ${inversed ? theme.greys.white : theme.notifications['error-2.1']};
color: ${inversed ? theme.notifications['error-2.1'] : theme.greys.white};
&:hover {
background-color: ${inversed ? theme.greys.white : '#62071b'};
color: ${inversed ? '#62071b' : theme.greys.white};
}
&:disabled {
&,
&:focus,
&:hover {
background-color: ${inversed ? theme.greys.white : '#ea8da3'};
border-color: ${inversed ? theme.greys.white : '#ea8da3'};
color: ${inversed ? '#ea8da3' : theme.greys.white};
}
}
`;
}
}}
${getButtonTypeStyles}
`;

export function Button({
children, label, type = 'submit', buttonType, disabled, onClick, ...props
children, className, label, type = 'submit', buttonType, disabled, onClick, ...props
}: ButtonProps): ReactElement {
const { isMobile } = useDeviceContext();

Expand All @@ -111,6 +38,7 @@ export function Button({
isMobile={isMobile}
type={type}
buttonType={buttonType}
className={className}
disabled={disabled}
onClick={onClick}
{...props /* eslint-disable-line react/jsx-props-no-spreading *//* To spread aria-* and data-* */}
Expand Down
Loading

0 comments on commit d784a81

Please sign in to comment.