diff --git a/packages/components/src/core/Callout/__storybook__/constants.tsx b/packages/components/src/core/Callout/__storybook__/constants.tsx index 47854bf3c..aa2fc0db6 100644 --- a/packages/components/src/core/Callout/__storybook__/constants.tsx +++ b/packages/components/src/core/Callout/__storybook__/constants.tsx @@ -1,13 +1,16 @@ -import { action } from "@storybook/addon-actions"; import CustomSdsIcon from "src/common/storybook/customSdsIcon"; import CustomSvgIcon from "src/common/storybook/customSvgIcon"; export const CALLOUT_EXCLUDED_CONTROLS = [ "autoDismiss", - "expandable", "icon", "intent", "onClose", + "sdsStyle", + "hideTitle", + "hideBody", + "title", + "body", ]; export const CALLOUT_ICON_OPTIONS = [ @@ -17,4 +20,8 @@ export const CALLOUT_ICON_OPTIONS = [ "CheckCircle", ]; -export const CALLOUT_ON_CLOSE_OPTIONS = [action("onClick"), undefined]; +export const CALLOUT_SDS_STYLE_OPTIONS = [ + "persistent", + "expandable", + "dismissible", +]; diff --git a/packages/components/src/core/Callout/__storybook__/index.stories.tsx b/packages/components/src/core/Callout/__storybook__/index.stories.tsx index 555f5f9fd..30dd02184 100644 --- a/packages/components/src/core/Callout/__storybook__/index.stories.tsx +++ b/packages/components/src/core/Callout/__storybook__/index.stories.tsx @@ -1,6 +1,6 @@ import { Meta } from "@storybook/react"; import { BADGE } from "@geometricpanda/storybook-addon-badges"; -import { CALLOUT_ICON_OPTIONS, CALLOUT_ON_CLOSE_OPTIONS } from "./constants"; +import { CALLOUT_ICON_OPTIONS, CALLOUT_SDS_STYLE_OPTIONS } from "./constants"; import { Callout } from "./stories/default"; export default { @@ -17,17 +17,6 @@ export default { defaultValue: { summary: "-" }, description: "The body text of the callout.", }, - expandable: { - control: { type: "boolean" }, - defaultValue: { summary: "false" }, - description: "If true, the callout will be expandable.", - }, - extraContent: { - control: { type: "boolean" }, - defaultValue: { summary: "-" }, - description: - "The extra content in the Callout is passed as children to the component, allowing you to add custom content to it. For Storybook purposes, a predefined example of extra content has been added to the Callout component. You can toggle this boolean to test it out. Note that this is not an actual prop on the Callout component.", - }, hideBody: { control: { type: "boolean" }, defaultValue: { summary: "false" }, @@ -60,16 +49,16 @@ export default { description: "The intent of the callout.", options: ["info", "negative", "positive", "notice"], }, - onClose: { + sdsStyle: { control: { - labels: ["() => {}", "undefined"], + labels: ["persistent", "expandable", "dismissible"], type: "select", }, - defaultValue: { summary: "-" }, + defaultValue: { summary: "persistent" }, description: - "If set to a function, the callout will have a close button.", - mapping: CALLOUT_ON_CLOSE_OPTIONS, - options: Object.keys(CALLOUT_ON_CLOSE_OPTIONS), + "The style of the Callout determines its behavior: Persistent Callouts are always visible, Expandable Callouts can be toggled to show or hide extra content, and Dismissible Callouts can be closed by the user.", + mapping: CALLOUT_SDS_STYLE_OPTIONS, + options: Object.keys(CALLOUT_SDS_STYLE_OPTIONS), }, title: { control: { type: "text" }, @@ -92,9 +81,7 @@ export default { export const Default = { args: { autoDismiss: false, - body: "Callout text—replace the content here and the height of the component will adjust automatically.", - expandable: false, - onClose: false, - title: "Title", + body: "Callout text — replace the content here and the height of the component will adjust automatically.", + title: "The callout title goes here", }, }; diff --git a/packages/components/src/core/Callout/__storybook__/stories/default.tsx b/packages/components/src/core/Callout/__storybook__/stories/default.tsx index a1f3b96b9..a602717db 100644 --- a/packages/components/src/core/Callout/__storybook__/stories/default.tsx +++ b/packages/components/src/core/Callout/__storybook__/stories/default.tsx @@ -1,4 +1,4 @@ -import { FormControlLabel } from "@mui/material"; +import { Box, FormControlLabel } from "@mui/material"; import { Args } from "@storybook/react"; import { useState } from "react"; import RawCallout from "src/core/Callout"; @@ -7,7 +7,7 @@ import { SHORT_LOREM_IPSUM } from "src/common/storybook/loremIpsum"; import TooltipTableContent from "src/core/TooltipTable"; export const Callout = (props: Args): JSX.Element => { - const { intent, onClose, autoDismiss, extraContent, ...rest } = props; + const { intent, autoDismiss, ...rest } = props; const [dismissed, setDismissed] = useState(false); @@ -15,10 +15,10 @@ export const Callout = (props: Args): JSX.Element => { setDismissed((prev) => !prev); }; - const finalOnclose = !onClose ? undefined : () => setDismissed(true); + const finalOnclose = (_: React.SyntheticEvent) => setDismissed(true); return ( - <> + {!autoDismiss && ( } @@ -38,7 +38,7 @@ export const Callout = (props: Args): JSX.Element => { onClose={finalOnclose} {...rest} > - {extraContent && ( + { {SHORT_LOREM_IPSUM} @@ -55,8 +55,8 @@ export const Callout = (props: Args): JSX.Element => { /> - )} + } - > + ); }; diff --git a/packages/components/src/core/Callout/index.tsx b/packages/components/src/core/Callout/index.tsx index 3ccaf6af5..71688eb55 100644 --- a/packages/components/src/core/Callout/index.tsx +++ b/packages/components/src/core/Callout/index.tsx @@ -12,6 +12,7 @@ const SDS_STAGE_OPEN = "open"; const SDS_STAGE_CLOSED = "closed"; export type CalloutIntentType = "info" | "negative" | "notice" | "positive"; +export type CalloutSdsStyleType = "persistent" | "expandable" | "dismissible"; export interface CalloutProps { autoDismiss?: boolean | number; dismissed?: boolean; @@ -24,7 +25,7 @@ export interface CalloutProps { body?: string; hideBody?: boolean; extraContent?: React.ReactNode; - expandable?: boolean; + sdsStyle?: CalloutSdsStyleType; } export type ExposedCalloutProps = Omit & CalloutProps; @@ -32,22 +33,22 @@ export type ExposedCalloutProps = Omit & CalloutProps; /** * @see https://mui.com/material-ui/react-alert/ */ -const Callout = ({ - autoDismiss, - dismissed, - expandable, - onClose, - icon, - sdsIconProps, - intent, - sdsStage, - title, - body, - hideTitle = false, - hideBody = false, - children, - ...rest -}: ExposedCalloutProps): JSX.Element => { +const Callout = (props: ExposedCalloutProps): JSX.Element => { + const { + autoDismiss, + dismissed, + icon, + sdsIconProps, + intent, + sdsStage, + title, + body, + hideTitle = false, + hideBody = false, + sdsStyle = "persistent", + children, + ...rest + } = props; const [hide, setHide] = useState(dismissed); const [stage, setStage] = useState(sdsStage || SDS_STAGE_CLOSED); @@ -64,7 +65,7 @@ const Callout = ({ const handleClose = (event: React.SyntheticEvent) => { setHide(true); - if (onClose) onClose(event); + if (props?.onClose) props?.onClose(event); }; const getIcon = () => { @@ -93,7 +94,7 @@ const Callout = ({ }; const getAction = (collapsed: boolean) => { - if (expandable) { + if (sdsStyle === "expandable") { return ( ); + } else if (sdsStyle === "dismissible") { + return ( + + ); } - return onClose ? ( - - ) : null; + + return null; }; - const collapsed = (expandable && stage === SDS_STAGE_CLOSED) || false; + const collapsed = + (sdsStyle === "expandable" && stage === SDS_STAGE_CLOSED) || false; return ( <> {!hideTitle && {title}} {!hideBody && {body}} - {!collapsed && ( + {sdsStyle === "expandable" && !collapsed && ( {children} diff --git a/packages/components/src/core/Callout/style.ts b/packages/components/src/core/Callout/style.ts index 787904ed1..30c4c3725 100644 --- a/packages/components/src/core/Callout/style.ts +++ b/packages/components/src/core/Callout/style.ts @@ -14,23 +14,25 @@ import { getSemanticColors, getSpaces, } from "src/core/styles"; -import { CalloutIntentType } from "src/core/Callout"; +import { CalloutIntentType, CalloutSdsStyleType } from "src/core/Callout"; interface CalloutExtraProps extends CommonThemeProps { collapsed?: boolean; intent?: CalloutIntentType; + sdsStyle?: CalloutSdsStyleType; } type CalloutProps = Omit & CalloutExtraProps; -const doNotForwardProps = ["calloutTitle", "collapsed", "severity"]; +const doNotForwardProps = ["calloutTitle", "collapsed", "severity", "sdsStyle"]; export const StyledCallout = styled(Alert, { shouldForwardProp: (prop: string) => !doNotForwardProps.includes(prop), })` ${fontBodyXs} + ${(props: CalloutProps) => { - const { intent = "info" } = props; + const { intent = "info", sdsStyle } = props; const spaces = getSpaces(props); const corners = getCorners(props); @@ -43,8 +45,6 @@ export const StyledCallout = styled(Alert, { semanticColors?.[intent]?.surfaceSecondary ?? "white"; return ` - position: relative; - width: 360px; margin: ${spaces?.m}px 0; border-radius: ${corners?.m}px; color: ${palette?.text?.primary}; @@ -63,8 +63,9 @@ export const StyledCallout = styled(Alert, { } .${alertClasses.message} { + width: 100%; padding: 0; - margin-right: ${spaces?.m}px; + margin: 0; .${alertTitleClasses.root} { margin: 0; @@ -72,13 +73,10 @@ export const StyledCallout = styled(Alert, { } .${alertClasses.action} { - position: absolute; - right: ${spaces?.m}px; - top: ${spaces?.m}px; - margin-right: 0; + display: ${sdsStyle === "persistent" ? "none" : "block"}; + margin: 0 0 0 ${spaces?.s}px; padding: 0; align-items: flex-start; - margin-top: ${spaces?.xxs}px; > button { padding: 0;