Skip to content

Commit

Permalink
feat(ui): implemented button component
Browse files Browse the repository at this point in the history
  • Loading branch information
akhilmhdh committed Jan 23, 2023
1 parent 201c835 commit 68f1887
Show file tree
Hide file tree
Showing 6 changed files with 264 additions and 11 deletions.
51 changes: 49 additions & 2 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"start:docker": "next build && next start",
"lint": "eslint --fix --ext js,ts,tsx ./src",
"type-check": "tsc --project tsconfig.json",
"storybook": "storybook dev -p 6006",
"storybook": "storybook dev -p 6006 -s ./public",
"build-storybook": "storybook build"
},
"dependencies": {
Expand Down Expand Up @@ -37,6 +37,7 @@
"axios-auth-refresh": "^3.3.3",
"classnames": "^2.3.1",
"cookies": "^0.8.0",
"cva": "npm:class-variance-authority@^0.4.0",
"fs": "^0.0.1-security",
"gray-matter": "^4.0.3",
"http-proxy": "^1.18.1",
Expand Down
71 changes: 70 additions & 1 deletion frontend/src/components/v2/Button/Button.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { faPlus } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import type { Meta, StoryObj } from '@storybook/react';

import { Button } from './Button';
Expand All @@ -6,7 +8,16 @@ const meta: Meta<typeof Button> = {
title: 'Components/Button',
component: Button,
tags: ['v2'],
argTypes: {}
argTypes: {
isRounded: {
defaultValue: true,
type: 'boolean'
},
isFullWidth: {
defaultValue: false,
type: 'boolean'
}
}
};

export default meta;
Expand All @@ -18,3 +29,61 @@ export const Primary: Story = {
children: 'Hello Infisical'
}
};

export const Secondary: Story = {
args: {
children: 'Hello Infisical',
colorSchema: 'secondary',
variant: 'outline'
}
};

export const Danger: Story = {
args: {
children: 'Hello Infisical',
colorSchema: 'danger',
variant: 'solid'
}
};

export const Plain: Story = {
args: {
children: 'Hello Infisical',
variant: 'plain'
}
};

export const Disabled: Story = {
args: {
children: 'Hello Infisical',
disabled: true
}
};

export const FullWidth: Story = {
args: {
children: 'Hello Infisical',
isFullWidth: true
}
};

export const Loading: Story = {
args: {
children: 'Hello Infisical',
isLoading: true
}
};

export const LeftIcon: Story = {
args: {
children: 'Hello Infisical',
leftIcon: <FontAwesomeIcon icon={faPlus} className="pr-0.5" />
}
};

export const RightIcon: Story = {
args: {
children: 'Hello Infisical',
rightIcon: <FontAwesomeIcon icon={faPlus} className="pr-0.5" />
}
};
148 changes: 141 additions & 7 deletions frontend/src/components/v2/Button/Button.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,166 @@
import { ButtonHTMLAttributes, forwardRef, ReactNode } from 'react';
import { cva, VariantProps } from 'cva';
import { twMerge } from 'tailwind-merge';

type Props = {
children: ReactNode;
isDisabled?: boolean;
leftIcon?: ReactNode;
rightIcon?: ReactNode;
// loading state
isLoading?: boolean;
// various button sizes
size: 'sm' | 'md' | 'lg';
};

export type ButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & Props;
const buttonVariants = cva(
[
'button',
'transition-all',
'font-medium',
'cursor-pointer',
'inline-flex items-center justify-center',
'relative'
],
{
variants: {
colorSchema: {
primary: ['bg-primary', 'text-black', 'border-primary hover:bg-opacity-80'],
secondary: ['bg-mineshaft-200', 'text-white', 'border-mineshaft-200'],
danger: ['bg-red', 'text-white', 'border-red']
},
variant: {
solid: '',
outline: ['bg-transparent', 'border', 'border-solid'],
plain: ''
},
isDisabled: {
true: 'bg-opacity-70',
false: ''
},
isFullWidth: {
true: 'w-full',
false: ''
},
isRounded: {
true: 'rounded-md',
false: ''
},
size: {
xs: ['text-xs', 'py-1', 'px-2'],
sm: ['text-sm', 'py-2', 'px-4'],
md: ['text-md', 'py-2', 'px-6'],
lg: ['text-lg', 'py-2', 'px-8']
}
},
compoundVariants: [
{
colorSchema: 'primary',
variant: 'outline',
className: 'text-primary hover:bg-primary hover:text-black'
},
{
colorSchema: 'secondary',
variant: 'outline',
className: 'text-mineshaft-200 hover:bg-mineshaft-400 hover:text-white'
},
{
colorSchema: 'danger',
variant: 'outline',
className: 'text-red hover:bg-red hover:text-black'
},
{
colorSchema: 'primary',
variant: 'plain',
className: 'text-primary'
},
{
colorSchema: 'secondary',
variant: 'plain',
className: 'text-mineshaft-400'
},
{
colorSchema: 'danger',
variant: 'plain',
className: 'text-red'
},
{
colorSchema: ['danger', 'primary', 'secondary'],
variant: ['plain'],
className: 'bg-transparent py-1 px-1'
}
]
}
);

export type ButtonProps = ButtonHTMLAttributes<HTMLButtonElement> &
VariantProps<typeof buttonVariants> &
Props;

export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
({ children, isDisabled = false, className, ...props }, ref): JSX.Element => {
(
{
children,
isDisabled = false,
className = '',
size = 'md',
variant = 'solid',
isFullWidth,
isRounded = true,
leftIcon,
rightIcon,
isLoading,
colorSchema = 'primary',
...props
},
ref
): JSX.Element => {
const loadingToggleClass = isLoading ? 'opacity-0' : 'opacity-100';

return (
<button
ref={ref}
aria-disabled={isDisabled}
type="button"
className={twMerge(
'bg-primary hover:opacity-80 transition-all text-sm px-4 py-2 font-bold rounded',
className
buttonVariants({
className,
colorSchema,
size,
variant,
isRounded,
isDisabled,
isFullWidth
})
)}
disabled={isDisabled}
{...props}
>
{children}
{isLoading && (
<img
src="/images/loading/loadingblack.gif"
width={36}
alt="loading animation"
className="rounded-xl absolute"
/>
)}
<span
className={twMerge(
'transition-all shrink-0 cursor-pointer',
loadingToggleClass,
size === 'xs' ? 'mr-1' : 'mr-2'
)}
>
{leftIcon}
</span>
<span className={twMerge('transition-all', loadingToggleClass)}>{children}</span>
<span
className={twMerge(
'transition-all shrink-0 cursor-pointer',
loadingToggleClass,
size === 'xs' ? 'ml-1' : 'ml-2'
)}
>
{rightIcon}
</span>
</button>
);
}
Expand Down
1 change: 1 addition & 0 deletions frontend/src/components/v2/Button/index.tsx
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export type { ButtonProps } from './Button';
export { Button } from './Button';
1 change: 1 addition & 0 deletions frontend/src/components/v2/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './Button';

0 comments on commit 68f1887

Please sign in to comment.