Merge pull request 'Button Component - Closed issues #6 and #7' (#67) from feature/add-button-component into develop

Reviewed-on: http://85.143.176.51:3000/free-land/front-end/pulls/67
This commit is contained in:
Denis Gorbunov 2022-08-12 09:59:32 +00:00
commit a0605f1567
5 changed files with 197 additions and 130 deletions

View File

@ -1,116 +0,0 @@
/* -------------------------------------------------------------------------- */
/* Imports */
/* -------------------------------------------------------------------------- */
import React from "react";
import classNames from "classnames";
import '../index.css'
import { StyleType } from "core/_variants";
/* -------------------------------------------------------------------------- */
/* Component props */
/* -------------------------------------------------------------------------- */
type Props = {
emphasis?: StyleType | undefined,
disabled?:boolean,
iconed?: boolean,
} & Omit<React.ComponentPropsWithoutRef<"button">, "">
/* -------------------------------------------------------------------------- */
/* Emphasis styles */
/* -------------------------------------------------------------------------- */
const buttonEnableHighEmphasis = `
bg-blue-500
hover:bg-blue-400
active:bg-blue-700
focus:shadow-lg shadow-blue-500
focus:outline outline-blue-400/10 outline-8`;
const buttonDisabledHighEmphasis =
`bg-gray-200
focus:outline-none`;
const buttonGeneralHighEmphasis = `
text-white
`
const buttonEnabledMediumEmphasis =
`text-blue-500
border-gray-500
active:border-blue-600
active:text-blue-600
hover:border-blue-400
hover:text-blue-400
focus:outline outline-blue-400/10 outline-8
focus:border-blue-600/70`;
const buttonDisabledMediumEmphasis =
`text-gray-200
border-gray-200
focus:outline-none`;
const buttonGeneralMediumEmphasis =
`bg-white
border`;
const buttonEnabledLowEmphasis =
`text-gray-900
hover:text-blue-400
active:text-blue-600
focus:bg-gray-50`;
const buttonDisabledLowEmphasis =
`text-gray-200`;
const buttonGenerealLowEmphasis =
`focus:outline-none
bg-transparent`;
/* -------------------------------------------------------------------------- */
/* Component implementation */
/* -------------------------------------------------------------------------- */
export const Button = ({
emphasis ='high',
disabled = false,
iconed = false,
className,
children, ...props} : Props) => {
return(
<button
//TODO change on click event
onClick={!disabled ? () => alert('Click') : undefined}
className={classNames([
'text-center',
'px-4 py-2 text-[15px]',
'rounded',
{
'!cursor-default': disabled,
'transition-all': !disabled,
'transition duration-200':!disabled,
},
{ // Define high emphasis
[`${buttonEnableHighEmphasis}`]: !disabled && emphasis === 'high',
[`${buttonDisabledHighEmphasis}`]: disabled && emphasis === 'high',
[`${buttonGeneralHighEmphasis}`] : emphasis === 'high',
// Define medium emphasis
[`${buttonEnabledMediumEmphasis}`]: !disabled && emphasis === 'medium',
[`${buttonDisabledMediumEmphasis}`]: disabled && emphasis === 'medium',
[`${buttonGeneralMediumEmphasis}`]: emphasis === 'medium',
// Define low emphasis
[`${buttonEnabledLowEmphasis}`]: !disabled && emphasis === 'low',
[`${buttonDisabledLowEmphasis}`]: disabled && emphasis ==='low',
[`${buttonGenerealLowEmphasis}`]: emphasis === 'low',
},
className,
])}
{...props}>
{children}
</button>
);
}

View File

@ -0,0 +1,86 @@
/* -------------------------------------------------------------------------- */
/* Imports */
/* -------------------------------------------------------------------------- */
import React from "react";
import classNames from "classnames";
import { StyleType } from "core/_variants";
import * as btnEmphasis from "./_btnEmphasis";
import IconButton from "./IconButton";
/* -------------------------------------------------------------------------- */
/* Extention for component */
/* -------------------------------------------------------------------------- */
type ButtonExtentions = {
Icon: React.FC<{
children: Required<React.ReactElement>;
className?: string;
}>;
};
/* -------------------------------------------------------------------------- */
/* Component props */
/* -------------------------------------------------------------------------- */
type ButtonProps = {
emphasis?: StyleType | undefined; //Choose one of three variants of button. By default it will be "high"
disabled?: boolean;
} & Omit<React.ComponentPropsWithoutRef<"button">, "">;
/* -------------------------------------------------------------------------- */
/* Component implementation */
/* -------------------------------------------------------------------------- */
export const Button: React.FC<ButtonProps> & ButtonExtentions = ({
emphasis = "high",
disabled = false,
className,
children,
...props
}) => {
console.log(
React.isValidElement(children) && React.Children.only(children).type
);
const isOnlyIcon =
children &&
React.isValidElement(children) &&
React.Children.only(children).type == IconButton;
const padding = isOnlyIcon ? "px-2.5 py-2" : "px-4 py-2";
return (
<button
//TODO change on click event
onClick={!disabled ? () => alert("Click") : undefined}
className={classNames([
"flex content-center justify-between",
"text-center",
padding,
"rounded",
{
"!cursor-default": disabled,
"transition-all": !disabled,
"transition duration-200": !disabled,
},
{
// Define high emphasis
[`${btnEmphasis.EnableHigh}`]: !disabled && emphasis === "high",
[`${btnEmphasis.DisabledHigh}`]: disabled && emphasis === "high",
[`${btnEmphasis.GeneralHigh}`]: emphasis === "high",
// Dbtnefine medium emphasis
[`${btnEmphasis.EnabledMedium}`]: !disabled && emphasis === "medium",
[`${btnEmphasis.DisabledMedium}`]: disabled && emphasis === "medium",
[`${btnEmphasis.GeneralMedium}`]: emphasis === "medium",
// Dbtnefine low emphasis
[`${btnEmphasis.EnabledLow}`]: !disabled && emphasis === "low",
[`${btnEmphasis.DisabledLow}`]: disabled && emphasis === "low",
[`${btnEmphasis.GenerealLow}`]: emphasis === "low",
},
className,
])}
{...props}
>
{children}
</button>
);
};
Button.Icon = IconButton;

View File

@ -0,0 +1,21 @@
import classNames from "classnames";
import React, { FunctionComponent as FC } from "react";
import { SVGSearch } from "../icons";
type IconButtonProps = {
children: Required<JSX.Element>;
className?: string;
} & Omit<React.ComponentPropsWithoutRef<"div">, "">;
const IconButton: React.FC<IconButtonProps> = ({
children,
className,
}): JSX.Element => {
return className
? React.cloneElement(children, {
className: classNames(className),
})
: children;
};
IconButton.displayName = "ButtonIcon";
export default IconButton;

View File

@ -0,0 +1,65 @@
/* -------------------------------------------------------------------------- */
/* styles */
/* -------------------------------------------------------------------------- */
export const EnableHigh = `bg-blue-500
hover:bg-blue-400
active:bg-blue-700
focus:shadow-lg shadow-blue-500
focus:outline outline-blue-400/10 outline-8
`;
export const DisabledHigh = `bg-gray-200
focus:outline-none`;
export const GeneralHigh = `
text-white
fill-white
stroke-white
`;
export const EnabledMedium = `text-blue-500
border-gray-500
active:border-blue-600
active:text-blue-600
hover:border-blue-400
hover:text-blue-400
focus:outline outline-blue-400/10 outline-8
focus:border-blue-600/70
fill-blue-500
hover:fill-blue-400
active:fill-blue-600
focus:fill-blue-600
stroke-blue-500
hover:stroke-blue-400
active:stroke-blue-600
focus:stroke-blue-600
`;
export const DisabledMedium = `text-gray-200
border-gray-200
fill-gray-200
stroke-gray-200
focus:outline-none`;
export const GeneralMedium = `bg-white
border`;
export const EnabledLow = ` text-gray-900
hover:bg-gray-100
active:text-blue-600
active:bg-blue-100
focus:bg-blue-100
fill-gray-900
stroke-gray-900
active:fill-blue-500
active:stroke-blue-500
`;
export const DisabledLow = `text-gray-200
fill-gray-200
stroke-gray-200`;
export const GenerealLow = `focus:outline-none
bg-transparent
`;

View File

@ -1,11 +1,10 @@
import React, { Children } from "react"; import React, { Children } from "react";
import { ComponentStory, ComponentMeta } from '@storybook/react'; import { ComponentStory, ComponentMeta } from "@storybook/react";
import { Button } from "../components/Button"; import { Button } from "../components/Button/Button";
import { SVGBookmark } from "../components/icons";
export default {
title: "Button",
export default{
title: 'Button',
component: Button, component: Button,
} as ComponentMeta<typeof Button>; } as ComponentMeta<typeof Button>;
@ -13,18 +12,30 @@ const Template: ComponentStory<typeof Button> = (args) => <Button {...args} />;
export const High = Template.bind({}); export const High = Template.bind({});
High.args = { High.args = {
emphasis: 'high', emphasis: "high",
children: ['High'], children: (
<Button.Icon className="w-8">
<SVGBookmark />
</Button.Icon>
),
}; };
export const Medium = Template.bind({}); export const Medium = Template.bind({});
Medium.args = { Medium.args = {
emphasis: 'medium', emphasis: "medium",
children: ['Medium'], children: (
<Button.Icon>
<SVGBookmark className="w-8" />
</Button.Icon>
),
}; };
export const Low = Template.bind({}); export const Low = Template.bind({});
Low.args = { Low.args = {
emphasis:'low', emphasis: "low",
children:['Low'], children: (
<Button.Icon>
<SVGBookmark className="w-8" />
</Button.Icon>
),
}; };