;
-const notificationText = `Lorem ipsum dolor sit amet, consectetur adipiscing elit,
-sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
-Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris
-nisi ut aliquip ex ea commodo consequat.`;
+const notificationText = `Lorem ipsum dolor sit amet, consectetur adipiscing elit, magna aliqua.`;
const Actions = () => {
- const onClick = (e: React.MouseEvent) => {
- e.stopPropagation();
- };
return (
<>
-
+ Share
>
);
};
-const ActionsInline = () => {
- return (
-
- window.open('mailto:test@fortanix.com')} />
-
- );
-};
-
export const Success: Story = {
- render: (args) => (
- <>
- notify.success(notificationText)}>
- Notify Success
-
-
- >
+ args: {
+ options: {},
+ },
+ render: (args) => (
+ notify.success(args)}>
+ Notify Success
+
),
};
export const Info: Story = {
- render: (args) => (
- <>
- notify.info(notificationText)}>
- Notify Info
-
-
- >
+ args: {
+ options: {},
+ },
+ render: (args) => (
+ notify.info(args)}>
+ Notify Info
+
),
};
export const Error: Story = {
+ args: {
+ options: {},
+ },
render: (args) => (
- <>
- notify.error(notificationText)}>
- Notify Error
-
-
- >
+ notify.error(args)}>
+ Notify Error
+
),
};
-export const WithActions: Story = {
+export const ErrorWithMessage: Story = {
+ args: {
+ message: notificationText,
+ options: {},
+ },
render: (args) => (
- <>
- notify.info(notificationText, { actions: , autoClose: false })}>
- Notify Info with actions
-
-
- >
+ notify.error(args)}>
+ Notify Error with message (includes a default copy button)
+
),
};
-export const WithActionsInline: Story = {
+export const SuccessWithMessageAndLink: Story = {
+ args: {
+ message: (
+ <>
+ {`${notificationText} `}
+ Link
+ >
+ ),
+ options: {
+ autoClose: false,
+ },
+ },
render: (args) => (
- <>
- notify.info(notificationText, { actionsInline: , autoClose: false })}>
- Notify Info with actions inline
-
-
- >
+ notify.success(args)}>
+ Notify success with message and link
+
),
};
-export const WithActionsAndActionsInline: Story = {
+export const SuccessWithCloseButton: Story = {
+ args: {
+ message: notificationText,
+ options: {
+ closeButton: true,
+ autoClose: false,
+ },
+ },
render: (args) => (
- <>
- notify.info(notificationText, { actions: , actionsInline: , autoClose: false })}>
- Notify Info with actions and actions inline
-
-
- >
+ notify.success(args)}>
+ Notify success with close button
+
+ ),
+};
+
+export const SuccessWithActions: Story = {
+ args: {
+ message: notificationText,
+ options: {
+ closeButton: true,
+ autoClose: false,
+ actions: ,
+ },
+ },
+ render: (args) => (
+ notify.success(args)}>
+ Notify success with actions
+
),
};
export const PreventDuplicate: Story = {
+ args: {
+ options: {
+ toastId: 'uniqueId',
+ },
+ },
render: (args) => (
- <>
- notify.success(notificationText, { toastId: 'uniqueId' })}>
- Notify
-
-
- >
+ notify.success(args)}>
+ Notify
+
),
};
export const AddProgressBarToAllToasts: Story = {
+ args: {
+ message: notificationText,
+ options: {
+ closeButton: true,
+ actions: ,
+ hideProgressBar: false,
+ }
+ },
render: (args) => (
<>
- { notify.success(notificationText); }}>
- Notify success
+ notify.success(args)}>
+ Notify success with progress bar
- { notify.info(notificationText); }}>
- Notify info
+ notify.info(args)}>
+ Notify info with progress bar
- { notify.error(notificationText); }}>
- Notify error
+ notify.error(args)}>
+ Notify error with progress bar
-
>
),
};
-export const AddProgressBarToSelectedToasts: Story = {
+export const AddProgressBarToAllToastsWithAutoDelay: Story = {
+ args: {
+ message: notificationText,
+ options: {
+ delay: 3000,
+ closeButton: true,
+ actions: ,
+ hideProgressBar: false,
+ }
+ },
render: (args) => (
<>
- { notify.success(notificationText, { hideProgressBar: false }); }}>
- Notify success with progress bar
+ notify.success(args)}>
+ Notify success with progress bar after 3 seconds
- { notify.info(notificationText); }}>
- Notify info
+ notify.info(args)}>
+ Notify info with progress bar after 3 seconds
- { notify.error(notificationText, { hideProgressBar: false }); }}>
- Notify error with progress bar
+ notify.error(args)}>
+ Notify error with progress bar after 3 seconds
-
>
),
};
diff --git a/src/components/overlays/Toast/Toast.tsx b/src/components/overlays/Toast/Toast.tsx
index 6f289d3..57ec8f4 100644
--- a/src/components/overlays/Toast/Toast.tsx
+++ b/src/components/overlays/Toast/Toast.tsx
@@ -3,9 +3,9 @@
|* the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */
import * as React from 'react';
+import * as ReactDOM from 'react-dom';
import { classNames as cx, type ClassNameArgument } from '../../../util/componentUtil.ts';
-
import {
toast,
ToastContainer as ToastifyContainer,
@@ -16,29 +16,40 @@ import {
import 'react-toastify/dist/ReactToastify.css';
import { Icon } from '../../graphics/Icon/Icon.tsx';
-//import CloseButton from '../../internal/CloseButton';
import { TooltipProvider } from '../Tooltip/TooltipProvider.tsx';
+import { Button, type ButtonProps } from '../../actions/Button/Button.tsx';
+import { Link, type LinkProps } from '../../actions/Link/Link.tsx';
-import './Toast.css';
+import './ToastyOverride.scss';
+import cl from './Toast.module.scss';
+export { cl as ToastClassNames };
export { type ToastContent };
-export type ToastOptions = Omit & {
- className?: ClassNameArgument,
- bodyClassName?: ClassNameArgument,
- actions?: React.ReactElement,
- actionsInline?: React.ReactElement,
+
+export const ToastLink = ({ className, ...propsRest }: LinkProps) => {
+ return (
+
+ );
+};
+
+export const ToastButton = ({ className, ...propsRest }: ButtonProps) => {
+ return (
+
+ );
};
export type CopyActionButton = {
+ /** A tooltip message of this component. */
message: ToastContent,
- className?: string,
+
+ /** A classname of this component. */
+ className?: ClassNameArgument,
};
-export const CopyActionButton = ({ message, className }: CopyActionButton): React.ReactElement => {
+export const CopyActionButton = ({ message = null, className }: CopyActionButton): React.ReactElement | null => {
const defaultTooltipMessage = 'Copy message';
- const [tooltipMessage, setTooltipMessage] = React.useState(defaultTooltipMessage);
-
+ const [tooltipMessage, setTooltipMessage] = React.useState(defaultTooltipMessage);
const isStringMessage = typeof message === 'string';
const handleCopy = async (event: React.MouseEvent) => {
@@ -47,11 +58,9 @@ export const CopyActionButton = ({ message, className }: CopyActionButton): Reac
try {
await navigator.clipboard.writeText(message);
setTooltipMessage('Successfully copied');
- setTimeout(() => {
- setTooltipMessage(defaultTooltipMessage);
- }, 2000);
} catch (error: unknown) {
setTooltipMessage('Failed to copy');
+ } finally {
setTimeout(() => {
setTooltipMessage(defaultTooltipMessage);
}, 2000);
@@ -62,124 +71,163 @@ export const CopyActionButton = ({ message, className }: CopyActionButton): Reac
return (
<>
{isStringMessage &&
-
-
+
+ >
+ Copy
+
}
>
);
};
-type ToastMessageProps = {
- message: ToastContent,
- actions?: React.ReactElement,
- actionsInline?: React.ReactElement,
-};
-export const ToastMessage = (props: ToastMessageProps): React.ReactElement => {
- const {
- message,
- actions,
- actionsInline,
- } = props;
-
- if (!actions && !actionsInline) {
- return <>{message}>;
- }
+export const ToastMessage = (props: NotifyProps): React.ReactElement => {
+ const { title, message, options = {} } = props;
return (
<>
-
-
{typeof message === 'function' ? null : message}
- {actionsInline &&
-
- {actionsInline}
-
- }
+
+
+ {title}
+
+ {(message && typeof message !== 'function') &&
{message}
}
- {actions &&
-
- {actions}
+ {options.actions &&
+
+ {options.actions}
}
>
);
};
-const success = (message: ToastContent, options: ToastOptions = {}) => {
- const { className, bodyClassName, ...restOptions } = options;
- return toast.success(message, {
+type ToastOptions = Omit
& {
+ className?: ClassNameArgument,
+ bodyClassName?: ClassNameArgument,
+ actions?: React.ReactElement,
+};
+export type NotifyProps = {
+ /** A title of this component. */
+ title: string | React.ReactNode,
+
+ /** A message of this component. */
+ message?: ToastContent,
+
+ /** Options of this component. */
+ options?: ToastOptions,
+}
+const success = ({ title, message, options = {} }: NotifyProps) => {
+ const { className, bodyClassName, actions, closeButton = false, ...restOptions } = options;
+ const content = ;
+ const updatedOptions: ToastifyOptions = {
autoClose: 5000,
- className: cx('bk-toast--success', className),
- bodyClassName: cx('bk-toast__body', bodyClassName),
- progressClassName: 'bk-toast__progress-bar--success',
+ className: cx(cl['bk-toast--success'], className),
+ bodyClassName: cx(cl['bk-toast__body'], bodyClassName),
+ progressClassName: cx(cl['bk-toast__progress-bar--success']),
+ icon: ,
+ closeButton: closeButton === true ? : closeButton,
...restOptions,
- });
+ };
+ return toast.success(content, updatedOptions);
};
-const info = (message: ToastContent, options: ToastOptions = {}) => {
- const { className, bodyClassName, actions, actionsInline, ...restOptions } = options;
- return toast.info( , {
+const info = ({ title, message, options = {} }: NotifyProps) => {
+ const { className, bodyClassName, actions, closeButton = false, ...restOptions } = options;
+ const content = ;
+ const updatedOptions: ToastifyOptions = {
autoClose: 5000,
- className: cx('bk-toast--info', className),
- bodyClassName: cx('bk-toast__body', bodyClassName),
- progressClassName: 'bk-toast__progress-bar--info',
+ className: cx(cl['bk-toast--info'], className),
+ bodyClassName: cx(cl['bk-toast__body'], bodyClassName),
+ progressClassName: cx(cl['bk-toast__progress-bar--info']),
+ icon: ,
+ closeButton: closeButton === true ? : closeButton,
...restOptions,
- });
+ };
+ return toast.info(content, updatedOptions);
};
-const error = (message: ToastContent, options: ToastOptions = {}) => {
- const { className, bodyClassName, actions, actionsInline, ...restOptions } = options;
- return toast.error(
+const error = ({ title, message, options = {} }: NotifyProps) => {
+ const { className, bodyClassName, actions, closeButton = false, ...restOptions } = options;
+ const content = (
}
- actionsInline={actionsInline}
- />, {
- autoClose: 5000,
- className: cx('bk-toast--error', className),
- bodyClassName: cx('bk-toast__body', bodyClassName),
- progressClassName: 'bk-toast__progress-bar--error',
- ...restOptions,
- });
+ options={{
+ ...options,
+ ...(actions || message) && { actions: actions || },
+ }}
+ />
+ );
+ const updatedOptions: ToastifyOptions = {
+ autoClose: 5000,
+ className: cx(cl['bk-toast--error'], className),
+ bodyClassName: cx(cl['bk-toast__body'], bodyClassName),
+ progressClassName: cx(cl['bk-toast__progress-bar--error']),
+ icon: ,
+ closeButton: closeButton === true ? : closeButton,
+ ...restOptions,
+ };
+ return toast.error(content, updatedOptions);
};
const dismiss = (id?: string | number): boolean | void => toast.dismiss(id);
-export const notify = {
- success,
- info,
- error,
- dismiss,
-};
+export const notify = { success, info, error, dismiss };
type CloseToastButtonProps = {
closeToast?: () => void,
};
const CloseToastButton = ({ closeToast }: CloseToastButtonProps) => (
-
+
);
-export type ToastContainerProps = Omit & {
+type ToastProviderProps = Omit & {
+ /** Whether this component should be unstyled. */
+ unstyled?: undefined | boolean,
+
+ /** A classname of this component. */
className?: ClassNameArgument,
+
+ /** Whether this component should have a close button. */
+ hasCloseButton?: boolean,
+
+ /** Whether this component should display progress bar. */
showProgressBar?: boolean,
+
+ /** Components or elements to be rendered within the Provider. */
+ children: React.ReactNode,
};
-export const ToastContainer = (props: ToastContainerProps) => {
+export const ToastProvider = (props: ToastProviderProps) => {
const {
+ unstyled = false,
+ hasCloseButton = false,
className = '',
showProgressBar = false,
+ children,
...propsRest
} = props;
return (
- }
- {...propsRest}
- />
+ <>
+ {children}
+ {ReactDOM.createPortal(
+ }
+ {...propsRest}
+ />,
+ window.document.body,
+ )}
+ >
);
};
diff --git a/src/components/overlays/Toast/ToastyOverride.scss b/src/components/overlays/Toast/ToastyOverride.scss
new file mode 100644
index 0000000..ecb3ac0
--- /dev/null
+++ b/src/components/overlays/Toast/ToastyOverride.scss
@@ -0,0 +1,27 @@
+/* Copyright (c) Fortanix, Inc.
+|* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of
+|* the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+@use '../../../styling/defs.scss' as bk;
+
+// Define styling to override react-toastify's styles, as overriding directly from Toast.module.scss is not possible.
+.Toastify {
+ .Toastify__toast {
+ &:has(.Toastify__progress-bar--wrp) {
+ padding-bottom: calc(bk.$spacing-4 + 4px);
+ overflow: visible; // to display progress bar over the border
+ }
+ }
+
+ .Toastify__progress-bar--wrp {
+ height: 4px;
+ left: -2px;
+ width: calc(100% + 2px);
+ border-bottom-right-radius: var(--toastify-toast-bd-radius);
+ }
+
+ .Toastify__progress-bar--bg {
+ background: transparent;
+ }
+}
+
diff --git a/src/styling/variables.scss b/src/styling/variables.scss
index bde02ad..1db7619 100644
--- a/src/styling/variables.scss
+++ b/src/styling/variables.scss
@@ -288,20 +288,20 @@ $light-dropdown-menu-header-border-default: $color-blackberry-300 !default;
$light-dropdown-menu-header-tab-default: $color-blueberry-500 !default;
$light-dropdown-menu-header-text-default: $color-neutral-10 !default;
$light-dropdown-menu-header-background-focused: $color-blackberry-800 !default;
-$light-notifcation-success-background-default: $color-apple-50 !default;
-$light-notifcation-success-border-default: $color-apple-100 !default;
-$light-notifcation-text-default: $color-neutral-900 !default;
-$light-notifcation-informational-background-default: $color-blueberry-50 !default;
-$light-notifcation-informational-border-default: $color-blueberry-900 !default;
-$light-notifcation-alert-background-default: $color-cherry-50 !default;
-$light-notifcation-alert-border-default: $color-cherry-600 !default;
+$light-notification-success-background-default: $color-apple-50 !default;
+$light-notification-success-border-default: $color-apple-500 !default;
+$light-notification-text-default: $color-neutral-900 !default;
+$light-notification-informational-background-default: $color-blueberry-50 !default;
+$light-notification-informational-border-default: $color-blueberry-500 !default;
+$light-notification-alert-background-default: $color-cherry-50 !default;
+$light-notification-alert-border-default: $color-cherry-600 !default;
$light-breadcrumb-text-link: $color-blueberry-600 !default;
$light-header-background-default: $color-blackberry-400 !default;
$light-header-icon-default: $color-neutral-10 !default;
$light-header-text-default: $color-neutral-10 !default;
$light-dropdown-menu-header-icon-default: $color-neutral-10 !default;
$light-header-icon-background-default: $color-blackberry-300 !default;
-$light-notifcation-icon-default: $color-neutral-900 !default;
+$light-notification-icon-default: $color-neutral-900 !default;
$light-side-nav-menu-background-default: $color-blackberry-400 !default;
$light-side-nav-menu-tab-default: $color-blueberry-500 !default;
$light-side-nav-menu-text-default: $color-neutral-10 !default;
@@ -419,7 +419,7 @@ $light-tooltip-action-menu-background-hover: $color-neutral-20 !default;
$light-tooltip-action-menu-background-default: $color-neutral-0 !default;
$light-tooltip-action-menu-background-selected: $color-neutral-20 !default;
$light-tooltip-action-text-default: $color-neutral-900 !default;
-$light-notifcation-text-link: $color-blueberry-600 !default;
+$light-notification-text-link: $color-blueberry-700 !default;
$light-panel-background-secondary: $color-neutral-20 !default;
$light-accordion-border-default: $color-blackberry-20 !default;
$light-accordion-text-default: $color-neutral-900 !default;
@@ -523,20 +523,20 @@ $dark-dropdown-menu-header-border-default: $color-blackberry-300 !default;
$dark-dropdown-menu-header-tab-default: $color-blueberry-400 !default;
$dark-dropdown-menu-header-text-default: $color-neutral-10 !default;
$dark-dropdown-menu-header-background-focused: $color-blackberry-800 !default;
-$dark-notifcation-success-background-default: $color-apple-50 !default;
-$dark-notifcation-success-border-default: $color-apple-100 !default;
-$dark-notifcation-text-default: $color-neutral-900 !default;
-$dark-notifcation-informational-background-default: $color-blueberry-50 !default;
-$dark-notifcation-informational-border-default: $color-blueberry-900 !default;
-$dark-notifcation-alert-background-default: $color-cherry-50 !default;
-$dark-notifcation-alert-border-default: $color-cherry-600 !default;
+$dark-notification-success-background-default: $color-apple-50 !default;
+$dark-notification-success-border-default: $color-apple-500 !default;
+$dark-notification-text-default: $color-neutral-900 !default;
+$dark-notification-informational-background-default: $color-blueberry-50 !default;
+$dark-notification-informational-border-default: $color-blueberry-500 !default;
+$dark-notification-alert-background-default: $color-cherry-50 !default;
+$dark-notification-alert-border-default: $color-cherry-600 !default;
$dark-breadcrumb-text-link: $color-blueberry-500 !default;
$dark-header-background-default: $color-blackberry-400 !default;
$dark-header-icon-default: $color-neutral-10 !default;
$dark-header-text-default: $color-neutral-10 !default;
$dark-dropdown-menu-header-icon-default: $color-neutral-10 !default;
$dark-header-icon-background-default: $color-blackberry-300 !default;
-$dark-notifcation-icon-default: $color-neutral-900 !default;
+$dark-notification-icon-default: $color-neutral-900 !default;
$dark-side-nav-menu-background-default: $color-blackberry-400 !default;
$dark-side-nav-menu-tab-default: $color-blueberry-400 !default;
$dark-side-nav-menu-text-default: $color-neutral-10 !default;
@@ -654,7 +654,7 @@ $dark-tooltip-action-menu-background-hover: $color-blackberry-800 !default;
$dark-tooltip-action-menu-background-default: $color-grape-800 !default;
$dark-tooltip-action-menu-background-selected: $color-blackberry-800 !default;
$dark-tooltip-action-text-default: $color-neutral-10 !default;
-$dark-notifcation-text-link: $color-blueberry-600 !default;
+$dark-notification-text-link: $color-blueberry-700 !default;
$dark-panel-background-secondary: $color-blackberry-800 !default;
$dark-accordion-border-default: $color-blackberry-300 !default;
$dark-accordion-text-default: $color-neutral-10 !default;
@@ -758,20 +758,20 @@ $theme-dropdown-menu-header-border-default: #{ld($light-dropdown-menu-header-bor
$theme-dropdown-menu-header-tab-default: #{ld($light-dropdown-menu-header-tab-default, $dark-dropdown-menu-header-tab-default)} !default;
$theme-dropdown-menu-header-text-default: #{ld($light-dropdown-menu-header-text-default, $dark-dropdown-menu-header-text-default)} !default;
$theme-dropdown-menu-header-background-focused: #{ld($light-dropdown-menu-header-background-focused, $dark-dropdown-menu-header-background-focused)} !default;
-$theme-notifcation-success-background-default: #{ld($light-notifcation-success-background-default, $dark-notifcation-success-background-default)} !default;
-$theme-notifcation-success-border-default: #{ld($light-notifcation-success-border-default, $dark-notifcation-success-border-default)} !default;
-$theme-notifcation-text-default: #{ld($light-notifcation-text-default, $dark-notifcation-text-default)} !default;
-$theme-notifcation-informational-background-default: #{ld($light-notifcation-informational-background-default, $dark-notifcation-informational-background-default)} !default;
-$theme-notifcation-informational-border-default: #{ld($light-notifcation-informational-border-default, $dark-notifcation-informational-border-default)} !default;
-$theme-notifcation-alert-background-default: #{ld($light-notifcation-alert-background-default, $dark-notifcation-alert-background-default)} !default;
-$theme-notifcation-alert-border-default: #{ld($light-notifcation-alert-border-default, $dark-notifcation-alert-border-default)} !default;
+$theme-notification-success-background-default: #{ld($light-notification-success-background-default, $dark-notification-success-background-default)} !default;
+$theme-notification-success-border-default: #{ld($light-notification-success-border-default, $dark-notification-success-border-default)} !default;
+$theme-notification-text-default: #{ld($light-notification-text-default, $dark-notification-text-default)} !default;
+$theme-notification-informational-background-default: #{ld($light-notification-informational-background-default, $dark-notification-informational-background-default)} !default;
+$theme-notification-informational-border-default: #{ld($light-notification-informational-border-default, $dark-notification-informational-border-default)} !default;
+$theme-notification-alert-background-default: #{ld($light-notification-alert-background-default, $dark-notification-alert-background-default)} !default;
+$theme-notification-alert-border-default: #{ld($light-notification-alert-border-default, $dark-notification-alert-border-default)} !default;
$theme-breadcrumb-text-link: #{ld($light-breadcrumb-text-link, $dark-breadcrumb-text-link)} !default;
$theme-header-background-default: #{ld($light-header-background-default, $dark-header-background-default)} !default;
$theme-header-icon-default: #{ld($light-header-icon-default, $dark-header-icon-default)} !default;
$theme-header-text-default: #{ld($light-header-text-default, $dark-header-text-default)} !default;
$theme-dropdown-menu-header-icon-default: #{ld($light-dropdown-menu-header-icon-default, $dark-dropdown-menu-header-icon-default)} !default;
$theme-header-icon-background-default: #{ld($light-header-icon-background-default, $dark-header-icon-background-default)} !default;
-$theme-notifcation-icon-default: #{ld($light-notifcation-icon-default, $dark-notifcation-icon-default)} !default;
+$theme-notification-icon-default: #{ld($light-notification-icon-default, $dark-notification-icon-default)} !default;
$theme-side-nav-menu-background-default: #{ld($light-side-nav-menu-background-default, $dark-side-nav-menu-background-default)} !default;
$theme-side-nav-menu-tab-default: #{ld($light-side-nav-menu-tab-default, $dark-side-nav-menu-tab-default)} !default;
$theme-side-nav-menu-text-default: #{ld($light-side-nav-menu-text-default, $dark-side-nav-menu-text-default)} !default;
@@ -889,7 +889,7 @@ $theme-tooltip-action-menu-background-hover: #{ld($light-tooltip-action-menu-bac
$theme-tooltip-action-menu-background-default: #{ld($light-tooltip-action-menu-background-default, $dark-tooltip-action-menu-background-default)} !default;
$theme-tooltip-action-menu-background-selected: #{ld($light-tooltip-action-menu-background-selected, $dark-tooltip-action-menu-background-selected)} !default;
$theme-tooltip-action-text-default: #{ld($light-tooltip-action-text-default, $dark-tooltip-action-text-default)} !default;
-$theme-notifcation-text-link: #{ld($light-notifcation-text-link, $dark-notifcation-text-link)} !default;
+$theme-notification-text-link: #{ld($light-notification-text-link, $dark-notification-text-link)} !default;
$theme-panel-background-secondary: #{ld($light-panel-background-secondary, $dark-panel-background-secondary)} !default;
$theme-accordion-border-default: #{ld($light-accordion-border-default, $dark-accordion-border-default)} !default;
$theme-accordion-text-default: #{ld($light-accordion-text-default, $dark-accordion-text-default)} !default;