chore(ui): move toast to top right (#13092)
* chore(ui): display toast in top right corner * fix: error as well * refactor: feedback * chore: move the rest of the modal controls to footer --------- Co-authored-by: William Bouchard <46496014+willbouch@users.noreply.github.com>
This commit is contained in:
5
.changeset/wise-yaks-wink.md
Normal file
5
.changeset/wise-yaks-wink.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@medusajs/ui": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
chore(ui): display toast in top right corner
|
||||||
@@ -148,14 +148,6 @@ export const EditCategoryProductsForm = ({
|
|||||||
{form.formState.errors.product_ids.message}
|
{form.formState.errors.product_ids.message}
|
||||||
</Hint>
|
</Hint>
|
||||||
)}
|
)}
|
||||||
<RouteFocusModal.Close asChild>
|
|
||||||
<Button size="small" variant="secondary">
|
|
||||||
{t("actions.cancel")}
|
|
||||||
</Button>
|
|
||||||
</RouteFocusModal.Close>
|
|
||||||
<Button size="small" type="submit" isLoading={isMutating}>
|
|
||||||
{t("actions.save")}
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
</RouteFocusModal.Header>
|
</RouteFocusModal.Header>
|
||||||
<RouteFocusModal.Body className="size-full overflow-hidden">
|
<RouteFocusModal.Body className="size-full overflow-hidden">
|
||||||
@@ -178,6 +170,16 @@ export const EditCategoryProductsForm = ({
|
|||||||
search="autofocus"
|
search="autofocus"
|
||||||
/>
|
/>
|
||||||
</RouteFocusModal.Body>
|
</RouteFocusModal.Body>
|
||||||
|
<RouteFocusModal.Footer>
|
||||||
|
<RouteFocusModal.Close asChild>
|
||||||
|
<Button size="small" variant="secondary">
|
||||||
|
{t("actions.cancel")}
|
||||||
|
</Button>
|
||||||
|
</RouteFocusModal.Close>
|
||||||
|
<Button size="small" type="submit" isLoading={isMutating}>
|
||||||
|
{t("actions.save")}
|
||||||
|
</Button>
|
||||||
|
</RouteFocusModal.Footer>
|
||||||
</KeyboundForm>
|
</KeyboundForm>
|
||||||
</RouteFocusModal.Form>
|
</RouteFocusModal.Form>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -157,14 +157,6 @@ export const AddProductsToCollectionForm = ({
|
|||||||
{form.formState.errors.add && (
|
{form.formState.errors.add && (
|
||||||
<Hint variant="error">{form.formState.errors.add.message}</Hint>
|
<Hint variant="error">{form.formState.errors.add.message}</Hint>
|
||||||
)}
|
)}
|
||||||
<RouteFocusModal.Close asChild>
|
|
||||||
<Button size="small" variant="secondary">
|
|
||||||
{t("actions.cancel")}
|
|
||||||
</Button>
|
|
||||||
</RouteFocusModal.Close>
|
|
||||||
<Button size="small" type="submit" isLoading={isMutating}>
|
|
||||||
{t("actions.save")}
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
</RouteFocusModal.Header>
|
</RouteFocusModal.Header>
|
||||||
<RouteFocusModal.Body className="size-full overflow-hidden">
|
<RouteFocusModal.Body className="size-full overflow-hidden">
|
||||||
@@ -187,6 +179,16 @@ export const AddProductsToCollectionForm = ({
|
|||||||
search="autofocus"
|
search="autofocus"
|
||||||
/>
|
/>
|
||||||
</RouteFocusModal.Body>
|
</RouteFocusModal.Body>
|
||||||
|
<RouteFocusModal.Footer>
|
||||||
|
<RouteFocusModal.Close asChild>
|
||||||
|
<Button size="small" variant="secondary">
|
||||||
|
{t("actions.cancel")}
|
||||||
|
</Button>
|
||||||
|
</RouteFocusModal.Close>
|
||||||
|
<Button size="small" type="submit" isLoading={isMutating}>
|
||||||
|
{t("actions.save")}
|
||||||
|
</Button>
|
||||||
|
</RouteFocusModal.Footer>
|
||||||
</KeyboundForm>
|
</KeyboundForm>
|
||||||
</RouteFocusModal.Form>
|
</RouteFocusModal.Form>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -46,25 +46,13 @@ export const CreateCollectionForm = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RouteFocusModal.Form form={form}>
|
<RouteFocusModal.Form form={form}>
|
||||||
<KeyboundForm onSubmit={handleSubmit}>
|
<KeyboundForm
|
||||||
<RouteFocusModal.Header>
|
onSubmit={handleSubmit}
|
||||||
<div className="flex items-center justify-end gap-x-2">
|
className="flex h-full flex-col overflow-hidden"
|
||||||
<RouteFocusModal.Close asChild>
|
>
|
||||||
<Button size="small" variant="secondary">
|
<RouteFocusModal.Header />
|
||||||
{t("actions.cancel")}
|
|
||||||
</Button>
|
<RouteFocusModal.Body className="flex size-full flex-col items-center p-16">
|
||||||
</RouteFocusModal.Close>
|
|
||||||
<Button
|
|
||||||
size="small"
|
|
||||||
variant="primary"
|
|
||||||
type="submit"
|
|
||||||
isLoading={isPending}
|
|
||||||
>
|
|
||||||
{t("actions.create")}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</RouteFocusModal.Header>
|
|
||||||
<RouteFocusModal.Body className="flex flex-col items-center p-16">
|
|
||||||
<div className="flex w-full max-w-[720px] flex-col gap-y-8">
|
<div className="flex w-full max-w-[720px] flex-col gap-y-8">
|
||||||
<div>
|
<div>
|
||||||
<Heading>{t("collections.createCollection")}</Heading>
|
<Heading>{t("collections.createCollection")}</Heading>
|
||||||
@@ -111,6 +99,21 @@ export const CreateCollectionForm = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</RouteFocusModal.Body>
|
</RouteFocusModal.Body>
|
||||||
|
<RouteFocusModal.Footer>
|
||||||
|
<RouteFocusModal.Close asChild>
|
||||||
|
<Button size="small" variant="secondary">
|
||||||
|
{t("actions.cancel")}
|
||||||
|
</Button>
|
||||||
|
</RouteFocusModal.Close>
|
||||||
|
<Button
|
||||||
|
size="small"
|
||||||
|
variant="primary"
|
||||||
|
type="submit"
|
||||||
|
isLoading={isPending}
|
||||||
|
>
|
||||||
|
{t("actions.create")}
|
||||||
|
</Button>
|
||||||
|
</RouteFocusModal.Footer>
|
||||||
</KeyboundForm>
|
</KeyboundForm>
|
||||||
</RouteFocusModal.Form>
|
</RouteFocusModal.Form>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -137,19 +137,6 @@ export const AddCustomersForm = ({
|
|||||||
{form.formState.errors.customer_ids.message}
|
{form.formState.errors.customer_ids.message}
|
||||||
</Hint>
|
</Hint>
|
||||||
)}
|
)}
|
||||||
<RouteFocusModal.Close asChild>
|
|
||||||
<Button variant="secondary" size="small">
|
|
||||||
{t("actions.cancel")}
|
|
||||||
</Button>
|
|
||||||
</RouteFocusModal.Close>
|
|
||||||
<Button
|
|
||||||
type="submit"
|
|
||||||
variant="primary"
|
|
||||||
size="small"
|
|
||||||
isLoading={isPending}
|
|
||||||
>
|
|
||||||
{t("actions.save")}
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
</RouteFocusModal.Header>
|
</RouteFocusModal.Header>
|
||||||
<RouteFocusModal.Body className="size-full overflow-hidden">
|
<RouteFocusModal.Body className="size-full overflow-hidden">
|
||||||
@@ -176,6 +163,21 @@ export const AddCustomersForm = ({
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</RouteFocusModal.Body>
|
</RouteFocusModal.Body>
|
||||||
|
<RouteFocusModal.Footer>
|
||||||
|
<RouteFocusModal.Close asChild>
|
||||||
|
<Button variant="secondary" size="small">
|
||||||
|
{t("actions.cancel")}
|
||||||
|
</Button>
|
||||||
|
</RouteFocusModal.Close>
|
||||||
|
<Button
|
||||||
|
type="submit"
|
||||||
|
variant="primary"
|
||||||
|
size="small"
|
||||||
|
isLoading={isPending}
|
||||||
|
>
|
||||||
|
{t("actions.save")}
|
||||||
|
</Button>
|
||||||
|
</RouteFocusModal.Footer>
|
||||||
</KeyboundForm>
|
</KeyboundForm>
|
||||||
</RouteFocusModal.Form>
|
</RouteFocusModal.Form>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -44,12 +44,12 @@ export function OrderCreateShipmentForm({
|
|||||||
|
|
||||||
const handleSubmit = form.handleSubmit(async (data) => {
|
const handleSubmit = form.handleSubmit(async (data) => {
|
||||||
const addedLabels = data.labels
|
const addedLabels = data.labels
|
||||||
.filter((l) => !!l.tracking_number)
|
.filter((l) => !!l.tracking_number)
|
||||||
.map((l) => ({
|
.map((l) => ({
|
||||||
tracking_number: l.tracking_number,
|
tracking_number: l.tracking_number,
|
||||||
tracking_url: "#",
|
tracking_url: "#",
|
||||||
label_url: "#",
|
label_url: "#",
|
||||||
}))
|
}))
|
||||||
|
|
||||||
await createShipment(
|
await createShipment(
|
||||||
{
|
{
|
||||||
@@ -78,18 +78,8 @@ export function OrderCreateShipmentForm({
|
|||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
className="flex h-full flex-col overflow-hidden"
|
className="flex h-full flex-col overflow-hidden"
|
||||||
>
|
>
|
||||||
<RouteFocusModal.Header>
|
<RouteFocusModal.Header />
|
||||||
<div className="flex items-center justify-end gap-x-2">
|
|
||||||
<RouteFocusModal.Close asChild>
|
|
||||||
<Button size="small" variant="secondary">
|
|
||||||
{t("actions.cancel")}
|
|
||||||
</Button>
|
|
||||||
</RouteFocusModal.Close>
|
|
||||||
<Button size="small" type="submit" isLoading={isMutating}>
|
|
||||||
{t("actions.save")}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</RouteFocusModal.Header>
|
|
||||||
<RouteFocusModal.Body className="flex h-full w-full flex-col items-center divide-y overflow-y-auto">
|
<RouteFocusModal.Body className="flex h-full w-full flex-col items-center divide-y overflow-y-auto">
|
||||||
<div className="flex size-full flex-col items-center overflow-auto p-16">
|
<div className="flex size-full flex-col items-center overflow-auto p-16">
|
||||||
<div className="flex w-full max-w-[736px] flex-col justify-center px-2 pb-2">
|
<div className="flex w-full max-w-[736px] flex-col justify-center px-2 pb-2">
|
||||||
@@ -166,6 +156,16 @@ export function OrderCreateShipmentForm({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</RouteFocusModal.Body>
|
</RouteFocusModal.Body>
|
||||||
|
<RouteFocusModal.Footer>
|
||||||
|
<RouteFocusModal.Close asChild>
|
||||||
|
<Button size="small" variant="secondary">
|
||||||
|
{t("actions.cancel")}
|
||||||
|
</Button>
|
||||||
|
</RouteFocusModal.Close>
|
||||||
|
<Button size="small" type="submit" isLoading={isMutating}>
|
||||||
|
{t("actions.save")}
|
||||||
|
</Button>
|
||||||
|
</RouteFocusModal.Footer>
|
||||||
</KeyboundForm>
|
</KeyboundForm>
|
||||||
</RouteFocusModal.Form>
|
</RouteFocusModal.Form>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -310,18 +310,7 @@ export function ManageVariantInventoryItemsForm({
|
|||||||
return (
|
return (
|
||||||
<RouteFocusModal.Form form={form}>
|
<RouteFocusModal.Form form={form}>
|
||||||
<KeyboundForm className="flex h-full flex-col" onSubmit={handleSubmit}>
|
<KeyboundForm className="flex h-full flex-col" onSubmit={handleSubmit}>
|
||||||
<RouteFocusModal.Header>
|
<RouteFocusModal.Header />
|
||||||
<div className="flex items-center justify-end gap-x-2">
|
|
||||||
<RouteFocusModal.Close asChild>
|
|
||||||
<Button size="small" variant="secondary">
|
|
||||||
{t("actions.cancel")}
|
|
||||||
</Button>
|
|
||||||
</RouteFocusModal.Close>
|
|
||||||
<Button size="small" type="submit" isLoading={isPending}>
|
|
||||||
{t("actions.save")}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</RouteFocusModal.Header>
|
|
||||||
<RouteFocusModal.Body className="flex justify-center overflow-auto">
|
<RouteFocusModal.Body className="flex justify-center overflow-auto">
|
||||||
<div className="flex w-full flex-col gap-y-8 px-6 pt-12 md:w-[720px] md:pt-24">
|
<div className="flex w-full flex-col gap-y-8 px-6 pt-12 md:w-[720px] md:pt-24">
|
||||||
<Heading>
|
<Heading>
|
||||||
@@ -371,6 +360,16 @@ export function ManageVariantInventoryItemsForm({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</RouteFocusModal.Body>
|
</RouteFocusModal.Body>
|
||||||
|
<RouteFocusModal.Footer>
|
||||||
|
<RouteFocusModal.Close asChild>
|
||||||
|
<Button size="small" variant="secondary">
|
||||||
|
{t("actions.cancel")}
|
||||||
|
</Button>
|
||||||
|
</RouteFocusModal.Close>
|
||||||
|
<Button size="small" type="submit" isLoading={isPending}>
|
||||||
|
{t("actions.save")}
|
||||||
|
</Button>
|
||||||
|
</RouteFocusModal.Footer>
|
||||||
</KeyboundForm>
|
</KeyboundForm>
|
||||||
</RouteFocusModal.Form>
|
</RouteFocusModal.Form>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -129,18 +129,8 @@ export const AddCountriesForm = ({ region }: AddCountriesFormProps) => {
|
|||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
className="flex h-full flex-col overflow-hidden"
|
className="flex h-full flex-col overflow-hidden"
|
||||||
>
|
>
|
||||||
<RouteFocusModal.Header>
|
<RouteFocusModal.Header />
|
||||||
<div className="flex items-center justify-end gap-x-2">
|
|
||||||
<RouteFocusModal.Close asChild>
|
|
||||||
<Button size="small" variant="secondary">
|
|
||||||
{t("actions.cancel")}
|
|
||||||
</Button>
|
|
||||||
</RouteFocusModal.Close>
|
|
||||||
<Button size="small" isLoading={isLoading} type="submit">
|
|
||||||
{t("actions.add")}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</RouteFocusModal.Header>
|
|
||||||
<RouteFocusModal.Body className="overflow-hidden">
|
<RouteFocusModal.Body className="overflow-hidden">
|
||||||
<_DataTable
|
<_DataTable
|
||||||
table={table}
|
table={table}
|
||||||
@@ -158,6 +148,16 @@ export const AddCountriesForm = ({ region }: AddCountriesFormProps) => {
|
|||||||
prefix={PREFIX}
|
prefix={PREFIX}
|
||||||
/>
|
/>
|
||||||
</RouteFocusModal.Body>
|
</RouteFocusModal.Body>
|
||||||
|
<RouteFocusModal.Footer>
|
||||||
|
<RouteFocusModal.Close asChild>
|
||||||
|
<Button size="small" variant="secondary">
|
||||||
|
{t("actions.cancel")}
|
||||||
|
</Button>
|
||||||
|
</RouteFocusModal.Close>
|
||||||
|
<Button size="small" isLoading={isLoading} type="submit">
|
||||||
|
{t("actions.add")}
|
||||||
|
</Button>
|
||||||
|
</RouteFocusModal.Footer>
|
||||||
</KeyboundForm>
|
</KeyboundForm>
|
||||||
</RouteFocusModal.Form>
|
</RouteFocusModal.Form>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -186,18 +186,7 @@ export const CreateRegionForm = ({
|
|||||||
className="flex h-full flex-col overflow-hidden"
|
className="flex h-full flex-col overflow-hidden"
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
>
|
>
|
||||||
<RouteFocusModal.Header>
|
<RouteFocusModal.Header />
|
||||||
<div className="flex items-center justify-end gap-x-2">
|
|
||||||
<RouteFocusModal.Close asChild>
|
|
||||||
<Button size="small" variant="secondary">
|
|
||||||
{t("actions.cancel")}
|
|
||||||
</Button>
|
|
||||||
</RouteFocusModal.Close>
|
|
||||||
<Button size="small" type="submit" isLoading={isPendingRegion}>
|
|
||||||
{t("actions.save")}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</RouteFocusModal.Header>
|
|
||||||
<RouteFocusModal.Body className="flex overflow-hidden">
|
<RouteFocusModal.Body className="flex overflow-hidden">
|
||||||
<div
|
<div
|
||||||
className={clx(
|
className={clx(
|
||||||
@@ -434,6 +423,16 @@ export const CreateRegionForm = ({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</RouteFocusModal.Body>
|
</RouteFocusModal.Body>
|
||||||
|
<RouteFocusModal.Footer>
|
||||||
|
<RouteFocusModal.Close asChild>
|
||||||
|
<Button size="small" variant="secondary">
|
||||||
|
{t("actions.cancel")}
|
||||||
|
</Button>
|
||||||
|
</RouteFocusModal.Close>
|
||||||
|
<Button size="small" type="submit" isLoading={isPendingRegion}>
|
||||||
|
{t("actions.save")}
|
||||||
|
</Button>
|
||||||
|
</RouteFocusModal.Footer>
|
||||||
</KeyboundForm>
|
</KeyboundForm>
|
||||||
</RouteFocusModal.Form>
|
</RouteFocusModal.Form>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ import { ToastAction, ToastVariant, ToasterPosition } from "@/types"
|
|||||||
import * as React from "react"
|
import * as React from "react"
|
||||||
import { ExternalToast, toast as toastFn } from "sonner"
|
import { ExternalToast, toast as toastFn } from "sonner"
|
||||||
|
|
||||||
|
const DEFAULT_TOAST_POSITION = "top-right"
|
||||||
|
|
||||||
interface BaseToastProps {
|
interface BaseToastProps {
|
||||||
id?: string | number
|
id?: string | number
|
||||||
position?: ToasterPosition
|
position?: ToasterPosition
|
||||||
@@ -16,7 +18,11 @@ interface ToastProps extends BaseToastProps {
|
|||||||
action?: ToastAction
|
action?: ToastAction
|
||||||
}
|
}
|
||||||
|
|
||||||
function create(variant: ToastVariant, title: React.ReactNode, props: ToastProps = {}) {
|
function create(
|
||||||
|
variant: ToastVariant,
|
||||||
|
title: React.ReactNode,
|
||||||
|
props: ToastProps = {}
|
||||||
|
) {
|
||||||
const external: ExternalToast = {
|
const external: ExternalToast = {
|
||||||
position: props.position,
|
position: props.position,
|
||||||
duration: props.duration,
|
duration: props.duration,
|
||||||
@@ -50,13 +56,15 @@ function message(
|
|||||||
/**
|
/**
|
||||||
* The props of the toast.
|
* The props of the toast.
|
||||||
*/
|
*/
|
||||||
props: ToastProps = {}
|
props: ToastProps = {
|
||||||
|
position: DEFAULT_TOAST_POSITION,
|
||||||
|
}
|
||||||
) {
|
) {
|
||||||
return create("message", title, props)
|
return create("message", title, props)
|
||||||
}
|
}
|
||||||
|
|
||||||
function custom() {
|
function custom() {
|
||||||
return create("message", "Custom",)
|
return create("message", "Custom")
|
||||||
}
|
}
|
||||||
|
|
||||||
interface VariantToastProps extends Omit<ToastProps, "icon"> {}
|
interface VariantToastProps extends Omit<ToastProps, "icon"> {}
|
||||||
@@ -68,7 +76,9 @@ function info(
|
|||||||
/**
|
/**
|
||||||
* The props of the toast.
|
* The props of the toast.
|
||||||
*/
|
*/
|
||||||
props: VariantToastProps = {}
|
props: VariantToastProps = {
|
||||||
|
position: DEFAULT_TOAST_POSITION,
|
||||||
|
}
|
||||||
) {
|
) {
|
||||||
return create("info", title, props)
|
return create("info", title, props)
|
||||||
}
|
}
|
||||||
@@ -80,7 +90,9 @@ function error(
|
|||||||
/**
|
/**
|
||||||
* The props of the toast.
|
* The props of the toast.
|
||||||
*/
|
*/
|
||||||
props: VariantToastProps = {}
|
props: VariantToastProps = {
|
||||||
|
position: DEFAULT_TOAST_POSITION,
|
||||||
|
}
|
||||||
) {
|
) {
|
||||||
return create("error", title, props)
|
return create("error", title, props)
|
||||||
}
|
}
|
||||||
@@ -92,7 +104,9 @@ function success(
|
|||||||
/**
|
/**
|
||||||
* The props of the toast.
|
* The props of the toast.
|
||||||
*/
|
*/
|
||||||
props: VariantToastProps = { }
|
props: VariantToastProps = {
|
||||||
|
position: DEFAULT_TOAST_POSITION,
|
||||||
|
}
|
||||||
) {
|
) {
|
||||||
return create("success", title, props)
|
return create("success", title, props)
|
||||||
}
|
}
|
||||||
@@ -104,7 +118,9 @@ function warning(
|
|||||||
/**
|
/**
|
||||||
* The props of the toast.
|
* The props of the toast.
|
||||||
*/
|
*/
|
||||||
props: VariantToastProps = {}
|
props: VariantToastProps = {
|
||||||
|
position: DEFAULT_TOAST_POSITION,
|
||||||
|
}
|
||||||
) {
|
) {
|
||||||
return create("warning", title, props)
|
return create("warning", title, props)
|
||||||
}
|
}
|
||||||
@@ -116,7 +132,9 @@ function loading(
|
|||||||
/**
|
/**
|
||||||
* The props of the toast.
|
* The props of the toast.
|
||||||
*/
|
*/
|
||||||
props: VariantToastProps = {}
|
props: VariantToastProps = {
|
||||||
|
position: DEFAULT_TOAST_POSITION,
|
||||||
|
}
|
||||||
) {
|
) {
|
||||||
return create("loading", title, { ...props, dismissable: false })
|
return create("loading", title, { ...props, dismissable: false })
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user