= {
+ primary: 'border-transparent text-slate-500 bg-slate-300',
+ secondary: 'border-transparent text-slate-400 bg-slate-200',
+ special: 'border-transparent text-slate-500 bg-slate-300',
+ success: 'border-transparent text-slate-500 bg-slate-300',
+ tertiary: 'border-slate-300 text-slate-400 bg-slate-100',
+};
+
+export default function Button({
+ addonPosition = 'end',
+ 'aria-controls': ariaControls,
+ className,
+ display = 'inline',
+ href,
+ icon: Icon,
+ isDisabled = false,
+ isLabelHidden = false,
+ isLoading = false,
+ label,
+ size = 'md',
+ type = 'button',
+ variant,
+ onClick,
+}: Props) {
+ const iconSpacingClass = (() => {
+ if (!isLabelHidden && addonPosition === 'start') {
+ return sizeIconSpacingStartClasses[size];
+ }
+
+ if (!isLabelHidden && addonPosition === 'end') {
+ return sizeIconSpacingEndClasses[size];
+ }
+ })();
+ const addOnClass = clsx(iconSpacingClass, sizeIconClasses[size]);
+
+ const addOn = isLoading ? (
+
+ ) : Icon != null ? (
+
+ ) : null;
+
+ const children = (
+ <>
+ {addonPosition === 'start' && addOn}
+ {!isLabelHidden && label}
+ {addonPosition === 'end' && addOn}
+ >
+ );
+
+ const commonProps = {
+ 'aria-controls': ariaControls ?? undefined,
+ 'aria-label': isLabelHidden ? label : undefined,
+ children,
+ className: clsx(
+ display === 'block' ? 'flex w-full justify-center' : 'inline-flex',
+ 'whitespace-nowrap items-center border font-medium focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500',
+ isDisabled ? variantDisabledClasses[variant] : variantClasses[variant],
+ isDisabled && 'pointer-events-none',
+ isLabelHidden ? iconOnlySizeClasses[size] : sizeClasses[size],
+ baseClasses[size],
+ className,
+ ),
+ disabled: isDisabled,
+ onClick,
+ };
+
+ if (href == null) {
+ return (
+
+ );
+ }
+
+ return (
+
+
+
+ );
+}
diff --git a/packages/ui/src/Button/index.ts b/packages/ui/src/Button/index.ts
new file mode 100644
index 00000000..301ea717
--- /dev/null
+++ b/packages/ui/src/Button/index.ts
@@ -0,0 +1,4 @@
+import Button from './Button';
+
+export * from './Button';
+export default Button;
diff --git a/packages/ui/src/CounterButton.tsx b/packages/ui/src/CounterButton.tsx
index f61f0ad7..6a9017c7 100644
--- a/packages/ui/src/CounterButton.tsx
+++ b/packages/ui/src/CounterButton.tsx
@@ -10,7 +10,7 @@ export function CounterButton() {
fontWeight: 500,
padding: '1.5rem',
}}>
-
+
This component is from{' '}
;
+
+const colorClasses: Record = {
+ default: 'text-slate-400',
+ inherit: '',
+};
+
+const sizeClasses: Record = {
+ lg: 'w-12 h-12 border-[6px]',
+ md: 'w-8 h-8 border-4',
+ sm: 'w-6 h-6 border-[3px]',
+ xs: 'w-4 h-4 border-2',
+};
+
+export default function Spinner({
+ className,
+ color = 'default',
+ display = 'inline',
+ label = 'Loading...',
+ size,
+}: Props) {
+ const spinner = (
+
+ {label}
+
+ );
+
+ if (display === 'block') {
+ return {spinner}
;
+ }
+
+ return spinner;
+}
diff --git a/packages/ui/src/Spinner/index.ts b/packages/ui/src/Spinner/index.ts
new file mode 100644
index 00000000..0e0be394
--- /dev/null
+++ b/packages/ui/src/Spinner/index.ts
@@ -0,0 +1,4 @@
+import Spinner from './Spinner';
+
+export * from './Spinner';
+export default Spinner;
diff --git a/packages/ui/src/index.tsx b/packages/ui/src/index.tsx
index 97ab35fa..00b92547 100644
--- a/packages/ui/src/index.tsx
+++ b/packages/ui/src/index.tsx
@@ -1,2 +1,4 @@
+export { default as Button } from './Button';
+export * from './Button';
export { CounterButton } from './CounterButton';
export { NewTabLink } from './NewTabLink';
diff --git a/packages/ui/src/styles.css b/packages/ui/src/styles.css
new file mode 100644
index 00000000..bd6213e1
--- /dev/null
+++ b/packages/ui/src/styles.css
@@ -0,0 +1,3 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
\ No newline at end of file
diff --git a/packages/ui/tailwind.config.js b/packages/ui/tailwind.config.js
new file mode 100644
index 00000000..ff9c6d11
--- /dev/null
+++ b/packages/ui/tailwind.config.js
@@ -0,0 +1,3 @@
+const config = require('@tih/tailwind-config/tailwind.config.js');
+
+module.exports = config;
diff --git a/yarn.lock b/yarn.lock
index 5b16f40a..c33d6b77 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5332,6 +5332,15 @@ cliui@^7.0.2:
strip-ansi "^6.0.0"
wrap-ansi "^7.0.0"
+cliui@^8.0.1:
+ version "8.0.1"
+ resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa"
+ integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==
+ dependencies:
+ string-width "^4.2.0"
+ strip-ansi "^6.0.1"
+ wrap-ansi "^7.0.0"
+
clone-deep@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387"
@@ -5515,6 +5524,21 @@ concat-stream@^1.5.0:
readable-stream "^2.2.2"
typedarray "^0.0.6"
+concurrently@^7.4.0:
+ version "7.4.0"
+ resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-7.4.0.tgz#bb0e344964bc172673577c420db21e963f2f7368"
+ integrity sha512-M6AfrueDt/GEna/Vg9BqQ+93yuvzkSKmoTixnwEJkH0LlcGrRC2eCmjeG1tLLHIYfpYJABokqSGyMcXjm96AFA==
+ dependencies:
+ chalk "^4.1.0"
+ date-fns "^2.29.1"
+ lodash "^4.17.21"
+ rxjs "^7.0.0"
+ shell-quote "^1.7.3"
+ spawn-command "^0.0.2-1"
+ supports-color "^8.1.0"
+ tree-kill "^1.2.2"
+ yargs "^17.3.1"
+
configstore@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/configstore/-/configstore-5.0.1.tgz#d365021b5df4b98cdd187d6a3b0e3f6a7cc5ed96"
@@ -5961,6 +5985,11 @@ damerau-levenshtein@^1.0.8:
resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7"
integrity sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==
+date-fns@^2.29.1:
+ version "2.29.3"
+ resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.29.3.tgz#27402d2fc67eb442b511b70bbdf98e6411cd68a8"
+ integrity sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==
+
debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.9:
version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
@@ -10217,7 +10246,7 @@ next-auth@~4.10.3:
preact-render-to-string "^5.1.19"
uuid "^8.3.2"
-next@12.3.1:
+next@12.3.1, next@^12.3.1:
version "12.3.1"
resolved "https://registry.yarnpkg.com/next/-/next-12.3.1.tgz#127b825ad2207faf869b33393ec8c75fe61e50f1"
integrity sha512-l7bvmSeIwX5lp07WtIiP9u2ytZMv7jIeB8iacR28PuUEFG5j0HGAPnMqyG5kbZNBG2H7tRsrQ4HCjuMOPnANZw==
@@ -12493,7 +12522,7 @@ run-queue@^1.0.0, run-queue@^1.0.3:
dependencies:
aproba "^1.1.1"
-rxjs@^7.5.4:
+rxjs@^7.0.0, rxjs@^7.5.4:
version "7.5.7"
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.7.tgz#2ec0d57fdc89ece220d2e702730ae8f1e49def39"
integrity sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA==
@@ -13007,6 +13036,11 @@ space-separated-tokens@^1.0.0:
resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz#85f32c3d10d9682007e917414ddc5c26d1aa6899"
integrity sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==
+spawn-command@^0.0.2-1:
+ version "0.0.2-1"
+ resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2-1.tgz#62f5e9466981c1b796dc5929937e11c9c6921bd0"
+ integrity sha512-n98l9E2RMSJ9ON1AKisHzz7V42VDiBQGY6PB1BwRglz99wpVsSuGzQ+jOi6lFXBGVTCrRpltvjm+/XA+tpeJrg==
+
spdx-correct@^3.0.0:
version "3.1.1"
resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9"
@@ -13381,7 +13415,7 @@ supports-color@^7.0.0, supports-color@^7.1.0:
dependencies:
has-flag "^4.0.0"
-supports-color@^8.0.0:
+supports-color@^8.0.0, supports-color@^8.1.0:
version "8.1.1"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c"
integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==
@@ -14784,6 +14818,11 @@ yargs-parser@^20.2.2, yargs-parser@^20.2.9:
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee"
integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==
+yargs-parser@^21.0.0:
+ version "21.1.1"
+ resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35"
+ integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==
+
yargs@^16.2.0:
version "16.2.0"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66"
@@ -14797,6 +14836,19 @@ yargs@^16.2.0:
y18n "^5.0.5"
yargs-parser "^20.2.2"
+yargs@^17.3.1:
+ version "17.6.0"
+ resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.6.0.tgz#e134900fc1f218bc230192bdec06a0a5f973e46c"
+ integrity sha512-8H/wTDqlSwoSnScvV2N/JHfLWOKuh5MVla9hqLjK3nsfyy6Y4kDSYSvkU5YCUEPOSnRXfIyx3Sq+B/IWudTo4g==
+ dependencies:
+ cliui "^8.0.1"
+ escalade "^3.1.1"
+ get-caller-file "^2.0.5"
+ require-directory "^2.1.1"
+ string-width "^4.2.3"
+ y18n "^5.0.5"
+ yargs-parser "^21.0.0"
+
yocto-queue@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"