diff --git a/apps/studio/components/to-be-cleaned/Storage/StorageExplorer/FileExplorerHeader.tsx b/apps/studio/components/to-be-cleaned/Storage/StorageExplorer/FileExplorerHeader.tsx
index 451c70485b8..d1b725d7477 100644
--- a/apps/studio/components/to-be-cleaned/Storage/StorageExplorer/FileExplorerHeader.tsx
+++ b/apps/studio/components/to-be-cleaned/Storage/StorageExplorer/FileExplorerHeader.tsx
@@ -6,9 +6,13 @@ import {
Button,
DropdownMenu,
DropdownMenuContent,
- DropdownMenuSeparator,
DropdownMenuItem,
+ DropdownMenuSeparator,
+ DropdownMenuSub,
+ DropdownMenuSubContent,
+ DropdownMenuSubTrigger,
DropdownMenuTrigger,
+ IconCheck,
IconChevronLeft,
IconChevronRight,
IconColumns,
@@ -21,18 +25,14 @@ import {
IconUpload,
IconX,
Input,
- IconCheck,
- DropdownMenuSub,
- DropdownMenuSubTrigger,
- DropdownMenuSubContent,
} from 'ui'
+import { useIsAPIDocsSidePanelEnabled } from 'components/interfaces/App/FeaturePreview/FeaturePreviewContext'
+import APIDocsButton from 'components/ui/APIDocsButton'
import { useCheckPermissions } from 'hooks'
import { useStorageStore } from 'localStores/storageExplorer/StorageExplorerStore'
import { useStorageExplorerStateSnapshot } from 'state/storage-explorer'
import { STORAGE_SORT_BY, STORAGE_SORT_BY_ORDER, STORAGE_VIEWS } from '../Storage.constants'
-import APIDocsButton from 'components/ui/APIDocsButton'
-import { useIsAPIDocsSidePanelEnabled } from 'components/interfaces/App/FeaturePreview/FeaturePreviewContext'
const VIEW_OPTIONS = [
{ key: STORAGE_VIEWS.COLUMNS, name: 'As columns' },
diff --git a/apps/studio/localStores/storageExplorer/StorageExplorerStore.ts b/apps/studio/localStores/storageExplorer/StorageExplorerStore.ts
index 632ce1df1b2..1f400d094fc 100644
--- a/apps/studio/localStores/storageExplorer/StorageExplorerStore.ts
+++ b/apps/studio/localStores/storageExplorer/StorageExplorerStore.ts
@@ -5,6 +5,7 @@ import { BlobReader, BlobWriter, ZipWriter } from '@zip.js/zip.js'
import { chunk, compact, find, findIndex, has, isEqual, some, uniq, uniqBy } from 'lodash'
import { makeAutoObservable } from 'mobx'
import toast from 'react-hot-toast'
+import { toast as UiToast } from 'ui'
import {
STORAGE_ROW_STATUS,
@@ -283,22 +284,13 @@ class StorageExplorerStore {
if (formattedName === null) return
if (!/^[a-zA-Z0-9_-\s]*$/.test(formattedName)) {
- return this.ui.setNotification({
- message: 'Folder name contains invalid special characters',
- category: 'error',
- duration: 8000,
- })
- }
- /**
- * todo: move this to a util file, as renameFolder() uses same logic
- */
- if (formattedName.includes('/') || formattedName.includes('\\')) {
- return this.ui.setNotification({
- message: 'Folder names should not have forward or back slashes.',
- category: 'error',
- duration: 8000,
+ return UiToast({
+ variant: 'destructive',
+ description: 'Folder name contains invalid special characters',
+ duration: 6000,
})
}
+
if (formattedName.length === 0) {
return this.removeTempRows(columnIndex)
}
@@ -425,10 +417,7 @@ class StorageExplorerStore {
// https://stackoverflow.com/a/53058574
getFilesDataTransferItems = async (items) => {
- const toastId = this.ui.setNotification({
- category: 'loading',
- message: 'Retrieving items to upload...',
- })
+ const { dismiss } = UiToast({ description: 'Retrieving items to upload...' })
const files = []
const queue = []
for (const item of items) {
@@ -446,7 +435,7 @@ class StorageExplorerStore {
queue.push(...(await this.readAllDirectoryEntries(entry.createReader())))
}
}
- toast.dismiss(toastId)
+ dismiss()
return files
}
@@ -663,7 +652,8 @@ class StorageExplorerStore {
let numberOfFilesMovedFail = 0
this.clearSelectedItems()
- const infoToastId = toast('Please do not close the browser until the move is completed', {
+ const { dismiss } = UiToast({
+ description: 'Please do not close the browser until the move is completed',
duration: Infinity,
})
@@ -690,20 +680,16 @@ class StorageExplorerStore {
)
if (numberOfFilesMovedFail === this.selectedItemsToMove.length) {
- this.ui.setNotification({
- message: 'Failed to move files',
- category: 'error',
- })
+ UiToast({ variant: 'destructive', description: 'Failed to move files' })
} else {
- this.ui.setNotification({
- message: `Successfully moved ${
+ UiToast({
+ description: `Successfully moved ${
this.selectedItemsToMove.length - numberOfFilesMovedFail
- } to ${formattedNewPathToFile}`,
- category: 'success',
+ } files to ${formattedNewPathToFile.length > 0 ? formattedNewPathToFile : 'the root of your bucket'}`,
})
}
- toast.dismiss(infoToastId)
+ dismiss()
// Clear file preview cache if moved files exist in cache
const idsOfItemsToMove = this.selectedItemsToMove.map((item) => item.id)
diff --git a/apps/studio/pages/_app.tsx b/apps/studio/pages/_app.tsx
index 9e54f4ff3c8..9e96606394c 100644
--- a/apps/studio/pages/_app.tsx
+++ b/apps/studio/pages/_app.tsx
@@ -59,6 +59,7 @@ import { useAppStateSnapshot } from 'state/app-state'
import { RootStore } from 'stores'
import HCaptchaLoadedStore from 'stores/hcaptcha-loaded-store'
import { AppPropsWithLayout } from 'types'
+import { Toaster } from 'ui'
dayjs.extend(customParseFormat)
dayjs.extend(utc)
@@ -182,6 +183,7 @@ function CustomApp({ Component, pageProps }: AppPropsWithLayout) {
+
{!isTestEnv && }
diff --git a/packages/ui/index.tsx b/packages/ui/index.tsx
index e4a92577b6b..77b83b88a65 100644
--- a/packages/ui/index.tsx
+++ b/packages/ui/index.tsx
@@ -81,6 +81,9 @@ export * from './src/components/ThemeProvider/prefixedThemes'
// shadcn
export * from './src/components/shadcn/ui/dropdown-menu'
+export * from './src/components/shadcn/ui/use-toast'
+export * from './src/components/shadcn/ui/toast'
+export * from './src/components/shadcn/ui/toaster'
export {
Command as Command_Shadcn_,
diff --git a/packages/ui/src/components/shadcn/ui/toast.tsx b/packages/ui/src/components/shadcn/ui/toast.tsx
index bba0efd8c58..9f865254157 100644
--- a/packages/ui/src/components/shadcn/ui/toast.tsx
+++ b/packages/ui/src/components/shadcn/ui/toast.tsx
@@ -14,7 +14,7 @@ const ToastViewport = React.forwardRef<