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:
commit
a0605f1567
@ -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>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
86
src/components/Button/Button.tsx
Normal file
86
src/components/Button/Button.tsx
Normal 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;
|
21
src/components/Button/IconButton.tsx
Normal file
21
src/components/Button/IconButton.tsx
Normal 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;
|
65
src/components/Button/_btnEmphasis.tsx
Normal file
65
src/components/Button/_btnEmphasis.tsx
Normal 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
|
||||||
|
`;
|
@ -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>
|
||||||
|
),
|
||||||
};
|
};
|
Loading…
x
Reference in New Issue
Block a user