unify button definition

This commit is contained in:
Gustavo Maronato 2023-08-21 10:45:56 -03:00
parent 7052420b79
commit 9b07c526a5
Signed by: maronato
SSH Key Fingerprint: SHA256:2Gw7kwMz/As+2UkR1qQ/qYYhn+WNh3FGv6ozhoRrLcs
6 changed files with 73 additions and 29 deletions

View File

@ -0,0 +1,44 @@
import {
FunctionComponent,
DetailedHTMLProps,
ButtonHTMLAttributes,
} from "react"
import classNames from "classnames"
type DefaultButtonProps = DetailedHTMLProps<
ButtonHTMLAttributes<HTMLButtonElement>,
HTMLButtonElement
>
const Button: FunctionComponent<
Pick<
DefaultButtonProps,
"className" | "onClick" | "type" | "disabled" | "children"
> & {
color?: "blue" | "red" | "green"
}
> = ({ color, children, className, ...props }) => {
let colorClasses = "bg-blue-100 text-blue-500 hover:bg-blue-500"
if (color === "red") {
colorClasses = "bg-red-100 text-red-500 hover:bg-red-500"
} else if (color === "green") {
colorClasses = "bg-green-100 text-green-500 hover:bg-green-500"
}
return (
<button
{...props}
className={classNames(
"font-bold hover:text-white disabled:text-slate-600",
"disabled:bg-slate-200 disabled:hover:bg-slate-200",
"rounded transition-colors duration-200 select-none",
colorClasses,
className
)}>
{children}
</button>
)
}
export default Button

View File

@ -16,6 +16,8 @@ import { Link } from "react-router-dom"
import { useDoubleclickDelete } from "../hooks/useOnUpdateItem"
import Button from "./Button"
const ItemBase: FunctionComponent<
PropsWithChildren<{
copyString?: string
@ -34,20 +36,19 @@ const ItemBase: FunctionComponent<
<div className="flex flex-row justify-between items-center mt-2">
<div className="flex flex-row gap-2">
{copyString && (
<span
onClick={copy}
className="px-1 py-1 border border-slate-200 rounded-md block text-sm text-green-500 max-w-fit hover:text-white hover:bg-green-500 duration-200 transition-colors cursor-pointer select-none">
<Button onClick={copy} className="px-2 py-1 text-sm" color="green">
<ClipboardIcon className="inline-block w-4 h-4 mb-0.5 mr-1 leading-1" />
{copied ? "Copied!" : "Copy"}
</span>
</Button>
)}
{doDelete && (
<span
<Button
onClick={triggerDelete}
className="px-2 py-1 border border-slate-200 rounded-md block text-sm text-red-500 max-w-fit hover:text-white hover:bg-red-500 duration-200 transition-colors cursor-pointer select-none">
className="px-2 py-1 text-sm"
color="red">
<TrashIcon className="inline-block w-4 h-4 mb-0.5 mr-1 leading-1" />
{deleting ? "Are you sure?" : "Delete"}
</span>
</Button>
)}
</div>
<div>

View File

@ -7,6 +7,7 @@ import {
useNavigation,
} from "react-router-dom"
import Button from "../components/Button"
import Header from "../components/Header"
import ItemList from "../components/ItemList"
import ShortItem from "../components/ShortItem"
@ -111,11 +112,9 @@ export const Component: FunctionComponent = () => {
{actionData.error}
</p>
) : null}
<button
type="submit"
className="px-4 py-3 rounded-md bg-blue-100 text-blue-500 hover:bg-blue-200 text-2xl font-semibold transition-colors duration-200 disabled:bg-slate-200 disabled:text-slate-400">
<Button type="submit" className="py-3 text-2xl">
{isShortening ? "Shortening..." : "Shorten it"}
</button>
</Button>
</Form>
<div className="mt-10">
<ItemList

View File

@ -6,6 +6,7 @@ import {
useSearchParams,
} from "react-router-dom"
import Button from "../components/Button"
import Header from "../components/Header"
export function Component() {
@ -57,12 +58,13 @@ export function Component() {
className="p-2 font-light border-b-2 bg-slate-50 border-slate-400 text-lg focus:outline-none focus:border-blue-500 transition-colors duration-200"
/>
</label>
<button
className="mt-6 px-8 py-3 bg-blue-100 text-blue-600 font-bold rounded max-w-fit mx-auto hover:bg-blue-200 disabled:bg-slate-200 disabled:hover:bg-slate-200 disabled:text-slate-600 transition-colors duration-200"
<Button
type="submit"
disabled={isSigningUp}>
color="blue"
disabled={isSigningUp}
className="mt-6 px-8 py-3 max-w-fit mx-auto">
{isSigningUp ? "Logging in..." : "Log in"}
</button>
</Button>
<span className="text-slate-500 font-light text-center text-sm">
{`Don't have an account? `}
<Link

View File

@ -6,6 +6,7 @@ import {
useSearchParams,
} from "react-router-dom"
import Button from "../components/Button"
import Header from "../components/Header"
export function Component() {
@ -57,12 +58,13 @@ export function Component() {
className="p-2 font-light border-b-2 bg-slate-50 border-slate-400 text-lg focus:outline-none focus:border-blue-500 transition-colors duration-200"
/>
</label>
<button
className="mt-6 px-8 py-3 bg-blue-100 text-blue-600 font-bold rounded max-w-fit mx-auto hover:bg-blue-200 disabled:bg-slate-200 disabled:hover:bg-slate-200 disabled:text-slate-600 transition-colors duration-200"
<Button
type="submit"
disabled={isSigningUp}>
color="blue"
disabled={isSigningUp}
className="mt-6 px-8 py-3 max-w-fit mx-auto">
{isSigningUp ? "Signing up..." : "Sign up"}
</button>
</Button>
<span className="text-slate-500 font-light text-center text-sm">
{`Have an account? `}
<Link

View File

@ -1,9 +1,9 @@
import { FunctionComponent, useMemo } from "react"
import { PlusIcon } from "@heroicons/react/24/outline"
import classNames from "classnames"
import { LoaderFunction, redirect } from "react-router-dom"
import Button from "../components/Button"
import Header from "../components/Header"
import TokenItem from "../components/TokenItem"
import { protectedLoader } from "../hooks/useAuth"
@ -39,17 +39,13 @@ export function Component() {
return (
<>
<Header title="Tokens" />
<button
<Button
disabled={creating}
onClick={() => createItem()}
className="absolute self-end mt-14 px-4 py-3 text-blue-500 flex flex-row font-semibold text-lg hover:text-blue-600 transition-colors duration-200 disabled:text-slate-500">
<PlusIcon
className={classNames("h-4 w-4 mr-1 my-auto", {
"animate-spin": creating,
})}
/>
className="absolute self-end mt-14 px-4 py-3 text-lg">
<PlusIcon className="inline-block w-5 h-5 mb-0.5 mr-1 leading-1" />
<span>New token</span>
</button>
</Button>
{data.length > 0 ? <Tokens /> : <NoTokens />}
</>
)
@ -59,7 +55,7 @@ export const loader: LoaderFunction = async (args) => {
const resp = await protectedLoader(args)
if (resp) return resp
// const data = await fetchAPI<Session[]>("/sessions")
// const data = await fetchAPI<Token[]>("/tokens")
const data = { ok: true, data: [] }
if (data.ok) {
return data.data