mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-06 20:27:12 +00:00
feat(ui): implemented button component
This commit is contained in:
Generated
+49
-2
@@ -28,8 +28,10 @@
|
|||||||
"add": "^2.0.6",
|
"add": "^2.0.6",
|
||||||
"axios": "^0.27.2",
|
"axios": "^0.27.2",
|
||||||
"axios-auth-refresh": "^3.3.3",
|
"axios-auth-refresh": "^3.3.3",
|
||||||
|
"class-variance-authority": "^0.4.0",
|
||||||
"classnames": "^2.3.1",
|
"classnames": "^2.3.1",
|
||||||
"cookies": "^0.8.0",
|
"cookies": "^0.8.0",
|
||||||
|
"cva": "npm:class-variance-authority@^0.4.0",
|
||||||
"fs": "^0.0.1-security",
|
"fs": "^0.0.1-security",
|
||||||
"gray-matter": "^4.0.3",
|
"gray-matter": "^4.0.3",
|
||||||
"http-proxy": "^1.18.1",
|
"http-proxy": "^1.18.1",
|
||||||
@@ -9299,6 +9301,22 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/class-variance-authority": {
|
||||||
|
"version": "0.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.4.0.tgz",
|
||||||
|
"integrity": "sha512-74enNN8O9ZNieycac/y8FxqgyzZhZbxmCitAtAeUrLPlxjSd5zA7LfpprmxEcOmQBnaGs5hYhiSGnJ0mqrtBLQ==",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://joebell.co.uk"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"typescript": ">= 4.5.5 < 5"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"typescript": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/classnames": {
|
"node_modules/classnames": {
|
||||||
"version": "2.3.1",
|
"version": "2.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz",
|
||||||
@@ -9938,6 +9956,23 @@
|
|||||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz",
|
||||||
"integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA=="
|
"integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA=="
|
||||||
},
|
},
|
||||||
|
"node_modules/cva": {
|
||||||
|
"name": "class-variance-authority",
|
||||||
|
"version": "0.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.4.0.tgz",
|
||||||
|
"integrity": "sha512-74enNN8O9ZNieycac/y8FxqgyzZhZbxmCitAtAeUrLPlxjSd5zA7LfpprmxEcOmQBnaGs5hYhiSGnJ0mqrtBLQ==",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://joebell.co.uk"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"typescript": ">= 4.5.5 < 5"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"typescript": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/damerau-levenshtein": {
|
"node_modules/damerau-levenshtein": {
|
||||||
"version": "1.0.8",
|
"version": "1.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
|
||||||
@@ -21135,7 +21170,7 @@
|
|||||||
"version": "4.9.3",
|
"version": "4.9.3",
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.3.tgz",
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.3.tgz",
|
||||||
"integrity": "sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==",
|
"integrity": "sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==",
|
||||||
"dev": true,
|
"devOptional": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"tsc": "bin/tsc",
|
"tsc": "bin/tsc",
|
||||||
"tsserver": "bin/tsserver"
|
"tsserver": "bin/tsserver"
|
||||||
@@ -28787,6 +28822,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"class-variance-authority": {
|
||||||
|
"version": "0.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.4.0.tgz",
|
||||||
|
"integrity": "sha512-74enNN8O9ZNieycac/y8FxqgyzZhZbxmCitAtAeUrLPlxjSd5zA7LfpprmxEcOmQBnaGs5hYhiSGnJ0mqrtBLQ==",
|
||||||
|
"requires": {}
|
||||||
|
},
|
||||||
"classnames": {
|
"classnames": {
|
||||||
"version": "2.3.1",
|
"version": "2.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz",
|
||||||
@@ -29292,6 +29333,12 @@
|
|||||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz",
|
||||||
"integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA=="
|
"integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA=="
|
||||||
},
|
},
|
||||||
|
"cva": {
|
||||||
|
"version": "npm:[email protected]",
|
||||||
|
"resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.4.0.tgz",
|
||||||
|
"integrity": "sha512-74enNN8O9ZNieycac/y8FxqgyzZhZbxmCitAtAeUrLPlxjSd5zA7LfpprmxEcOmQBnaGs5hYhiSGnJ0mqrtBLQ==",
|
||||||
|
"requires": {}
|
||||||
|
},
|
||||||
"damerau-levenshtein": {
|
"damerau-levenshtein": {
|
||||||
"version": "1.0.8",
|
"version": "1.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
|
||||||
@@ -37538,7 +37585,7 @@
|
|||||||
"version": "4.9.3",
|
"version": "4.9.3",
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.3.tgz",
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.3.tgz",
|
||||||
"integrity": "sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==",
|
"integrity": "sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==",
|
||||||
"dev": true
|
"devOptional": true
|
||||||
},
|
},
|
||||||
"uc.micro": {
|
"uc.micro": {
|
||||||
"version": "1.0.6",
|
"version": "1.0.6",
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
"start:docker": "next build && next start",
|
"start:docker": "next build && next start",
|
||||||
"lint": "eslint --fix --ext js,ts,tsx ./src",
|
"lint": "eslint --fix --ext js,ts,tsx ./src",
|
||||||
"type-check": "tsc --project tsconfig.json",
|
"type-check": "tsc --project tsconfig.json",
|
||||||
"storybook": "storybook dev -p 6006",
|
"storybook": "storybook dev -p 6006 -s ./public",
|
||||||
"build-storybook": "storybook build"
|
"build-storybook": "storybook build"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -37,6 +37,7 @@
|
|||||||
"axios-auth-refresh": "^3.3.3",
|
"axios-auth-refresh": "^3.3.3",
|
||||||
"classnames": "^2.3.1",
|
"classnames": "^2.3.1",
|
||||||
"cookies": "^0.8.0",
|
"cookies": "^0.8.0",
|
||||||
|
"cva": "npm:class-variance-authority@^0.4.0",
|
||||||
"fs": "^0.0.1-security",
|
"fs": "^0.0.1-security",
|
||||||
"gray-matter": "^4.0.3",
|
"gray-matter": "^4.0.3",
|
||||||
"http-proxy": "^1.18.1",
|
"http-proxy": "^1.18.1",
|
||||||
|
|||||||
@@ -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 type { Meta, StoryObj } from '@storybook/react';
|
||||||
|
|
||||||
import { Button } from './Button';
|
import { Button } from './Button';
|
||||||
@@ -6,7 +8,16 @@ const meta: Meta<typeof Button> = {
|
|||||||
title: 'Components/Button',
|
title: 'Components/Button',
|
||||||
component: Button,
|
component: Button,
|
||||||
tags: ['v2'],
|
tags: ['v2'],
|
||||||
argTypes: {}
|
argTypes: {
|
||||||
|
isRounded: {
|
||||||
|
defaultValue: true,
|
||||||
|
type: 'boolean'
|
||||||
|
},
|
||||||
|
isFullWidth: {
|
||||||
|
defaultValue: false,
|
||||||
|
type: 'boolean'
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default meta;
|
export default meta;
|
||||||
@@ -18,3 +29,61 @@ export const Primary: Story = {
|
|||||||
children: 'Hello Infisical'
|
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" />
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,32 +1,166 @@
|
|||||||
import { ButtonHTMLAttributes, forwardRef, ReactNode } from 'react';
|
import { ButtonHTMLAttributes, forwardRef, ReactNode } from 'react';
|
||||||
|
import { cva, VariantProps } from 'cva';
|
||||||
import { twMerge } from 'tailwind-merge';
|
import { twMerge } from 'tailwind-merge';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
isDisabled?: boolean;
|
isDisabled?: boolean;
|
||||||
|
leftIcon?: ReactNode;
|
||||||
|
rightIcon?: ReactNode;
|
||||||
// loading state
|
// loading state
|
||||||
isLoading?: boolean;
|
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>(
|
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 (
|
return (
|
||||||
<button
|
<button
|
||||||
ref={ref}
|
ref={ref}
|
||||||
aria-disabled={isDisabled}
|
aria-disabled={isDisabled}
|
||||||
type="button"
|
type="button"
|
||||||
className={twMerge(
|
className={twMerge(
|
||||||
'bg-primary hover:opacity-80 transition-all text-sm px-4 py-2 font-bold rounded',
|
buttonVariants({
|
||||||
className
|
className,
|
||||||
|
colorSchema,
|
||||||
|
size,
|
||||||
|
variant,
|
||||||
|
isRounded,
|
||||||
|
isDisabled,
|
||||||
|
isFullWidth
|
||||||
|
})
|
||||||
)}
|
)}
|
||||||
disabled={isDisabled}
|
disabled={isDisabled}
|
||||||
{...props}
|
{...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>
|
</button>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
|
export type { ButtonProps } from './Button';
|
||||||
export { Button } from './Button';
|
export { Button } from './Button';
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
export * from './Button';
|
||||||
Reference in New Issue
Block a user