This commit is contained in:
Benjamin Toby
2024-10-17 09:06:54 +01:00
parent 25daf1844e
commit f73b56cdc4
25 changed files with 408 additions and 35 deletions
+102 -9
View File
@@ -3,25 +3,44 @@ import {
ButtonHTMLAttributes,
DetailedHTMLProps,
HTMLAttributeAnchorTarget,
HTMLAttributes,
} from "react";
import { ClassNameValue, twMerge } from "tailwind-merge";
import { twMerge } from "tailwind-merge";
import Loading from "../elements/Loading";
/**
* # Buttons
* @className twui-button-general
* @className twui-button-content-wrapper
* @className twui-button-primary
* @className twui-button-primary-outlined
* @className twui-button-primary-ghost
* @className twui-button-secondary
* @className twui-button-secondary-outlined
* @className twui-button-secondary-ghost
* @className twui-button-accent
* @className twui-button-accent-outlined
* @className twui-button-accent-ghost
* @className twui-button-gray
* @className twui-button-gray-outlined
* @className twui-button-gray-ghost
*/
export default function Button({
href,
target,
variant,
color,
linkProps,
loading,
...props
}: DetailedHTMLProps<
ButtonHTMLAttributes<HTMLButtonElement>,
HTMLButtonElement
> & {
variant?: "normal" | "ghost" | "outlined";
color?: "primary" | "secondary" | "accent";
color?: "primary" | "secondary" | "accent" | "gray";
href?: string;
target?: HTMLAttributeAnchorTarget;
loading?: boolean;
linkProps?: DetailedHTMLProps<
AnchorHTMLAttributes<HTMLAnchorElement>,
HTMLAnchorElement
@@ -29,14 +48,76 @@ export default function Button({
}) {
const finalClassName: string = (() => {
if (variant == "normal" || !variant) {
if (color == "primary" || !color) return "bg-blue-500 text-white";
if (color == "primary" || !color)
return twMerge(
"bg-blue-500 hover:bg-blue-600 text-white",
"twui-button-primary"
);
if (color == "secondary")
return twMerge(
"bg-emerald-500 hover:bg-emerald-600 text-white",
"twui-button-secondary"
);
if (color == "accent")
return twMerge(
"bg-violet-500 hover:bg-violet-600 text-white",
"twui-button-accent"
);
if (color == "gray")
return twMerge(
"bg-slate-300 hover:bg-slate-200 text-slate-800",
"twui-button-gray"
);
} else if (variant == "outlined") {
if (color == "primary" || !color)
return (
"bg-transparent outline outline-1 outline-blue-500" +
" text-blue-500"
return twMerge(
"bg-transparent outline outline-1 outline-blue-500",
"text-blue-500",
"twui-button-primary-outlined"
);
if (color == "secondary")
return twMerge(
"bg-transparent outline outline-1 outline-emerald-500",
"text-emerald-500",
"twui-button-secondary-outlined"
);
if (color == "accent")
return twMerge(
"bg-transparent outline outline-1 outline-violet-500",
"text-violet-500",
"twui-button-accent-outlined"
);
if (color == "gray")
return twMerge(
"bg-transparent outline outline-1 outline-slate-300",
"text-slate-600",
"twui-button-gray-outlined"
);
} else if (variant == "ghost") {
if (color == "primary" || !color)
return twMerge(
"bg-transparent outline-none p-2",
"text-blue-500",
"twui-button-primary-ghost"
);
if (color == "secondary")
return twMerge(
"bg-transparent outline-none p-2",
"text-emerald-500",
"twui-button-secondary-ghost"
);
if (color == "accent")
return twMerge(
"bg-transparent outline-none p-2",
"text-violet-500",
"twui-button-accent-ghost"
);
if (color == "gray")
return twMerge(
"bg-transparent outline-none p-2",
"text-slate-600",
"twui-button-gray-ghost"
);
}
return "";
@@ -47,11 +128,23 @@ export default function Button({
{...props}
className={twMerge(
"bg-blue-600 text-white text-base font-medium px-4 py-2 rounded",
"flex items-center justify-center relative transition-all",
"twui-button-general",
finalClassName,
props.className
props.className,
loading ? "pointer-events-none opacity-80" : "l"
)}
>
{props.children}
<div
className={twMerge(
"flex items-center gap-2",
loading ? "opacity-0" : "",
"twui-button-content-wrapper"
)}
>
{props.children}
</div>
{loading && <Loading className="absolute" />}
</button>
);
+2 -1
View File
@@ -12,7 +12,8 @@ export default function Container({
<div
{...props}
className={twMerge(
"flex flex-row items-center w-full max-w-[1200px]",
"flex items-center w-full max-w-[1200px] gap-4 justify-between",
"flex-wrap flex-col xl:flex-row",
"twui-container",
props.className
)}
+27
View File
@@ -0,0 +1,27 @@
import { DetailedHTMLProps, HTMLAttributes } from "react";
import { twMerge } from "tailwind-merge";
/**
* # Vertical and Horizontal Divider
* @className twui-divider
*/
export default function Divider({
vertical,
...props
}: DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement> & {
vertical?: boolean;
}) {
return (
<div
{...props}
className={twMerge(
"border-slate-200 dark:border-white/10",
vertical
? "border-0 border-l h-full min-h-5"
: "border-0 border-t w-full",
"twui-divider",
props.className
)}
/>
);
}
+6 -2
View File
@@ -1,11 +1,15 @@
import { DetailedHTMLProps, HTMLAttributes } from "react";
import { twMerge } from "tailwind-merge";
/**
* # General Footer
* @className twui-footer
*/
export default function Footer({
...props
}: DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>) {
return (
<header
<footer
{...props}
className={twMerge(
"flex flex-col items-center justify-center",
@@ -16,6 +20,6 @@ export default function Footer({
)}
>
{props.children}
</header>
</footer>
);
}
+8 -1
View File
@@ -1,11 +1,18 @@
import { DetailedHTMLProps, HTMLAttributes } from "react";
import { twMerge } from "tailwind-merge";
/**
* # H1 Headers
* @className twui-h1
*/
export default function H1({
...props
}: DetailedHTMLProps<HTMLAttributes<HTMLHeadingElement>, HTMLHeadingElement>) {
return (
<h1 {...props} className={twMerge("text-5xl mb-4", props.className)}>
<h1
{...props}
className={twMerge("text-5xl mb-4", "twui-h1", props.className)}
>
{props.children}
</h1>
);
+8 -1
View File
@@ -1,11 +1,18 @@
import { DetailedHTMLProps, HTMLAttributes } from "react";
import { twMerge } from "tailwind-merge";
/**
* # H2 Headers
* @className twui-h2
*/
export default function H2({
...props
}: DetailedHTMLProps<HTMLAttributes<HTMLHeadingElement>, HTMLHeadingElement>) {
return (
<h2 {...props} className={twMerge("text-3xl mb-4", props.className)}>
<h2
{...props}
className={twMerge("text-3xl mb-4", "twui-h2", props.className)}
>
{props.children}
</h2>
);
+8 -1
View File
@@ -1,11 +1,18 @@
import { DetailedHTMLProps, HTMLAttributes } from "react";
import { twMerge } from "tailwind-merge";
/**
* # H3 Headers
* @className twui-h3
*/
export default function H3({
...props
}: DetailedHTMLProps<HTMLAttributes<HTMLHeadingElement>, HTMLHeadingElement>) {
return (
<h3 {...props} className={twMerge("text-xl mb-4", props.className)}>
<h3
{...props}
className={twMerge("text-xl mb-4", "twui-h3", props.className)}
>
{props.children}
</h3>
);
+8 -1
View File
@@ -1,11 +1,18 @@
import { DetailedHTMLProps, HTMLAttributes } from "react";
import { twMerge } from "tailwind-merge";
/**
* # H4 Headers
* @className twui-h4
*/
export default function H4({
...props
}: DetailedHTMLProps<HTMLAttributes<HTMLHeadingElement>, HTMLHeadingElement>) {
return (
<h4 {...props} className={twMerge("text-base mb-4", props.className)}>
<h4
{...props}
className={twMerge("text-base mb-4", "twui-h4", props.className)}
>
{props.children}
</h4>
);
+8 -1
View File
@@ -1,11 +1,18 @@
import { DetailedHTMLProps, HTMLAttributes } from "react";
import { twMerge } from "tailwind-merge";
/**
* # H5 Headers
* @className twui-h5
*/
export default function H5({
...props
}: DetailedHTMLProps<HTMLAttributes<HTMLHeadingElement>, HTMLHeadingElement>) {
return (
<h5 {...props} className={twMerge("text-sm mb-4", props.className)}>
<h5
{...props}
className={twMerge("text-sm mb-4", "twui-h5", props.className)}
>
{props.children}
</h5>
);
+6 -1
View File
@@ -1,6 +1,10 @@
import { DetailedHTMLProps, HTMLAttributes } from "react";
import { twMerge } from "tailwind-merge";
/**
* # Horizonta Rule (hr)
* @className twui-hr
*/
export default function HR({
...props
}: DetailedHTMLProps<HTMLAttributes<HTMLHRElement>, HTMLHRElement>) {
@@ -8,7 +12,8 @@ export default function HR({
<hr
{...props}
className={twMerge(
"bg-slate-400 w-full dark:bg-white/20 my-4",
"border-slate-200 dark:border-white/20 w-full my-4",
"twui-hr",
props.className
)}
/>
+2 -2
View File
@@ -13,8 +13,8 @@ export default function Header({
{...props}
className={twMerge(
"flex flex-col items-center justify-center",
"px-4 sm:px-10 py-2",
"border-0 border-b border-slate-200 border-solid",
"px-4 sm:px-10 py-3 flex-wrap",
"border-0 border-b border-slate-200 dark:border-white/10 border-solid",
"twui-header",
props.className
)}
+8
View File
@@ -1,6 +1,10 @@
import { AnchorHTMLAttributes, DetailedHTMLProps } from "react";
import { twMerge } from "tailwind-merge";
/**
* # General Anchor Elements
* @className twui-a | twui-anchor
*/
export default function Link({
...props
}: DetailedHTMLProps<
@@ -12,6 +16,10 @@ export default function Link({
{...props}
className={twMerge(
"text-base text-link-500 no-underline hover:text-link-500/50",
"text-blue-600 dark:text-blue-400",
"border-0 border-b border-blue-300 border-solid leading-4",
"twui-anchor",
"twui-a",
props.className
)}
>
+54
View File
@@ -0,0 +1,54 @@
import {
AnchorHTMLAttributes,
DetailedHTMLProps,
HTMLAttributes,
OlHTMLAttributes,
} from "react";
import { twMerge } from "tailwind-merge";
/**
* # Ordered and unorder Lists
* @className twui-ol
* @className twui-ul
*/
export default function List({
ordered,
items,
...props
}: DetailedHTMLProps<HTMLAttributes<HTMLUListElement>, HTMLUListElement> &
DetailedHTMLProps<OlHTMLAttributes<HTMLOListElement>, HTMLOListElement> & {
items: {
content: React.ReactNode | string;
}[];
ordered?: boolean;
}) {
const listContent = (
<>
{items.map((item, index) => (
<li key={index}>{item.content}</li>
))}
</>
);
const className = "flex flex-col items-start gap-4";
if (ordered) {
return (
<ol
{...props}
className={twMerge(className, "twui-ol", props.className)}
>
{listContent}
</ol>
);
}
return (
<ul
{...props}
className={twMerge(className, "twui-ul", props.className)}
>
{listContent}
</ul>
);
}
+6 -1
View File
@@ -1,6 +1,10 @@
import { DetailedHTMLProps, HTMLAttributes } from "react";
import { twMerge } from "tailwind-merge";
/**
* # Main Wrapper
* @className twui-h1
*/
export default function Main({
...props
}: DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>) {
@@ -8,7 +12,8 @@ export default function Main({
<main
{...props}
className={twMerge(
"flex flex-col items-start w-full",
"flex flex-col items-center w-full",
"twui-main",
props.className
)}
>
+13 -1
View File
@@ -1,11 +1,23 @@
import { DetailedHTMLProps, HTMLAttributes } from "react";
import { twMerge } from "tailwind-merge";
/**
* # Paragraph Tag
* @className twui-p | twui-paragraph
*/
export default function P({
...props
}: DetailedHTMLProps<HTMLAttributes<HTMLHeadingElement>, HTMLHeadingElement>) {
return (
<p {...props} className={twMerge("text-base py-4", props.className)}>
<p
{...props}
className={twMerge(
"text-base py-4",
"twui-p",
"twui-paragraph",
props.className
)}
>
{props.children}
</p>
);
+6 -1
View File
@@ -1,6 +1,10 @@
import { DetailedHTMLProps, HTMLAttributes } from "react";
import { twMerge } from "tailwind-merge";
/**
* # Flexbox Row
* @className twui-row
*/
export default function Row({
...props
}: DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>) {
@@ -8,7 +12,8 @@ export default function Row({
<div
{...props}
className={twMerge(
"flex flex-row items-center gap-2",
"flex flex-row items-center gap-2 flex-wrap",
"twui-row",
props.className
)}
>
+5
View File
@@ -1,6 +1,10 @@
import { DetailedHTMLProps, HTMLAttributes } from "react";
import { twMerge } from "tailwind-merge";
/**
* # General Section
* @className twui-section
*/
export default function Section({
...props
}: DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>) {
@@ -10,6 +14,7 @@ export default function Section({
className={twMerge(
"flex flex-col items-center w-full",
"px-4 sm:px-10 py-10",
"twui-section",
props.className
)}
>
+8 -1
View File
@@ -1,11 +1,18 @@
import { DetailedHTMLProps, HTMLAttributes } from "react";
import { twMerge } from "tailwind-merge";
/**
* # Span element
* @className twui-span
*/
export default function Span({
...props
}: DetailedHTMLProps<HTMLAttributes<HTMLHeadingElement>, HTMLHeadingElement>) {
return (
<span {...props} className={twMerge("text-base", props.className)}>
<span
{...props}
className={twMerge("text-base", "twui-span", props.className)}
>
{props.children}
</span>
);
+9 -1
View File
@@ -1,13 +1,21 @@
import { DetailedHTMLProps, HTMLAttributes } from "react";
import { twMerge } from "tailwind-merge";
/**
* # Flexbox Column
* @className twui-stack
*/
export default function Stack({
...props
}: DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>) {
return (
<div
{...props}
className={twMerge("flex flex-col items-start", props.className)}
className={twMerge(
"flex flex-col items-start",
"twui-stack",
props.className
)}
>
{props.children}
</div>