Skip to content

Buttons & spinner #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Apr 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{
"parser": "@typescript-eslint/parser",
"env": {
"browser": true,
"es2021": true
},
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"next/core-web-vitals",
"plugin:react/recommended",
"prettier",
"plugin:prettier/recommended"
],
"overrides": [],
"parserOptions": {
"ecmaVersion": "latest",
"sourceType": "module",
"project": ["./tsconfig.json"]
},
"plugins": ["react", "prettier", "@typescript-eslint"],
"rules": {
"react/react-in-jsx-scope": 0,
"@typescript-eslint/no-unused-vars": 1,
"@typescript-eslint/no-explicit-any": "off",
"react/jsx-props-no-spreading": 0,
"no-restricted-syntax": "off",
"no-underscore-dangle": "off",
"@typescript-eslint/naming-convention": "off",
"@typescript-eslint/no-non-null-assertion": "off",
"react/require-default-props": "off",
"radix": "off",
"@typescript-eslint/no-non-null-asserted-optional-chain": "off",
"no-unsafe-optional-chaining": "off",
"@typescript-eslint/ban-ts-comment": "off",
"consistent-return": 1,
"no-void": 1,
"no-return-assign": 1,
"react/jsx-no-useless-fragment": "off",
"no-continue": "off",
"react/no-array-index-key": "off"
},
"globals": {
"React": "writable"
}
}
35 changes: 35 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# local env files
.env*.local

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts
22 changes: 22 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"i18n-ally.localesPaths": ["config/languages"],
"editor.defaultFormatter": "rvest.vs-code-prettier-eslint",
"editor.formatOnPaste": false, // required
"editor.formatOnType": false, // required
"editor.formatOnSave": true, // optional
"editor.formatOnSaveMode": "file", // required to format on save
"files.autoSave": "onFocusChange", // optional but recommended
"editor.codeActionsOnSave": {
// For ESLint
"source.fixAll.eslint": true,
// For TSLint
"source.fixAll.tslint": true,
// For Stylelint
"source.fixAll.stylelint": true
},
"typescript.tsdk": "node_modules/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true,
"[tailwindcss]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
}
143 changes: 143 additions & 0 deletions @ui/components/Button/index.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
.xs {
@apply px-4 py-0.5 text-sm font-semibold rounded-md;
}

.sm {
@apply px-6 py-1 text-sm font-semibold rounded-md;
}

.md {
@apply px-8 py-1.5 text-base font-semibold rounded-md;
}

.lg {
@apply px-10 py-2 text-lg font-semibold rounded-lg;
}

.xl {
@apply px-12 py-3 text-xl font-semibold rounded-lg;
}

.button {
@apply relative overflow-hidden transition-all duration-300 flex items-center justify-center disabled:opacity-50 disabled:pointer-events-none disabled:select-none;
}

.primary {
@apply bg-primary text-white border border-primary hover:bg-opacity-80 active:bg-opacity-90 focus:ring-2 focus:ring-primary focus:ring-offset-2;
}

.secondary {
@apply bg-secondary text-white border border-secondary hover:bg-opacity-80 active:bg-opacity-90 focus:ring-2 focus:ring-secondary focus:ring-offset-2;
}

.success {
@apply bg-success text-white border border-success hover:bg-opacity-80 active:bg-opacity-90 focus:ring-2 focus:ring-success focus:ring-offset-2;
}

.error {
@apply bg-error text-white border border-error hover:bg-opacity-80 active:bg-opacity-90 focus:ring-2 focus:ring-error focus:ring-offset-2;
}

.warning {
@apply bg-warning text-white border border-warning hover:bg-opacity-80 active:bg-opacity-90 focus:ring-2 focus:ring-warning focus:ring-offset-2;
}

.info {
@apply bg-info text-white border border-info hover:bg-opacity-80 active:bg-opacity-90 focus:ring-2 focus:ring-info focus:ring-offset-2;
}

.dark {
@apply bg-dark text-white border border-dark hover:bg-opacity-80 active:bg-opacity-90 focus:ring-2 focus:ring-dark focus:ring-offset-2;
}

.bordered {
@apply border bg-transparent;
}

.bordered.primary {
@apply border border-primary bg-transparent text-primary hover:bg-primary hover:text-white;
}

.bordered.secondary {
@apply border border-secondary bg-transparent text-secondary hover:bg-secondary hover:text-white;
}

.bordered.success {
@apply border border-success bg-transparent text-success hover:bg-success hover:text-white;
}

.bordered.warning {
@apply border border-warning bg-transparent text-warning hover:bg-warning hover:text-white;
}

.bordered.error {
@apply border border-error bg-transparent text-error hover:bg-error hover:text-white;
}

.bordered.info {
@apply border border-info bg-transparent text-info hover:bg-info hover:text-white;
}

.bordered.dark {
@apply border border-dark bg-transparent text-dark hover:bg-dark hover:text-white;
}

.flat {
@apply bg-opacity-20 border-none hover:bg-opacity-40 active:bg-opacity-60;
}

.flat.primary {
@apply text-primary;
}

.flat.secondary {
@apply text-secondary;
}

.flat.success {
@apply text-success;
}

.flat.warning {
@apply text-warning;
}

.flat.error {
@apply text-error;
}

.flat.info {
@apply text-info;
}

.flat.dark {
@apply text-dark;
}

.square {
@apply rounded-none;
}

.pill {
@apply rounded-full;
}

.blockBtn {
@apply block w-full;
}

.btnGroup {
@apply inline-flex items-center;
}

.btnGroup .button:first-child {
@apply rounded-r-none;
}

.btnGroup .button:not(:first-child):not(:last-child) {
@apply rounded-none;
}

.btnGroup .button:last-child {
@apply rounded-l-none;
}
63 changes: 63 additions & 0 deletions @ui/components/Button/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
"use client";
import React, { useRef } from "react";
import { ButtonProps } from "./type";
import classNames from "classnames";
import styles from "./index.module.css";
import Spinner from "@ui/components/Spinner";
import useRippleEffect from "@ui/hooks/useRippleEffect";
import { UIColorWithWhite } from "@ui/ui";

export default function Button(props: ButtonProps) {
const {
className,
color = "primary",
size = "md",
bordered,
children,
flat,
square,
pill,
block,
loading,
spinnerColor,
...buttonProps
} = props;

const buttonRef = useRef<HTMLButtonElement>(null);

useRippleEffect("." + styles.button);

const getSpinnerColor = (): UIColorWithWhite => {
if (spinnerColor) {
return spinnerColor;
}

if (flat) {
return color;
}

return "white";
};

return (
<button
ref={buttonRef}
{...buttonProps}
className={classNames(
className,
styles.button,
styles[size],
styles[color],
{
[styles.bordered]: bordered,
[styles.flat]: flat,
[styles.square]: square,
[styles.pill]: pill,
[styles.blockBtn]: block,
}
)}
>
{loading ? <Spinner size={size} color={getSpinnerColor()} /> : children}
</button>
);
}
17 changes: 17 additions & 0 deletions @ui/components/Button/type.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { UIColor, UIColorWithWhite, UISize } from "../ui";

export interface ButtonProps
extends React.DetailedHTMLProps<
React.ButtonHTMLAttributes<HTMLButtonElement>,
HTMLButtonElement
> {
bordered?: boolean;
flat?: boolean;
color?: UIColor;
size?: UISize;
square?: boolean;
pill?: boolean;
block?: boolean;
loading?: boolean;
spinnerColor?: UIColorWithWhite;
}
7 changes: 7 additions & 0 deletions @ui/components/ButtonGroup/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import React from "react";
import { ButtonGroupProps } from "./type";
import styles from "@ui/components/Button/index.module.css";

export default function ButtonGroup({ children }: ButtonGroupProps) {
return <div className={styles.btnGroup}>{children}</div>;
}
5 changes: 5 additions & 0 deletions @ui/components/ButtonGroup/type.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { ButtonProps } from "@ui/Button/type";

export interface ButtonGroupProps {
children: Array<React.ReactElement<ButtonProps>>;
}
Loading