diff --git a/packages/paste-core/components/account-switcher/src/AccountSwitcher.tsx b/packages/paste-core/components/account-switcher/src/AccountSwitcher.tsx index d906c5efac..fdad9acfd3 100644 --- a/packages/paste-core/components/account-switcher/src/AccountSwitcher.tsx +++ b/packages/paste-core/components/account-switcher/src/AccountSwitcher.tsx @@ -15,6 +15,11 @@ export interface AccountSwitcherProps extends MenuProps { element?: BoxProps["element"]; } +/** + * An Account Switcher component is a stylized Menu Badge with a list of actions related to a user's accounts. + * + * @link [Account Switcher](https://paste.twilio.design/components/account-switcher) + */ const AccountSwitcher = React.forwardRef( ({ children, element = "ACCOUNT_SWITCHER", ...props }, ref) => { return ( diff --git a/packages/paste-core/components/account-switcher/src/AccountSwitcherBadge.tsx b/packages/paste-core/components/account-switcher/src/AccountSwitcherBadge.tsx index 2e8776cc82..1b46f9ae91 100644 --- a/packages/paste-core/components/account-switcher/src/AccountSwitcherBadge.tsx +++ b/packages/paste-core/components/account-switcher/src/AccountSwitcherBadge.tsx @@ -15,6 +15,11 @@ export interface AccountSwitcherBadgeProps extends Omit( ({ children, element = "ACCOUNT_SWITCHER_BADGE", ...props }, ref) => { return ( diff --git a/packages/paste-core/components/account-switcher/src/AccountSwitcherGroup.tsx b/packages/paste-core/components/account-switcher/src/AccountSwitcherGroup.tsx index b1aa43fc6b..ad5ca84b16 100644 --- a/packages/paste-core/components/account-switcher/src/AccountSwitcherGroup.tsx +++ b/packages/paste-core/components/account-switcher/src/AccountSwitcherGroup.tsx @@ -14,6 +14,11 @@ export interface AccountSwitcherGroupProps extends MenuGroupProps { element?: BoxProps["element"]; } +/** + * Used to group similar items together in the Account Switcher menu. An example of this might be a list of recent accounts. + * + * @link [Account Switcher Group](https://paste.twilio.design/components/account-switcher#account-switcher-group) + */ const AccountSwitcherGroup = React.forwardRef( ({ children, element = "ACCOUNT_SWITCHER_GROUP", label, ...props }, ref) => { return ( diff --git a/packages/paste-core/components/account-switcher/src/AccountSwitcherItem.tsx b/packages/paste-core/components/account-switcher/src/AccountSwitcherItem.tsx index a69383e4ae..e361c6468e 100644 --- a/packages/paste-core/components/account-switcher/src/AccountSwitcherItem.tsx +++ b/packages/paste-core/components/account-switcher/src/AccountSwitcherItem.tsx @@ -15,6 +15,11 @@ export interface AccountSwitcherItemProps extends MenuItemProps { element?: BoxProps["element"]; } +/** + * A menu item that can either perform an action or navigate to a new URL. + * + * @link [Account Switcher Item](https://paste.twilio.design/components/account-switcher#account-switcher-item) + */ const AccountSwitcherItem = React.forwardRef( ({ children, element = "ACCOUNT_SWITCHER_ITEM", ...props }, ref) => { return ( diff --git a/packages/paste-core/components/account-switcher/src/AccountSwitcherItemRadio.tsx b/packages/paste-core/components/account-switcher/src/AccountSwitcherItemRadio.tsx index 830e2b0d93..7801f23eea 100644 --- a/packages/paste-core/components/account-switcher/src/AccountSwitcherItemRadio.tsx +++ b/packages/paste-core/components/account-switcher/src/AccountSwitcherItemRadio.tsx @@ -15,6 +15,11 @@ export interface AccountSwitcherItemRadioProps extends MenuItemRadioProps { element?: BoxProps["element"]; } +/** + * A menu item that can perform a single selection of an item within a named group. Similar to a radio button group, only one item can be selected at a time. Each item in the group should have a name and value and must be contained in a Group. + * + * @link [Account Switcher Item Radio](https://paste.twilio.design/components/account-switcher#account-switcher-itemradio) + */ const AccountSwitcherItemRadio = React.forwardRef( ({ children, element = "ACCOUNT_SWITCHER_ITEM_RADIO", ...props }, ref) => { return ( diff --git a/packages/paste-core/components/account-switcher/src/AccountSwitcherSeparator.tsx b/packages/paste-core/components/account-switcher/src/AccountSwitcherSeparator.tsx index eacddc7a72..950e1061ee 100644 --- a/packages/paste-core/components/account-switcher/src/AccountSwitcherSeparator.tsx +++ b/packages/paste-core/components/account-switcher/src/AccountSwitcherSeparator.tsx @@ -14,6 +14,11 @@ export interface AccountSwitcherSeparatorProps extends MenuSeparatorProps { element?: BoxProps["element"]; } +/** + * Simple horizontal rule used to separate groups or individual items. + * + * @link [Account Switcher Separator](https://paste.twilio.design/components/account-switcher#account-switcher-separator) + */ const AccountSwitcherSeparator = React.forwardRef( ({ children, element = "ACCOUNT_SWITCHER_SEPARATOR", ...props }, ref) => { return ( diff --git a/packages/paste-core/components/alert-dialog/src/AlertDialog.tsx b/packages/paste-core/components/alert-dialog/src/AlertDialog.tsx index 741a93b25e..c3bee3c3be 100644 --- a/packages/paste-core/components/alert-dialog/src/AlertDialog.tsx +++ b/packages/paste-core/components/alert-dialog/src/AlertDialog.tsx @@ -1,6 +1,7 @@ +import type { SpringValue } from "@react-spring/web"; import { useTransition } from "@twilio-paste/animation-library"; -import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; import type { BoxProps } from "@twilio-paste/box"; +import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; import { ModalDialogOverlay } from "@twilio-paste/modal"; import type { HTMLPasteProps } from "@twilio-paste/types"; import { useUID } from "@twilio-paste/uid-library"; @@ -11,8 +12,10 @@ import { AlertDialogContent } from "./AlertDialogContent"; import { AlertDialogFooter } from "./AlertDialogFooter"; import { AlertDialogHeader } from "./AlertDialogHeader"; -// eslint-disable-next-line @typescript-eslint/no-explicit-any -const getAnimationStates = (): any => ({ +/** + * Animation states for the Alert Dialog. + */ +const AnimationStates = { from: { opacity: 0, transform: `scale(0.675)` }, enter: { opacity: 1, transform: `scale(1)` }, leave: { opacity: 0, transform: `scale(0.675)` }, @@ -22,7 +25,7 @@ const getAnimationStates = (): any => ({ tension: 370, friction: 26, }, -}); +}; export interface AlertDialogProps extends HTMLPasteProps<"div"> { children: NonNullable; @@ -92,6 +95,35 @@ export interface AlertDialogProps extends HTMLPasteProps<"div"> { element?: BoxProps["element"]; } +interface NormalizeStylesArg { + opacity: SpringValue; + transform: SpringValue; +} + +interface NormalizeStylesReturn { + opacity: number; + transform: string; +} + +/** + * Normalize ReactSpring styles to be used in the AlertDialog. + * + * @param {NormalizeStylesArg} styles - ReactSpring styles + * @returns {NormalizeStylesReturn} - Normalized styles + */ +const normalizeStyles = (styles: NormalizeStylesArg): NormalizeStylesReturn => { + return { + ...styles, + opacity: styles.opacity.get(), + transform: styles.transform.get(), + }; +}; + +/** + * An Alert Dialog is a page overlay that displays critical information, blocks interaction with the page, and only closes after an action is performed. + * + * @link [Alert Dialog](https://paste.twilio.design/components/alert-dialog) + */ export const AlertDialog = React.forwardRef( ( { @@ -109,48 +141,49 @@ export const AlertDialog = React.forwardRef( }, ref, ) => { - const transitions = useTransition(isOpen, getAnimationStates()); + const transitions = useTransition(isOpen, AnimationStates); const headingID = useUID(); const bodyID = useUID(); - return ( - <> - {transitions( - (styles, item) => - item && ( - - - - {heading} - - - {children} - - - - - ), - )} - - ); + return transitions((rawStyles, item) => { + if (!item) { + return null; + } + // Normalizing ReactSpring styles. + const styles = normalizeStyles(rawStyles); + + return ( + + + + {heading} + + + {children} + + + + + ); + }); }, ); diff --git a/packages/paste-core/components/alert-dialog/src/AlertDialogBody.tsx b/packages/paste-core/components/alert-dialog/src/AlertDialogBody.tsx index 0153acd064..aa6dd48224 100644 --- a/packages/paste-core/components/alert-dialog/src/AlertDialogBody.tsx +++ b/packages/paste-core/components/alert-dialog/src/AlertDialogBody.tsx @@ -8,6 +8,11 @@ export interface AlertDialogBodyProps extends HTMLPasteProps<"div">, Pick; } +/** + * Internal body component for the AlertDialog component. + * + * @private + */ export const AlertDialogBody = React.forwardRef( ({ bodyID, children, element = "ALERT_DIALOG_BODY", ...props }, ref) => { return ( diff --git a/packages/paste-core/components/alert-dialog/src/AlertDialogContent.tsx b/packages/paste-core/components/alert-dialog/src/AlertDialogContent.tsx index 8c907ea3f4..525545716c 100644 --- a/packages/paste-core/components/alert-dialog/src/AlertDialogContent.tsx +++ b/packages/paste-core/components/alert-dialog/src/AlertDialogContent.tsx @@ -4,12 +4,15 @@ import { css, styled } from "@twilio-paste/styling-library"; export type AlertDialogContentProps = ModalDialogContentProps; -const AlertDialogContent = styled(ModalDialogContent)(() => +/** + * Content area for the AlertDialog component. + * + * @private + */ +export const AlertDialogContent = styled(ModalDialogContent)(() => css({ maxWidth: "size40", }), ); AlertDialogContent.displayName = "AlertDialogContent"; - -export { AlertDialogContent }; diff --git a/packages/paste-core/components/alert-dialog/src/AlertDialogFooter.tsx b/packages/paste-core/components/alert-dialog/src/AlertDialogFooter.tsx index 253ba95bf6..1ed94cd80d 100644 --- a/packages/paste-core/components/alert-dialog/src/AlertDialogFooter.tsx +++ b/packages/paste-core/components/alert-dialog/src/AlertDialogFooter.tsx @@ -6,14 +6,25 @@ import type { HTMLPasteProps } from "@twilio-paste/types"; import * as React from "react"; export interface AlertDialogFooterProps extends HTMLPasteProps<"div">, Pick { + /** Determines if the Alert Dialog is destructive. _Only changes the button color of confirm button._ */ destructive?: boolean; + /** Function to run on confirmation of the Alert Dialog. */ onConfirm: () => void; + /** Text of the confirm button. */ onConfirmLabel: string; + /** Function to run on dismiss of the Alert Dialog. */ onDismiss: () => void; + /** Text of the dismiss button. */ onDismissLabel: string; + /** Property to disable the confirm button. _Has no effect if destructive is not true._ */ onConfirmDisabled?: boolean; } +/** + * Alert Dialog footer component for the AlertDialog component. + * + * @private + */ export const AlertDialogFooter = React.forwardRef( ( { diff --git a/packages/paste-core/components/alert-dialog/src/AlertDialogHeader.tsx b/packages/paste-core/components/alert-dialog/src/AlertDialogHeader.tsx index 9db23dd7cf..4a203db21f 100644 --- a/packages/paste-core/components/alert-dialog/src/AlertDialogHeader.tsx +++ b/packages/paste-core/components/alert-dialog/src/AlertDialogHeader.tsx @@ -6,9 +6,15 @@ import * as React from "react"; export interface AlertDialogHeaderProps extends HTMLPasteProps<"header">, Pick { children: string; + /** ID for the internal heading element. */ headingID: string; } +/** + * Internal alert dialog header component for the AlertDialog component. + * + * @private + */ export const AlertDialogHeader = React.forwardRef( ({ children, element = "ALERT_DIALOG_HEADER", headingID, ...props }, ref) => { return ( diff --git a/packages/paste-core/components/alert/src/Alert.tsx b/packages/paste-core/components/alert/src/Alert.tsx index 5fe6f952ad..409d22238d 100644 --- a/packages/paste-core/components/alert/src/Alert.tsx +++ b/packages/paste-core/components/alert/src/Alert.tsx @@ -10,23 +10,28 @@ import { ScreenReaderOnly } from "@twilio-paste/screen-reader-only"; import type { HTMLPasteProps, ValueOf } from "@twilio-paste/types"; import * as React from "react"; +/** Alert component variants keys. */ type AlertVariantKeys = "ERROR" | "NEUTRAL" | "WARNING"; +/** Alert component roles. */ export const AlertRoles = { ERROR: "alert", NEUTRAL: "status", WARNING: "alert", } as const; +/** Alert component variants. */ export const AlertVariants = { ERROR: "error", NEUTRAL: "neutral", WARNING: "warning", } as const; +/** Alert component background colors. */ export const AlertBackgroundColors = { ERROR: "colorBackgroundErrorWeakest", NEUTRAL: "colorBackgroundNeutralWeakest", WARNING: "colorBackgroundWarningWeakest", } as const; +/** Alert component text colors. */ export const AlertTextColors = { ERROR: "colorTextError", NEUTRAL: "colorTextNeutral", @@ -107,7 +112,16 @@ export interface AlertProps extends HTMLPasteProps<"div"> { element?: BoxProps["element"]; } -const renderAlertIcon = (variant: AlertVariants, element: string, title: string): React.ReactElement => { +interface AlertIconProps { + variant: AlertVariants; + element: string; + title: string; +} + +/** + * Component to display the appropriate alert icon. + */ +const AlertIcon: React.FC = ({ variant, element, title }): React.ReactElement => { switch (variant) { case AlertVariants.ERROR: return ( @@ -142,7 +156,13 @@ const renderAlertIcon = (variant: AlertVariants, element: string, title: string) ); } }; +AlertIcon.displayName = "AlertIcon"; +/** + * An Alert is a banner that notifies users to high-priority or time-sensitive information. + * + * @link [Alert](https://paste.twilio.design/components/alert) + */ const Alert = React.forwardRef( ( { @@ -180,7 +200,7 @@ const Alert = React.forwardRef( > - {renderAlertIcon(variant, element, i18nLabelVariantMap[variant])} + {children}