mirror of
https://github.com/nextui-org/nextui.git
synced 2025-12-08 19:26:11 +00:00
fix(toast): icons (#5246)
* feat(shared-icons): add loading icon * fix(toast): icons * chore(toast): revise types for icons * chore(changeset): add changeset
This commit is contained in:
parent
ee4d2ebe25
commit
8df9716dfa
6
.changeset/fast-ways-hang.md
Normal file
6
.changeset/fast-ways-hang.md
Normal file
@ -0,0 +1,6 @@
|
||||
---
|
||||
"@heroui/shared-icons": patch
|
||||
"@heroui/toast": patch
|
||||
---
|
||||
|
||||
support render icons by function in Toast
|
||||
@ -1,3 +1,5 @@
|
||||
import type {ReactElement} from "react";
|
||||
|
||||
import {forwardRef} from "@heroui/system";
|
||||
import {Button, ButtonProps} from "@heroui/button";
|
||||
import {
|
||||
@ -56,12 +58,19 @@ const Toast = forwardRef<"div", ToastProps>((props, ref) => {
|
||||
ref,
|
||||
});
|
||||
|
||||
const customIcon = icon && isValidElement(icon) ? cloneElement(icon, getIconProps()) : null;
|
||||
const customIcon =
|
||||
typeof icon === "function"
|
||||
? icon(getIconProps())
|
||||
: isValidElement(icon) && cloneElement(icon as ReactElement, getIconProps());
|
||||
|
||||
const IconComponent = severity ? iconMap[severity] : iconMap[color] || iconMap.default;
|
||||
|
||||
const customLoadingIcon =
|
||||
loadingIcon && isValidElement(loadingIcon)
|
||||
? cloneElement(loadingIcon, getLoadingIconProps())
|
||||
: null;
|
||||
typeof loadingIcon === "function"
|
||||
? loadingIcon(getLoadingIconProps())
|
||||
: isValidElement(loadingIcon) &&
|
||||
cloneElement(loadingIcon as ReactElement, getLoadingIconProps());
|
||||
|
||||
const loadingIconComponent = isLoading
|
||||
? customLoadingIcon || (
|
||||
<Spinner
|
||||
@ -73,7 +82,9 @@ const Toast = forwardRef<"div", ToastProps>((props, ref) => {
|
||||
: null;
|
||||
|
||||
const customCloseIcon =
|
||||
closeIcon && isValidElement(closeIcon) ? cloneElement(closeIcon, {}) : null;
|
||||
typeof closeIcon === "function"
|
||||
? closeIcon({})
|
||||
: isValidElement(closeIcon) && cloneElement(closeIcon as ReactElement, {});
|
||||
|
||||
const toastContent = (
|
||||
<Component ref={domRef} {...getToastProps()}>
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import type {SlotsToClasses, ToastSlots, ToastVariantProps} from "@heroui/theme";
|
||||
import type {DOMAttributes} from "react";
|
||||
|
||||
import {HTMLHeroUIProps, PropGetter, mapPropsVariants, useProviderContext} from "@heroui/system";
|
||||
import {toast as toastTheme} from "@heroui/theme";
|
||||
@ -67,15 +68,15 @@ export interface ToastProps extends ToastVariantProps {
|
||||
/**
|
||||
* Icon to be displayed in the toast - overrides the default icon
|
||||
*/
|
||||
icon?: ReactNode;
|
||||
icon?: ReactNode | ((props: DOMAttributes<HTMLElement>) => ReactNode);
|
||||
/**
|
||||
* Icon to be displayed in the close button - overrides the default close icon
|
||||
*/
|
||||
closeIcon?: ReactNode | ((props: any) => ReactNode);
|
||||
closeIcon?: ReactNode | ((props: DOMAttributes<HTMLElement>) => ReactNode);
|
||||
/**
|
||||
* Icon to be displayed in the loading toast - overrides the loading icon
|
||||
*/
|
||||
loadingIcon?: ReactNode;
|
||||
loadingIcon?: ReactNode | ((props: DOMAttributes<HTMLElement>) => ReactNode);
|
||||
/**
|
||||
* Whether the toast-icon should be hidden.
|
||||
* @default false
|
||||
@ -157,6 +158,7 @@ export function useToast<T extends ToastProps>(originalProps: UseToastProps<T>)
|
||||
timeout = 6000,
|
||||
shouldShowTimeoutProgress = false,
|
||||
icon,
|
||||
loadingIcon,
|
||||
onClose,
|
||||
severity,
|
||||
maxVisibleToasts,
|
||||
@ -261,7 +263,6 @@ export function useToast<T extends ToastProps>(originalProps: UseToastProps<T>)
|
||||
]);
|
||||
|
||||
const Component = as || "div";
|
||||
const loadingIcon: ReactNode = icon;
|
||||
|
||||
const domRef = useDOMRef(ref);
|
||||
const baseStyles = clsx(className, classNames?.base);
|
||||
|
||||
@ -11,6 +11,7 @@ import {
|
||||
useDisclosure,
|
||||
} from "@heroui/modal";
|
||||
import {Drawer, DrawerContent} from "@heroui/drawer";
|
||||
import {LoadingIcon, AvatarIcon, CloseIcon} from "@heroui/shared-icons";
|
||||
|
||||
import {Toast, ToastProps, ToastProvider, addToast, closeAll} from "../src";
|
||||
|
||||
@ -352,7 +353,7 @@ const CustomToastTemplate = (args) => {
|
||||
);
|
||||
};
|
||||
|
||||
const CustomCloseButtonTemplate = (args) => {
|
||||
const CustomCloseIconTemplate = (args) => {
|
||||
return (
|
||||
<>
|
||||
<ToastProvider
|
||||
@ -367,23 +368,9 @@ const CustomCloseButtonTemplate = (args) => {
|
||||
<Button
|
||||
onPress={() =>
|
||||
addToast({
|
||||
title: "Toast Title",
|
||||
title: "Custom Close Icon",
|
||||
description: "Toast Description",
|
||||
closeIcon: (
|
||||
<svg
|
||||
fill="none"
|
||||
height="32"
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
viewBox="0 0 24 24"
|
||||
width="32"
|
||||
>
|
||||
<path d="M18 6 6 18" />
|
||||
<path d="m6 6 12 12" />
|
||||
</svg>
|
||||
),
|
||||
closeIcon: CloseIcon,
|
||||
})
|
||||
}
|
||||
>
|
||||
@ -408,33 +395,14 @@ export const WithDescription = {
|
||||
},
|
||||
};
|
||||
|
||||
export const WithCustomIcon = {
|
||||
render: Template,
|
||||
export const WithEndContent = {
|
||||
render: WithEndContentTemplate,
|
||||
args: {
|
||||
...defaultProps,
|
||||
title: "Custom Icon",
|
||||
icon: (
|
||||
<svg height={24} viewBox="0 0 24 24" width={24}>
|
||||
<g
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeMiterlimit={10}
|
||||
strokeWidth={1.5}
|
||||
>
|
||||
<path
|
||||
d="M11.845 21.662C8.153 21.662 5 21.088 5 18.787s3.133-4.425 6.845-4.425c3.692 0 6.845 2.1 6.845 4.4s-3.134 2.9-6.845 2.9z"
|
||||
data-name="Stroke 1"
|
||||
/>
|
||||
<path d="M11.837 11.174a4.372 4.372 0 10-.031 0z" data-name="Stroke 3" />
|
||||
</g>
|
||||
</svg>
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
export const iconHidden = {
|
||||
export const IconHidden = {
|
||||
render: Template,
|
||||
args: {
|
||||
...defaultProps,
|
||||
@ -470,13 +438,6 @@ export const Placement = {
|
||||
},
|
||||
};
|
||||
|
||||
export const WithEndContent = {
|
||||
render: WithEndContentTemplate,
|
||||
args: {
|
||||
...defaultProps,
|
||||
},
|
||||
};
|
||||
|
||||
export const ToastFromOverlay = {
|
||||
render: WithToastFromOverlayTemplate,
|
||||
args: {
|
||||
@ -491,8 +452,26 @@ export const CustomStyles = {
|
||||
},
|
||||
};
|
||||
|
||||
export const CustomCloseButton = {
|
||||
render: CustomCloseButtonTemplate,
|
||||
export const CustomIcon = {
|
||||
render: Template,
|
||||
args: {
|
||||
...defaultProps,
|
||||
title: "Custom Icon",
|
||||
icon: AvatarIcon,
|
||||
},
|
||||
};
|
||||
|
||||
export const CustomLoadingIcon = {
|
||||
render: PromiseToastTemplate,
|
||||
args: {
|
||||
...defaultProps,
|
||||
title: "Custom Loading Icon",
|
||||
loadingIcon: LoadingIcon,
|
||||
},
|
||||
};
|
||||
|
||||
export const CustomCloseIcon = {
|
||||
render: CustomCloseIconTemplate,
|
||||
args: {
|
||||
...defaultProps,
|
||||
},
|
||||
|
||||
@ -28,6 +28,7 @@ export * from "./eye-filled";
|
||||
export * from "./eye-slash-filled";
|
||||
export * from "./search";
|
||||
export * from "./lock-filled";
|
||||
export * from "./loading";
|
||||
export * from "./edit";
|
||||
export * from "./delete";
|
||||
export * from "./eye";
|
||||
|
||||
39
packages/utilities/shared-icons/src/loading.tsx
Normal file
39
packages/utilities/shared-icons/src/loading.tsx
Normal file
@ -0,0 +1,39 @@
|
||||
import type {IconSvgProps} from "./types";
|
||||
|
||||
export const LoadingIcon = (props: IconSvgProps) => (
|
||||
<svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg" {...props}>
|
||||
<circle cx="40" cy="65" fill="#3871FF" r="15" stroke="#3871FF" strokeWidth="15">
|
||||
<animate
|
||||
attributeName="cy"
|
||||
begin="-.4"
|
||||
calcMode="spline"
|
||||
dur="2"
|
||||
keySplines=".5 0 .5 1;.5 0 .5 1"
|
||||
repeatCount="indefinite"
|
||||
values="65;135;65;"
|
||||
/>
|
||||
</circle>
|
||||
<circle cx="100" cy="65" fill="#3871FF" r="15" stroke="#3871FF" strokeWidth="15">
|
||||
<animate
|
||||
attributeName="cy"
|
||||
begin="-.2"
|
||||
calcMode="spline"
|
||||
dur="2"
|
||||
keySplines=".5 0 .5 1;.5 0 .5 1"
|
||||
repeatCount="indefinite"
|
||||
values="65;135;65;"
|
||||
/>
|
||||
</circle>
|
||||
<circle cx="160" cy="65" fill="#3871FF" r="15" stroke="#3871FF" strokeWidth="15">
|
||||
<animate
|
||||
attributeName="cy"
|
||||
begin="0"
|
||||
calcMode="spline"
|
||||
dur="2"
|
||||
keySplines=".5 0 .5 1;.5 0 .5 1"
|
||||
repeatCount="indefinite"
|
||||
values="65;135;65;"
|
||||
/>
|
||||
</circle>
|
||||
</svg>
|
||||
);
|
||||
Loading…
x
Reference in New Issue
Block a user