Skip to content

Commit

Permalink
Introduce toasts and update button colors
Browse files Browse the repository at this point in the history
  • Loading branch information
svemat01 committed Dec 3, 2024
1 parent dcefdd7 commit b01f7d2
Show file tree
Hide file tree
Showing 8 changed files with 216 additions and 21 deletions.
7 changes: 7 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,11 @@
"vsicons.associations.folders": [
{ "icon": "engine", "extensions": ["engine"], "format": "svg" }
],
"tailwindCSS.experimental.classRegex": [
[ "cva\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]", ],
[ "cvax\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]", ],
[ "cx\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]" ],
[ "cn\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]" ],
[ "tw\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]" ]
]
}
1 change: 1 addition & 0 deletions web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"react-dropzone": "^14.3.5",
"react-icons": "^5.3.0",
"react-leaflet": "^4.2.1",
"sonner": "^1.7.0",
"tailwind-merge": "^2.5.5",
"tailwindcss": "^3.4.3",
"tailwindcss-animate": "^1.0.7",
Expand Down
14 changes: 14 additions & 0 deletions web/pnpm-lock.yaml

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

20 changes: 10 additions & 10 deletions web/src/components/ui/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ const [buttonVariants, buttonVariantsConfig] = cvax(
variants: {
variant: {
default:
'bg-white text-neutral-800 border border-solid border-neutral-200 hover:bg-neutral-50',
'bg-background text-foreground border border-solid border-border hover:bg-popover',
primary: [
'text-white border',
'bg-blue-500 hover:bg-blue-600 border-blue-400 hover:border-blue-500',
'text-background border',
'bg-blue-400 hover:bg-blue-400/80 border-transparent',
'disabled:bg-blue-300 disabled:text-blue-500 disabled:border-blue-300 disabled:hover:bg-blue-300 disabled:hover:border-blue-300 disabled:cursor-not-allowed',
],
secondary: [
Expand All @@ -34,17 +34,17 @@ const [buttonVariants, buttonVariantsConfig] = cvax(
],
link: 'text-blue-500 hover:underline border-transparent bg-transparent',
success: [
'bg-green-500 text-white hover:bg-green-600 border border-green-400 hover:border-green-500',
'disabled:bg-green-300 disabled:text-green-500 disabled:border-green-300 disabled:hover:bg-green-300 disabled:hover:border-green-300 disabled:cursor-not-allowed',
'bg-green-400 text-foreground hover:bg-green-400/80 border-transparent',
'disabled:bg-green-300 disabled:text-green-500 disabled:border-transparent disabled:hover:bg-green-300 disabled:hover:border-transparent disabled:cursor-not-allowed',
],
warning: [
'bg-yellow-500 text-white hover:bg-yellow-600 border border-yellow-400 hover:border-yellow-500',
'disabled:bg-yellow-300 disabled:text-yellow-500 disabled:border-yellow-300 disabled:hover:bg-yellow-300 disabled:hover:border-yellow-300 disabled:cursor-not-allowed',
'bg-yellow-400 text-foreground hover:bg-yellow-400/80 border-transparent',
'disabled:bg-yellow-300 disabled:text-yellow-500 disabled:border-transparent disabled:hover:bg-yellow-300 disabled:hover:border-transparent disabled:cursor-not-allowed',
],
destructive: [
'text-white border',
'bg-red-500 hover:bg-red-600 border-red-400 hover:border-red-500',
'disabled:bg-red-300 disabled:text-red-500 disabled:border-red-300 disabled:hover:bg-red-300 disabled:hover:border-red-300 disabled:cursor-not-allowed',
'text-foreground border',
'bg-red-400 hover:bg-red-400/80 border-transparent',
'disabled:bg-red-300 disabled:text-red-500 disabled:border-transparent disabled:hover:bg-red-300 disabled:hover:border-transparent disabled:cursor-not-allowed',
],
},
size: {
Expand Down
52 changes: 52 additions & 0 deletions web/src/components/ui/Toaster.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { cx } from 'class-variance-authority';
import { ComponentProps } from 'react';
import { Toaster as Sonner } from 'sonner';

import { cn, tw } from '@/util/style';

type ToasterProperties = ComponentProps<typeof Sonner>;

const baseToast = cx(
'flex items-center gap-2',
'p-4 rounded-md w-[--width]',
'text-sm',
'bg-background text-foreground border border-border'
);

const Toaster = ({ ...properties }: ToasterProperties) => {
return (
<Sonner
className="toaster group"
toastOptions={{
unstyled: true,
duration: 15_000,
classNames: {
// toast: 'group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border',
// description: 'group-[.toast]:text-muted-foreground',
// actionButton:
// 'group-[.toast]:bg-primary group-[.toast]:text-primary-foreground',
// cancelButton:
// 'group-[.toast]:bg-muted group-[.toast]:text-muted-foreground',
toast: cx(
'flex items-center gap-2',
'p-4 rounded-md w-[--width]',
'text-sm',
'bg-popover text-foreground border border-border'
),
closeButton: '',
actionButton: 'bg-primary text-primary-foreground',
cancelButton: 'bg-muted text-muted-foreground',
// Toast types
info: tw('border-blue-200'),
success: tw('border-green-200 bg-green-50'),
error: tw('border-red-200 bg-red-50'),
warning: tw('border-yellow-200 bg-yellow-50'),
},
}}
cn={cn}
{...properties}
/>
);
};

export { Toaster };
2 changes: 2 additions & 0 deletions web/src/routes/__root.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { createRootRoute, Outlet } from '@tanstack/react-router';

import { Navbar } from '@/components/Navbar';
import { Toaster } from '@/components/ui/Toaster';

export const Route = createRootRoute({
component: () => (
<>
<Navbar />
<Toaster />
<Outlet />
{/* <TanStackRouterDevtools /> */}
</>
Expand Down
138 changes: 127 additions & 11 deletions web/src/routes/debug.lazy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { createLazyFileRoute } from '@tanstack/react-router';
import { cva, VariantProps } from 'class-variance-authority';
import { ReactNode, useState } from 'react';
import { FaGear } from 'react-icons/fa6';
import { toast } from 'sonner';

import {
AlertDialog,
Expand Down Expand Up @@ -112,13 +113,13 @@ const DebugVariants = <
{variant}
</VariantTitle>
<div
className="flex gap-2 items-center p-4 justify-around"
className="flex flex-wrap gap-2 items-center p-4 justify-around"
key={`container-${variant}-${index}`}
>
{combos.map((combo, index) => (
<div
key={`button-${variant}-${index}`}
className="w-full flex items-center justify-center"
className="contents"
>
{children({
variant,
Expand Down Expand Up @@ -201,15 +202,24 @@ const component = () => {
variants={buttonVariants}
>
{(properties) => (
<Button {...properties}>
{properties.size === 'icon' ? (
<FaGear />
) : (
<>
{properties.variant} {properties.size}
</>
)}
</Button>
<>
<Button {...properties}>
{properties.size === 'icon' ? (
<FaGear />
) : (
<>
{properties.variant} {properties.size}
</>
)}
</Button>
<Button {...properties} disabled>
{properties.size === 'icon' ? (
<FaGear />
) : (
<>Disabled</>
)}
</Button>
</>
)}
</DebugVariants>

Expand Down Expand Up @@ -351,6 +361,112 @@ const component = () => {
</>
)}
</CustomComponentSection>

<CustomComponentSection displayName="Toasts">
<div className="flex gap-2 flex-wrap">
{/* default, info, success, warning, error, action, cancel, promise, loading, custom */}
<Button onClick={() => toast('Normal Toast')}>Toast</Button>

<Button
variant="primary"
onClick={() => toast.info('Info Toast')}
>
Info
</Button>

<Button
variant="success"
onClick={() =>
toast.success('Your media has been uploaded!', {
duration: 15_000,
})
}
>
Success Toast
</Button>

<Button
variant="warning"
onClick={() => toast.warning('Warning Toast')}
>
Warning
</Button>

<Button
variant="destructive"
onClick={() =>
toast.error(
'It appears your piano fell down the skyrise'
)
}
>
Error Toast
</Button>
<Button
onClick={() =>
toast('My action toast', {
action: {
label: 'Action',
onClick: () => toast('Action clicked!'),
},
cancel: {
label: 'Cancel',
onClick: () => toast('Cancel clicked!'),
},
})
}
>
Action Toast
</Button>
<Button
onClick={() =>
toast('My action toast', {
action: (
<Button
variant="destructive"
onClick={() => {
toast.success(
'Your genius plan has been executed'
);
}}
>
Destroy them all
</Button>
),
})
}
>
Custom Action Toast
</Button>

<Button
onClick={() =>
toast.promise(
new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() > 0.5) {
resolve('Viva la vida!');
} else {
reject('No revolution for you!');
}
}, 1000);
}),
{
loading: 'Loading...',
success: (data) => {
return `'${data}' toast has been added`;
},
error: (data) => {
return `'${data}' failed`;
},
}
)
}
>
Promise Toast
</Button>
</div>
</CustomComponentSection>
</SCPage>
);
};
Expand Down
3 changes: 3 additions & 0 deletions web/src/util/style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,7 @@ export const cn = (...inputs: ClassValue[]) => {
export const cvax = <T>(...arguments_: Parameters<typeof cva<T>>) =>
[cva(...arguments_), arguments_[1]!] as const;

/** No-op wrapper for tailwind classes for vscode intellisense */
export const tw = <T extends ClassValue>(input: T) => input;

export type BaseVariants = Record<string, Record<string, ClassValue>>;

0 comments on commit b01f7d2

Please sign in to comment.