Skip to content

Commit

Permalink
Add initial button component
Browse files Browse the repository at this point in the history
  • Loading branch information
raducristianpopa committed Dec 21, 2023
1 parent ec3182f commit c0fad38
Show file tree
Hide file tree
Showing 7 changed files with 182 additions and 6 deletions.
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,12 @@
"lint:prettier": "prettier \"**/*.(md|json|yml)\" --ignore-path .gitignore --check",
"lint:type": "tsc --noEmit",
"local-signatures": "pnpm tsx --watch ./local-signatures/index.ts",
"test": "jest --maxWorkers=2",
"test": "jest --maxWorkers=2 --passWithNoTests",
"ci:test": "run-s \" test --ci --reporters=\"default\" --reporters=\"github-actions\" \""
},
"dependencies": {
"axios": "^1.5.1",
"class-variance-authority": "^0.7.0",
"clean-webpack-plugin": "^4.0.0",
"copy-webpack-plugin": "^11.0.0",
"core-js": "^3.32.1",
Expand All @@ -36,6 +37,7 @@
"sass": "^1.66.1",
"sass-loader": "^13.3.2",
"style-loader": "^3.3.3",
"tailwind-merge": "^2.1.0",
"terser-webpack-plugin": "^5.3.9",
"uuid": "^9.0.1",
"webextension-polyfill": "^0.10.0",
Expand Down Expand Up @@ -94,6 +96,7 @@
"postcss-loader": "^7.3.3",
"prettier": "^3.0.3",
"tailwindcss": "^3.4.0",
"ts-jest": "^29.1.1",
"ts-loader": "^9.4.4",
"ts-node": "^10.9.2",
"tsx": "^4.6.2",
Expand Down
73 changes: 71 additions & 2 deletions pnpm-lock.yaml

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

58 changes: 58 additions & 0 deletions src/components/button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { type VariantProps, cva } from 'class-variance-authority'
import React, { forwardRef } from 'react'

import { LoadingSpinner } from '@/components/loading-spinner'
import { cn } from '@/utils/cn'

const buttonVariants = cva(
[
'relative inline-flex items-center justify-center whitespace-nowrap rounded-xl font-semibold',
'focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-500',
'disabled:pointer-events-none disabled:select-none disabled:opacity-50',
],

{
variants: {
variant: {
default: 'bg-button-base text-white hover:bg-button-base-hover active:bg-red-500',
},
size: {
default: 'py-4 px-6 font-medium',
},
fullWidth: {
true: 'w-full',
},
loading: {
true: 'text-transparent',
},
},
defaultVariants: {
variant: 'default',
size: 'default',
},
},
)

export interface ButtonProps
extends VariantProps<typeof buttonVariants>,
React.ButtonHTMLAttributes<HTMLButtonElement> {
loading?: boolean
['aria-label']: string
}

export const Button = forwardRef<HTMLButtonElement, ButtonProps>(function Button(
{ variant, size, fullWidth, loading, className, type = 'button', children, ...props },
ref,
) {
return (
<button
ref={ref}
type={type}
className={cn(buttonVariants({ variant, size, fullWidth, loading }), className)}
disabled={props.disabled ?? loading ?? false}
aria-disabled={props.disabled ?? loading ?? false}
{...props}>
{loading ? <LoadingSpinner /> : children}
</button>
)
})
19 changes: 19 additions & 0 deletions src/components/icons.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from 'react'

export const Spinner = (props: React.SVGProps<SVGSVGElement>) => {
return (
<svg
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 16 16"
{...props}>
<path
stroke="currentColor"
strokeLinecap="round"
strokeWidth="2"
d="M2.204 6.447A6 6 0 108 2"
/>
</svg>
)
}
22 changes: 22 additions & 0 deletions src/components/loading-spinner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { type VariantProps, cva } from 'class-variance-authority'
import React from 'react'

import { Spinner } from '@/components/icons'

const loadingSpinnerStyles = cva('animate-spin text-white', {
variants: {
variant: {
md: 'h-4 w-4',
lg: 'h-6 w-6',
},
},
defaultVariants: {
variant: 'lg',
},
})

export type LoadingIndicatorProps = VariantProps<typeof loadingSpinnerStyles>

export const LoadingSpinner = ({ variant }: LoadingIndicatorProps) => {
return <Spinner className={loadingSpinnerStyles({ variant })} />
}
6 changes: 6 additions & 0 deletions src/utils/cn.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { cx, CxOptions } from 'class-variance-authority'
import { twMerge } from 'tailwind-merge'

export function cn(...inputs: CxOptions) {
return twMerge(cx(inputs))
}
5 changes: 2 additions & 3 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,8 @@
"@/components/*": ["./components/*"],
"@/types/*": ["./types/*"],
"@/hooks/*": ["./hooks/*"]
},
"typeRoots": ["node_modules/@types", "./src/types"]
}
},
"include": ["src/**/*", "local-signature/**/*"],
"include": ["./src/**/*", "local-signature/**/*", "./jest.config.ts", "./jest.setup.ts"],
"exclude": ["dist", "dev", "temp"]
}

0 comments on commit c0fad38

Please sign in to comment.