Skip to content

Commit

Permalink
refactor: use sonner instead of react-hot-toast ♻️➕ (#110)
Browse files Browse the repository at this point in the history
  • Loading branch information
kareemmahlees authored Sep 19, 2024
1 parent 97cbc0b commit ef16190
Show file tree
Hide file tree
Showing 22 changed files with 166 additions and 108 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,5 @@ next-env.d.ts
/**/target
**/bin/
**/dist
gen
gen
*.log
3 changes: 2 additions & 1 deletion apps/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,13 @@
"hotkeys-js": "^3.13.7",
"lucide-react": "^0.292.0",
"mini-svg-data-uri": "^1.4.4",
"next-themes": "^0.3.0",
"react": "^18.3.1",
"react-day-picker": "8.10.1",
"react-dom": "^18.3.1",
"react-hook-form": "^7.53.0",
"react-hot-toast": "^2.4.1",
"react-resizable-panels": "^2.1.1",
"sonner": "^1.5.0",
"tailwind-merge": "^2.5.2",
"tailwindcss-animate": "^1.0.7",
"usehooks-ts": "^3.1.0",
Expand Down
4 changes: 2 additions & 2 deletions apps/core/src/commands/connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import { customToast } from "@/lib/utils"

export const testConnectionCmd = async (connString: string) => {
const commandResult = await commands.testConnection(connString)
customToast(commandResult, () => {}, "test_connection")
customToast(commandResult, "test_connection")
}

export const deleteConnectionCmd = async (connId: string) => {
const commandResult = await commands.deleteConnectionRecord(connId)
customToast(commandResult, () => {}, "delete_connection")
customToast(commandResult, "delete_connection")
}
8 changes: 4 additions & 4 deletions apps/core/src/commands/row.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { commands } from "@/bindings"
import { customToast } from "@/lib/utils"
import type { Row } from "@tanstack/react-table"
import toast from "react-hot-toast"
import { toast } from "sonner"

export const createRowCmd = async (
tableName: string,
Expand All @@ -10,7 +10,7 @@ export const createRowCmd = async (
) => {
const commandResult = await commands.createRow(tableName, data)

customToast(commandResult, () => toggleSheet(false), "create_row")
customToast(commandResult, "create_row", () => toggleSheet(false))
}

export const deleteRowsCmd = async (
Expand All @@ -29,7 +29,7 @@ export const deleteRowsCmd = async (
rows.map((row) => row.getValue(pkColumn)),
tableName
)
customToast(command, () => {}, "delete_row")
customToast(command, "delete_row")
}

export const updateRowCmd = async (
Expand All @@ -45,5 +45,5 @@ export const updateRowCmd = async (
pkColValue,
data
)
customToast(command, () => toggleSheet(false), "update_row")
customToast(command, "update_row", () => toggleSheet(false))
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,23 @@ import { TabsContent } from "@/components/ui/tabs"
import { useKeybindings, type EditedBinding } from "@/keybindings/manager"
import { Edit2, FileJson2 } from "lucide-react"
import { useEffect, useState, type Dispatch, type SetStateAction } from "react"
import { toast } from "sonner"

const KeybindingsTab = () => {
const keybindings = useKeybindings()
const [editedKeybindings, setEditKeybindings] = useState<EditedBinding[]>([])

const handleKeybindingsSave = async () => {
const result = await commands.writeIntoKeybindingsFile(keybindings.bindings)
if (result.status === "error") {
return toast.error("Failed to update keybindings", {
description: "Please try again"
})
}
keybindings.reRegister(editedKeybindings)
toast.success("Keybindings updated successfully")
}

return (
<TabsContent value="keybindings">
<Table>
Expand Down Expand Up @@ -58,13 +71,7 @@ const KeybindingsTab = () => {
</TableBody>
</Table>
<div className="absolute bottom-7 right-4 flex flex-row-reverse items-center gap-x-3">
<Button
size={"sm"}
onClick={async () => {
await commands.writeIntoKeybindingsFile(keybindings.bindings)
keybindings.reRegister(editedKeybindings)
}}
>
<Button size={"sm"} onClick={handleKeybindingsSave}>
Save
</Button>
<Button
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { zodResolver } from "@hookform/resolvers/zod"
import { FileJson2 } from "lucide-react"
import type { PropsWithChildren } from "react"
import { useForm } from "react-hook-form"
import { toast } from "sonner"
import z from "zod"

const formSchema = z.object({
Expand All @@ -40,7 +41,19 @@ const SettingsTab = () => {
})

const onSubmit = async (data: z.infer<typeof formSchema>) => {
await commands.writeIntoSettingsFile(data)
const result = await commands.writeIntoSettingsFile(data)
if (result.status === "error") {
return toast.error("Failed to update settings.", {
description: result.error.details
})
}
return toast.success("Successfully updated settings", {
description: "A hard refresh is required",
action: {
label: "Refresh",
onClick: () => location.reload()
}
})
}

return (
Expand Down
2 changes: 1 addition & 1 deletion apps/core/src/components/sheets/edit-row-sheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { useTableState } from "@/state/tableState"
import { zodResolver } from "@hookform/resolvers/zod"
import type { Row } from "@tanstack/react-table"
import { useForm } from "react-hook-form"
import toast from "react-hot-toast"
import { toast } from "sonner"
import { z } from "zod"
import DynamicFormInput from "./components/dynamic-input"

Expand Down
23 changes: 12 additions & 11 deletions apps/core/src/components/ui/dialog.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
"use client"

import * as React from "react"
import * as DialogPrimitive from "@radix-ui/react-dialog"
import { X } from "lucide-react"
import * as React from "react"

import { cn } from "@tablex/lib/utils"

Expand Down Expand Up @@ -42,6 +42,15 @@ const DialogContent = React.forwardRef<
className
)}
{...props}
onInteractOutside={(e) => {
const { originalEvent } = e.detail
if (
originalEvent.target instanceof Element &&
originalEvent.target.closest(".group.toast")
) {
e.preventDefault()
}
}}
>
{children}
<DialogPrimitive.Close className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute right-4 top-4 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:pointer-events-none">
Expand Down Expand Up @@ -109,14 +118,6 @@ const DialogDescription = React.forwardRef<
DialogDescription.displayName = DialogPrimitive.Description.displayName

export {
Dialog,
DialogPortal,
DialogOverlay,
DialogClose,
DialogTrigger,
DialogContent,
DialogHeader,
DialogFooter,
DialogTitle,
DialogDescription
Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger
}

24 changes: 13 additions & 11 deletions apps/core/src/components/ui/sheet.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
"use client"

import * as React from "react"
import * as SheetPrimitive from "@radix-ui/react-dialog"
import { cva, type VariantProps } from "class-variance-authority"
import { X } from "lucide-react"
import * as React from "react"

import { cn } from "@tablex/lib/utils"

Expand Down Expand Up @@ -62,6 +62,15 @@ const SheetContent = React.forwardRef<
<SheetPrimitive.Content
ref={ref}
className={cn(sheetVariants({ side }), className)}
onInteractOutside={(e) => {
const { originalEvent } = e.detail
if (
originalEvent.target instanceof Element &&
originalEvent.target.closest(".group.toast")
) {
e.preventDefault()
}
}}
{...props}
>
{children}
Expand Down Expand Up @@ -127,14 +136,7 @@ const SheetDescription = React.forwardRef<
SheetDescription.displayName = SheetPrimitive.Description.displayName

export {
Sheet,
SheetPortal,
SheetOverlay,
SheetTrigger,
SheetClose,
SheetContent,
SheetHeader,
SheetFooter,
SheetTitle,
SheetDescription
Sheet, SheetClose,
SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger
}

31 changes: 31 additions & 0 deletions apps/core/src/components/ui/sonner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
"use client"

import { useTheme } from "next-themes"
import { Toaster as Sonner } from "sonner"

type ToasterProps = React.ComponentProps<typeof Sonner>

const Toaster = ({ ...props }: ToasterProps) => {
const { theme = "system" } = useTheme()

return (
<Sonner
theme={theme as ToasterProps["theme"]}
className="toaster group"
toastOptions={{
classNames: {
toast:
"group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg",
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",
},
}}
{...props}
/>
)
}

export { Toaster }
4 changes: 2 additions & 2 deletions apps/core/src/hooks/table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ const fuzzyFilter: FilterFn<any> = (row, columnId, value, addMeta) => {
type SetupReactTableOptions<TData, TValue> = {
columns: ColumnDef<TData, TValue>[]
tableName: string
connectionId: string
connectionId?: string
}

/**
Expand Down Expand Up @@ -125,7 +125,7 @@ export const useSetupReactTable = <TData, TValue>({
* Sets up the state and memoization for page index & page size
* to be used in paginating the rows.
*/
const useSetupPagination = (connectionId: string) => {
const useSetupPagination = (connectionId?: string) => {
const settings = useSettings()
const [{ pageIndex: persistedPageIndex }] =
useLocalStorage<TableLocalStorage>(`@tablex/${connectionId}`, {
Expand Down
51 changes: 26 additions & 25 deletions apps/core/src/lib/utils.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import type { ColumnProps, TxError } from "@/bindings"
import ErrorDialog from "@/components/dialogs/error-dialog"
import { Separator } from "@/components/ui/separator"
import { Button } from "@/components/ui/button"
import { cn } from "@tablex/lib/utils"
import { error } from "@tauri-apps/plugin-log"
import { ErrorIcon, toast } from "react-hot-toast"
import { toast } from "sonner"
import { ConnectionStringParams, Drivers } from "./types"

/**
Expand Down Expand Up @@ -31,34 +32,34 @@ export type Result<T extends any | null> =

export function customToast<T extends string>(
commandResult: Result<T>,
onSuccess: () => void,
id?: string
id?: string,
onSuccess?: () => void
) {
if (commandResult.status === "error") {
error(
`message: ${commandResult.error.message}, details: ${commandResult.error.details}.`
)
return toast(
<div className="flex items-center justify-between gap-x-2">
<p>{commandResult.error.message}</p>
{commandResult.error.details && (
<>
<Separator orientation="vertical" />
<ErrorDialog error={commandResult.error.details}>
<button className="hover:bg-muted-foreground rounded-md p-1 font-semibold text-black transition-all">
more
</button>
</ErrorDialog>
</>
)}
</div>,
{
icon: <ErrorIcon />,
id: "toast_error"
}
)
return toast.error(commandResult.error.message, {
action: (
<ErrorDialog error={commandResult.error.details}>
<Button
size={"sm"}
className={cn(
"ml-auto hidden",
commandResult.error.details && "block"
)}
>
more
</Button>
</ErrorDialog>
),
position: "bottom-center",
id
})
}
if (onSuccess) {
onSuccess()
}
onSuccess()

toast.success(commandResult.data, { id })
}
Expand All @@ -70,7 +71,7 @@ export function customToast<T extends string>(
*/
export function unwrapResult<T>(result: Result<T>): false | T {
if (result.status === "error") {
customToast(result, () => {})
customToast(result)
return false
}
return result.data
Expand Down
15 changes: 13 additions & 2 deletions apps/core/src/routes/__root.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Toaster } from "@/components/ui/sonner"
import { createRootRoute, Outlet } from "@tanstack/react-router"
import React, { Suspense } from "react"
import { Toaster } from "react-hot-toast"

const TanStackRouterDevtools =
process.env.NODE_ENV === "production"
Expand All @@ -16,7 +16,18 @@ export const Route = createRootRoute({
component: () => {
return (
<main className="dark h-full w-full">
<Toaster position="top-right" />
<Toaster
closeButton
richColors
position="top-right"
pauseWhenPageIsHidden
toastOptions={{
classNames: {
toast:
"group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg group-[.toaster]:pointer-events-auto "
}
}}
/>
<Outlet />
<Suspense>
<TanStackRouterDevtools position="bottom-right" />
Expand Down
Loading

0 comments on commit ef16190

Please sign in to comment.