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 { ComponentStory, ComponentMeta } from '@storybook/react';
|
||||
import { Button } from "../components/Button";
|
||||
import { ComponentStory, ComponentMeta } from "@storybook/react";
|
||||
import { Button } from "../components/Button/Button";
|
||||
import { SVGBookmark } from "../components/icons";
|
||||
|
||||
|
||||
|
||||
export default{
|
||||
title: 'Button',
|
||||
export default {
|
||||
title: "Button",
|
||||
component: Button,
|
||||
} as ComponentMeta<typeof Button>;
|
||||
|
||||
@ -13,18 +12,30 @@ const Template: ComponentStory<typeof Button> = (args) => <Button {...args} />;
|
||||
|
||||
export const High = Template.bind({});
|
||||
High.args = {
|
||||
emphasis: 'high',
|
||||
children: ['High'],
|
||||
emphasis: "high",
|
||||
children: (
|
||||
<Button.Icon className="w-8">
|
||||
<SVGBookmark />
|
||||
</Button.Icon>
|
||||
),
|
||||
};
|
||||
|
||||
export const Medium = Template.bind({});
|
||||
Medium.args = {
|
||||
emphasis: 'medium',
|
||||
children: ['Medium'],
|
||||
emphasis: "medium",
|
||||
children: (
|
||||
<Button.Icon>
|
||||
<SVGBookmark className="w-8" />
|
||||
</Button.Icon>
|
||||
),
|
||||
};
|
||||
|
||||
export const Low = Template.bind({});
|
||||
Low.args = {
|
||||
emphasis:'low',
|
||||
children:['Low'],
|
||||
emphasis: "low",
|
||||
children: (
|
||||
<Button.Icon>
|
||||
<SVGBookmark className="w-8" />
|
||||
</Button.Icon>
|
||||
),
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user