Skip to content

Commit

Permalink
feat(Buttons): introduce SocialButton (#1803)
Browse files Browse the repository at this point in the history
Changes:
Adding primarySubtle and criticalSubtle types to Button.
Adding critical type to ButtonLink.
Introducing new component SocialButton.
Introducing new component AlertButton, sub-component of Alert.
BREAKING CHANGE:
Removing info, success, warning, facebook, google types from Button.
Removing bordered property from Button.
  • Loading branch information
vepor committed Apr 27, 2020
1 parent ba9597b commit ac41d60
Show file tree
Hide file tree
Showing 53 changed files with 856 additions and 327 deletions.
27 changes: 17 additions & 10 deletions src/Alert/Alert.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { action } from "@storybook/addon-actions";
import { text, boolean, select } from "@storybook/addon-knobs";

import * as Icons from "../icons";
import Button from "../Button";
import { TYPE_OPTIONS } from "./consts";
import RenderInRtl from "../utils/rtl/RenderInRtl";
import SPACINGS_AFTER from "../common/getSpacingToken/consts";
Expand All @@ -16,7 +15,7 @@ import Stack from "../Stack";
import Heading from "../Heading";
import CountryFlag from "../CountryFlag";

import Alert from "./index";
import Alert, { AlertButton } from "./index";

const getIcons = defaultIcon => select("Icon", [null, ...Object.keys(Icons)], defaultIcon);
const getIcon = source => Icons[source];
Expand Down Expand Up @@ -126,9 +125,9 @@ storiesOf("Alert", module)
closable={closable}
onClose={action("Close")}
inlineActions={
<Button type={type} size="small" href="#">
<AlertButton type={type} size="small" href="#">
{button}
</Button>
</AlertButton>
}
/>
);
Expand Down Expand Up @@ -163,7 +162,7 @@ storiesOf("Alert", module)
dataTest={dataTest}
spaceAfter={spaceAfter}
>
<Stack spacing="condensed">
<Stack spacing="compact">
<Stack spacing="tight">
<div>{message}</div>
<List>
Expand All @@ -173,9 +172,17 @@ storiesOf("Alert", module)
<ListItem>623 Kč will be refunded by your payment card</ListItem>
</List>
</Stack>
<Button type={type} size="small" href="#">
{button}
</Button>
<Stack direction="row" spacing="condensed">
<AlertButton type={type} size="small" href="#">
{button}
</AlertButton>
{/*
$FlowExpected
*/}
<AlertButton type={`${type}Subtle`} size="small" href="#">
{button}
</AlertButton>
</Stack>
</Stack>
</Alert>
);
Expand Down Expand Up @@ -209,9 +216,9 @@ storiesOf("Alert", module)
<ListItem icon={<CountryFlag code="pl" name="Poland" />}>Poland</ListItem>
</List>
</Stack>
<Button type="info" size="small">
<AlertButton type="info" size="small">
Check Visa Requirements
</Button>
</AlertButton>
</Stack>
</Alert>
</RenderInRtl>
Expand Down
20 changes: 20 additions & 0 deletions src/Alert/AlertButton/consts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// @flow
export const TYPE_OPTIONS = {
INFO: "info",
SUCCESS: "success",
WARNING: "warning",
CRITICAL: "critical",
INFO_SUBTLE: "infoSubtle",
SUCCESS_SUBTLE: "successSubtle",
WARNING_SUBTLE: "warningSubtle",
CRITICAL_SUBTLE: "criticalSubtle",
};

export const TOKENS = {
backgroundButton: "backgroundButton",
backgroundButtonHover: "backgroundButtonHover",
backgroundButtonActive: "backgroundButtonActive",
backgroundButtonFocus: "backgroundButtonFocus",
colorTextButton: "colorTextButton",
borderColorButtonFocus: "borderColorButtonFocus",
};
34 changes: 34 additions & 0 deletions src/Alert/AlertButton/helpers/getAlertButtonBoxShadow.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// @flow
import convertHexToRgba from "@kiwicom/orbit-design-tokens/lib/convertHexToRgba";

import { TOKENS, TYPE_OPTIONS } from "../consts";
import { BUTTON_STATES } from "../../../primitives/ButtonPrimitive/common/consts";
import getAlertButtonTypeToken from "./getAlertButtonTypeToken";
import type { GetAlertButtonBoxShadow } from "./getAlertButtonBoxShadow";

const opacity = {
[TYPE_OPTIONS.INFO]: 15,
[TYPE_OPTIONS.SUCCESS]: 15,
[TYPE_OPTIONS.WARNING]: 15,
[TYPE_OPTIONS.CRITICAL]: 15,
[TYPE_OPTIONS.INFO_SUBTLE]: 8,
[TYPE_OPTIONS.SUCCESS_SUBTLE]: 8,
[TYPE_OPTIONS.WARNING_SUBTLE]: 8,
[TYPE_OPTIONS.CRITICAL_SUBTLE]: 8,
};

const getAlertButtonBoxShadow: GetAlertButtonBoxShadow = (state, disabled, theme, type) => {
const wrappedButtonTypeToken = name => getAlertButtonTypeToken(name, type, theme);
if (disabled) {
return null;
}
if (state === BUTTON_STATES.ACTIVE) {
return `inset 0 0 6px 3px ${convertHexToRgba(theme.orbit.paletteInkNormal, opacity[type])};`;
}
if (state === BUTTON_STATES.FOCUS) {
return `0 0 0 3px ${wrappedButtonTypeToken(TOKENS.borderColorButtonFocus)}`;
}
return null;
};

export default getAlertButtonBoxShadow;
14 changes: 14 additions & 0 deletions src/Alert/AlertButton/helpers/getAlertButtonBoxShadow.js.flow
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// @flow
import type { Type } from "../index";
import type { Theme } from "../../../defaultTheme";

type State = "default" | "focus" | "active" | "hover";

export type GetAlertButtonBoxShadow = (
state: State,
disabled: boolean,
theme: Theme,
type: Type,
) => ?string;

declare export default GetAlertButtonBoxShadow;
10 changes: 10 additions & 0 deletions src/Alert/AlertButton/helpers/getAlertButtonIconForeground.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// @flow
import { TOKENS } from "../consts";
import getAlertButtonTypeToken from "./getAlertButtonTypeToken";
import type { GetAlertButtonIconForeground } from "./getAlertButtonIconForeground";

const getAlertButtonIconForeground: GetAlertButtonIconForeground = ({ theme, type }) => ({
foreground: getAlertButtonTypeToken(TOKENS.colorTextButton, type, theme),
});

export default getAlertButtonIconForeground;
11 changes: 11 additions & 0 deletions src/Alert/AlertButton/helpers/getAlertButtonIconForeground.js.flow
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// @flow
import type { ThemeProps } from "../../../defaultTheme";
import type { Type } from "../index";
import type { IconForeground } from "../../../primitives/ButtonPrimitive";

export type GetAlertButtonIconForeground = ({
type: Type,
...ThemeProps,
}) => IconForeground;

declare export default GetAlertButtonIconForeground;
27 changes: 27 additions & 0 deletions src/Alert/AlertButton/helpers/getAlertButtonStyles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// @flow
import { BUTTON_STATES } from "../../../primitives/ButtonPrimitive/common/consts";
import getAlertButtonTypeToken from "./getAlertButtonTypeToken";
import { TOKENS } from "../consts";
import getAlertButtonBoxShadow from "./getAlertButtonBoxShadow";
import type { GetAlertButtonStyles } from "./getAlertButtonStyles";

const getAlertButtonStyles: GetAlertButtonStyles = ({ disabled, theme, type }) => {
const wrappedBoxShadow = state => getAlertButtonBoxShadow(state, disabled, theme, type);
const wrappedTypeToken = name => getAlertButtonTypeToken(name, type, theme);
const boxShadow = {
boxShadow: wrappedBoxShadow(BUTTON_STATES.DEFAULT),
boxShadowHover: wrappedBoxShadow(BUTTON_STATES.HOVER),
boxShadowActive: wrappedBoxShadow(BUTTON_STATES.ACTIVE),
boxShadowFocus: wrappedBoxShadow(BUTTON_STATES.FOCUS),
};
return {
background: wrappedTypeToken(TOKENS.backgroundButton),
backgroundHover: wrappedTypeToken(TOKENS.backgroundButtonHover),
backgroundActive: wrappedTypeToken(TOKENS.backgroundButtonActive),
backgroundFocus: null,
foreground: wrappedTypeToken(TOKENS.colorTextButton),
...boxShadow,
};
};

export default getAlertButtonStyles;
17 changes: 17 additions & 0 deletions src/Alert/AlertButton/helpers/getAlertButtonStyles.js.flow
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// @flow

import type { ThemeProps } from "../../../defaultTheme";
import type { Type } from "../index";
import type { Background, BoxShadow, Foreground } from "../../../primitives/ButtonPrimitive";

export type GetAlertButtonStyles = ({
disabled: boolean,
type: Type,
...ThemeProps,
}) => {|
...Background,
...Foreground,
...BoxShadow,
|};

declare export default GetAlertButtonStyles;
73 changes: 73 additions & 0 deletions src/Alert/AlertButton/helpers/getAlertButtonTypeToken.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// @flow
import convertHexToRgba from "@kiwicom/orbit-design-tokens/lib/convertHexToRgba";

import { TOKENS, TYPE_OPTIONS } from "../consts";
import type { GetAlertButtonTypeToken } from "./getAlertButtonTypeToken";

const getAlertButtonTypeToken: GetAlertButtonTypeToken = (name, type, theme) => {
const tokens = {
[TOKENS.backgroundButton]: {
[TYPE_OPTIONS.INFO]: theme.orbit.backgroundButtonInfo,
[TYPE_OPTIONS.SUCCESS]: theme.orbit.backgroundButtonSuccess,
[TYPE_OPTIONS.WARNING]: theme.orbit.backgroundButtonWarning,
[TYPE_OPTIONS.CRITICAL]: theme.orbit.backgroundButtonCritical,
[TYPE_OPTIONS.INFO_SUBTLE]: theme.orbit.paletteBlueLightHover,
[TYPE_OPTIONS.SUCCESS_SUBTLE]: theme.orbit.paletteGreenLightHover,
[TYPE_OPTIONS.WARNING_SUBTLE]: theme.orbit.paletteOrangeLightHover,
[TYPE_OPTIONS.CRITICAL_SUBTLE]: theme.orbit.paletteRedLightHover,
},
[TOKENS.backgroundButtonHover]: {
[TYPE_OPTIONS.INFO]: theme.orbit.backgroundButtonInfoHover,
[TYPE_OPTIONS.SUCCESS]: theme.orbit.backgroundButtonSuccessHover,
[TYPE_OPTIONS.WARNING]: theme.orbit.backgroundButtonWarningHover,
[TYPE_OPTIONS.CRITICAL]: theme.orbit.backgroundButtonCriticalHover,
[TYPE_OPTIONS.INFO_SUBTLE]: theme.orbit.paletteBlueLightHover,
[TYPE_OPTIONS.SUCCESS_SUBTLE]: theme.orbit.paletteGreenLightHover,
[TYPE_OPTIONS.WARNING_SUBTLE]: theme.orbit.paletteOrangeLightHover,
[TYPE_OPTIONS.CRITICAL_SUBTLE]: theme.orbit.paletteRedLightHover,
},
[TOKENS.backgroundButtonActive]: {
[TYPE_OPTIONS.INFO]: theme.orbit.backgroundButtonInfoActive,
[TYPE_OPTIONS.SUCCESS]: theme.orbit.backgroundButtonSuccessActive,
[TYPE_OPTIONS.WARNING]: theme.orbit.backgroundButtonWarningActive,
[TYPE_OPTIONS.CRITICAL]: theme.orbit.backgroundButtonCriticalActive,
[TYPE_OPTIONS.INFO_SUBTLE]: theme.orbit.paletteBlueLightActive,
[TYPE_OPTIONS.SUCCESS_SUBTLE]: theme.orbit.paletteGreenLightActive,
[TYPE_OPTIONS.WARNING_SUBTLE]: theme.orbit.paletteOrangeLightActive,
[TYPE_OPTIONS.CRITICAL_SUBTLE]: theme.orbit.paletteRedLightActive,
},
[TOKENS.backgroundButtonFocus]: {
[TYPE_OPTIONS.INFO]: convertHexToRgba(theme.orbit.paletteBlueNormal, 10),
[TYPE_OPTIONS.SUCCESS]: convertHexToRgba(theme.orbit.paletteGreenNormal, 10),
[TYPE_OPTIONS.WARNING]: convertHexToRgba(theme.orbit.paletteOrangeNormal, 10),
[TYPE_OPTIONS.CRITICAL]: convertHexToRgba(theme.orbit.paletteRedNormal, 10),
[TYPE_OPTIONS.INFO_SUBTLE]: theme.orbit.paletteBlueLight,
[TYPE_OPTIONS.SUCCESS_SUBTLE]: theme.orbit.paletteGreenLight,
[TYPE_OPTIONS.WARNING_SUBTLE]: theme.orbit.paletteOrangeLight,
[TYPE_OPTIONS.CRITICAL_SUBTLE]: theme.orbit.paletteRedLight,
},
[TOKENS.colorTextButton]: {
[TYPE_OPTIONS.INFO]: theme.orbit.colorTextButtonInfo,
[TYPE_OPTIONS.SUCCESS]: theme.orbit.colorTextButtonSuccess,
[TYPE_OPTIONS.WARNING]: theme.orbit.colorTextButtonWarning,
[TYPE_OPTIONS.CRITICAL]: theme.orbit.colorTextButtonCritical,
[TYPE_OPTIONS.INFO_SUBTLE]: theme.orbit.paletteBlueDark,
[TYPE_OPTIONS.SUCCESS_SUBTLE]: theme.orbit.paletteGreenDark,
[TYPE_OPTIONS.WARNING_SUBTLE]: theme.orbit.paletteOrangeDark,
[TYPE_OPTIONS.CRITICAL_SUBTLE]: theme.orbit.paletteRedDark,
},
[TOKENS.borderColorButtonFocus]: {
[TYPE_OPTIONS.INFO]: convertHexToRgba(theme.orbit.paletteBlueNormal, 50),
[TYPE_OPTIONS.SUCCESS]: convertHexToRgba(theme.orbit.paletteGreenNormal, 50),
[TYPE_OPTIONS.WARNING]: convertHexToRgba(theme.orbit.paletteOrangeNormal, 50),
[TYPE_OPTIONS.CRITICAL]: convertHexToRgba(theme.orbit.paletteRedNormal, 50),
[TYPE_OPTIONS.INFO_SUBTLE]: convertHexToRgba(theme.orbit.paletteBlueNormal, 50),
[TYPE_OPTIONS.SUCCESS_SUBTLE]: convertHexToRgba(theme.orbit.paletteGreenNormal, 50),
[TYPE_OPTIONS.WARNING_SUBTLE]: convertHexToRgba(theme.orbit.paletteOrangeNormal, 50),
[TYPE_OPTIONS.CRITICAL_SUBTLE]: convertHexToRgba(theme.orbit.paletteRedNormal, 50),
},
};
return tokens[name][type];
};

export default getAlertButtonTypeToken;
15 changes: 15 additions & 0 deletions src/Alert/AlertButton/helpers/getAlertButtonTypeToken.js.flow
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// @flow
import type { Type } from "../index";
import type { Theme } from "../../../defaultTheme";

export type TokenName =
| "backgroundButton"
| "backgroundButtonHover"
| "backgroundButtonActive"
| "backgroundButtonFocus"
| "colorTextButton"
| "borderColorButtonFocus";

export type GetAlertButtonTypeToken = (name: TokenName, type: Type, theme: Theme) => string;

declare export default GetAlertButtonTypeToken;
39 changes: 39 additions & 0 deletions src/Alert/AlertButton/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// @flow
import * as React from "react";

import { TYPE_OPTIONS } from "./consts";
import ButtonPrimitive from "../../primitives/ButtonPrimitive";
import getIconContainer from "../../primitives/ButtonPrimitive/common/getIconContainer";
import getCommonProps from "../../primitives/ButtonPrimitive/common/getCommonProps";
import useTheme from "../../hooks/useTheme";
import getAlertButtonStyles from "./helpers/getAlertButtonStyles";
import getAlertButtonIconForeground from "./helpers/getAlertButtonIconForeground";

import type { Props } from "./index";

const AlertButton = React.forwardRef<Props, HTMLButtonElement>(
({ type = TYPE_OPTIONS.INFO, disabled = false, ...props }, ref) => {
const theme = useTheme();
const propsWithTheme = { theme, ...props };
const commonProps = getCommonProps(propsWithTheme);
const buttonStyles = getAlertButtonStyles({ type, theme, disabled });
const icons = getIconContainer({
...propsWithTheme,
iconForeground: getAlertButtonIconForeground({ type, theme }),
});
return (
<ButtonPrimitive
ref={ref}
disabled={disabled}
{...props}
{...buttonStyles}
{...commonProps}
{...icons}
/>
);
},
);

AlertButton.displayName = "AlertButton";

export default AlertButton;
21 changes: 21 additions & 0 deletions src/Alert/AlertButton/index.js.flow
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// @flow
import * as React from "react";

import type { ButtonCommonProps } from "../../primitives/ButtonPrimitive";

export type Type =
| "info"
| "success"
| "warning"
| "critical"
| "infoSubtle"
| "successSubtle"
| "warningSubtle"
| "criticalSubtle";

export type Props = {|
+type?: Type,
...ButtonCommonProps,
|};

declare export default React.AbstractComponent<Props, HTMLButtonElement>;
Loading

0 comments on commit ac41d60

Please sign in to comment.